【问题标题】:Comparison Between one way sha256 hash in Node js vs PythonNode js与Python中一种方式sha256哈希的比较
【发布时间】:2014-11-18 05:27:08
【问题描述】:

我有以下版本的 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��

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

【问题讨论】:

  • 您使用的是什么版本的 Node?我很困惑,因为至少对我来说,hashDigestBuffer,所以你的示例输出不可能是正确的。对于 python,如果你真的打印出 hash_digest 的字节,你会得到什么?在我的测试中,我在运行这段代码时得到了相同的二进制内容。
  • 节点版本 0.10.25。对于节点,只需执行 console.log('OP:'+hashDigest)。我仍然无法确定我做错了什么。你能粘贴你的输出吗?
  • 我也在Node 0.10.32上试过了,输出和上面一样。
  • 您究竟为什么要比较字符串值而不是十六进制值?

标签: python node.js cryptography cryptojs hashlib


【解决方案1】:

它适合我。

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'

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

【讨论】:

  • 是的,就像我提到的那样,十六进制代码可以,但二进制代码不同,这没有任何意义(因此问题),我认为我在做一些愚蠢的事情,一直超过一天了。
【解决方案2】:

TL;DR

您的节点代码正在尝试将哈希结果解析为 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'' 指定的单独字符串类支持 Unicode。

然后比较你打印输出的例子,为了可读性而缩短

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 字符更容易阅读。

【讨论】:

  • 感谢您的澄清和帮助理解这一点。问题是,我使用它来验证请求,而开发我正在使用的平台的开发人员创建了 hmacs 签名减去十六进制转换。
  • 明白了。我会专注于将它作为单字节字符串(Python)和缓冲区(节点)使用,但是如果你将它打印出来,你可以随时将它转换为十六进制,所以你不必转储它直接到控制台。
【解决方案3】:

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

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

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

上面 sn-p 的示例输出。

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

这是散列后得到的字节的字符串表示形式 它的 Nodejs Equivalent 就像

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

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

上面nodejs sn-p的示例输出

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

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

【讨论】:

    猜你喜欢
    • 2013-10-21
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 2018-02-11
    • 2018-01-18
    • 1970-01-01
    • 1970-01-01
    • 2011-03-27
    相关资源
    最近更新 更多