一、对称加密算法概念
我们通过计算机网络传输数据时,如果无法防止他人窃听, 可以利用密码学技术将发送的数据变换成对任何不知道如何做逆变换的人都不可理解的形式, 从而保证了数据的机密性。这种变换被称为加密( encryption),被加密的数据被称为密 文( ciphertext),而加密前的数据被称为明文( plaintext)。 接收方必须能通过某种逆变换将密文重新变换回原来的明文,该逆变换被称为解密( decryption)。加密和解密过程可以以一个密钥( key)为参数,并且加密和解密过程可以公开, 而只有密钥需要保密。 即只有知道密钥的人才能解密密文,而任何人,即使知道加密或解密算法也无法解密密文。
加密密钥和解密密钥可以相同,也可以不同,取决于采用的是对称密钥密码体制还是公开密钥密码体制。
所谓对称密钥密码体制是一种加密密钥与解密密钥相同的密码体制。在这种加密系统中, 两个参与者共享同一个秘密密钥,如果用一个特定的密钥加密一条消息,也必须要使用相同的密钥来解密该消息。该系统又称为对称密钥系统。
数据加密标准( Data Encryption Standard, DES)是对称密钥密码的典型代表,由IBM公司研制,于1977年被美国定为联邦信息标准 。其加密解密基本流程如下图:
二、.NET 使用 DES 加密
DES使用的密钥为64 位( 实际密钥长度为56 位,有8位用于奇偶校验)。密码的字节长度不能低于64位(8个字节),下面是实现代码:
1 /// <summary> 2 /// DES 加密与解密 3 /// DES加密:https://www.zhihu.com/question/36767829 4 /// 加密基本知识:https://www.biaodianfu.com/des.html 5 /// </summary> 6 public static class DesUtil 7 { 8 public static Encoding Encoding { get; set; } 9 10 #region .ctor 11 12 static DesUtil() 13 { 14 Encoding = Encoding.UTF8; 15 } 16 #endregion 17 18 private const string Key = "https://www.cnblogs.com/dongweian/"; 19 20 /// <summary> 21 /// 进行DES加密 22 /// </summary> 23 /// <param name="pToEncrypt">需要加密的字符串</param> 24 /// <param name="sKey">密钥</param> 25 /// <returns></returns> 26 public static string Encrypt(this string pToEncrypt, string sKey = Key) 27 { 28 string base64 = null; 29 using (var des = new DESCryptoServiceProvider()) 30 { 31 byte[] keys = Encoding.Default.GetBytes(sKey).Skip(0).Take(8).ToArray(); 32 byte[] inputByteArray = Encoding.GetBytes(pToEncrypt); 33 des.Key = keys; 34 des.IV = keys; 35 des.Padding = PaddingMode.PKCS7; 36 des.Mode = CipherMode.CBC; 37 using (var ms = new MemoryStream()) 38 { 39 using (var cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write)) 40 { 41 cs.Write(inputByteArray, 0, inputByteArray.Length); 42 cs.FlushFinalBlock(); 43 } 44 base64 = Convert.ToBase64String(ms.ToArray()); 45 } 46 return base64; 47 } 48 } 49 50 /// <summary> 51 /// 进行DES解密 52 /// </summary> 53 /// <param name="pToDecrypt">需要解密的字符串</param> 54 /// <param name="sKey">密钥</param> 55 /// <returns></returns> 56 public static string Decrypt(this string pToDecrypt, string sKey = Key) 57 { 58 string returnValue = null; 59 byte[] inputByteArray = Convert.FromBase64String(pToDecrypt); 60 61 using (var des = new DESCryptoServiceProvider()) 62 { 63 byte[] keys = Encoding.GetBytes(sKey).Skip(0).Take(8).ToArray(); 64 des.Key = keys; 65 des.IV = keys; 66 des.Padding = PaddingMode.PKCS7; 67 des.Mode = CipherMode.CBC; 68 using (var ms = new MemoryStream()) 69 { 70 using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write)) 71 { 72 cs.Write(inputByteArray, 0, inputByteArray.Length); 73 cs.FlushFinalBlock(); 74 cs.Close(); 75 } 76 returnValue = Encoding.GetString(ms.ToArray()); 77 } 78 return returnValue; 79 } 80 } 81 }
二、.NET 使用 3DES 加密
DES使用的密钥为64 位,它是一个优秀的密码算法,目前还没有发现比蛮力攻击更好的破解方法。但随着计算机运算速度的快速提高,56位长的密钥已显得太短。56位长的密钥意味着共有256种可能的密钥,也就是说,共约有7. 6 × 1016 种密钥。假设一台计算机1 µ s可执行一次DES加密,同时假定平均只需搜索密钥空间的一半即可找到密钥,那么破译DES要超过1千年。但现在利用并行计算技术已经设计出搜索DES密钥的专用芯片。例如,在1999年有一批在因特网上合作的人借助于一台不到25万美元的专用计算机,在略大于22h的时间就破译了56 位密钥的DES。
为解决DES密钥太短的问题,人们提出了三重DES(Triple DES, 3DES),并在1985年成为美国的一个商用加密标准[ RFC 2420]。3DES在加密时,用三个密钥,执行三次DES算法: 即 E运算 → D运算 → E运算。 解密时,按相反顺序使用这三个密钥,执行D运算 → E运算 → D运算。
3DES目前正在被2001年发布的高级加密标准( Advanced Encryption Standard, AES)所替代。AES能够使用128位、192位和256位长的密钥,用硬件和软件都可以快速实现。它不需要太多内存,因此适用于小型移动设备。美国国家标准与技术研究所NIST估计,如果用1s破解56位DES的计算机来破解一个128位的AES密钥的话,要用大约149万亿年的时间才有可能。
3DES 使用现有的DES算法,并且当三个密钥相同时,效果就和DES一样。这有利于逐步推广使用3DES。也可以仅使用两个密钥,即 K1= K3,相当于密钥长度112位,这对于多数商业应用也已经足够长了。下面代码我们采用密钥长度56*3=168位的3EDS算法:
1 /// <summary> 2 /// 3DES加密与解密 3 /// </summary> 4 public static class TripleDesUtil 5 { 6 private const string Key = "https://www.cnblogs.com/dongweian/"; 7 public static Encoding Encoding { get; set; } 8 9 #region .ctor 10 11 static TripleDesUtil() 12 { 13 Encoding = Encoding.UTF8; 14 } 15 #endregion 16 17 18 /// <summary> 19 /// 进行3DES加密 20 /// </summary> 21 /// <param name="pToEncrypt">需要加密的字符串</param> 22 /// <param name="sKey">密钥(用于3DES算法的密钥。密钥大小必须为192位)</param> 23 /// <returns></returns> 24 public static string Encrypt(this string pToEncrypt, string sKey = Key) 25 { 26 string base64 = null; 27 using (var des = new TripleDESCng()) 28 { 29 byte[] keys = Encoding.GetBytes(sKey); 30 byte[] inputByteArray = Encoding.GetBytes(pToEncrypt); 31 des.Key = keys.Skip(0).Take(24).ToArray(); 32 des.IV = keys.Skip(0).Take(8).ToArray(); 33 des.Padding = PaddingMode.PKCS7; 34 des.Mode = CipherMode.CBC; 35 using (var ms = new MemoryStream()) 36 { 37 using (var cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write)) 38 { 39 cs.Write(inputByteArray, 0, inputByteArray.Length); 40 cs.FlushFinalBlock(); 41 } 42 base64 = Convert.ToBase64String(ms.ToArray()); 43 } 44 return base64; 45 } 46 } 47 48 /// <summary> 49 /// 进行3DES解密 50 /// </summary> 51 /// <param name="pToDecrypt">需要解密的字符串</param> 52 /// <param name="sKey">密钥</param> 53 /// <returns></returns> 54 public static string Decrypt(this string pToDecrypt, string sKey = Key) 55 { 56 string returnValue = null; 57 byte[] inputByteArray = Convert.FromBase64String(pToDecrypt); 58 59 using (var des = new TripleDESCng()) 60 { 61 byte[] keys = Encoding.GetBytes(sKey); 62 des.Key = keys.Skip(0).Take(24).ToArray(); 63 des.IV = keys.Skip(0).Take(8).ToArray(); 64 des.Padding = PaddingMode.PKCS7; 65 des.Mode = CipherMode.CBC; 66 using (var ms = new MemoryStream()) 67 { 68 using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write)) 69 { 70 cs.Write(inputByteArray, 0, inputByteArray.Length); 71 cs.FlushFinalBlock(); 72 cs.Close(); 73 } 74 returnValue = Encoding.GetString(ms.ToArray()); 75 } 76 return returnValue; 77 } 78 } 79 }
三、测试代码与效果
1 static void Main(string[] args) 2 { 3 string key = "https://www.cnblogs.com/dongweian/"; 4 Console.Write($"请输入内容:"); 5 string input = Console.ReadLine(); 6 var encrypt = TripleDesUtil.Encrypt(input, key); 7 Console.WriteLine($"DES加密后内容:{encrypt}"); 8 Console.WriteLine($"DES解密后内容:{TripleDesUtil.Decrypt(encrypt, key)}"); 9 10 var encrypt3 = TripleDesUtil.Encrypt(input, key); 11 Console.WriteLine($"3DES加密后内容:{encrypt3}"); 12 Console.WriteLine($"3EDS解密后内容:{TripleDesUtil.Decrypt(encrypt3, key)}"); 13 Console.ReadKey(); 14 }