Load ASN.1/DER encoded RSA keypair in C#

2019-01-28 23:12发布

问题:

I have DER encoded RSA keypair created in Crypto++, as well as cipher. They are Base64Encoded string. I first decode the data from Base64 to byte array, but I am not sure how to load them into RSACryptoServiceProvider.

static void Main()
{
    string pbkeystr = "mypublickey";
    string pvkeystr = "myprivatekey";
    string cipherstr = "mycipher";

    byte[] pbkey = Convert.FromBase64String(pbkeystr);
    byte[] pvkey = Convert.FromBase64String(pvkeystr);
    byte[] cipher = Convert.FromBase64String(cipherstr);

    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

    //Set keys here..

    //Decrypt the cipher using private key
    rsa.Decrypt(pvkey, false);
}

There are no functions to set keys. The only thing I found was ImportParameters method, which takes RSAParameters class which consists of p, q, n, modulus, exponent etc. I don't have access to these.

Is there any way I can load the keys as string? How can I load the key into RSACryptoServiceProvider?

回答1:

Is there any way I can load the keys as string? How can I load the key into RSACryptoServiceProvider?

From your other Crypto++ question, How to load Base64 RSA keys in Crypto++, it looks like you have only the public and private keys because you used DEREncode and BERDecode. That is, you have the RSA parameters, and not the subject public key info and the private key info. Your keys lack the OID identifiers and version numbers. Things are fine that way.

From Cryptographic Interoperability: Keys on the Code Project, you will need a C# class that parses the ASN.1/DER after you Base64 decode it. The CodeProject article provides a C# class called AsnKeyParser to read the ASN.1/DER and returns a RSAParameters to load into a CSP.

The code for the AsnKeyParser class is about 800 lines, and there are five other supporting files to make it all happen, so its not really appropriate to place it here. You should download it yourself. The file of interest is called CSInteropKeys.zip.

Once you wire-in the AsnKeyParser class, it will be as simple as the following for a RSA Public key. The private key will be similar, and the code is given on the CodeProject site.

// Your ASN.1/DER parser class
AsnKeyParser keyParser = new AsnKeyParser("rsa-public.der");
RSAParameters publicKey = keyParser.ParseRSAPublicKey();

// .Net class
CspParameters csp = new CspParameters;
csp.KeyContainerName = "RSA Test (OK to Delete)";    
csp.ProviderType = PROV_RSA_FULL;    // 1
csp.KeyNumber = AT_KEYEXCHANGE;      // 1

// .Net class
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp);
rsa.PersistKeyInCsp = false;
rsa.ImportParameters(publicKey);

Linking to files on another site is frowned upon, but I don't know how to provide the information otherwise. There's too much source code involved to place in an answer.


For completeness, .Net does not make interop easy. They do not accept ASN.1/DER or PEM. Rather, .Net accepts some XML representation of the keys. I believe you can find it in RFC 3275, XML-Signature Syntax and Processing. Microsoft does not state that for you. I kind of pieced it together when I wrote the Code Project article.

Maybe we should add a class to Crypto++ to regurgitate XML in addition to ASN.1/DER and PEM.