SHA256哈希结果在Android和安卓系统中有所不同。适用于大数字的iOS [英] SHA256 Hash results different across Android & iOS for Big numbers

查看:251
本文介绍了SHA256哈希结果在Android和安卓系统中有所不同。适用于大数字的iOS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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




$ b $ i





  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 fprintf(stderr,%2x,buff [z]);
fprintf(stderr,\\\
);
free(bin);
}

结果:

<$ $ p






b









b







Android Hash = 06eb7d6a69ee19e5fbdf749018d3d2abfa04bcbd1365db312eb86dc7169389b8
iOS Hash = a8100ae6aa1940d0b663bb31cd466142ebbdbd5187131b92d93818987832eb89


解决方案

问题出在JAVA代码中。 新的BigInteger(s,16).toByteArray() 对于前导零不安全。请参阅将十六进制转储的字符串表示形式转换为字节数组使用Java?



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



只需使用链接后的一种方法将Hex转换为字节转换器即可获得相同的字节数组零)。例如

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


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

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






为了正确的十六进制打印,更改 BigInteger d = new BigInteger(digest); with

  BigInteger d = new BigInteger(1 ,消化); 


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

这篇关于SHA256哈希结果在Android和安卓系统中有所不同。适用于大数字的iOS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆