From 75c60b71e20986e04aada7ff5b5f8f12f1a730d2 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Tue, 12 May 2026 20:42:49 -0400 Subject: [PATCH] Port AES/CBC code from Serialization --- SabreTools.Security.Cryptography/AESCBC.cs | 88 ++++++++++++++++++++++ SabreTools.Security.Cryptography/AESCTR.cs | 4 +- 2 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 SabreTools.Security.Cryptography/AESCBC.cs diff --git a/SabreTools.Security.Cryptography/AESCBC.cs b/SabreTools.Security.Cryptography/AESCBC.cs new file mode 100644 index 0000000..f740bba --- /dev/null +++ b/SabreTools.Security.Cryptography/AESCBC.cs @@ -0,0 +1,88 @@ +using System; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace SabreTools.Security.Cryptography +{ + public static class AESCBC + { + /// + /// Create AES/CBC with no padding decryption cipher and intialize + /// + /// Byte array representation of 128-bit encryption key + /// AES initial value for counter + /// Initialized AES cipher + /// + /// Thrown if does not have a length of 16. + /// + public static IBufferedCipher CreateDecryptionCipher(byte[] key, byte[] iv) + { + if (key.Length != 16) + throw new ArgumentOutOfRangeException(nameof(key)); + + var keyParam = new KeyParameter(key); + var cipher = CipherUtilities.GetCipher("AES/CBC/NoPadding"); + cipher.Init(forEncryption: false, new ParametersWithIV(keyParam, iv)); + return cipher; + } + + /// + /// Create AES/CBC with no padding encryption cipher and intialize + /// + /// Byte array representation of 128-bit encryption key + /// AES initial value for counter + /// Initialized AES cipher + /// + /// Thrown if does not have a length of 16. + /// + public static IBufferedCipher CreateEncryptionCipher(byte[] key, byte[] iv) + { + if (key.Length != 16) + throw new ArgumentOutOfRangeException(nameof(key)); + + var keyParam = new KeyParameter(key); + var cipher = CipherUtilities.GetCipher("AES/CBC/NoPadding"); + cipher.Init(forEncryption: true, new ParametersWithIV(keyParam, iv)); + return cipher; + } + + /// + /// Decrypts with AES-128-CBC (no padding). + /// Returns null if any argument is invalid or decryption fails. + /// + /// Ciphertext to decrypt. + /// 16-byte AES key. + /// 16-byte initialisation vector. + public static byte[]? Decrypt(byte[] data, byte[] key, byte[] iv) + { + // Validate the key and IV + if (key.Length != 16) + return null; + if (iv.Length != 16) + return null; + + var cipher = CreateDecryptionCipher(key, iv); + return cipher.DoFinal(data); + } + + /// + /// Encrypts with AES-128-CBC (no padding). + /// Returns null if any argument is invalid or encryption fails. + /// + /// Plaintext to encrypt. + /// 16-byte AES key. + /// 16-byte initialisation vector. + public static byte[]? Encrypt(byte[] data, byte[] key, byte[] iv) + { + // Validate the key and IV + if (key.Length != 16) + return null; + if (iv.Length != 16) + return null; + + var cipher = CreateEncryptionCipher(key, iv); + return cipher.DoFinal(data); + } + } +} diff --git a/SabreTools.Security.Cryptography/AESCTR.cs b/SabreTools.Security.Cryptography/AESCTR.cs index a09fd69..bd7322e 100644 --- a/SabreTools.Security.Cryptography/AESCTR.cs +++ b/SabreTools.Security.Cryptography/AESCTR.cs @@ -11,7 +11,7 @@ namespace SabreTools.Security.Cryptography public static class AESCTR { /// - /// Create AES decryption cipher and intialize + /// Create AES/CTR decryption cipher and intialize /// /// Byte array representation of 128-bit encryption key /// AES initial value for counter @@ -31,7 +31,7 @@ namespace SabreTools.Security.Cryptography } /// - /// Create AES encryption cipher and intialize + /// Create AES/CTR encryption cipher and intialize /// /// Byte array representation of 128-bit encryption key /// AES initial value for counter