SHA256 Hash results different across Android & iOS for Big numbers

I'm trying to Hash a BigInteger/BigNum and I'm getting different results in Android/iOS. I need to get the same Hash result so that both the apps work as per the SRP protocol. On closer inspection it is working fine for positive numbers but not working for negative numbers (first nibble greater than 7). Not sure which one is correct and which one is to be adjusted to match with the other.

Android:

    void hashBigInteger(String s) {
    try {
        BigInteger a = new BigInteger(s, 16);
        MessageDigest sha = MessageDigest.getInstance("SHA-256");
        byte[] b = a.toByteArray();
        sha.update(b, 0, b.length);
        byte[] digest = sha.digest();
        BigInteger d = new BigInteger(digest);
        Log.d("HASH", "H = " + d.toString(16));
    } catch (NoSuchAlgorithmException e) {
        throw new UnsupportedOperationException(e);
    }
}

iOS:

void hashBigNum(unsigned char *c) {
    BIGNUM *n = BN_new();
    BN_hex2bn(&n, c);
    unsigned char   buff[ SHA256_DIGEST_LENGTH ];
    int             len  = BN_num_bytes(n);
    unsigned char * bin    = (unsigned char *) malloc( len );
    BN_bn2bin(n, bin);
    hash( SRP_SHA256, bin, len, buff ); 
    fprintf(stderr, "H: ");
    for (int z = 0; z < SHA256_DIGEST_LENGTH; z++)
        fprintf(stderr, "%2x", buff[z]);
    fprintf(stderr, "n");
    free(bin);
}

Results:

Source String = "6F"
Android Hash = 65c74c15a686187bb6bbf9958f494fc6b80068034a659a9ad44991b08c58f2d2
iOS     Hash = 65c74c15a686187bb6bbf9958f494fc6b80068034a659a9ad44991b08c58f2d2

Source String = "FF"
Android Hash = 06eb7d6a69ee19e5fbdf749018d3d2abfa04bcbd1365db312eb86dc7169389b8
iOS     Hash = a8100ae6aa1940d0b663bb31cd466142ebbdbd5187131b92d93818987832eb89

The problem is in the JAVA code. new BigInteger(s, 16).toByteArray() is not safe for leading zeros. See poster comment at Convert a string representation of a hex dump to a byte array using Java?

The bit representation of FF with Android is 00000000 11111111 whereas in iOS is 11111111 . The leading zeros is the reason because the SHA256 hashing is different.

Just change the Hex to byte converter using one method of the linked post to get the same byte array (without zeros). For example

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

void hashBigInteger(String s){
    try{
        MessageDigest sha = MessageDigest.getInstance("SHA-256");
        byte b[] = hexStringToByteArray(s);
        sha.update(b,0,b.length);
        byte digest[] = sha.digest();
        BigInteger d = new BigInteger(1,digest);

        System.out.println("H "+d.toString(16));
    }catch (NoSuchAlgorithmException e){
        throw new UnsupportedOperationException(e);
    }
}

To proper HEX printing, change also BigInteger d = new BigInteger(digest); with

BigInteger d = new BigInteger(1,digest); 

一种方法是将你的大数字转换为字符串,并得到它们的散列。

链接地址: http://www.djcxy.com/p/35736.html

上一篇: 在两个循环UIBezierPath之间进行动画时出现奇怪的行为

下一篇: 对于大数字,SHA256散列结果在Android和iOS上会有所不同