搜尋此網誌

2016年4月3日 星期日

利用.Net實作DES加密演算法

DES加密演算法為1976年所提出的最早加密演算法
資料加密標準(英語:Data Encryption Standard,縮寫為 DES)
https://goo.gl/52G6fK
他是一種對稱型的演算法
需要一把安全鑰匙與檢查鑰匙
都為8位元長度
但因為只有八位元
而且可以逆向反組譯
所以是不安全的,以現在技術來說是可以被破解的
目前銀行或ATM Center已經都不採用這種演算法了



接下來就用c#.Net來實作DES加密演算法
先設計一個簡單的UI介面
並且實作兩種字串的長度格式
一種是64位元的,加密後的字串比較精簡
一種是傳統的

假定安全鑰匙跟檢查鑰匙的密碼分別如下:
  1. public string strKey = "C.W.Kuan";  
  2.         public string strCheckCode = "19810313";  

先示範第一種Base64的
原始資料輸入一段文字後,按下加密(Base64)後,得到加密後的結果資料如下圖
  1. private void btnEncrypt64_Click(object sender, EventArgs e)  
  2.         {  
  3.             txtResult.Text = desEncryptBase64(txtSource.Text, strKey, strCheckCode);  
  4.         }  
  1. private string desEncryptBase64(string source, string strkey, string strCheckCode)  
  2.         {  
  3.             DESCryptoServiceProvider des = new DESCryptoServiceProvider();  
  4.             byte[] key = Encoding.ASCII.GetBytes(strkey);  
  5.             byte[] iv = Encoding.ASCII.GetBytes(strCheckCode);  
  6.             byte[] dataByteArray = Encoding.UTF8.GetBytes(source);  
  7.   
  8.             des.Key = key;  
  9.             des.IV = iv;  
  10.             string encrypt = "";  
  11.             using (MemoryStream ms = new MemoryStream())  
  12.             using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))  
  13.             {  
  14.                 cs.Write(dataByteArray, 0, dataByteArray.Length);  
  15.                 cs.FlushFinalBlock();  
  16.                 encrypt = Convert.ToBase64String(ms.ToArray());  
  17.             }  
  18.             return encrypt;  
  19.         }  

 接著再試著將加密後的字串進行解密,驗證看是否正確
  1. private void btnDecrypt64_Click(object sender, EventArgs e)  
  2. {  
  3.     txtResult.Text = desDecryptBase64(txtSource.Text, strKey, strCheckCode);  
  4. }  

  1. private string desDecryptBase64(string encrypt, string strkey, string strCheckCode)  
  2. {  
  3.     DESCryptoServiceProvider des = new DESCryptoServiceProvider();  
  4.     byte[] key = Encoding.ASCII.GetBytes(strkey);  
  5.     byte[] iv = Encoding.ASCII.GetBytes(strCheckCode);  
  6.     des.Key = key;  
  7.     des.IV = iv;  
  8.   
  9.     byte[] dataByteArray = Convert.FromBase64String(encrypt);  
  10.     using (MemoryStream ms = new MemoryStream())  
  11.     {  
  12.         using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write))  
  13.         {  
  14.             cs.Write(dataByteArray, 0, dataByteArray.Length);  
  15.             cs.FlushFinalBlock();  
  16.             return Encoding.UTF8.GetString(ms.ToArray());  
  17.         }  
  18.     }  
  19. }  
第二種傳統字串方法,實作如下圖
  1. private void btnEncrypt_Click(object sender, EventArgs e)  
  2. {  
  3.     txtResult.Text = desEncrypt(txtSource.Text, strKey, strCheckCode);  
  4. }  

  1. private string desEncrypt(string source, string strkey, string strCheckCode)  
  2. {  
  3.     StringBuilder sb = new StringBuilder();  
  4.     DESCryptoServiceProvider des = new DESCryptoServiceProvider();  
  5.     byte[] key = Encoding.ASCII.GetBytes(strkey);  
  6.     byte[] iv = Encoding.ASCII.GetBytes(strCheckCode);  
  7.     byte[] dataByteArray = Encoding.UTF8.GetBytes(source);  
  8.   
  9.     des.Key = key;  
  10.     des.IV = iv;  
  11.     string encrypt = "";  
  12.     using (MemoryStream ms = new MemoryStream())  
  13.     using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))  
  14.     {  
  15.         cs.Write(dataByteArray, 0, dataByteArray.Length);  
  16.         cs.FlushFinalBlock();  
  17.         //輸出資料  
  18.         foreach (byte b in ms.ToArray())  
  19.         {  
  20.             sb.AppendFormat("{0:X2}", b);  
  21.         }  
  22.         encrypt = sb.ToString();  
  23.     }  
  24.     return encrypt;  
  25. }  
 接著再試著解密驗證看看
  1. private void btnDecrypt_Click(object sender, EventArgs e)  
  2. {  
  3.     txtResult.Text = desDecrypt(txtSource.Text, strKey, strCheckCode);  
  4. }  

  1. private string desDecrypt(string encrypt, string strkey, string strCheckCode)  
  2. {  
  3.     byte[] dataByteArray = new byte[encrypt.Length / 2];  
  4.     for (int x = 0; x < encrypt.Length / 2; x++)  
  5.     {  
  6.         int i = (Convert.ToInt32(encrypt.Substring(x * 2, 2), 16));  
  7.         dataByteArray[x] = (byte)i;  
  8.     }  
  9.   
  10.     DESCryptoServiceProvider des = new DESCryptoServiceProvider();  
  11.     byte[] key = Encoding.ASCII.GetBytes(strkey);  
  12.     byte[] iv = Encoding.ASCII.GetBytes(strCheckCode);  
  13.     des.Key = key;  
  14.     des.IV = iv;  
  15.   
  16.     using (MemoryStream ms = new MemoryStream())  
  17.     {  
  18.         using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write))  
  19.         {  
  20.             cs.Write(dataByteArray, 0, dataByteArray.Length);  
  21.             cs.FlushFinalBlock();  
  22.             return Encoding.UTF8.GetString(ms.ToArray());  
  23.         }  
  24.     }  
  25. }  
兩種方法
最終結果都正確
提供有興趣的人可以實作看看喔

沒有留言:

張貼留言