【问题标题】:node.js crypto signature and openssl signature does not matchnode.js 加密签名和 openssl 签名不匹配
【发布时间】:2015-05-15 18:11:55
【问题描述】:

我想对 node.js 中的文件执行 RSA-SHA512。我可以计算给定数据文件的 sha512 哈希值,它与 openssl 的哈希值相匹配。 但是,当尝试在同一个哈希上获取数字签名时,node.js 签名与 openssl 签名不同。 下面是一个示例代码sn-p:

var data = new Buffer(512);
data = fs.readFileSync('/tmp/data');
var pem = fs.readFileSync('/tmp/boot2-prvKey.pem');
var privateKey = pem.toString('ascii');

var signer = crypto.createSign("RSA-SHA256");
signer.update(data);
var sign = signer.sign(privateKey, 'hex');
console.log("SIGN " + sign + '\n');

Openssl 命令对数据进行签名:

openssl rsautl -sign -in /tmp/data -inkey /tmp/boot2-prvKey.pem -out sig

以上两种都生成不同的签名。

我有几个问题 1)我想计算一个文件的 RSA-SHA256,所以我首先计算整个文件的 sha256 哈希,并将这个哈希作为输入传递给签名函数。 这是一个正确的方法吗? 2)如果是,上面的代码可能出了什么问题?如果不是,正确的做法是什么?

我使用的node.js版本是0.10.36,openssl版本是1.0,1。

【问题讨论】:

  • "我首先计算整个文件的 sha256 哈希值,并将这个哈希值作为输入传递给签名函数" -- 我没有在你的代码中使用哈希函数'已经提供。这不是你的真实代码,还是我误解了你的描述?
  • 实际上我的数据文件的哈希值存储在 /tmp/data 中,我正在阅读上面的代码进行签名。抱歉文件命名不当。

标签: node.js openssl rsa digital-signature sha256


【解决方案1】:

当您向签名程序提供输入时,它可能会假设输入尚未散列,并会在签名之前对其进行散列。这里的问题是 Node 正在(重新)对输入进行哈希处理,而 rsautl 正在按原样使用输入。 (请注意,即使您在将输入提供给rsautl 之前单独重新散列输入,它仍然不会匹配,因为rsautl 不使用 ASN1 编码;见下文。)

要让 OpenSSL 在生成 RSA 签名之前生成 SHA256 哈希(就像 Node 那样),您需要使用带有 -sha256-sign 参数的 dgst 命令:

openssl dgst -sha256 -sign /tmp/boot2-prvKey.pem -hex < /tmp/data

这将散列 /tmp/data 并使用 RSA 对散列进行签名,这正是 Node 的 RSA-SHA256 签名者所做的。

更多信息请见Difference between openSSL rsautl and dgst

简单的答案是dgst -sign 创建一个散列,ASN1 对其进行编码,然后对 ASN1 编码的散列进行签名,而 rsautl -sign 只是对输入进行签名,而不使用散列或 ASN1 编码。

Node 的sign 方法的行为类似于dgst -sign 而不是rsautl -sign

Node 似乎没有提供内置的 rsautl 类似机制,用于在没有散列和 ASN1 编码的情况下进行签名。出于这个原因,您可能需要直接对文档进行签名,而不是对文档的哈希进行操作。如果你真的因为某种原因不能这样做,你可以下载Node rsautl module from NPM,它为rsautl提供了节点绑定。

【讨论】:

  • 但是从 cmets 看到这个:"...实际上我的数据文件的哈希值存储在 /tmp/data..." 中。所以看起来他已经有了哈希值。我认为他需要将签名函数应用于哈希。或者他需要允许 OpenSSL 命令完成所有操作(如上所示)。如果他正在签名,那么签署 unknown 散列或 unknown 文档可能很危险。我认为这同样适用于验证,但它并不像只签名一个哈希那么糟糕。它应该是对文档的原子操作,而不是对离散部分的离散操作。
【解决方案2】:

问题是您的 Openssl 命令只是在没有散列函数的情况下签署您的数据。 您必须首先使用 openssl 以及与您的 nodejs 代码 (SHA-256) 中相同的函数对您的数据进行哈希处理,然后使用您的命令对哈希进行签名以获得最终签名: openssl rsautl -sign -in /tmp/data -inkey /tmp/boot2-prvKey.pem -out sig

你可以看到在这个命令中你没有指定任何散列函数。

获取签名:data -> SHA-256 = hash -> RSA = signature

我没有足够的时间来测试它并给你正确的代码,我希望它会有所帮助。

【讨论】:

  • 嗨,保罗,感谢您的回复。我确实计算了我的数据文件的哈希值。哈希存储在 /tmp/data 中。使用 openssl 和 node.js 计算的哈希(sha256)完美匹配,因此我跳过了代码中的那部分,而只有给定哈希上的符号不同。因此,我明确显示了这两种情况的签名部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-29
  • 2021-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-02
  • 2013-11-27
相关资源
最近更新 更多