不能让Openssl签名数据与.net签名数据或BouncyCastle签名数据匹配

本文关键字:数据 BouncyCastle net 不能 Openssl | 更新日期: 2023-09-27 17:55:04

上周五我一直在看这个,到现在我还是很困惑。

当我运行这个命令时:

echo -n "Data To Sign" | openssl pkeyutl -sign -inkey path/to/my.pem | openssl base64

通过openssl我得到输出:

1c284UkFgC6pqyJ+woSU+DiWB4MabWVDVhhUbBrTtF7CkpG8MjY+KkPFsZm9ZNM8vCjZjf...Kw=

我想在c#中复制这个行为。我做的第一次尝试是使用openssl从我的。pem文件创建一个。p12文件。我通过运行以下两个openssl命令来做到这一点:

openssl req -new -key path/to/my.pem -x509 -batch > my.crt
openssl pkcs12 -export -in my.crt -inkey path/to/my.pem -out my.p12

,然后使用X509Certificate2RSACryptoServiceProvider类加载。p12并签名。下列代码:

var dataToSign = "Data To Sign";
var p12 = new X509Certificate2(@"path'to'my.p12","");
var rsa = (RSACryptoServiceProvider)p12.PrivateKey;
var signedBytes = rsa.SignData(Encoding.UTF8.GetBytes(dataToSign), "SHA1");
var result = Convert.ToBase64String(signedBytes);

收益率:

B2qM6MTjoZFSbnckezzpXrKFq67vFgsCPYBmaAbKOFmzVQLIU4a+GC6LWTMdNO4...Q0=

不幸的是,输出不匹配。在与这个问题斗争了一段时间后,我决定走蹦蹦跳跳的城堡路线。下面是我使用这个库编写的代码:

StreamReader sr = new StreamReader(@"path'to'my.pem");
PemReader pr = new PemReader(sr);
var pemKeyParams = (RsaPrivateCrtKeyParameters)pr.ReadObject();
var cypherParams = new RsaKeyParameters(true, pemKeyParams.Modulus, pemKeyParams.Exponent);
ISigner sig = SignerUtilities.GetSigner("SHA1withRSA");
sig.Init(true, cypherParams);
var bytes = Encoding.UTF8.GetBytes("Data To Sign");
sig.BlockUpdate(bytes, 0, bytes.Length);
byte[] signature = sig.GenerateSignature();
var result = Convert.ToBase64String(signature);

也产生:

B2qM6MTjoZFSbnckezzpXrKFq67vFgsCPYBmaAbKOFmzVQLIU4a+GC6LWTMdNO4...Q0=

BouncyCastle输出与使用Security命名空间中的本机库的c#代码给出的输出相匹配,但我想匹配openssl的输出。我做错了什么?

版本——
OpenSSL 1.0.1c
net 4.0
BouncyCastle 1.7.0
Windows 7

我的。pem -

-----BEGIN私钥-----MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOtk3bYdQsjeG1Xy2 kgf8ecwcpudplenv32oibta + h2hXQ853ZRsxusopm7vmqtI2/aVfc2vyw9AGY0UcjqPnyEq7et5oQydo5 + aTEW3PenP9DR3MJ273ipPbrYX + I3XzJ + 16//k6DO/OAIAJLlXc9iT1pblSrHymFNEkIFiUgj3AgMBAAECgYBtP1Lmwo3MS8jECwEieh/a8D9fh4ozbd7dFqnxDicGuW1HM8PyrsljOmqD8hAGjroHpznLzFqhqU4ye9rH8wAWsKUjQst RjyDU3SNscyU/eg + ezuawUXafpPUEUTJ0aofdHn9GIVipiIi/4 uapp/IYtuCU2smep4C2 + geqfTugQJBAP5MTaRQjoYBGKS/Bgd0JB16MHFV6FPDCX3NZ2CLTyZmo8edQZI4SbWoxkJaGqBOqDbz/dSmTLfRNmpAmC + az5sCQQDs + CyDLbs3URvD7ajxJjsJoPbuVmqPBPGmAy/4 qt3qvp9awk + 9 ucku90dymqjp5bdgoeokma65uuecvqbsyzfVAkEA018FIlE7RjNfEoEdN9DXvBC2d14a0JTLLOAwz1S8I4UpGWCjAjD7Q53XvYs7mogG1jaUg87 + 8 cnayzlzbi5xhqjanyqbajqgqb2awj8cum81buvu0k2lhxowi5hoXXprmynfTyL3N2r99gSNswcuqkqRPT9KfBRuMSzhZUi5IZ05tQJBAKdQ3mJZ1 vys2neaxbqd5/ldi1 + VF/0 t4z + JxqFBjqtsAoASBN + kSiPAnRl3r175oZ9m9gkd5 yisn0l + WD5Bf4U =-----结束私钥-----

为了这个问题的目的,我生成了一个新的。pem,上面的密钥不保护任何重要的东西,但是我提供它来复制上面的步骤。

到目前为止我考虑过的事情:
*编码(ASCII vs UTF8)
*端序(-rev to openssl仍然不匹配任何编码结果)
*哈希(我找不到任何地方"SHA1"是正式使用的正确哈希算法,但它似乎是其他人使用的,尝试其他选项没有帮助)
*换行符(我认为echo上的-n需要与库保持一致,但删除它没有帮助)
*询问SO(结果等待:-))

TIA

不能让Openssl签名数据与.net签名数据或BouncyCastle签名数据匹配

我猜openssl pkeyutl命令实际上是直接对数据签名,而不是对数据摘要签名。

关于pkeyutl的openssl文档包含了这个暗示性的注释:

"除非另有说明,否则所有算法都支持摘要:alg选项,该选项指定用于签名、验证和verifyrecover操作。值alg应该表示摘要名称在EVP_get_digestbyname()函数中使用,例如sha1。"

我在命令行中没有看到摘要选项。此外,从相同的文档(在RSA部分):

"在pkcs# 1填充中,如果没有设置消息摘要,则提供直接对数据进行签名或验证,而不是使用DigestInfo结构。如果设置了摘要,则使用a DigestInfo结构它的长度必须对应于摘要类型。"

参见openssl dgst的文档

RSA签名可以使用不同的填充模式(pkcs# 1, PSS等)。对于最后一个,它使用一些随机的盐,所以每次签名都会不同。因此,首先检查openssl是否每次都生成相同的值(我没有发现openssl代码使用的默认填充,您可以使用-rsa_padding_mode参数更改它),并且,实际上,如果两个签名都可以被另一方正确验证。