c#中的数字签名,不使用BouncyCastle

时间:2018-02-21 12:02:32

标签: c# rsa signature sha256 digital

如果不使用第三方BouncyCastle库,有没有办法读取自定义私钥并签名邮件? (sha256 hash +使用私钥加密)

2 个答案:

答案 0 :(得分:3)

技术上,是的。根据你所拥有的密钥类型,答案会变得更加棘手。

PKCS#8 PrivateKeyInfo(PEM" BEGIN PRIVATE KEY")

如果您有这种类型的文件,并且您使用的是.NET 4.6或更高版本,那么是。您需要使用DER编码(vs PEM编码)数据blob(如果它是PEM,请参见下文)。

using (CngKey key = CngKey.Import(blob, CngKeyBlobFormat.Pkcs8PrivateBlob))
using (RSA rsa = new RSACng(key))
{
    return rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
RSA需要4.6,ECDSA需要4.6.1,DSA需要4.6.2。

PKCS#8 EncryptedPrivateKeyInfo(PEM" BEGIN ENCRYPTED PRIVATE KEY")

恭喜,您的私钥传输非常强大。遗憾的是,如果您想要实际处理它,则需要写入最大量的代码。你不想处理它。你真的,真的,想要

  • 为密钥创建证书
  • 将证书和密钥放入PFX文件
  • 将PFX加载到X509Certificate2
  • 使用cert.GetRSAPrivateKey(),cert.GetDSAPrivateKey()或cert.GetECDsaPrivateKey()(视情况而定)

请参阅How is a private key encrypted in a pem certificate?,然后继续阅读下一节中的入门知识。不过,你有更多的工作要做。您需要读取文件,了解加密方案和参数,解密blob,然后使用CNG读取PKCS#8,或者只是继续潜入兔子洞并享受文件解析器。

PKCS#1 RSAPrivateKey(PEM" BEGIN RSA PRIVATE KEY")

你处于“#34;相对简单"”的不幸融合之中。并且"比较辛苦"数学专业所知道的是#34;练习留给读者#34;

强烈考虑从EncryptedPrivateKeyInfo执行PFX方法。或者,您可以在自定义代码中执行此操作。自定义代码?好的,让我们这样做。此时您需要的参考文本是

  1. ITU.T-REC X.680-201508
    • 这定义了ASN.1语言,它告诉您如何阅读RSAPrivateKey(等)对象结构定义。
    • 对于RSAPrivateKey,这几乎是可选的,因为它使用的SEQUENCE没有很多细微差别,而且INTEGER非常简单。
  2. ITU.T-REC X.690-201508
    • 本文档描述了ASN.1的BER(和CER)和DER编码规则。
    • 这些关键文件位于DER中。 (除非他们在PEM中,但我们很快会解决这个问题)
  3. 适合您的对象类型的RFC。
  4. 好的,让我们继续。

    1. 如果文件是PEM编码的(" -----开始RSA私钥-----"或者" -----开始私钥----- "等)你需要" un-PEM"它。
      • PEM格式是
        • (换行或文件开头)
        • 5个连字符,BEGIN,空格,类型标识符,5个连字符,换行符
        • base64编码的有效负载(每72个文本字符后有换行符)
        • 换行符(除非您以换行结束,因为您是72个文本字符的倍数)
        • 5个连字符,END,与之前相同的类型标识符,5个连字符
      • 我们想要的部分是有效载荷。通过Convert.FromBase64String运行它,现在我们为关键对象提供了DER编码的byte[]
    2. 使用类型定义和ITU文档,为您的密钥文件格式编写解析器。
    3. 解析密钥。
    4. 将解析后的密钥转换为RSAParameters对象(或DSAParameters,或ECParameters,视情况而定)
    5. 致电RSA.Create()(等)
    6. 通过ImportParameters方法加载密钥。
    7. 很高兴。
    8. 对于第4步,有一些事情需要注意。具体来说,ASN.1 / DER INTEGER组件有两个RSAParameters不喜欢的规则。

      • 删除所有前导0x00值。
      • 如果前导字节的高位设置(> = 0x80)但数字应为正数,则插入0x00。

      .NET希望将值作为big-endian字节数组(与DER编码的字节顺序相同),具有以下关系:

      • 指数尽可能大,只要它不以0x00开头。
      • 模数尽可能大,只要它不以0x00开头。
      • D必须与模数相同(必要时插入0x00)
      • P必须是"半圆形"模数的大小((Modulus.Length + 1)/ 2),必要时插入0x00。
      • Q,DP,DQ和InverseQ必须与P具有相同的长度(根据需要插入0x00)。

      其他一些格式

      确定哪些RFC为您的密钥格式定义了ASN.1结构,然后记住这一点并评估RSAPrivateKey部分。

      DSAParameters和ECParameters都有自己的空间期望。

      进一步阅读

      其中一些包括不总是优雅但经常运作的代码:

答案 1 :(得分:0)

Microsoft提供了一个SignedXML类来签名文件。要了解详情,请结帐https://msdn.microsoft.com/en-us/library/system.security.cryptography.xml.signedxml(v=vs.110).aspx