Overview
This implementation uses a public key in XML format to encrypt sensitive text data. In modern .NET environments, it is recommended to use the factory methods of the abstract RSA class instead of RSACryptoServiceProvider and explicitly specify a secure padding mode such as OAEP.
Specifications (Input/Output)
- Input:
- The string to be encrypted (UTF-8).
- RSA public key (XML formatted string).
- Output: Encrypted data as a Base64 string.
- Constraint: The size of data that can be directly encrypted with RSA is limited based on the key length and padding method. It is not suitable for large data volumes.
Basic Usage
using System.Security.Cryptography;
using System.Text;
// Create an RSA instance
using var rsa = RSA.Create();
rsa.FromXmlString(publicKeyXml);
var data = Encoding.UTF8.GetBytes("Secret Message");
// Encrypt (OAEP SHA256 padding is recommended)
var encrypted = rsa.Encrypt(data, RSAEncryptionPadding.OaepSHA256);
Full Code Example
The following code is a console application that demonstrates the flow from key generation to encryption.
using System;
using System.Security.Cryptography;
using System.Text;
class Program
{
static void Main()
{
// 1. Prepare the message
var originalMessage = "This is a secret message only for you.";
Console.WriteLine($"[Original] {originalMessage}");
// 2. Prepare the RSA key
// For testing, we generate a new key pair here to obtain a public key.
// In a real scenario, use the public key string received from your partner.
string publicKeyXml = GenerateSamplePublicKey();
// 3. Execute encryption
try
{
string encryptedBase64 = EncryptString(originalMessage, publicKeyXml);
Console.WriteLine("\n[Encrypted] (Base64)");
Console.WriteLine(encryptedBase64);
}
catch (CryptographicException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
/// <summary>
/// Encrypts a string using an RSA public key and returns it as a Base64 string.
/// </summary>
static string EncryptString(string text, string publicKeyXml)
{
// Create a cross-platform RSA instance
using var rsa = RSA.Create();
// Load the public key in XML format
rsa.FromXmlString(publicKeyXml);
// Convert string to byte array
byte[] dataBytes = Encoding.UTF8.GetBytes(text);
// Execute encryption
// Modern implementations recommend OAEP (Optimal Asymmetric Encryption Padding)
// We specify RSAEncryptionPadding.OaepSHA256 here.
byte[] encryptedBytes = rsa.Encrypt(dataBytes, RSAEncryptionPadding.OaepSHA256);
// Convert result to Base64 string
return Convert.ToBase64String(encryptedBytes);
}
/// <summary>
/// Creates an RSA key pair for testing and returns only the public key XML.
/// </summary>
static string GenerateSamplePublicKey()
{
using var rsa = RSA.Create(2048);
// Extract only the public key by setting includePrivateParameters to false
return rsa.ToXmlString(includePrivateParameters: false);
}
}
Customization Points
- Padding Mode Selection:
RSAEncryptionPadding.OaepSHA256is recommended for high security. However, if compatibility with older systems is required, you might need to change it toRSAEncryptionPadding.Pkcs1. - Encoding of Input Data: This code uses
UTF-8. You can change this to an appropriate encoding likeShift-JISif your specific requirements differ. - Public Key Source: While the sample generates a key on the fly, in practice, you should assign an XML string obtained from a file, database, or API response to the
publicKeyXmlvariable.
Important Notes
- Data Size Limitations: RSA is intended for encrypting short data like “keys” or “hash values.” When using OAEP (SHA256) with a 2048-bit key, the maximum size you can encrypt is roughly 190 bytes. To encrypt long text or entire files, use “Hybrid Encryption.” This involves encrypting the data with a symmetric key (like AES) and then encrypting that “symmetric key” with RSA.
- Absence of Private Key: This code only performs “encryption.” Decryption requires the corresponding “private key.” You cannot restore the original text within this program if you only have the public key.
- Exception Handling: Passing incorrectly formatted XML keys or data exceeding the size limit will throw a
CryptographicException. Always use try-catch blocks to handle these errors.
Advanced Usage
Compatibility with Legacy APIs (RSACryptoServiceProvider)
Example for porting older code that used a bool fOAEP argument:
// Old style: rsa.Encrypt(bytes, true); // 'true' often represented OAEP SHA1
// ↓
// Modern style (equivalent behavior):
var output = rsa.Encrypt(bytes, RSAEncryptionPadding.OaepSHA1);
Conclusion
RSA encryption can be implemented securely and in a platform-independent way by combining the abstract RSA class with the RSAEncryptionPadding enum. The most important consideration is the input data size limit. For larger data, you must switch to a hybrid encryption approach. Additionally, since XML-formatted keys are specific to the .NET ecosystem, consider migrating to the PEM format when integrating with other programming languages.
