有幸接觸了一下傳說中的對稱加密算法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中的位數。