Java与Python HMAC-SHA256不匹配

Java与Python HMAC-SHA256不匹配,java,android,python,hmac,Java,Android,Python,Hmac,根据最近关于这个问题的反馈和发现,我重写了这个问题以消除噪音 我有两个独立的代码路径,一个是Java(Android),另一个是Python,它们完成了以下任务,以便协商Android设备和Python/Django之间的配对 爪哇: 生成同步密钥 使用presharedKey(包括syncKey)散列各种值的串联字符串 使用预共享密钥加密syncKey 将哈希、加密的syncKey、DeviceId和任意变量发送到web服务器 蟒蛇 从deviceId获取预共享密钥 解密加密的同步密钥

根据最近关于这个问题的反馈和发现,我重写了这个问题以消除噪音

我有两个独立的代码路径,一个是Java(Android),另一个是Python,它们完成了以下任务,以便协商Android设备和Python/Django之间的配对

爪哇:

  • 生成同步密钥
  • 使用presharedKey(包括syncKey)散列各种值的串联字符串
  • 使用预共享密钥加密syncKey
  • 将哈希、加密的syncKey、DeviceId和任意变量发送到web服务器
蟒蛇

  • 从deviceId获取预共享密钥
  • 解密加密的同步密钥
  • 使用预共享密钥(包括解密的syncKey)散列各种值的串联字符串
  • 确保哈希匹配,从而确认syncKey已成功解密,并且deviceId持有正确的预共享密钥
现在,如果我发送未加密的syncKey,这个过程就可以工作了。最后的散列匹配,这证明deviceId具有正确的预共享密钥,但是,只要我将en/解密添加到进程中,散列就不再匹配,尽管syncKey和串联字符串看起来都与Java/Python的调试输出中的字符完全匹配

这个过程的一个怪癖是AES256加密算法需要一个256比特的密钥,所以我将512比特的预共享密钥切成两半。如果只使用256bit键,则需要在python端通过
encode('ascii')
传递该键,否则在使用较短键进行散列时会抛出错误

以下是相关代码:

爪哇:


从下面的调试输出中,您可以看到
syncKey
已成功加密和解密,并且
concat
是相同的。但是,结果的
散列
会有所不同。

您的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的值之一不是您认为的值
在调用
hmac.new
之前立即打印它们,您应该可以看到不匹配的地方。

尝试将
key.getBytes()
更改为
key.getBytes(“US-ASCII”)
;如果这不起作用,请尝试
key.getBytes(“ISO-8859-1”)
谢谢,我按照您的建议尝试了许多不同的密钥编码,但是所有选项似乎都提供相同的哈希字符串。我在python端也尝试了同样的方法,但是这也提供了同样的不匹配哈希。这可能与此无关,但看起来您在Java代码中使用了填充方案,而在python端没有考虑它?PyCrypto本身不处理该填充。此外,如图所示的Python代码无效:params不包含名为“serial_number”的键,而是包含“device_id”。@alcarithame:Thank修复了serial_number ref。我将查看您提到的填充。@DanH Yes;我说这可能不相关,因为它解密正确,但如果以后要在其他数据上使用这种类型的加密(不是块大小的倍数),则需要处理它。我不太懂Java,但是Python方面的一切看起来都很好。很抱歉,我没有看到我在Python中解码的
preshared\u key
concat
?我只是在解密。作为记录,我使用的是Python2.7,我猜您使用的是3+,给出了
b'
符号?那有关系吗?抱歉,如果我是一个noob,我就是看不到:)@DanH我根本无法复制Python中的内容。我刚才提到的那些值应该是十六进制解码的。这里没有任何Python 2/3的区别。不管编码是什么,您在Python的某个地方犯了一个错误。如果在调用
hmac.new
之前打印出这些值,您会发现它们与Java中传递的值不匹配——因为如果像我一样传递这些值,您会得到与Java中相同的答案。所以你眼前的问题是Python。好吧,我再看一看,代码对我来说已经没有意义了!只是像素D:不幸的是还没有,但是我已经被从项目中删除了,令人沮丧,所以我不确定我是否能在赏金落地之前找到解决方案,谢谢你到现在为止的帮助:)
>>> preshared_key_hex
b'f8250b0d5960444e4de6ecc3a78900bb941246a1dece7848fc72b90092ab3ecd0c1c8e36fddba501ef92e72c95b47e07f98f7fd9cb63da75c008a3201124ea5d'
>>> concat_hex
b'824C1EE9EF507B52EA28362C71BD4AD512A5F82ACFAE80DEF531F73AC124CA814BA30CE805A157D6ADB9EC04FC99AAE6FDC4238FCD76B87CE22BC2FE33B2E5C9'
>>> base64.b64encode(hmac.new(preshared_key_hex, concat_hex, hashlib.sha256).digest())
b'FpDE2JLmCBr+/rW+n/jBHH13F8AV80sUM2fQAY2IpRs='