Java vs Python HMAC-SHA256 Несоответствие

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

У меня есть 2 отдельных пути кода, один в Java (Android), один и Python, которые выполняют следующие задачи для согласования сопряжения между Android-устройством и Python / Django.

Ява:

  • Создание синхронизирующего ключа
  • Хешируйте конкатенированную строку различных значений, используя presharedKey (включая syncKey)
  • Шифровать syncKey, используя presharedKey
  • Отправьте хэш, зашифрованный syncKey, DeviceId и произвольные переменные на веб-сервер

питон

  • Получить предварительный ключ от устройства.
  • Расшифровать зашифрованный syncKey
  • Хешируйте конкатенированную строку различных значений, используя presharedKey (включая расшифрованный syncKey)
  • Убедитесь, что хеш совпадает, что подтверждает, что syncKey был успешно расшифрован и что deviceId содержит правильный presharedKey.

Теперь этот процесс работает, если я отправляю syncKey незашифрованным. Конечные хэш-совпадения, которые доказывают, что у deviceId есть правильный предварительный ключ, однако, как только я добавляю en / decryption в процесс, хеш больше не совпадает, несмотря на то, что как syncKey, так и конкатенированная строка выглядят идеально Символ для символа из вывода отладки как Java / Python.

Одна из особенностей этого процесса заключается в том, что для алгоритма шифрования AES256 необходим 256-битный ключ, поэтому я сокращаю 512 бит presharedKey пополам. Альтернатива использованию только 256-битного ключа по всей доске требовала, чтобы я передавал ключ через encode('ascii') на стороне python, иначе он выкидывал ошибки во время хэширования с более коротким ключом.

Вот соответствующий код:

Ява:

 String presharedKey = getKey(); // f8250b0d5960444e4de6ecc3a78900bb941246a1dece7848fc72b90092ab3ecd0c1c8e36fddba501ef92e72c95b47e07f98f7fd9cb63da75c008a3201124ea5d String deviceId = getDeviceId(); // 1605788742789230 SyncKey syncKey = generateSyncKey(); // 824C1EE9EF507B52EA28362C71BD4AD512A5F82ACFAE80DEF531F73AC124CA814BA30CE805A157D6ADB9EC04FC99AAE6FDC4238FCD76B87CE22BC2FE33B2E5C9 String concat = syncKey.hexString(); // 824C1EE9EF507B52EA28362C71BD4AD512A5F82ACFAE80DEF531F73AC124CA814BA30CE805A157D6ADB9EC04FC99AAE6FDC4238FCD76B87CE22BC2FE33B2E5C9 String ALGORITHM = "HmacSHA256"; String hash = null; try { SecretKeySpec keySpec = new SecretKeySpec( presharedKey.getBytes(), ALGORITHM); Mac mac = Mac.getInstance(ALGORITHM); mac.init(keySpec); byte[] result = mac.doFinal(concat.getBytes()); hash = Base64.encodeToString(result, Base64.DEFAULT); // FpDE2JLmCBr+/rW+n/jBHH13F8AV80sUM2fQAY2IpRs= } catch (NoSuchAlgorithmException x) { } catch (InvalidKeyException x) { } String encKey = presharedKey.substring(0, presharedKey.length() / 2); // f8250b0d5960444e4de6ecc3a78900bb941246a1dece7848fc72b90092ab3ecd int len = encKey.length(); byte[] encKeyBytes = new byte[len / 2]; for (int i = 0; i < len; i += 2) { encKeyBytes[i / 2] = (byte) ((Character.digit(encKey.charAt(i), 16) << 4) + Character.digit(encKey.charAt(i+1), 16)); } String encryptedSyncKey = null; try { byte[] iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv); SecretKeySpec encKeySpec = new SecretKeySpec(encKeyBytes, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, encKeySpec, ivSpec); byte[] encryptedSyncKeyBytes = cipher.doFinal(syncKey.hexString().getBytes()); encryptedSyncKey = Base64.encodeToString(encryptedSyncKeyBytes, Base64.DEFAULT); /* Yrl0/SuTUUTC6oJ8o4TCOy65EwO0JzoXfEi9kLq0AOlf6rH+nN7+BEc0s5uE7TIo1UlJb/DvR2Ca ACmQVXXhgpZUTB4sQ0eSo+t32lg0EEb9xKI5CZ4l9QO5raw0xBn7r/tfIdVm8AIFkN9QCcthS0DF KH3oWhpwNS+tfEuibLPgGqP/zGTozmido9U9lb4n */ } catch (InvalidAlgorithmParameterException e) { } catch (NoSuchAlgorithmException e) { } catch (NoSuchPaddingException e) { } catch (InvalidKeyException e) { } catch (IllegalBlockSizeException e) { } catch (BadPaddingException e) { } sendStuffToWeb(encryptedSyncKey, deviceId, hash); 

Python:

 hash = getHash(request) # hash from Java: FpDE2JLmCBr+/rW+n/jBHH13F8AV80sUM2fQAY2IpRs= encrypted_sync_key = getEncSyncKey(request) # encryptedSyncKey from Java: # Yrl0/SuTUUTC6oJ8o4TCOy65EwO0JzoXfEi9kLq0AOlf6rH+nN7+BEc0s5uE7TIo1UlJb/DvR2Ca # ACmQVXXhgpZUTB4sQ0eSo+t32lg0EEb9xKI5CZ4l9QO5raw0xBn7r/tfIdVm8AIFkN9QCcthS0DF # KH3oWhpwNS+tfEuibLPgGqP/zGTozmido9U9lb4n device_id = getDeviceId(request) # 1605788742789230 preshared_key = getPresharedKeyFromDevice(deviceId) # f8250b0d5960444e4de6ecc3a78900bb941246a1dece7848fc72b90092ab3ecd0c1c8e36fddba501ef92e72c95b47e07f98f7fd9cb63da75c008a3201124ea5d enc_key = preshared_key[:len(preshared_key)/2] # f8250b0d5960444e4de6ecc3a78900bb941246a1dece7848fc72b90092ab3ecd aes = AES.new(enc_key.decode('hex'), AES.MODE_CBC, IV="\x00"*16) sync_key = aes.decrypt(base64.b64decode(encrypted_sync_key)) # 824C1EE9EF507B52EA28362C71BD4AD512A5F82ACFAE80DEF531F73AC124CA814BA30CE805A157D6ADB9EC04FC99AAE6FDC4238FCD76B87CE22BC2FE33B2E5C9 concat = sync_key # 824C1EE9EF507B52EA28362C71BD4AD512A5F82ACFAE80DEF531F73AC124CA814BA30CE805A157D6ADB9EC04FC99AAE6FDC4238FCD76B87CE22BC2FE33B2E5C9 import hashlib from hmac import new as hmac verify_hash = hmac(preshared_key, concat, hashlib.sha256).digest().encode('base64') # IoSc2w2sQ4/fwhJTdUQHw/Hdyjy+ranzQ1z3J5LfYbA= 

Из вывода отладки ниже вы можете увидеть, что syncKey зашифрован и дешифрован успешно, а concat идентичен. Однако полученный hash заканчивается разным.

Solutions Collecting From Web of "Java vs Python HMAC-SHA256 Несоответствие"

Ваш код Python неверен. Я могу воспроизвести в Python ответ, который вы получили на Java.

Если я использую ваши входы:

 >>> preshared_key_hex b'f8250b0d5960444e4de6ecc3a78900bb941246a1dece7848fc72b90092ab3ecd0c1c8e36fddba501ef92e72c95b47e07f98f7fd9cb63da75c008a3201124ea5d' >>> concat_hex b'824C1EE9EF507B52EA28362C71BD4AD512A5F82ACFAE80DEF531F73AC124CA814BA30CE805A157D6ADB9EC04FC99AAE6FDC4238FCD76B87CE22BC2FE33B2E5C9' 

Я получаю то же значение, что и в Java:

 >>> base64.b64encode(hmac.new(preshared_key_hex, concat_hex, hashlib.sha256).digest()) b'FpDE2JLmCBr+/rW+n/jBHH13F8AV80sUM2fQAY2IpRs=' 

Однако это значение, вероятно, также неверно. Вы почти наверняка должны быть шестнадцатеричным декодированием входных значений.

Я не могу воспроизвести то, что вы получили на Python; Одно из значений, которые вы передаете hmac.new – это не то, что вы думаете. print их непосредственно перед вызовом hmac.new и вы увидите, что не соответствует.