Symmetric Encryption Algorithms in .NET Core Using BouncyCastle
This article introduces symmetric encryption algorithms such as DES, 3DES, and AES, explains their principles, advantages and drawbacks, and provides complete .NET Core sample code using the BouncyCastle library for encryption and decryption with various padding modes.
Introduction
The series was created to address the current state of encryption, including compatibility across Linux and Windows, language interoperability (C#, Java, etc.), inconsistent online resources, and the incompleteness of .NET's built‑in cryptographic algorithms.
System environment compatibility (Linux, Windows)
Language interoperability (e.g., C#, Java) – encryption itself is language‑agnostic.
Online documentation is often outdated or incomplete.
.NET official libraries do not provide a full set of algorithms, making cross‑language adaptation difficult.
This series explains how to use asymmetric encryption, encoding, hash, signature, symmetric encryption, and national‑standard algorithms in .NET Core, and invites readers to point out any mistakes.
The goal is to help readers quickly and easily understand encryption integration and to combine algorithms from the BouncyCastle cryptographic package.
Project repository: https://github.com/fuluteam/ICH.BouncyCastle.git
Previous article: .NET Core Encryption Series – Message Digest and Digital Signature Algorithms
Functional Dependency
BouncyCastle ( https://www.bouncycastle.org/csharp ) is an open‑source lightweight cryptographic library that supports many algorithms not available in the standard .NET Core libraries.
Supported platforms: .NET 4, .NET Standard 1.0‑2.0, WP, Silverlight, MonoAndroid, Xamarin.iOS, .NET Core.
Feature
Dependency
Portable.BouncyCastle
Portable.BouncyCastle • 1.8.5
Symmetric Encryption Algorithms
Algorithm Overview
Symmetric encryption is an early and mature technology where the sender encrypts plaintext with a secret key, producing ciphertext. The receiver must possess the same key to decrypt the data, meaning both parties share a single secret key that must be exchanged securely beforehand.
Common algorithms include DES, 3DES, TDEA, Blowfish, RC5, IDEA, with the most widely used being DES, AES, and 3DES.
Algorithm Characteristics
Symmetric algorithms are public, have low computational overhead, and provide fast encryption with high efficiency.
However, because both parties use the same key, key management becomes a major challenge, especially in large distributed systems where the number of keys grows exponentially.
Key management complexity and the lack of built‑in signing capabilities limit the use of symmetric algorithms compared to asymmetric ones.
Despite these drawbacks, symmetric encryption offers high speed and strong resistance to brute‑force attacks when long keys are used.
Common Symmetric Algorithms
DES
DES (Data Encryption Standard) was introduced in 1976, uses a 56‑bit key, and is based on the Feistel structure. It is no longer considered secure due to its short key length and has been replaced by AES.
3DES
3DES (also known as TDEA) applies the DES algorithm three times to each data block, providing stronger security than DES. It has been deprecated in many standards (e.g., TLS 1.3) because of vulnerabilities such as the Sweet32 attack.
AES
AES (Advanced Encryption Standard), also known as Rijndael, was approved by NIST in 2001 and supports key sizes of 128, 192, and 256 bits. It is the most widely used symmetric algorithm today, employed in Wi‑Fi security, SSL/TLS, file encryption, VPNs, and many government systems.
Sample Code
Cipher Algorithm Constants
public class Algorithms
{
public const string AES_CBC_NoPadding = "AES/CBC/NoPadding";
public const string AES_CBC_PKCS7Padding = "AES/CBC/PKCS7Padding";
public const string AES_CBC_ZerosPadding = "AES/CBC/ZerosPadding";
public const string AES_CBC_ANSIX923Padding = "AES/CBC/ANSIX923Padding";
public const string AES_CBC_ISO10126Padding = "AES/CBC/ISO10126Padding";
public const string AES_ECB_NoPadding = "AES/ECB/NoPadding";
public const string AES_ECB_PKCS7Padding = "AES/ECB/PKCS7Padding";
public const string AES_ECB_ZerosPadding = "AES/ECB/ZerosPadding";
public const string AES_ECB_ANSIX923Padding = "AES/ECB/ANSIX923Padding";
public const string AES_ECB_ISO10126Padding = "AES/ECB/ISO10126Padding";
public const string AES_OFB_NoPadding = "AES/OFB/NoPadding";
public const string AES_OFB_PKCS7Padding = "AES/OFB/PKCS7Padding";
public const string AES_OFB_ZerosPadding = "AES/OFB/ZerosPadding";
public const string AES_OFB_ANSIX923Padding = "AES/OFB/ANSIX923Padding";
public const string AES_OFB_ISO10126Padding = "AES/OFB/ISO10126Padding";
// ... similar constants for DES, DESede, etc.
}DES Implementation
Code
///
/// Encrypt
///
///
Plain data to encrypt
///
Secret key
///
Initialization vector (not needed for ECB)
///
Cipher algorithm
///
Encrypted data
public static byte[] Encrypt(byte[] data, byte[] key, byte[] iv, string algorithm)
{
if (data == null) throw new ArgumentNullException(nameof(data));
if (key == null) throw new ArgumentNullException(nameof(key));
if (algorithm == null) throw new ArgumentNullException(nameof(algorithm));
var cipher = CipherUtilities.GetCipher(algorithm);
if (iv == null)
cipher.Init(true, ParameterUtilities.CreateKeyParameter("DES", key));
else
cipher.Init(true, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("DES", key), iv));
return cipher.DoFinal(data);
}
///
/// Decrypt
///
///
Cipher data to decrypt
///
Secret key
///
Initialization vector (not needed for ECB)
///
Cipher algorithm
///
Plain data
public static byte[] Decrypt(byte[] data, byte[] key, byte[] iv, string algorithm)
{
if (data == null) throw new ArgumentNullException(nameof(data));
if (key == null) throw new ArgumentNullException(nameof(key));
if (algorithm == null) throw new ArgumentNullException(nameof(algorithm));
var cipher = CipherUtilities.GetCipher(algorithm);
if (iv == null)
cipher.Init(false, ParameterUtilities.CreateKeyParameter("DES", key));
else
cipher.Init(false, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("DES", key), iv));
return cipher.DoFinal(data);
}Sample Usage
private static void DES_Sample()
{
Console.WriteLine("Encryption algorithm: DES, mode: CBC, padding: PKCS7Padding, charset: utf8");
var keyBytes = DES.GenerateKey();
var keyBase64Str = Base64.ToBase64String(keyBytes);
Console.WriteLine($"Key length: 192bit, Key (Base64): {keyBase64Str}");
var ivStr = Str.GenerateRandom(8);
var iv = Strings.ToByteArray(ivStr);
Console.WriteLine($"IV: {ivStr}");
var content = "hello des";
Console.WriteLine($"Plain text: {content}");
var cipherStr = Base64.ToBase64String(DES.Encrypt(Strings.ToUtf8ByteArray(content), Base64.Decode(keyBase64Str), iv, Algorithms.DES_CBC_PKCS7Padding));
Console.WriteLine($"Cipher (Base64): {cipherStr}");
var originalStr = Strings.FromUtf8ByteArray(DES.Decrypt(Base64.Decode(cipherStr), Base64.Decode(keyBase64Str), iv, Algorithms.DES_CBC_PKCS7Padding));
Console.WriteLine($"Decrypted text: {originalStr}");
Console.WriteLine();
}3DES Implementation
Code
///
/// Encrypt using 3DES
///
public static byte[] Encrypt(byte[] data, byte[] key, byte[] iv, string algorithm)
{
// Same validation as DES
var cipher = CipherUtilities.GetCipher(algorithm);
if (iv == null)
cipher.Init(true, ParameterUtilities.CreateKeyParameter("DESEDE", key));
else
cipher.Init(true, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("DESEDE", key), iv));
return cipher.DoFinal(data);
}
///
/// Decrypt using 3DES
///
public static byte[] Decrypt(byte[] data, byte[] key, byte[] iv, string algorithm)
{
var cipher = CipherUtilities.GetCipher(algorithm);
if (iv == null)
cipher.Init(false, ParameterUtilities.CreateKeyParameter("DESEDE", key));
else
cipher.Init(false, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("DESEDE", key), iv));
return cipher.DoFinal(data);
}Sample Usage
private static void TripleDES_Sample()
{
Console.WriteLine("Encryption algorithm: 3DES, mode: CBC, padding: PKCS7Padding, charset: utf8");
var keyBytes = TripleDES.GenerateKey(192);
var keyBase64Str = Base64.ToBase64String(keyBytes);
Console.WriteLine($"Key length: 192bit, Key (Base64): {keyBase64Str}");
var ivStr = Str.GenerateRandom(8);
var iv = Strings.ToByteArray(ivStr);
Console.WriteLine($"IV: {ivStr}");
var content = "hello 3des";
Console.WriteLine($"Plain text: {content}");
var cipherStr = Base64.ToBase64String(TripleDES.Encrypt(Strings.ToUtf8ByteArray(content), Base64.Decode(keyBase64Str), iv, Algorithms.DESede_CBC_PKCS7Padding));
Console.WriteLine($"Cipher (Base64): {cipherStr}");
var originalStr = Strings.FromUtf8ByteArray(TripleDES.Decrypt(Base64.Decode(cipherStr), Base64.Decode(keyBase64Str), iv, Algorithms.DESede_CBC_PKCS7Padding));
Console.WriteLine($"Decrypted text: {originalStr}");
Console.WriteLine();
}AES Implementation
Code
///
/// Encrypt using AES
///
public static byte[] Encrypt(byte[] data, byte[] key, byte[] iv, string algorithm)
{
// Validation omitted for brevity
var cipher = CipherUtilities.GetCipher(algorithm);
if (iv == null)
cipher.Init(true, ParameterUtilities.CreateKeyParameter("AES", key));
else
cipher.Init(true, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", key), iv));
return cipher.DoFinal(data);
}
///
/// Decrypt using AES
///
public static byte[] Decrypt(byte[] data, byte[] key, byte[] iv, string algorithm)
{
var cipher = CipherUtilities.GetCipher(algorithm);
if (iv == null)
cipher.Init(false, ParameterUtilities.CreateKeyParameter("AES", key));
else
cipher.Init(false, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", key), iv));
return cipher.DoFinal(data);
}Sample Usage
private static void AES_Sample()
{
Console.WriteLine("Encryption algorithm: AES, mode: CBC, padding: PKCS7Padding, charset: utf8");
var keyBytes = AES.GenerateKey();
var keyBase64Str = Base64.ToBase64String(keyBytes);
Console.WriteLine($"Key length: 192bit, Key (Base64): {keyBase64Str}");
var ivStr = Str.GenerateRandom(16);
var iv = Strings.ToByteArray(ivStr);
Console.WriteLine($"IV: {ivStr}");
var content = "hello aes";
Console.WriteLine($"Plain text: {content}");
var cipherStr = Base64.ToBase64String(AES.Encrypt(Strings.ToUtf8ByteArray(content), Base64.Decode(keyBase64Str), iv, Algorithms.AES_CBC_PKCS7Padding));
Console.WriteLine($"Cipher (Base64): {cipherStr}");
var originalStr = Strings.FromUtf8ByteArray(AES.Decrypt(Base64.Decode(cipherStr), Base64.Decode(keyBase64Str), iv, Algorithms.AES_CBC_PKCS7Padding));
Console.WriteLine($"Decrypted text: {originalStr}");
Console.WriteLine();
}Next Issue Preview
The next article will cover certificate‑related operations. Stay tuned.
Fulu Network R&D Team
Providing technical literature sharing for Fulu Holdings' tech elite, promoting its technologies through experience summaries, technology consolidation, and innovation sharing.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.