Best way to store RSA key and use it in .Net core(looking for a cross-platform solution)
IMO, the question should be, is it possible to use the RSA key in .net core for cross-platform?
I have recently built open-source encryption and decryption library, spending hours investigating the same question you asked. The short answer it is not possible to use CspParameters with Linux, it is for Windows OS (as this answer mentions). And because the answer is not possible, there is no best way.
So to start with, let's see if we can answer the question of using the RSA key in the .net core for cross-platform.
To do that it is very simple, you need to do following:
Rsa = RSA.Create();
Rsa.KeySize = 2048;
This part does not require installing the library, it is part of netstandard2.0.
That is it, now to export and import a key that you generate, you can do the following.
When you RSA.Create()
first you can export the key and store it anywhere safe for later usage.
To export private key and it should be kept safe
Rsa.ToXmlString(true);
To export public key, to encrypt with
Rsa.ToXmlString(false);
When you need to import the key from a local store, you can do the following:
Rsa.FromXmlString(asymmetricKey);
This is the cross-platform compatible solution for windows, Linux, or Mac computers.
It is also possible to import certificates from a local computer using X509Certificate2
and use its public key for encryption and private key for decryption.
It is also possible to import private key parameters to RSAParameters
, which requires a helper method to translate XML tags from private key file:
<RSAKeyValue>
<Modulus>xxxx...</Modulus>
<Exponent>xxxx</Exponent>
<P>xxxx...</P>
<Q>xxxx...</Q>
<DP>xxxx...</DP>
<DQ>xxxx...</DQ>
<InverseQ>xxxx...</InverseQ>
<D>xxxx...</D>
</RSAKeyValue>
But I find it easier to use FromXmlString
and it is part of RSA
class when creating RSA.Create()
, so no need for a helper method, that said if performance means a lot for your project, you need to make a performance test to compare the results.
So finally I provide a simple example of how to store and load keys:
public static void Main(string[] args)
{
var rsa = RSA.Create();
rsa.KeySize = 2048;
// public key for decrypting
var privateKey = rsa.ToXmlString(true);
SaveKey(@"privateKey", privateKey);
// public key for encrypting
var publicKey = rsa.ToXmlString(false);
SaveKey(@"publicKey", publicKey);
// initialize the private for use on another instance
var rsaAnotherPlace = RSA.Create();
rsaAnotherPlace.KeySize = 2048;
rsaAnotherPlace.FromXmlString(LoadKey(@"privateKey"));
}
// store my keys
public static void SaveKey(string filename, string content)
{
var bytes = Encoding.ASCII.GetBytes(content);
using var fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
fs.Write(bytes, 0, bytes.Length);
}
// load key
public static string LoadKey(string filename)
{
var bytes = File.ReadAllBytes(filename);
return Encoding.ASCII.GetString(bytes);
}
I have tested the solution on Windows and Linux OS and it passes the macOS test on GitHub actions, but I have not tested it yet on macOS.
Disclaimer: this is the open-source library I am working on.