1

我有以下版本的 Python 代码:

import hashlib
msg = 'abc'
print msg
sha256_hash = hashlib.sha256()
sha256_hash.update(msg)
hash_digest = sha256_hash.digest()
print hash_digest

以及对应的Node js版本:

var crypto= require('crypto');
var msg = 'abc';
var shasum = crypto.createHash('sha256').update(msg);
var hashDigest = shasum.digest();
console.log(hashDigest);

但是,两者的二进制输出略有不同:

  • 节点:�x����AA@�]�"#�a��z���a��
  • Python:�x����AA@�]�"#�a��z���a��

尽管在两个库之间,十六进制表示是正确的。我在这里做错了吗?

4

3 回答 3

4

它适合我。

Python 2.7.3:

Python 2.7.3(默认,2012 年 4 月 10 日,23:24:47)[MSC v.1500 64 位 (AMD64)] 在 win32 上
输入“帮助”、“版权”、“信用”或“许可”以获取更多信息。
>>> 导入哈希库
>>> 味精 = 'abc'
>>> sha256_hash = hashlib.sha256()
>>> sha256_hash.update(msg)
>>> hash_digest = sha256_hash.hexdigest()
>>> 打印 hash_digest
ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
>>>

节点 v0.10.30:

> crypto.createHash('sha256').update('abc').digest('hex')
'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'

两个十六进制字符串匹配。

于 2014-11-18T06:18:35.817 回答
3

TL;博士

您的节点代码正在尝试将哈希结果解析为 utf8 并失败。


不同之处在于语言如何处理其二进制数据和字符串类型。在考虑最终的二进制输出时,您的示例都输出相同的值。因此,让我们以十六进制格式举例说明您的两个示例的输出:

ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad

在 Python 中:

'\xbax\x16\xbf\x8f\x01\xcf\xeaAA@\xde]\xae"#\xb0\x03a\xa3\x96\x17z\x9c\xb4\x10\xffa\xf2\x00\x15\xad'

在节点中:

<SlowBuffer ba 78 16 bf 8f 01 cf ea 41 41 40 de 5d ae 22 23 b0 03 61 a3 96 17 7a 9c b4 10 ff 61 f2 00 15 ad>

在这种情况下,需要注意的核心是 Python 中的结果以字符串形式返回。在 Python 中,字符串只是字符 (0-255) 值的数组。然而,Node 中的值存储为一个 Buffer,它实际上也表示一个值数组 (0-255)。这是这里不同的关键。Node 不返回字符串,因为 Node 中的字符串不是单字节字符的数组,而是 UTF-16 代码单元的数组。Python 使用由u''.

因此,然后比较您打印输出的示例,缩短了可读性

print '\xbax\x16\xbf\x8f\x01\xcf\xeaAA'

对比

console.log('' + 
    new Buffer([0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41]))

Python 代码说,将这个字节数组写入终端。然而,第二个说的是非常不同的东西,将这个字节数组转换为一个字符串,然后将该字符串写入终端。但是缓冲区是二进制数据,不是 UTF-8 编码的数据,所以它会无法将你的数据解码成字符串,导致结果乱码。如果您希望直接将二进制值与终端中的实际解码值进行比较,则需要提供两种语言的等效指令。

print '\xbax\x16\xbf\x8f\x01\xcf\xeaAA'

对比

process.stdout.write(
    new Buffer([0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41]))

process.stdout.write在这种情况下,这是一种将二进制值写入终端而不是字符串的方法。

但实际上,您应该将哈希值与十六进制进行比较,因为它已经是二进制值的字符串表示形式,并且比解码不正确的 unicode 字符更容易阅读。

于 2014-11-18T08:34:53.323 回答
0

我遇到了类似的情况,将下面的 python hmac256 函数转换为其等效的 Node.js

 def HmacSha256(key, sign):
        return hmac.new(key, sign, hashlib.sha256).digest()

 hash = HmacSha256("\0"*32, rawMsg)
 print hash

上面代码段的示例输出。

python test.py sasa
_��"/���q���h�u$�k�w�)R]n�mf�

这是散列后得到的字节的字符串表示形式 它的 Nodejs 等效项很简单

function HmacSha256(key, sign){
    return crypto
      .createHmac("sha256", key)
      .update(sign)
      .digest()
  }

const hash = HmacSha256("\0".repeat(32), rawMsg).toString()
    console.log(hash)

上面 nodejs 片段的示例输出

node test.js sasa
_��"/���q���h�u$�k�w�)R]n�mf�

请注意输出是相同的。我所要做的就是将返回的 Buffer 数组转换HmacSha256("\0".repeat(32), rawMsg)为字符串。我正在使用Node v8.11.2Python 2.7.15rc1

于 2018-09-18T07:56:42.170 回答