Okay, here’s the second consecutive blog post on serializing/deserializing RSA public/private keys, this time generated by the native RSACryptoServiceProvider available in .Net (the previous post available here related to serializing keys generated by open-source Bounty Castle library).

Serializing .Net’s RSA keys as such is simple using the ToXmlString method available. Here’s the code for generating and serializing the public and private keys to 2 separate strings:

 

CspParameters _cpsParameter;
_cpsParameter = new CspParameters();
_cpsParameter.Flags = CspProviderFlags.UseArchivableKey | CspProviderFlags.UseMachineKeyStore;
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(_cpsParameter);
string serialized=rsa.ToXmlString(true);

XElement element=XElement.Parse(serialized);

string publicKey = "";
publicKey += element.Element("Modulus").ToString();
publicKey += element.Element("Exponent").ToString();

privateKey = "";
privateKey += element.Element("P").ToString();
privateKey += element.Element("Q").ToString();
privateKey += element.Element("DP").ToString();
privateKey += element.Element("DQ").ToString();
privateKey += element.Element("InverseQ").ToString();
privateKey += element.Element("D").ToString();

The publicKey variable contains the Modulus and Exponent of the key pair constituting the public key, while the privateKey variable contains the other parts of the key pair, namely P, Q, DP, DQ, InverseQ and D.

The only interesting line above is passing in Flags to use the MachineKeyStore. If you don’t pass in this flag, you might get a “The System cannot find the file specified” error for the ToXmlString method, especially if the code is running under an ASP.NET application. This is because by default, the ToXmlString tries to use the current user’s key store and that might not exist for the ASP.NET account. This also means that the ASP.NET account should have access to the machine’s key store.

Converting the serialized strings back to an RSA object is also easy with the FromXmlString method available on RSACryptoServiceProvider. Here’s the code for the same:

 

{syntaxhighlighter brush: csharp;fontsize: 100; first-line: 1; }public static RsaKeyPair createFrom (string publicKey)
{
string serialized=”<RSAKeyValue>” + publicKey + “</RSAKeyValue>”;

var rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(serialized);

…..
}

public static RsaKeyPair createFrom (string privateKey, string publicKey)
{
string serialized=”<RSAKeyValue>” + publicKey + privateKey + “</RSAKeyValue>”;
CspParameters _cpsParameter;
_cpsParameter = new CspParameters();
_cpsParameter.Flags = CspProviderFlags.UseMachineKeyStore;
var rsa = new RSACryptoServiceProvider(_cpsParameter);
rsa.FromXmlString(serialized);

…..
}{/syntaxhighlighter}

The first method creates the RSA object from public key only, while the second creates it from both public and private keys. Again the second method (which creates the RSA object from private key) needs to specify to use the MachineKeyStore or it may throw the same exception (“The System cannot find the file specified.”)

Attached below is the complete code for serializing and deserializing .Net’s System.Security.Cryptography.RSA public and private key components.

As mentioned in the last blog post also, you might want to encrypt the private key before storing/transmitting it, or use the .Net secure Key containers for the purpose.