2016-08-18 19 views
7

BigInt/BigNum 해시를 시도하고 Android/iOS에서 다른 결과가 표시됩니다. 둘 다 앱이 SRP 프로토콜에 따라 작동하도록 동일한 해시 결과를 얻어야합니다. 정밀 검사에서 양수는 제대로 작동하지만 음수는 작동하지 않습니다 (첫 번째 니블이 7보다 큰 경우). 어떤 것이 맞는지, 어느 것이 다른 것과 조화를 이루도록 조정되어야하는지 확실하지 않습니다.SHA256 큰 번호의 경우 Android 및 iOS의 결과가 서로 다릅니다.

안드로이드 :

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

아이폰 OS :

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 
+0

으로도 BigInteger d = new BigInteger(digest); 변경합니다. 해시는 스펙에서 말하는 것과 일치해야합니다. 나는 다른 사람의 구현을 사용하고 그들이 얻은 해시를 보는 것이 좋습니다. –

+0

@brianbeuning,이 비트를 제외한 모든 프로토콜을 구현했습니다. 이제는 0 번 문제에 대한 JAVA 코드를 수정 했으므로 이제는 훌륭한 크로스 플랫폼을 사용하고 있습니다. – Harish

+0

예를 들어, OpenSSL은 SRP를 지원합니다. SRP 해시를 계산하는 방식이 OpenSSL이 SRP 해시를 계산하는 방식과 일치하지 않으면 코드가 OpenSSL과 통신 할 수 없습니다. –

답변

3

문제는 자바 코드에 있습니다. new BigInteger(s, 16).toByteArray()은 0으로 시작하는 데 안전하지 않습니다. 아이폰 OS에 11111111 반면 안드로이드와 FF의 비트 표현이 0000000011111111입니다 Convert a string representation of a hex dump to a byte array using Java?

에서 참조 포스터 코멘트. SHA256 해싱이 다르기 때문에 앞에 오는 0이 이유입니다.

링크 된 게시물의 한 가지 방법을 사용하여 16 진수를 바이트 변환기로 변경하면 동일한 바이트 배열을 얻을 수 있습니다 (0 제외). 당신이 SRP를 구현하려면 적절한 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); 
    } 
} 

를 들어, 안드로이드 및 iOS 사이의 해시 경기를하는 것만으로는 충분하지 않습니다,

BigInteger d = new BigInteger(1,digest); 
+2

다른 말로하면, 이것은 2의 보수에 대한 귀하의 질문에서했던 것과는 반대입니다. BigInteger를 byte 배열로 변환 해 선두의 제로 byte를 삭제 해, 수정 한 배열로 새로운 BigInteger를 작성합니다. 자바는 이것을 -1로 해석 할 것이지만 그것을 시도해보십시오. –

0

한 가지 방법은 문자열에 큰 숫자를 변환하고 그 해시를 얻을 수 있습니다.

+0

BigInteger/BigNum은 문자열에서만 생성되므로 다시 문자열로 변환하면 차이가 발생합니까? 또한 iOS에서 Hash는 낮은 수준의 C API 인 OpenSSL 라이브러리를 사용합니다. Hash API에 String을 사용하는 방법을 모릅니다. – Harish

+1

BigInteger와 BigNum의 구현이 다른 경우가 있기 (위해) 때문에, 바이트 배열에의 변환이 다른 결과를 생성하는 일이 있습니다. –

+0

그러나 SRP 프로토콜 (https://en.wikipedia.org/wiki/Secure_Remote_Password_protocol) 계산에는 BigInteger/BigNum이 필요하므로 동일한 해시 결과를 얻고 싶습니다. + ve 숫자에 대한 작업은 하나의 플랫폼이 -ve 숫자를 부호로 처리하고 다른 하나가 + ve로 취급하는지 알고 싶어합니다. – Harish