TL;DR...如何使用.Net Framework 4.5.2使用PEM私钥文件创建DSA签名

我很抱歉...这对我来说是全新的,因为我从来没有像这样处理过加密.所以请温柔一点!

Details...

我正在使用一个旧的ASP.NET项目,该项目使用.Net Framework4.5.2...yes, I'm very aware it's out of life, but is not something I can do anything about at this time.

我需要将数据发送到API,其中部分数据(由其他已知数据组成的"签名")使用DSA和客户端提供的私钥进行加密……and yes, I'm very aware that RSA should now be used, but that is what the client is demanding.

私钥已在PEM格式文件中提供(即文件以-----BEGIN DSA PRIVATE KEY-----开头)

我已经发现了AsnKeyParser class from codeproject.com,但到目前为止,我还没有弄清楚如何将这个类与PEM格式的文件一起使用.

This (purposefully) confusing answer分突出了我的困惑和缺乏理解.

我在调查上浪费了一整天的时间,但没有任何真正的成功,有人能给我一个指点,告诉我如何才能做到这一点吗?

在将Base64解码的证书(在标头之间)传递到AsnKeyParser类之前,是否需要将其从DER转换为ASN.1?如果是这样的话,是如何做到的呢?

(如果需要,我可以考虑使用更新的.Net版本创建一个外部服务,我可以从4.5.2代码中调用该服务...但更愿意把它包装成一个单一的项目.)


Edit...

应@Topaco的要求,以下是客户提供的一个示例密钥对,该客户告诉我(有点含糊地)according to Google: DSA Key Size: 2048 bits...

-----BEGIN DSA PRIVATE KEY-----
MIIBugIBAAKBgQDzGuacD99b5uI/yv8k9B0ayApGge79XN18K3NDals1M/ae31Aa
REiT3pM2Vy+rwZqMXkAjdvBRbAAIWULCPmwlJ25IHBg9zZmK0NymS3qaKd5g3LFC
QXRmOLEVhv0TkZAFmi3u71nvDY35hD5S1OlxXp317MIz8U6/usJhtHjQywIVAKAF
qSaXNbaXLei/kNvHeEMxJvPzAoGAcq8gQ4T1o+xkj7ilhEv1XxiAjKJAZao15JOc
G6D9itSkDTZk/4WftDdIwWV8cYCG6PHmbvGi4i/2Z/LIixnuqWJTUG/EpiXf2RAV
47wgUjGmKtIbpUURSGE+XFfYf5R63hmLp2Jn40NqU9OlAScCDEAqN62YB6+Kua71
/ngDzNACgYBUgc3Gw85Amc2BpFruGsUkB4spnonmueq5HV3bcYIxvrO03UTQovTi
8yvQRUPYSIfCzgS2800ntwizZ6NCwUj6lda6YVBZWw8rg7D9HYoD9aOz4GtN57Da
qml0C3Tqh/1wZI5K+lmyDJfex/nQ4iGQoCmzKftWf13x1iCKM08ULwIUZ8Ig9WT9
Q3BcHfdOKLqa3nbYXCw=
-----END DSA PRIVATE KEY-----

-----BEGIN PUBLIC KEY-----
MIIBtjCCASsGByqGSM44BAEwggEeAoGBAPMa5pwP31vm4j/K/yT0HRrICkaB7v1c
3Xwrc0NqWzUz9p7fUBpESJPekzZXL6vBmoxeQCN28FFsAAhZQsI+bCUnbkgcGD3N
mYrQ3KZLepop3mDcsUJBdGY4sRWG/RORkAWaLe7vWe8NjfmEPlLU6XFenfXswjPx
Tr+6wmG0eNDLAhUAoAWpJpc1tpct6L+Q28d4QzEm8/MCgYByryBDhPWj7GSPuKWE
S/VfGICMokBlqjXkk5wboP2K1KQNNmT/hZ+0N0jBZXxxgIbo8eZu8aLiL/Zn8siL
Ge6pYlNQb8SmJd/ZEBXjvCBSMaYq0hulRRFIYT5cV9h/lHreGYunYmfjQ2pT06UB
JwIMQCo3rZgHr4q5rvX+eAPM0AOBhAACgYBUgc3Gw85Amc2BpFruGsUkB4spnonm
ueq5HV3bcYIxvrO03UTQovTi8yvQRUPYSIfCzgS2800ntwizZ6NCwUj6lda6YVBZ
Ww8rg7D9HYoD9aOz4GtN57Daqml0C3Tqh/1wZI5K+lmyDJfex/nQ4iGQoCmzKftW
f13x1iCKM08ULw==
-----END PUBLIC KEY-----

推荐答案

对于DSA,.NET框架4.5.2在密钥大小(最大1024位,见here)和摘要(仅限SHA1,见here).

因此,从一开始就使用功能更强大的第三方Provider (如BouncyCastle)会更有意义.BouncyCastle还提供了PemReader以方便地导入PEM编码的密钥.

导入:

using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Crypto;
...
string privDsaPem = @"-----BEGIN DSA PRIVATE KEY-----
                    MII...
                    -----END DSA PRIVATE KEY-----";
PemReader pemReader = new PemReader(new StringReader(privDsaPem));
AsymmetricCipherKeyPair dsaKeyPair = (AsymmetricCipherKeyPair)pemReader.ReadObject();
AsymmetricKeyParameter dsaPrivParams = dsaKeyPair.Private;

签名:

using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto;
using System;
...
ISigner sig = SignerUtilities.GetSigner("SHA256withDSA");
sig.Init(true, dsaPrivParams);
sig.BlockUpdate(message, 0, message.Length);
byte[] signatureBC = sig.GenerateSignature();           // ASN.1/DER format
Console.WriteLine(Convert.ToBase64String(signatureBC)); // e.g. MEYCIQDDznPDx5YjsszeOvNbvX2pgTDP4qtkOXMlNo+9B9+xsAIhAKOf8G16Z7uFLlevnC1DzUE+Op5XmwoxbK6my/RjEIRG

适用于发布的解决方案:

  • DSA签名以ASN.1/DER编码格式返回(因此可以加载到ASN.1解析器中,例如https://lapo.it/asn1js/).
  • 应用AS摘要SHA256.

关于签名格式和摘要,请考虑以下内容:

DSA签名由rs两部分组成,请参见here.DSA签名有不同的格式.在上述解决方案中,签名的rs值以ASN.1/DER编码格式提供.另一种格式是IEEE P.1363,其中rs连接在一起.关于这两种格式的关系和它们之间的转换,请参见here.

除了SHA256之外,BouncyCastle还支持其他DSA摘要,有关更多摘要和标识符,请参见SignerUtilities.cs.

双方必须应用相同的摘要才能成功验证,并应尽可能使用相同的签名格式,以避免不必要的转换.

.net相关问答推荐

NET 6:控制器方法不可访问

在 Rx 中,处理线程安全是否是消费者(IObserver)的责任?

如何计算给定2个字符串的距离相似性度量?

StreamWriter.Flush() 和 StreamWriter.Close() 有什么区别?

标签从右向左增长

.NET 中是否有一种简单的方法来获得数字的st、nd、rd和th结尾?

为什么循环引用被认为是有害的?

哪个单元测试框架?

处理序列没有元素异常

如何在 WPF 中创建/制作圆角按钮?

使用只读属性或方法?

C# 的 Actors 有什么好的实现吗?

如何根据默认样式创建样式?

当我们按下 Enter 键时启动的 WPF 文本框命令

有没有像样的 C# 分析器?

Linq to SQL - 返回前 n 行

ReaderWriterLockSlim 什么时候比简单的锁更好?

判断 .NET 中的目录和文件写入权限

如何在 C# 中处理 XML

如何重新启动 WPF 应用程序?