How to use symmetric and asymmetric encryption in C#
By FoxLearn 1/2/2025 7:27:51 AM 122
Symmetric encryption uses a single key for both encryption and decryption, while asymmetric encryption involves a pair of keys one for encryption and another for decryption.
Encryption is used to secure data either "at rest" (stored data) or "in motion" (data being transmitted).
Symmetric encryption vs. asymmetric encryption
Encryption comes in two types: symmetric and asymmetric. Both methods help protect sensitive data, whether it's stored or transmitted.
In C#, the System.Security.Cryptography
namespace provides built-in support for both types. Symmetric encryption uses one key for both encryption and decryption, making it faster but less secure since anyone with the key can decrypt the data. Asymmetric encryption uses a public key for encryption and a private key for decryption, offering stronger security, though it is slower.
Symmetric encryption is best for large data (e.g., email) due to its efficiency, while asymmetric encryption is suited for small amounts of sensitive data like passwords or credit card numbers.
Implementing symmetric encryption in C#
To implement symmetric encryption, you need to generate a 256-bit key for encrypting and decrypting data. While symmetric encryption is faster than asymmetric encryption, it is less secure because the same key is used for both encryption and decryption.
In the example, you are instructed to create a static C# class called SymmetricEncryptionDecryptionManager
in a file named SymmetricEncryptionDecryptionManager.cs
for managing the encryption and decryption process.
using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace EncryptionDemo { public class SymmetricEncryptionDecryptionManager { private const int KeySize = 32; // 256 bits for AES-256 private const int IvSize = 16; // AES block size (128 bits) // Helper method for creating the AES encryptor/decryptor private static ICryptoTransform CreateAesTransform(string key, byte[] iv, bool isEncrypting) { using (Aes aes = Aes.Create()) { aes.Key = GetValidKey(key); aes.IV = iv; return isEncrypting ? aes.CreateEncryptor() : aes.CreateDecryptor(); } } // Ensures the key is exactly 256 bits (32 bytes) private static byte[] GetValidKey(string key) { byte[] keyBytes = Encoding.UTF8.GetBytes(key); Array.Resize(ref keyBytes, KeySize); // Ensure key size is 256 bits (32 bytes) return keyBytes; } // Generates a random initialization vector private static byte[] GenerateRandomIv() { byte[] iv = new byte[IvSize]; using (var rng = new RNGCryptoServiceProvider()) { rng.GetBytes(iv); } return iv; } // Encrypts the data using symmetric AES encryption public static string Encrypt(string data, string key) { byte[] iv = GenerateRandomIv(); // Generate random IV using (var memoryStream = new MemoryStream()) { using (var encryptor = CreateAesTransform(key, iv, true)) using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) using (var streamWriter = new StreamWriter(cryptoStream)) { streamWriter.Write(data); } byte[] encryptedData = memoryStream.ToArray(); byte[] result = new byte[IvSize + encryptedData.Length]; Buffer.BlockCopy(iv, 0, result, 0, IvSize); // Prepend IV to the encrypted data Buffer.BlockCopy(encryptedData, 0, result, IvSize, encryptedData.Length); return Convert.ToBase64String(result); } } // Decrypts the ciphertext using symmetric AES decryption public static string Decrypt(string cipherText, string key) { byte[] cipherBytes = Convert.FromBase64String(cipherText); byte[] iv = new byte[IvSize]; byte[] encryptedData = new byte[cipherBytes.Length - IvSize]; // Extract IV and encrypted data Buffer.BlockCopy(cipherBytes, 0, iv, 0, IvSize); Buffer.BlockCopy(cipherBytes, IvSize, encryptedData, 0, encryptedData.Length); using (var memoryStream = new MemoryStream(encryptedData)) { using (var decryptor = CreateAesTransform(key, iv, false)) using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) using (var streamReader = new StreamReader(cryptoStream)) { return streamReader.ReadToEnd(); } } } } }
In this example, we defines two methods: Encrypt
and Decrypt
. The Encrypt
method takes the data and a secret key, using the AES algorithm for symmetric encryption. The encrypted data is returned as a Base64 string. The Decrypt
method accepts the encrypted data and the secret key, converting the cipher text into a byte array to decrypt it. The decrypted data is then returned as a string. These methods can be used to encrypt and decrypt data by calling them from the SymmetricEncryptionDecryptionManager
class.
var encryptedText = SymmetricEncryptionDecryptionManager.Encrypt("This is sample text.", key); Console.WriteLine(encryptedText); var decryptedText = SymmetricEncryptionDecryptionManager.Decrypt(encryptedText, key); Console.WriteLine(decryptedText);
Implementing asymmetric encryption in C#
In asymmetric encryption, two keys are used: a public key for encryption and a private key for decryption. Both keys are required to implement this encryption method. To encrypt data, you first generate a public/private key pair, typically using the RSA algorithm.
var rsa = new RSACryptoServiceProvider(); string publicKeyXML = rsa.ToXmlString(false); string privateKeyXML = rsa.ToXmlString(true);
After generating the key pair, you can use the public key to encrypt data.
byte[] data = Encoding.UTF8.GetBytes("Hello world!"); byte[]encryptedData = rsa.Encrypt(data, false);
To decrypt the data, you will need to use the private key.
byte[] decryptedData = rsa.Decrypt(encryptedData, false); string message = Encoding.UTF8.GetString(decryptedData);
Create a new class called AsymmetricEncryptionDecryptionManager
with the provided code to handle asymmetric encryption and decryption.
using System; using System.Security.Cryptography; using System.Text; public class AsymmetricEncryptionDecryptionManager { // Encrypts the given data using the provided RSA parameters public static string Encrypt(string data, RSAParameters rsaParameters) { using (var rsa = new RSACryptoServiceProvider()) { rsa.ImportParameters(rsaParameters); byte[] byteData = Encoding.UTF8.GetBytes(data); byte[] encryptedData = rsa.Encrypt(byteData, RSAEncryptionPadding.OaepSHA256); // Secure padding return Convert.ToBase64String(encryptedData); } } // Decrypts the encrypted data using the provided RSA parameters public static string Decrypt(string cipherText, RSAParameters rsaParameters) { using (var rsa = new RSACryptoServiceProvider()) { byte[] cipherDataAsByte = Convert.FromBase64String(cipherText); rsa.ImportParameters(rsaParameters); byte[] decryptedData = rsa.Decrypt(cipherDataAsByte, RSAEncryptionPadding.OaepSHA256); // Secure padding return Encoding.UTF8.GetString(decryptedData); } } }
You can use the following code snippet to encrypt and decrypt data by calling the Encrypt
and Decrypt
methods of the AsymmetricEncryptionDecryptionManager
class.
var rsaCryptoServiceProvider = new RSACryptoServiceProvider(2048); // Initialize RSA with 2048-bit key var cipherText = AsymmetricEncryptionDecryptionManager.Encrypt("This is sample text.", rsaCryptoServiceProvider.ExportParameters(false)); // Encrypt with public key Console.WriteLine(cipherText); // Output the encrypted text var plainText = AsymmetricEncryptionDecryptionManager.Decrypt(cipherText, rsaCryptoServiceProvider.ExportParameters(true)); // Decrypt with private key Console.WriteLine(plainText); // Output the decrypted (original) text
You can combine both the SymmetricEncryptionDecryptionManager
and AsymmetricEncryptionDecryptionManager
into a single class by writing overloaded methods for symmetric and asymmetric encryption and decryption.
- How to fix 'Failure sending mail' in C#
- How to Parse a Comma-Separated String from App.config in C#
- How to convert a dictionary to a list in C#
- How to retrieve the Executable Path in C#
- How to validate an IP address in C#
- How to retrieve the Downloads Directory Path in C#
- C# Tutorial
- Dictionary with multiple values per key in C#