using System; using System.Security.Cryptography; namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities { using SKIT.FlurlHttpClient.Primitives; /// /// AES 算法工具类。 /// public static class AESUtility { /// /// 基于 CBC 模式解密数据。 /// /// AES 密钥字节数组。 /// 加密使用的初始化向量字节数组。 /// 待解密数据字节数组。 /// 解密后的数据字节数组。 public static byte[] DecryptWithCBC(byte[] keyBytes, byte[] ivBytes, byte[] cipherBytes) { if (keyBytes is null) throw new ArgumentNullException(nameof(keyBytes)); if (ivBytes is null) throw new ArgumentNullException(nameof(ivBytes)); if (cipherBytes is null) throw new ArgumentNullException(nameof(cipherBytes)); using (SymmetricAlgorithm aes = Aes.Create()) { aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; aes.Key = keyBytes; aes.IV = ivBytes; using ICryptoTransform transform = aes.CreateDecryptor(); return transform.TransformFinalBlock(cipherBytes, 0, cipherBytes.Length); } } /// /// 基于 CBC 模式解密数据。 /// /// 经过编码后的(通常为 Base64)AES 密钥。 /// 经过编码后的(通常为 Base64)初始化向量。 /// 经过编码后的(通常为 Base64)待解密数据。 /// 解密后的数据。 public static EncodedString DecryptWithCBC(EncodedString encodingKey, EncodedString encodingIV, EncodedString encodingCipher) { if (encodingKey.Value is null) throw new ArgumentNullException(nameof(encodingKey)); if (encodingIV.Value is null) throw new ArgumentNullException(nameof(encodingIV)); if (encodingCipher.Value is null) throw new ArgumentNullException(nameof(encodingCipher)); byte[] plainBytes = DecryptWithCBC( keyBytes: EncodedString.FromString(encodingKey, fallbackEncodingKind: EncodingKinds.Base64), ivBytes: EncodedString.FromString(encodingIV, fallbackEncodingKind: EncodingKinds.Base64), cipherBytes: EncodedString.FromString(encodingCipher, fallbackEncodingKind: EncodingKinds.Base64) ); return EncodedString.ToLiteralString(plainBytes); } /// /// 基于 CBC 模式加密数据。 /// /// AES 密钥字节数组。 /// 加密使用的初始化向量字节数组。 /// 待加密数据字节数组。 /// 加密后的数据字节数组。 public static byte[] EncryptWithCBC(byte[] keyBytes, byte[] ivBytes, byte[] plainBytes) { if (keyBytes is null) throw new ArgumentNullException(nameof(keyBytes)); if (ivBytes is null) throw new ArgumentNullException(nameof(ivBytes)); if (plainBytes is null) throw new ArgumentNullException(nameof(plainBytes)); using (SymmetricAlgorithm aes = Aes.Create()) { aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; aes.Key = keyBytes; aes.IV = ivBytes; using ICryptoTransform transform = aes.CreateEncryptor(); return transform.TransformFinalBlock(plainBytes, 0, plainBytes.Length); } } /// /// 基于 CBC 模式加密数据。 /// /// 经过编码后的(通常为 Base64)AES 密钥。 /// 经过编码后的(通常为 Base64)初始化向量。 /// 待加密数据。 /// 经过 Base64 编码的加密后的数据。 public static EncodedString EncryptWithCBC(EncodedString encodingKey, EncodedString encodingIV, string plainData) { if (encodingKey.Value is null) throw new ArgumentNullException(nameof(encodingKey)); if (encodingIV.Value is null) throw new ArgumentNullException(nameof(encodingIV)); if (plainData is null) throw new ArgumentNullException(nameof(plainData)); byte[] plainBytes = EncryptWithCBC( keyBytes: EncodedString.FromString(encodingKey, fallbackEncodingKind: EncodingKinds.Base64), ivBytes: EncodedString.FromString(encodingIV, fallbackEncodingKind: EncodingKinds.Base64), plainBytes: EncodedString.FromLiteralString(plainData) ); return EncodedString.ToBase64String(plainBytes); } } }