Overview
In modern .NET environments, you can generate RSA key pairs (private and public keys) using only standard libraries and export them in the highly portable PEM format (Base64 strings). This approach replaces the legacy XML format (ToXmlString) with a standard text format that is highly compatible with OpenSSL and other platforms.
Specifications (Input/Output)
- Input: Key size in bits (e.g., 2048, 4096).
- Output:
- Private key in PEM format (
-----BEGIN PRIVATE KEY----- ...) - Public key in PEM format (
-----BEGIN PUBLIC KEY----- ...)
- Private key in PEM format (
- Behavior: Generates the key in memory, displays it to the standard output, and verifies that the key information can be restored from the strings.
Basic Usage
using System.Security.Cryptography;
// Generate a key with 2048 bits
using var algorithm = RSA.Create(2048);
// Get the private key (PKCS#8) as a string
var privateKeyPem = algorithm.ExportRSAPrivateKeyPem();
// Get the public key (SPKI) as a string
var publicKeyPem = algorithm.ExportSubjectPublicKeyPem();
Full Code Example
This code is a console application designed for .NET 7 or later.
using System;
using System.Security.Cryptography;
class Program
{
static void Main()
{
// 1. Instantiate RSA algorithm with a specific key size
// Use the cross-platform 'RSA.Create' instead of the legacy 'RSACryptoServiceProvider'
using var secureIdentity = RSA.Create(2048);
Console.WriteLine($"[Key Generated] KeySize: {secureIdentity.KeySize} bits");
// 2. Export Private Key (PEM format: PKCS#8)
// This is sensitive information to be managed on the server side
string secretToken = secureIdentity.ExportRSAPrivateKeyPem();
Console.WriteLine("\n--- Exported Private Key (Keep Secret) ---");
Console.WriteLine(secretToken);
// 3. Export Public Key (PEM format: SubjectPublicKeyInfo)
// This info can be distributed to clients for encryption
string publicToken = secureIdentity.ExportSubjectPublicKeyPem();
Console.WriteLine("\n--- Exported Public Key (Distribute) ---");
Console.WriteLine(publicToken);
// 4. Verify restoration from strings (Import)
VerifyKeyImport(secretToken, publicToken);
}
/// <summary>
/// Verifies if the RSA instance can be restored from the exported PEM strings.
/// </summary>
static void VerifyKeyImport(string privatePem, string publicPem)
{
Console.WriteLine("\n[Validation] Testing key import...");
// Create a new instance for restoration
using var validationRsa = RSA.Create();
try
{
// Import including the private key (enables signing and decryption)
validationRsa.ImportFromPem(privatePem);
Console.WriteLine("- Private key import: Success");
// Verify a separate instance can be initialized with only the public key
using var publicOnlyRsa = RSA.Create();
publicOnlyRsa.ImportFromPem(publicPem);
Console.WriteLine("- Public key import: Success");
}
catch (CryptographicException ex)
{
Console.WriteLine($"- Import Error: {ex.Message}");
}
}
}
Customization Points
- Changing Key Size: You can change
RSA.Create(2048)to4096to increase security strength, though this will decrease processing speed. Adjust based on your needs. - Changing Storage: While this example uses
Console.WriteLine, in production, useSystem.IO.File.WriteAllTextto save as.pemfiles or store them in secure vaults like Azure Key Vault. - Format Selection: If integrating with legacy systems like older Java versions, consider using
ExportEncryptedPkcs8PrivateKeyPemto export with a password instead ofExportRSAPrivateKeyPem.
Important Notes
- Strict Private Key Management: Never share the
secretToken(private key) with third parties. Do not commit it to repositories like GitHub. - Avoid ToXmlString: The older
ToXmlStringmethod depends on Windows-specific implementations and may fail in Linux or Docker environments. Modern .NET development prefers PEM or DER (binary) formats. - Ephemeral Key Lifespan: Keys generated with
RSA.Create()exist only in memory. They vanish when the application ends, so you must export and save them if persistence is required.
Advanced Usage
Creating Digital Signatures (Using Private Key)
This example shows how to use the generated key to create a digital signature for detecting data tampering.
using System.Text;
// ... (Assuming keys were generated as shown above) ...
var data = "Important Contract Data";
var dataBytes = Encoding.UTF8.GetBytes(data);
// Create signature using SHA256 hash
byte[] signature = secureIdentity.SignData(dataBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
Console.WriteLine($"\nSignature generated: {BitConverter.ToString(signature).Replace("-", "")}");
Conclusion
Always manage private keys with extreme care and only perform export operations when necessary. Use RSA.Create() rather than RSACryptoServiceProvider for generating RSA keys. For converting keys to text, the modern standard is to use PEM format (Export...Pem) rather than the less compatible XML format.
