2016-08-18 8 views
7

Я пытаюсь взломать BigInteger/BigNum, и у меня разные результаты в Android/iOS. Мне нужно получить тот же результат Hash, чтобы оба приложения работали в соответствии с протоколом SRP. При ближайшем рассмотрении он отлично работает для положительных чисел, но не работает для отрицательных чисел (первый полубайт больше 7). Не знаете, какой из них правильный, и какой из них нужно скорректировать, чтобы соответствовать другому.SHA256 Хэш-результаты разные в Android и iOS для больших номеров

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

Результаты:

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

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

Если вы хотите реализовать SRP, это не достаточно, чтобы иметь хэш-матч между Android и IOS. Хэш должен соответствовать тому, что говорит спекуляция. Я предлагаю использовать чужую реализацию и видеть, какие хэши они получают. –

+0

@brianbeuning, мы внедрили весь протокол, кроме этого бита. Как только я исправил код JAVA для проблемы с ведущими 0s, теперь он работает над кросс-платформой. – Harish

+0

Например, OpenSSL поддерживает SRP. Если способ вычисления SRS-хэшей не совпадает с тем, как OpenSSL вычисляет хеширование SRP, ваш код не сможет разговаривать с OpenSSL. –

ответ

3

Проблема в коде JAVA. new BigInteger(s, 16).toByteArray()небезопасен для ведущих нулей. См плакат комментария на Convert a string representation of a hex dump to a byte array using Java?

битого представление FF с Android является 0000000011111111, тогда как в прошивке является 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); 
+2

Другими словами, это противоположность тому, что я сделал в вашем вопросе о дополнении двух. Преобразуйте BigInteger в массив байтов и * удалите * начальный нулевой байт и создайте новый BigInteger с модифицированным массивом. Java будет интерпретировать это как -1, но попробуйте. –

0

Одним из способов является конвертировать большие числа в строки и получить хэш из них.

+0

BigInteger/BigNum созданы только из строк, так что будет ли это иметь значение, если мы преобразуем их обратно в строки? Также в iOS Hash использует библиотеки OpenSSL, которые являются низкоуровневыми API-интерфейсами C, но не уверены, как мы можем использовать String для Hash API. – Harish

+1

BigInteger и BigNum могут иметь разные реализации, поэтому их преобразования в байтовые массивы могут давать разные результаты. –

+0

Но для протокола SRP (https://en.wikipedia.org/wiki/Secure_Remote_Password_protocol) нужны BigInteger/BigNum, и поэтому я хочу получить те же результаты Hash. Он работает для + ve чисел, поэтому хочу знать, обрабатывает ли одна платформа -ve номера как подписанные, а другие обрабатывает как + ve – Harish