OpenSSL以及大多数其他DSA实现以ASN.1格式输出签名。因此,由于ASN.1结构头,40字节签名(两个20字节整数)变为46字节。 (有关详细信息,请参阅this forum post。)
我的问题是,如何在C#中处理这种格式?(或其他地方,就此而言)
我花了一些时间尝试使用.NET System.Security.Crypto
软件包处理它,但放弃了它(非常令人沮丧,因为它显然有内部代码来解析ASN.1,因为它可以读取DER格式,但没有办法让你使用它 - 但我离题了...... )
然后,我开始使用BouncyCastle C#库。我可以把它变成Asn1Object
,如果我在调试时展开它,我会看到它包含一个带有两个整数的DerSequence
,但是如何将它们拉出来(最好是BigIntegers
所以我可以将它们提供给DSA.VerifySignature
?)
代码示例:
Byte[] msgText = ReadFile("test_msg.txt");
Byte[] msgSigRaw = ReadFile("test_sig_1.bin"); // reads binary ASN.1 sig using FileStream
Asn1Object sigASN = Asn1Object.FromByteArray(msgSigRaw); // parses into Asn1Object
...
X509Certificate implCert = ReadCertificate("pubcert_dsa.cer"); // cert in DER format
DsaSigner DSA = new DsaSigner();
DSA.Init(false, implCert.GetPublicKey());
...
BigInteger sigIntR, sigIntS;
... //TODO: how to get signature from sigASN into sigIntR, sigIntS?
Boolean validSig = DSA.VerifySignature(msgText, sigIntR, sigIntS); // my goal
答案 0 :(得分:4)
请查看此CodeProject文章:http://www.codeproject.com/KB/security/CryptoInteropSign.aspx
它包含将DSA签名转换为C#中预期的P1363格式的代码。
答案 1 :(得分:2)
如何在BouncyCastle C#中验证DSA签名的一些示例代码:
ISigner sig = SignerUtilities.GetSigner("SHA1withDSA");
sig.Init(false, implCert.GetPublicKey());
sig.BlockUpdate(msgText, 0, msgText.Length);
bool valid = sig.VerifySignature(msgSigRaw);
请注意,此签名者将为您处理ASN.1和消息摘要的计算(我假设这里使用了SHA-1)。
如果你真的想知道如何在ASN.1中转换{r,s}值,那么请查看DsaDigestSigner的源代码。在内部,它执行适当的ASN.1编码/解码,然后使用DsaSigner类进行低级sig操作。