有幸接触了一下传说中的对称加密算法3DES算法
感受这些加密算法与个人工做是想去甚远的,通常没什么机会接触这些东西安全
今次了解了一下3DES这个对称算法ide
原理算不上明白,算是踩了C#中的一些坑吧加密
C#中对于密钥的处理比较奇怪,花费了一夜一早上的时间才弄明白code
期间偷窥了很多C#的源代码orm
下面由我娓娓道来blog
定义算法最先期的标准被放在ANS X9.52中并在1998年发布并将其描述为三重数据加密算法(简称TDEA),在ANSI X3.92中定义了该算法的三个操做可是并无使用DES或者3DES,直到1999年发布的FIPS PUB 46-3在正式命名三重数据加密算法,大概在2004到2005的样子才正式引入三重数据加密算法,以前一直以TDEA存在着,也就是说TDEA就是3DES,可是没有使用3DES做为标准术语。ip
三重数据加密算法使用包括密钥K1,密钥K2和密钥约束K3,每个包含56位不包含奇偶校验,算法实现公式以下:ci
ciphertext = EK3(DK2(EK1(plaintext)))
即input
密文 = EK3(DK2(EK1(平文)))
用K1对数据进行加密,用K2对数据进行解密,用K3对数据再加密。
解密公式为以下:
plaintext = DK1(EK2(DK3(ciphertext)))
即
平文 = DK1(EK2(DK3(密文)))
用K3j对数据进行解密,用K2对数据进行加密,用K1对数据进行加密。每次加密都处理64位数据并造成一块。
定义了三种密钥选项。
(1)三个密钥相互独立。
(2)K1和K2密钥独立,但K1 = K3。
(3)三个密钥相等。
密钥选项1的强度最高,拥有3 x 56 = 168个独立的密钥位。
密钥选项2的安全性稍低,拥有2 x 56 = 112个独立的密钥位。该选项比简单的应用DES两次的强度较高,即便用K1和K2,由于它能够防护中途相遇攻击。
密钥选项3等同与DES,只有56个密钥位。这个选项提供了与DES的兼容性,由于第1和第2次DES操做相互抵消了。该选项再也不为国家标准科技协会(NIST)所推荐,亦不为ISO/IEC 18033-3所支持。
讲真简介里用来凑字数的这些内容我其实没怎么看明白
C#中使用TripleDESCryptoServiceProvider
类来实现相关功能
public static string DesEncrypt(string input, string key) { byte[] inputArray = Encoding.UTF8.GetBytes(input); TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider(); tripleDES.Key = Encoding.UTF8.GetBytes(key); tripleDES.Mode = CipherMode.ECB; tripleDES.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tripleDES.CreateEncryptor(); byte[] resultArray = cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length); tripleDES.Clear(); return Convert.ToBase64String(resultArray, 0, resultArray.Length); } public static string DesDecrypt(string input, string key) { byte[] inputArray = Convert.FromBase64String(input); TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider(); tripleDES.Key = Encoding.UTF8.GetBytes(key); tripleDES.Mode = CipherMode.ECB; tripleDES.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tripleDES.CreateDecryptor(); byte[] resultArray = cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length); tripleDES.Clear(); return Encoding.UTF8.GetString(resultArray); }
从下面源码中看出,该类接收的Key为16位或24位
而后对于这个Key,C#彷佛有本身的处理方式
如下为我的理解:
这个24位的key会被处理成3个8字节的独立密钥参与运算
当提供24位key时并无什么不妥
可是当提供16位的key时 会把提供的key拆分红两个块(block) 并以第一个块做为第三个块组成一个24位的密钥
以下:
输入密钥:49, 50, 51, 52, 53, 54, 55, 56, 57, 49, 50, 51, 52, 53, 54, 55 实际使用:49, 50, 51, 52, 53, 54, 55, 56, 57, 49, 50, 51, 52, 53, 54, 55, 49, 50, 51, 52, 53, 54, 55, 56
能够看出使用了前8位来进行后面8位的补全
这时候你可能要问,若是提供一个不是16位也不是24位的密钥时会发生什么
会抛异常
以上理解都是在.NetFramework中的体现
若是换到NetCore中,效果就又不同了
在NetCore中不存在TripleDESCryptoServiceProvider
取而代之的是 TripleDES
因此此时咱们的代码须要稍做修改
public static string DesEncrypt(string input, string key) { byte[] inputArray = Encoding.UTF8.GetBytes(input); var tripleDES = TripleDES.Create(); var byteKey = Encoding.UTF8.GetBytes(key); tripleDES.Key = byteKey; tripleDES.Mode = CipherMode.ECB; tripleDES.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tripleDES.CreateEncryptor(); byte[] resultArray = cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length); return Convert.ToBase64String(resultArray, 0, resultArray.Length); } public static string DesDecrypt(string input, string key) { byte[] inputArray = Convert.FromBase64String(input); var tripleDES = TripleDES.Create(); var byteKey = Encoding.UTF8.GetBytes(key); tripleDES.Key = byteKey; tripleDES.Mode = CipherMode.ECB; tripleDES.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tripleDES.CreateDecryptor(); byte[] resultArray = cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length); return Encoding.UTF8.GetString(resultArray); }
NetCore中一样要求咱们提供24位的Key
可是不在兼容16位的Key,若是你提供一个非24位的Key就会异常
不过不要紧,对于16位的Key咱们能够自行处理一下
同理使用前8位补全后8位
public static string DesEncrypt(string input, string key) { byte[] inputArray = Encoding.UTF8.GetBytes(input); var tripleDES = TripleDES.Create(); var byteKey = Encoding.UTF8.GetBytes(key); //复制前8位补全后8位 byte[] allKey = new byte[24]; Buffer.BlockCopy(byteKey, 0, allKey, 0, 16); Buffer.BlockCopy(byteKey, 0, allKey, 16, 8); tripleDES.Key = allKey; tripleDES.Mode = CipherMode.ECB; tripleDES.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tripleDES.CreateEncryptor(); byte[] resultArray = cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length); return Convert.ToBase64String(resultArray, 0, resultArray.Length); } public static string DesDecrypt(string input, string key) { byte[] inputArray = Convert.FromBase64String(input); var tripleDES = TripleDES.Create(); var byteKey = Encoding.UTF8.GetBytes(key); //复制前8位补全后8位 byte[] allKey = new byte[24]; Buffer.BlockCopy(byteKey, 0, allKey, 0, 16); Buffer.BlockCopy(byteKey, 0, allKey, 16, 8); tripleDES.Key = allKey; tripleDES.Mode = CipherMode.ECB; tripleDES.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tripleDES.CreateDecryptor(); byte[] resultArray = cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length); return Encoding.UTF8.GetString(resultArray); }
至此就能够正常兼容NetFramework的代码了
至此写下此文,也算是对3DES有了些许了解吧
须要记住
在.NET Core中利用3DES加密和解密必需要给出3个密钥即24个字节即便密钥3和密钥1相等,它不会像.NET Framework中会重用密钥1中的位数。