-->

How do I convert a large string into hex and then

2020-07-19 03:08发布

问题:

I work with cellphones and deal with MEID numbers on a daily basis. So instead of searching online for a MEID (a hex number of length 14) to pseudo ESN (a hex number of length 8) calculator, I figured I can make my own program. The way to obtain a pESN from MEID is fairly simple in theory. For example, given MEID 0xA0000000002329, to make a pESN, SHA-1 needs to be applied to the MEID. SHA-1 on A0000000002329 gives e3be267a2cd5c861f3c7ea4224df829a3551f1ab. Take the last 6 hex numbers of this result, and append it to 0x80 - the result is 0x8051F1AB.

Now here is the code I have so far:

public void sha1() throws NoSuchAlgorithmException {

    String hexMEID = "A0000000002329";

    MessageDigest mDigest = MessageDigest.getInstance("SHA1");      

    byte[] result = mDigest.digest(hexMEID.getBytes());
    StringBuilder sb = new StringBuilder();

    for (int i = 0; i < result.length; i++) {
        sb.append(Integer.toString((result[i] & 0xff) + 0x100, 16).substring(1));
    }

    System.out.println(sb.toString());
}  

The problem is that using this method, SHA-1 on A0000000002329 gives a89b611b421f57705bd013297ce3fc835f706ab0 instead of e3be267a2cd5c861f3c7ea4224df829a3551f1ab. What am I doing wrong here??

Someone gave me a hint that "the trick is to apply SHA-1 to the number representing the MEID, not the string representing the MEID. You'll need to process it byte-by-byte, so you must give it two hex numbers at a time (since two hex numbers make a byte) and make sure they are interpreted as numbers and not ASCII characters". If this is true then how do I change my string into hex and then into byte so that SHA1 can give me the correct result???

回答1:

You can use the following two methods

    public static synchronized String bytesToHex(byte [] buf){
        StringBuffer strbuf = new StringBuffer(buf.length * 2);
        int i;
        for (i = 0; i < buf.length; i++) {
            if (((int) buf[i] & 0xff) < 0x10){
                strbuf.append("0");
            }
            strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
        }
        return strbuf.toString();
    }

    public synchronized static byte[] hexToBytes(String hexString) {
         byte[] b = new BigInteger(hexString,16).toByteArray();     
         return b;
    }


回答2:

Without libraries, you can follow the example here:

In Java, how do you convert a hex string to a byte[]?

 byte[] b = new BigInteger(s,16).toByteArray();

One library (I'm sure there are many) that also provides this is POJava:

<dependency>
    <groupId>org.pojava</groupId>
    <artifactId>pojava</artifactId>
    <version>2.8.1</version>
</dependency>


 byte[] hexMEIDBytes=EncodingTool.hexDecode(hexMEID);

[EDIT] ==============

Here's a more complete example per your followup question:

    byte[] hexMEIDBytes = EncodingTool.hexDecode(hexMEID);
    byte[] hash = HashingTool.hash(hexMEIDBytes, HashingAlgorithm.SHA);
    String pESN="0x80" + EncodingTool.hexEncode(hash).substring(34).toUpperCase();
    // a hexMEID value of "A0000000002329" results in a pESN value of "0x8051F1AB"


回答3:

For String to Hex:

public String StrToHex(String arg) {

    return String.format("%040x", new BigInteger(arg.getBytes(//Your Charset//)));
}

For Hex to byte:

This below code wont work for "0".

public byte[] hexStrToByteArray(String s) {
    int leng = s.length();
    byte[] data = new byte[leng / 2];
    for (int i = 0; i < leng; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}