RSA-SHA1 签名在 JavaScript 和 PHP 中不同
RSA-SHA1 signature differs in JavaScript and PHP
我需要在 nodeJS 中创建一个 RSA-SHA1
签名,我正在使用以下代码
const crypto = require("crypto");
const sign = crypto.createSign('RSA-SHA1');
sign.update(data);
const result = sign.sign(privateKey, 'base64')
console.log(result);
我仔细检查了我的代码结果是否正确,如果我使用 select sha1WithRSA
算法,我与在线工具的结果相同,我在 PHP 中也得到相同的结果我使用 openssl_sign
函数
我需要为一家银行签署数据API,很遗憾他们不接受我的签名并且他们没有 NodeJS 实现
他们的文档也一团糟,这是C#
他们文档
的实现
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(“<RSAKeyValue><Modulus>oQRshGhLf2Fh...”);
string data = "DATA";
byte[] signMain = rsa.SignData(Encoding.UTF8.GetBytes(data), new
SHA1CryptoServiceProvider());
sign = Convert.ToBase64String(signMain);
谁能帮我理解为什么我的签名不等于 C#
实现(我不检查 C# 的结果,但他们的服务器是用 C# 编写的,他们不验证我的签名)
PHP 中其他官方代码片段的以下链接与他们的服务器一起工作,但结果不同于 PHP 中的标准 openssl_sign
函数:index L211-L216, RSAProcessor L45, rsa.class L17-L22, rsa.class L63-L82 .
- 他们的实现是非标准的 RSA-SHA1 吗?
- 他们不接受我的 NodeJS 代码有什么问题?
NodeJS代码和发布的C#代码为相同的待签名数据和相同的私钥提供相同的签名。
来自已发布的 link it can be seen that the SHA1 hashed data is passed to RSA::rsa_sign
,但 SHA1 摘要 ID 无处可寻。与此一致的是,函数参数中也没有指定摘要。
填充本身发生在 RSA::add_PKCS1_padding
中。这里,为了签名,应用 RSASSA-PKCS1-v1_5。如前所述,在不考虑摘要 ID 的情况下处理传递的(已经散列的)数据。
因此,PHP代码创建的签名不符合RSASSA-PKCS1-v1_5,而NodeJS代码和C#代码都符合标准。
据我所知,当使用 NodeJS 的 crypto 模块的 sign
方法签名时,摘要必须始终指定并且摘要 ID 始终设置为 隐式 ,因此 PHP 代码的签名无法用此复制。
如果使用相同的数据和私钥,允许不设置摘要ID的替代方法是crypto.privateEncrypt
. The following code generates the signature of the PHP code or the signing process described in the posted link:
var crypto = require('crypto')
var sha1 = crypto.createHash('sha1')
sha1.update(data)
var hash = sha1.digest()
var signature = crypto.privateEncrypt({key: privateKey, padding: crypto.constants.RSA_PKCS1_PADDING}, hash)
console.log(signature.toString('base64'))
另一个问题是这个签名是否可以被银行验证API。毕竟API的文档显然包含了两个不一致的实现,所以文档看起来不是很可靠。此外,其他缺陷当然是可能的,请参阅 fgrieu 的评论。
我需要在 nodeJS 中创建一个 RSA-SHA1
签名,我正在使用以下代码
const crypto = require("crypto");
const sign = crypto.createSign('RSA-SHA1');
sign.update(data);
const result = sign.sign(privateKey, 'base64')
console.log(result);
我仔细检查了我的代码结果是否正确,如果我使用 select sha1WithRSA
算法,我与在线工具的结果相同,我在 PHP 中也得到相同的结果我使用 openssl_sign
函数
我需要为一家银行签署数据API,很遗憾他们不接受我的签名并且他们没有 NodeJS 实现
他们的文档也一团糟,这是C#
他们文档
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(“<RSAKeyValue><Modulus>oQRshGhLf2Fh...”);
string data = "DATA";
byte[] signMain = rsa.SignData(Encoding.UTF8.GetBytes(data), new
SHA1CryptoServiceProvider());
sign = Convert.ToBase64String(signMain);
谁能帮我理解为什么我的签名不等于 C#
实现(我不检查 C# 的结果,但他们的服务器是用 C# 编写的,他们不验证我的签名)
PHP 中其他官方代码片段的以下链接与他们的服务器一起工作,但结果不同于 PHP 中的标准 openssl_sign
函数:index L211-L216, RSAProcessor L45, rsa.class L17-L22, rsa.class L63-L82 .
- 他们的实现是非标准的 RSA-SHA1 吗?
- 他们不接受我的 NodeJS 代码有什么问题?
NodeJS代码和发布的C#代码为相同的待签名数据和相同的私钥提供相同的签名。
来自已发布的 link it can be seen that the SHA1 hashed data is passed to RSA::rsa_sign
,但 SHA1 摘要 ID 无处可寻。与此一致的是,函数参数中也没有指定摘要。
填充本身发生在 RSA::add_PKCS1_padding
中。这里,为了签名,应用 RSASSA-PKCS1-v1_5。如前所述,在不考虑摘要 ID 的情况下处理传递的(已经散列的)数据。
因此,PHP代码创建的签名不符合RSASSA-PKCS1-v1_5,而NodeJS代码和C#代码都符合标准。
据我所知,当使用 NodeJS 的 crypto 模块的 sign
方法签名时,摘要必须始终指定并且摘要 ID 始终设置为 隐式 ,因此 PHP 代码的签名无法用此复制。
如果使用相同的数据和私钥,允许不设置摘要ID的替代方法是crypto.privateEncrypt
. The following code generates the signature of the PHP code or the signing process described in the posted link:
var crypto = require('crypto')
var sha1 = crypto.createHash('sha1')
sha1.update(data)
var hash = sha1.digest()
var signature = crypto.privateEncrypt({key: privateKey, padding: crypto.constants.RSA_PKCS1_PADDING}, hash)
console.log(signature.toString('base64'))
另一个问题是这个签名是否可以被银行验证API。毕竟API的文档显然包含了两个不一致的实现,所以文档看起来不是很可靠。此外,其他缺陷当然是可能的,请参阅 fgrieu 的评论。