【问题标题】:Can't get Openssl signed data to match .NET signed data or BouncyCastle signed Data无法获取 Openssl 签名数据以匹配 .NET 签名数据或 BouncyCastle 签名数据
【发布时间】:2013-01-21 18:12:41
【问题描述】:

上周五我一直在做这件事,但仍然很困惑。

当我运行这个命令时:

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=

很遗憾,输出不匹配。在与这个问题斗争了一段时间之后,我决定走 SO 上的几个答案所建议的 BouncyCastle 路线。这是我使用该库编写的代码:

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
视窗 7

我的.pem -

-----开始私钥----- MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOtk3bYdQsjeG1Xy 2KgF8ecWcPudPLEnV32OIbtA+h2hXQ853ZRsxusopm7vmqtI2/aVfc2vyw9AGY0U cjqPnyEq7et5oQydo5+aTEW3PenP9DR3MJ273ipPbrYX+I3XzJ+I6//k6DO/OAIA JLlXc9iT1pblSrHymFNEkIFiUgj3AgMBAAECgYBtP1Lmwo3MS8jECwEieh/a8D9f h4ozbd7dFqnxDicGuW1HM8PyrsljOmqD8hAGjroHpznLzFqhqU4ye9rH8wAWsKUj Qst/RjyDU3SNscyU/eg+ezuawUXafpPUEUTJ0aofdHn9GIVipiIi/4uaPP/IYtuC U2smep4C2+geqfTugQJBAP5MTaRQjoYBGKS/Bgd0JB16MHFV6FDCX3NZ2CLTyZm o8edQZI4SbWoxkJaGqBOqDbz/dSmTLfRNmpAmC+az5sCQQDs+CyDLbs3URvD7ajx JjsJoPbuVmqPBPGmAy/4Qt3QVp9AWk+9uckU90DYMqJp5bdGoeokmA65uuEcvqbs yzfVAkEA018FILEE7RjNfEoEdN9DXvBC2d14a0JTLLOAwz1S8I4UpGWCjAjD7Q53X vYs7mogG1jaUg87+8cNaYZLzbI5XhQJANyqbajqGQB2Awj8cum81BUvU0K2LhxoW i5hoXXprmynfTyL3N2r99gSNswcuqkqRPT9KfBRuMSzhZUi5IZ05tQJBAKdQ3mJZ 1Vys2nEAXbQD5/ldi1+VF/0t4Z+JxqFBjqtsAoASBN+kSiPAnRl3r175oZ9m9gkd 5YISN0L+WD5Bf4U= -----结束私钥-----

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

到目前为止我考虑过的事情:
* 编码(ASCII 与 UTF8)
* Endianess(openssl 的 -rev 仍然不匹配任一编码结果)
* hashalg(我在任何地方都找不到“SHA1”是正式使用的正确哈希算法,但它似乎是其他人正在使用的并且尝试其他选项没有帮助)
* 换行符(我相信 echo 上的 -n 必须与库相提并论,但删除它并没有帮助)
* 询问 SO(结果待定 :-))

TIA

【问题讨论】:

  • +1,谢谢老兄,帮了我很多

标签: c# openssl bouncycastle


【解决方案1】:

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

pkeyutl 上的 openssl 文档包含以下暗示性评论:

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

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

"在 PKCS#1 填充中,如果未设置消息摘要,则提供 直接对数据进行签名或验证,而不是使用 DigestInfo 结构体。如果设置了摘要,则使用 DigestInfo 结构 并且它的长度必须与摘要类型相对应。”

另请参阅 openssl dgst 的文档。

【讨论】:

  • 叮叮叮。这给了我需要的提示。运行以下命令 echo -n "Data To Sign" | openssl dgst -sha1 -sign my.pem | openssl base64 会给出与我的 C# 代码相同的签名。耶。现在我只需要弄清楚如何告诉 C# 代码在签名之前不要消化消息。
  • 好吧,就 BC 而言,只是切换到 SignerUtilites.GetSigner("RSA") 有效吗?对于 RSACryptoServiceProvider,您可能需要使用 SignHash,尽管该方法似乎要求相关数据实际上是通过某个命名哈希创建的...
  • 是的,GetSigner("RSA") 可以将 openssl 与 BC 匹配。 RSACsp 的 SignHash 出现异常。现在我将只依赖于 BC,稍后再讨论它。感谢大家的帮助!
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-14
    • 1970-01-01
    • 1970-01-01
    • 2014-07-04
    • 1970-01-01
    • 2019-10-17
    相关资源
    最近更新 更多