Reputation: 19953
TL;DR... how can I create a DSA signature using a PEM private key file using .Net Framework 4.5.2
I apologise up front... this is all completely new to me, as I've never had to deal with encryption like this. So please be gentle!
Details...
I'm working with an old ASP.Net project using .Net Framework 4.5.2... yes, I'm very aware it's out of life, but is not something I can do anything about at this time.
I need to send data to an API where part of that data (a "signature" made up of other piece of known data) is encrypted using DSA with a private key provided by the client... and yes, I'm very aware that RSA should now be used, but that is what the client is demanding.
The private key has been provided in a PEM format file (i.e. file starts with -----BEGIN DSA PRIVATE KEY-----
)
I've discovered the AsnKeyParser class from codeproject.com but I have so far failed to work out how to use that class with a PEM format file.
This (purposefully) confusing answer highlights my confusion and lack of understanding.
Can anybody, please, give me a pointer to how I can achieve this, as I've wasted a full day on my investigations without any real success?
Do I need to convert the Base64-decoded certificate (between the headers) from DER to ASN.1 before passing it to the AsnKeyParser
class? If so, how?
(If necessary, I can consider creating an external service using a more recent .Net version, that I can call from the 4.5.2 code... but would prefer it to be wrapped into a single project.)
Edit...
As requested by @Topaco, here is an example key pair supplied by the customer, who tells me (somewhat ambiguously) that 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-----
Upvotes: 2
Views: 840
Reputation: 49111
For DSA, .NET Framework 4.5.2 is very limited concerning key size (max. 1024 bits, see here) and digest (only SHA1, see here).
For this reason, it makes more sense to use a more capable third-party provider such as BouncyCastle from the start. BouncyCastle also provides PemReader
for convenient import of PEM encoded keys.
Import:
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;
Signing:
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
For the posted solution applies:
Regarding signature format and digest, consider the following:
A DSA signature consists of two parts, r and s, see here. There are different formats for DSA signatures. In the above solution, the r and s values of the signature are provided in ASN.1/DER encoded format. Another format is IEEE P.1363, where r and s are concatenated. See here for the relation of both formats and a conversion between them.
Besides SHA256, BouncyCastle supports other digests for DSA, see SignerUtilities.cs for more digests and identifiers.
Both sides must apply the same digest for a successful verification and, to avoid unnecessary conversions, should use the same signature format if possible.
Upvotes: 2