Asymmetric cryptography also known as public-key encryption uses a public/private key pair to encrypt and decrypt data. The public key in asymmetric cryptography is available to the public but the private key must be protected by the user, else it can be used to decrypt data.
In .NET, the RSACryptoServiceProvider and DSACryptoServiceProvider classes are used for asymmetric encryption. A random public/private key pair is generated when a new instance of the class is created.
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
Once keys are generated, we can use the ToXmlString or ExportParameters method to read the keys.
The ToXmlString method returns key information in XML as a string. The method takes a Boolean parameter. If passed false, it returns the public key only. If passed true, it returns both private and public pairs.
The following code snippet returns a public key.
string str = RSA.ToXmlString(false);
The public key looks like the following with a Modulus value and an Exponent value.
<RSAKeyValue>
<Modulus>lF1Yof6FXaY9M/StHwPC1voW5K5JOqSu8BXndS4WH06L9mOfrNI9Et0cRaHjiYd2bQNFZB9+ AZmN4ODc36DgVPqQqYY2tbH+9UY0hcdi+WnDuUZe7sgvWKfGwBKTcy7g8uUAzpTWEP1W0FqeMunmXljD8Iouoqp5oHtTW1GHIlE=</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
When a true value is passed.
string str = RSA.ToXmlString(true);
The output looks like the following which has both public and private keys.
<RSAKeyValue>
<Modulus>tMvvUeHhggKAVex8JzYKXYQ32HVmr05PdtT1KV3kTkKE26jO/9IVmg+bWwxR1vuMzmY7spwguSJQsnjutJXamH0 mblNgYHmWwhyhJMSTtnZp57VDNNedjCFQnLOn211yk/PpCQHEiDDvt84hnmcdXNBlfZfkQzQ+UO/elhP5NH0=</Modulus>
<Exponent>AQAB</Exponent>
<P>22SSx3JpSqYVUWuxiSKwmh/8RDDcgDvq8l+4dMlQ/F+BJhthTQ3UJGupWaxiJyXX95AYAJIJJvWVvmvI7tqbxw==</P>
<Q>0va2WFy0oUwX4eJtZElRbot9TOrwGcqI64rMAYjvxl/mayCRXf0ypwKofKWOsmjK/pX0xWaqnFWB/NdLFt4Fmw==</Q>
<DP>VbIYPz2qcRUkmJQnWbiqINnDkONBDfnZkOjgxQVp09p+OONTA2UWa09+a9+Qy1fV3wZyya5BUu10m1fAucO8Ow==</DP>
<DQ>Lm8hOZfGJk6SXySwgUdmBhfrz3dSu8qJkpatSpUyeY54MBIuDOsDMCF0pmLmYryQGbM1+hEb8mcbwmQ84d6iiw==</DQ>
<InverseQ>L67OLIIK+M3OF1nxSHTjZ+Kv/hwOHJPvdHHSuh9VEmw93kPGn6Qt6GudEreFb6xlFsuR6UM19LUIweapgaUagQ==</InverseQ>
<D>YbaGlZ6bHoTzj3zMbPTMDVbUR+zLnpuYXwUhq0XPimxxGbbWiXSlsCoXMNIruSEjLLocMaAoH2bobkzl1jvXdAI30NdZ/rpG5SRl dpaeIundLfHkSnZfHwHuP9OGXJSXmbmLCrO8dq7BjLauS4JiTRgjiXoq8c995MEF+vhw9hE=</D>
</RSAKeyValue>
The ExportParameters method returns an RSA parameters structure that holds the key information in separate fields.
// Get key into parameters
RSAParameters RSAKeyInfo = RSA.ExportParameters(true);
Console.WriteLine($"Modulus: {System.Text.Encoding.UTF8.GetString(RSAKeyInfo.Modulus)}");
Console.WriteLine($"Exponent: {System.Text.Encoding.UTF8.GetString(RSAKeyInfo.Exponent)}");
Console.WriteLine($"P: {System.Text.Encoding.UTF8.GetString(RSAKeyInfo.P)}");
Console.WriteLine($"Q: {System.Text.Encoding.UTF8.GetString(RSAKeyInfo.Q)}");
Console.WriteLine($"DP: {System.Text.Encoding.UTF8.GetString(RSAKeyInfo.DP)}");
Console.WriteLine($"DQ: {System.Text.Encoding.UTF8.GetString(RSAKeyInfo.DQ)}");
Here is a complete working example.
using System;
using System.Security.Cryptography;
class PrivatePublicKeyGenerator
{
static void Main(string[] args)
{
// Generate a public/private key using RSA
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
// Read public key in a string
string str = RSA.ToXmlString(true);
Console.WriteLine(str);
// Get key into parameters
RSAParameters RSAKeyInfo = RSA.ExportParameters(true);
Console.WriteLine($"Modulus: {System.Text.Encoding.UTF8.GetString(RSAKeyInfo.Modulus)}");
Console.WriteLine($"Exponent: {System.Text.Encoding.UTF8.GetString(RSAKeyInfo.Exponent)}");
Console.WriteLine($"P: {System.Text.Encoding.UTF8.GetString(RSAKeyInfo.P)}");
Console.WriteLine($"Q: {System.Text.Encoding.UTF8.GetString(RSAKeyInfo.Q)}");
Console.WriteLine($"DP: {System.Text.Encoding.UTF8.GetString(RSAKeyInfo.DP)}");
Console.WriteLine($"DQ: {System.Text.Encoding.UTF8.GetString(RSAKeyInfo.DQ)}");
Console.ReadKey();
}
}