大数字的SHA256散列结果在Android和iOS上不同

我试图哈希一个BigInteger / BigNum,我在Android / iOS获得不同的结果。 我需要获得相同的散列结果,以便两个应用程序按照SRP协议工作。 仔细观察,它对正数工作正常,但对负数不起作用(第一个半字节大于7)。 不知道哪一个是正确的,哪一个是要调整到与另一个匹配的。

安卓:

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); } 

结果:

 Source String = "6F" Android Hash = 65c74c15a686187bb6bbf9958f494fc6b80068034a659a9ad44991b08c58f2d2 iOS Hash = 65c74c15a686187bb6bbf9958f494fc6b80068034a659a9ad44991b08c58f2d2 Source String = "FF" Android Hash = 06eb7d6a69ee19e5fbdf749018d3d2abfa04bcbd1365db312eb86dc7169389b8 iOS Hash = a8100ae6aa1940d0b663bb31cd466142ebbdbd5187131b92d93818987832eb89 

问题出在JAVA代码中。 new BigInteger(s, 16).toByteArray() 对前导零不安全。 使用Java将hex转储的string表示forms转换为字节数组?

Android与FF的位表示是00000000 11111111而在iOS中是11111111 。 前导零是原因,因为SHA256哈希是不同的。

只需更改hex字节转换器使用链接后的一种方法来获得相同的字节数组(无零)。 例如

 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); } } 

为了正确的hex打印,还要改变BigInteger d = new BigInteger(digest);

 BigInteger d = new BigInteger(1,digest); 

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