OpenSSL, as well as most other DSA implementations, outputs signatures in ASN.1 format. Thus, the 40-byte signature (two 20-byte integers) becomes 46 bytes due to the ASN.1 structure headers. (See this forum post for details.)
My question is, how does one handle this format in C#? (or elsewhere, for that matter)
I spent a while trying to deal with it using the .NET System.Security.Crypto
packages, but gave up on that (really frustrating, because it clearly has internal code to parse ASN.1 since it can read DER format, but there's no way for you to use it -- but I digress...)
Then, I started working with the BouncyCastle C# library. I can get it into an Asn1Object
, and if I expand it while debugging I see that it contains a DerSequence
with the two integers, but how do I pull them out (preferably into BigIntegers
so I can feed them to DSA.VerifySignature
?)
Code sample:
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
Take a look at this CodeProject article: http://www.codeproject.com/KB/security/CryptoInteropSign.aspx
It contains code to convert the DSA signature into the P1363 format expected in C#.
Some example code of how to verify a DSA signature in BouncyCastle C#:
ISigner sig = SignerUtilities.GetSigner("SHA1withDSA");
sig.Init(false, implCert.GetPublicKey());
sig.BlockUpdate(msgText, 0, msgText.Length);
bool valid = sig.VerifySignature(msgSigRaw);
Note that this signer will deal with the ASN.1 and the calculation of the message digest (I've assumed SHA-1 was used here) for you.
If you still really want to know how the conversions of the {r,s} values to/from ASN.1 happen, then have a look in the source for DsaDigestSigner. Internally it does the appropriate ASN.1 encoding/decoding and then uses DsaSigner class for the low-level sig operation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With