SymmetricAlgorithmHelper對稱加密輔助類,支援DES,3DES,AES,RC2
阿新 • • 發佈:2019-02-13
理論上只要繼承自SymmetricAlgorithm的對稱加密演算法,該輔助類都支援加密解密,另外為了方便與JAVA互通,預設提供了ECB和CBC兩種加密模式、填充方式均為PKCS7的靜態方法
因為每種加密方式對Key長度的支援不一樣,所以除SymmetricAlgorithmHelper外,還通過繼承的方式覆蓋了建立祕鑰的Create方法,分別為TripleDESHelper、AESHelper、DESHelper、RC2Helper,KeyGenerator的程式碼在這裡,而測試程式碼如下using System.Security.Cryptography; public class SymmetricAlgorithmHelper<T> where T : SymmetricAlgorithm, new() { /// <summary> /// 加密 ECB PKCS7模式 /// </summary> /// <param name="str">要加密的資料</param> /// <param name="key">祕鑰(base64格式)</param> /// <returns>加密後的結果(base64格式)</returns> public static string EncryptWithECB(string str, string key) { return EncryptWithECB(str, Convert.FromBase64String(key)); } /// <summary> /// 加密 ECB PKCS7模式 /// </summary> /// <param name="str">要加密的資料</param> /// <param name="key">祕鑰</param> /// <returns>加密後的結果(base64格式)</returns> public static string EncryptWithECB(string str, byte[] key) { var toEncryptArray = Encoding.UTF8.GetBytes(str); return Convert.ToBase64String(Encrypt(toEncryptArray, key, null, CipherMode.ECB, PaddingMode.PKCS7)); } /// <summary> /// 解密 ECB PKCS7模式 /// </summary> /// <param name="str">要解密的資料(base64格式)</param> /// <param name="key">祕鑰(base64格式)</param> /// <returns>utf-8編碼返回解密後得資料</returns> public static string DecryptWithECB(string str, string key) { return DecryptWithECB(str, Convert.FromBase64String(key)); } /// <summary> /// 3DES 解密 ECB PKCS7模式 /// </summary> /// <param name="str">要解密的資料(base64格式)</param> /// <param name="key">祕鑰</param> /// <returns>utf-8編碼返回解密後得資料</returns> public static string DecryptWithECB(string str, byte[] key) { var toDecryptArray = Convert.FromBase64String(str); return Encoding.UTF8.GetString(Decrypt(toDecryptArray, key, null, CipherMode.ECB, PaddingMode.PKCS7)); } /// <summary> /// 加密 CBC PKCS7模式 /// </summary> /// <param name="str">要加密的資料</param> /// <param name="key">祕鑰(base64格式)</param> /// <param name="iv">向量(base64格式)</param> /// <returns>加密後的結果(base64格式)</returns> public static string EncryptWithCBC(string str, string key, string iv) { return EncryptWithCBC(str, Convert.FromBase64String(key), Convert.FromBase64String(iv)); } /// <summary> /// 加密 CBC PKCS7模式 /// </summary> /// <param name="str">要加密的資料</param> /// <param name="key">祕鑰</param> /// <param name="iv">向量</param> /// <returns>加密後的結果(base64格式)</returns> public static string EncryptWithCBC(string str, byte[] key, byte[] iv) { var toEncryptArray = Encoding.UTF8.GetBytes(str); return Convert.ToBase64String(Encrypt(toEncryptArray, key, iv, CipherMode.CBC, PaddingMode.PKCS7)); } /// <summary> /// 解密 CBC PKCS7模式 /// </summary> /// <param name="str">要解密的資料(base64格式)</param> /// <param name="key">祕鑰(base64格式)</param> /// <param name="iv">向量(base64格式)</param> /// <returns>utf-8編碼返回解密後得資料</returns> public static string DecryptWithCBC(string str, string key, string iv) { return DecryptWithCBC(str, Convert.FromBase64String(key), Convert.FromBase64String(iv)); } /// <summary> /// 解密 CBC PKCS7模式 /// </summary> /// <param name="str">要解密的資料(base64格式)</param> /// <param name="key">祕鑰</param> /// <param name="iv">向量</param> /// <returns>utf-8編碼返回解密後得資料</returns> public static string DecryptWithCBC(string str, byte[] key, byte[] iv) { var toDecryptArray = Convert.FromBase64String(str); return Encoding.UTF8.GetString(Decrypt(toDecryptArray, key, iv, CipherMode.CBC, PaddingMode.PKCS7)); } /// <summary> /// 加密 /// </summary> /// <param name="data">要加密的資料</param> /// <param name="key">祕鑰</param> /// <param name="iv">向量</param> /// <param name="cipherMode">塊模式</param> /// <param name="paddingMode">填充模式</param> /// <returns>加密後得到的陣列</returns> public static byte[] Encrypt(byte[] data, byte[] key, byte[] iv, CipherMode cipherMode, PaddingMode paddingMode) { return Transform(data, cipherMode, paddingMode, algorithm => algorithm.CreateEncryptor(key, iv)); } /// <summary> /// 解密 /// </summary> /// <param name="data">要解密的資料</param> /// <param name="key">祕鑰</param> /// <param name="iv">向量</param> /// <param name="cipherMode">塊模式</param> /// <param name="paddingMode">填充模式</param> /// <returns>解密後的到的陣列</returns> public static byte[] Decrypt(byte[] data, byte[] key, byte[] iv, CipherMode cipherMode, PaddingMode paddingMode) { return Transform(data, cipherMode, paddingMode, algorithm => algorithm.CreateDecryptor(key, iv)); } private static byte[] Transform(byte[] data, CipherMode cipherMode, PaddingMode paddingMode, Func<T, ICryptoTransform> func) { using (T algorithm = new T { Mode = cipherMode, Padding = paddingMode }) { using (ICryptoTransform cTransform = func(algorithm)) { return cTransform.TransformFinalBlock(data, 0, data.Length); } } } /// <summary> /// 生成祕鑰 /// </summary> /// <param name="key">祕鑰(base64格式)</param> /// <param name="iv">iv向量(base64格式)</param> /// <param name="keySize">要生成的KeySize</param> public static void Create(out string key, out string iv, int keySize) { KeyGenerator.CreateSymmetricAlgorithmKey<T>(out key, out iv, keySize); } } public class TripleDESHelper : SymmetricAlgorithmHelper<TripleDESCryptoServiceProvider> { /// <summary> /// 生成祕鑰 /// </summary> /// <param name="key">祕鑰(base64格式)</param> /// <param name="iv">iv向量(base64格式)</param> /// <param name="keySize">要生成的KeySize,只支援128、192</param> public static new void Create(out string key, out string iv, int keySize = 192) { KeyGenerator.CreateSymmetricAlgorithmKey<TripleDESCryptoServiceProvider>(out key, out iv, keySize); } } public class AESHelper : SymmetricAlgorithmHelper<AesCryptoServiceProvider>//RijndaelManaged { /// <summary> /// 生成祕鑰 /// </summary> /// <param name="key">祕鑰(base64格式)</param> /// <param name="iv">iv向量(base64格式)</param> /// <param name="keySize">要生成的KeySize,只支援128、192、256,java一般生成的祕鑰長度為128,所以這裡預設也採用128</param> public static new void Create(out string key, out string iv, int keySize = 128) { KeyGenerator.CreateSymmetricAlgorithmKey<AesCryptoServiceProvider>(out key, out iv, keySize); } } public class DESHelper : SymmetricAlgorithmHelper<DESCryptoServiceProvider> { /// <summary> /// 生成祕鑰 /// </summary> /// <param name="key">祕鑰(base64格式)</param> /// <param name="iv">iv向量(base64格式)</param> /// <param name="keySize">要生成的KeySize,DES只支援64,所以此處切勿傳其它值</param> public static new void Create(out string key, out string iv, int keySize = 64) { KeyGenerator.CreateSymmetricAlgorithmKey<DESCryptoServiceProvider>(out key, out iv, keySize); } } public class RC2Helper : SymmetricAlgorithmHelper<RC2CryptoServiceProvider> { /// <summary> /// 生成祕鑰 /// </summary> /// <param name="key">祕鑰(base64格式)</param> /// <param name="iv">iv向量(base64格式)</param> /// <param name="keySize">要生成的KeySize,支援的MinSize:40 MaxSize:128 SkipSize:8</param> public static new void Create(out string key, out string iv, int keySize = 96) { KeyGenerator.CreateSymmetricAlgorithmKey<RC2CryptoServiceProvider>(out key, out iv, keySize); } }
static void SymmetricAlgorithmDemo<T>(int keySize = 128) where T : SymmetricAlgorithm, new() { string key, iv; SymmetricAlgorithmHelper<T>.Create(out key, out iv, keySize); Console.WriteLine("Key:" + key); Console.WriteLine("IV:" + iv); SymmetricAlgorithmDemo<T>(key, iv); } static void SymmetricAlgorithmDemo<T>(string key, string iv) where T : SymmetricAlgorithm, new() { string content = "測試資料"; string name = typeof(T).Name; string encTxt = SymmetricAlgorithmHelper<T>.EncryptWithECB(content, key); Console.WriteLine(name + " ECB PKCS7加密結果:" + encTxt); Console.WriteLine(name + " ECB PKCS7解密結果:" + SymmetricAlgorithmHelper<T>.DecryptWithECB(encTxt, key)); encTxt = SymmetricAlgorithmHelper<T>.EncryptWithCBC(content, key, iv); Console.WriteLine(name + " CBC PKCS7加密結果:" + encTxt); Console.WriteLine(name + " CBC PKCS7解密結果:" + SymmetricAlgorithmHelper<T>.DecryptWithCBC(encTxt, key, iv)); encTxt = Convert.ToBase64String(SymmetricAlgorithmHelper<T>.Encrypt(Encoding.UTF8.GetBytes(content), Convert.FromBase64String(key), Convert.FromBase64String(iv), CipherMode.CFB, PaddingMode.Zeros)); Console.WriteLine(name + " CFB Zeros加密結果:" + encTxt); Console.WriteLine(name + " CFB Zeros解密結果:" + Encoding.UTF8.GetString(SymmetricAlgorithmHelper<T>.Decrypt(Convert.FromBase64String(encTxt), Convert.FromBase64String(key), Convert.FromBase64String(iv), CipherMode.CFB, PaddingMode.Zeros))); } static void Main(string[] args) { SymmetricAlgorithmDemo<TripleDESCryptoServiceProvider>(); SymmetricAlgorithmDemo<AesCryptoServiceProvider>(); SymmetricAlgorithmDemo<RijndaelManaged>();//AES SymmetricAlgorithmDemo<DESCryptoServiceProvider>(64); SymmetricAlgorithmDemo<RC2CryptoServiceProvider>(); string key, iv; SymmetricAlgorithmHelper<RijndaelManaged>.Create(out key, out iv, 256); Console.WriteLine("Key:" + key); Console.WriteLine("IV:" + iv); //驗證AesCryptoServiceProvider和RijndaelManaged加密結果是否一致 SymmetricAlgorithmDemo<AesCryptoServiceProvider>(key, iv); SymmetricAlgorithmDemo<RijndaelManaged>(key, iv);//AES //測試AESHelper加密結果是否與上面一致 string encTxt = AESHelper.EncryptWithECB("測試資料", key); Console.WriteLine("AESHelper ECB PKCS7加密結果:" + encTxt); Console.WriteLine("AESHelper ECB PKCS7解密結果:" + AESHelper.DecryptWithECB(encTxt, key)); }