Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to import DSA signature in ASN.1 format using BouncyCastle (C#)

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
like image 705
andersop Avatar asked Oct 23 '09 17:10

andersop


2 Answers

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#.

like image 111
Laurent Etiemble Avatar answered Sep 22 '22 11:09

Laurent Etiemble


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.

like image 39
Peter Dettman Avatar answered Sep 21 '22 11:09

Peter Dettman