node.js 加密签名和 openssl 签名不匹配
node.js crypto signature and openssl signature does not match
我想对 node.js 中的文件执行 RSA-SHA512。我可以计算与 openssl 匹配的给定数据文件的 sha512 哈希。
但是,当尝试在同一哈希上获取数字签名时,node.js 签名与 openssl 签名不同。
下面是一个示例代码片段:
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.
问题是您的 Openssl 命令只是在没有散列函数的情况下签署您的数据。
您必须首先使用 openssl 散列您的数据,并使用与您的 nodejs 代码 (SHA-256) 中相同的函数,然后使用您的命令对散列进行签名以获得最终签名:
openssl rsautl -sign -in /tmp/data -inkey /tmp/boot2-prvKey.pem -out sig
你可以看到在这个命令中你没有指定任何哈希函数。
获取签名:data -> SHA-256 = hash -> RSA = signature
我没有足够的时间来测试它并给你正确的代码,我希望它会有所帮助。
当您向签名程序提供输入时,它可能会假设输入尚未经过哈希处理,并会在签名前对其进行哈希处理。这里的问题是 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:
The simple answer is that dgst -sign
creates a hash, ASN1 encodes it, and then signs the ASN1 encoded hash, whereas rsautl -sign
just signs the input without hashing or ASN1 encoding.
Node 的 sign
方法的行为类似于 dgst -sign
而不是 rsautl -sign
。
Node 似乎没有提供类似 rsautl
的内置机制来进行无散列和 ASN1 编码的签名。因此,您可能需要直接对文档进行签名,而不是对文档的散列进行操作。如果由于某种原因你真的不能这样做,你可以下载 Node rsautl
module from NPM,它为 rsautl
.
提供节点绑定
我想对 node.js 中的文件执行 RSA-SHA512。我可以计算与 openssl 匹配的给定数据文件的 sha512 哈希。 但是,当尝试在同一哈希上获取数字签名时,node.js 签名与 openssl 签名不同。 下面是一个示例代码片段:
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.
问题是您的 Openssl 命令只是在没有散列函数的情况下签署您的数据。
您必须首先使用 openssl 散列您的数据,并使用与您的 nodejs 代码 (SHA-256) 中相同的函数,然后使用您的命令对散列进行签名以获得最终签名:
openssl rsautl -sign -in /tmp/data -inkey /tmp/boot2-prvKey.pem -out sig
你可以看到在这个命令中你没有指定任何哈希函数。
获取签名:data -> SHA-256 = hash -> RSA = signature
我没有足够的时间来测试它并给你正确的代码,我希望它会有所帮助。
当您向签名程序提供输入时,它可能会假设输入尚未经过哈希处理,并会在签名前对其进行哈希处理。这里的问题是 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:
The simple answer is that
dgst -sign
creates a hash, ASN1 encodes it, and then signs the ASN1 encoded hash, whereasrsautl -sign
just signs the input without hashing or ASN1 encoding.
Node 的 sign
方法的行为类似于 dgst -sign
而不是 rsautl -sign
。
Node 似乎没有提供类似 rsautl
的内置机制来进行无散列和 ASN1 编码的签名。因此,您可能需要直接对文档进行签名,而不是对文档的散列进行操作。如果由于某种原因你真的不能这样做,你可以下载 Node rsautl
module from NPM,它为 rsautl
.