【发布时间】:2021-05-17 10:28:56
【问题描述】:
我正在尝试使用 Express/NodeJS 构建一个 Web 服务,它对一条信息进行签名。用C# 编写的客户端接收并验证签名数据。请原谅我在密码学及其相关技术方面的经验不足。
首先,我为 C# 客户端 生成一个证书,为 NodeJS 应用程序 生成一个私钥使用 OpenSSL;
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365
在NodeJS应用程序中,我有如下代码;
const crypto = require('crypto')
const fs = require('fs')
var pem = fs.readFileSync('./keys/key.pem');
var key = pem.toString('ascii');
var privateKey = crypto.createPrivateKey({
'key': key,
'format': 'pem',
'passphrase': '<PASSPHRASE>',
});
function sign(identifier){
var sign = crypto.createSign('RSA-SHA256');
sign.update(identifier);
var sig = sign.sign(privateKey, 'base64');
return sig;
}
exports.sign = sign;
在这种情况下,参数identifier是要签名的数据。客户端将收到此信息,并生成签名sig。
在 C# 客户端我有以下 sn-p;
X509Certificate2 cert = new X509Certificate2(Convert.FromBase64String(pub));
using (var sha256 = SHA256.Create())
{
using (var rsa = cert.GetRSAPublicKey())
{
bool results = rsa.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
Console.WriteLine(results.ToString());
}
}
pub是Base64中生成的证书,它存储在const string中。 data 包含与 NodeJS 应用程序中的identifier 相同的信息,但它使用Convert.FromBase64String(...) 转换为字节,同样signature 是 NodeJS 应用程序中从sig 返回的数据,仅从 Base64 转换而来字节数据。
插入所有信息后,VerifyData() 返回 false,这让我相信 Web 服务和客户端的加密配置之间存在某种不匹配。
有什么想法吗?
【问题讨论】:
-
通常当 RSA 在 c# 和 JSON 之间传输时出现问题时,它是填充模式。 c# 中的默认填充模式与 JSON 不同。
-
为什么C#代码中的
data是Base64解码的?在 NodeJS 代码中这不会发生,identifier是 UTF8 编码的(默认情况下,因为在update()中没有指定显式编码)。对应的 C# 为Encoding.UTF8.GetBytes()。 -
我认为填充不是问题,因为
sign.sign()默认应用PKCS1 v1.5 填充,C# 代码中也使用了该填充。 -
@Topaco 这就是问题所在,感谢您指出!