SHA256 Hash results are different for Android and iOS for large numbers

I am trying to Hash BigInteger / BigNum and I have different results in Android / iOS. I need to get the same Hash result so that both applications work in accordance with the SRP protocol. Upon closer inspection, it works fine for positive numbers, but does not work for negative numbers (the first nibble is greater than 7). You do not know which one is correct, and which one needs to be adjusted to fit 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 
+7
android ios biginteger hash bignum
source share
2 answers

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

The FF bit representation with Android is 00000000 11111111 , while in iOS it is 11111111 . Leading zeros are the reason that SHA256 hashing is different.

Just change Hex to a byte converter using the same linked message method to get the same byte array (no 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 print HEX correctly, also change BigInteger d = new BigInteger(digest); on

 BigInteger d = new BigInteger(1,digest); 
+3
source share

One way is to convert your large numbers to strings and get a hash from them.

0
source share

All Articles