因為今天又有朋友問我,從我舊的Blog貼過來的。就是.NET對加密技術支援的一個簡介,包含一些基本元素的介紹。
.NET提供很多對稱加密法的演算法, 它們不止能對文字加密. 但我這裡以DES對文字加密作為例子. 你可以在System.Security.Cryptography找到其他對稱演算法的實作. RijndaelManaged, DESCryptoServiceProvider, RC2CryptoServiceProvider and RtipleDESCryptoServiceProvider都是SymmetricAlgorithm類別的實作.
有兩個概念我們要知道. 我們需要兩個元素去實行加密和解密. 一個初始向量和金鑰. 你有可能會問初始向量有甚麼用途. 如果我們用一個金鑰去做加密. 密件將會是多個同一長度的片段所組成. 這樣可以對密件的每個片段對照找出模式,比較容易破解. 所以我們用一種類似遞回的方法對我們的資料加密. 由三個輸入去產生一個加密過的片段. 分別是對上一個已加密片段, 現時還沒加密的資料片段和金鑰. 因為我們在演算法開始時並沒有’上一個加密過的片段’, 這就是要用到初始向量的時候了.
另一個概念是, 不同的對稱加密法有不同的合法金鑰長度, 就是有一個合法的金鑰長度範圍. 我們稍後再處理這個問題.
加密如下 :
public static string EncryptToString(string PlainText, string key, string initialVector) { // Create a memory stream. MemoryStream ms = new MemoryStream(); // Create the algorithm provider DESCryptoServiceProvider l_CryptoProvider = new DESCryptoServiceProvider(); byte[] l_key = GetValidKeyFromString(key, l_CryptoProvider); byte[] l_initialVector = System.Text.Encoding.Unicode.GetBytes(initialVector); // Create a CryptoStream using the memory stream and the // CSP DES key. CryptoStream encStream = new CryptoStream(ms, l_CryptoProvider.CreateEncryptor(l_key, l_initialVector), CryptoStreamMode.Write); // Create a StreamWriter to write a string // to the stream. StreamWriter sw = new StreamWriter(encStream); // Write the plaintext to the stream. sw.WriteLine(PlainText); // Close the StreamWriter and CryptoStream. sw.Flush(); sw.Close(); encStream.Close(); // Get an array of bytes that represents // the memory stream. byte[] buffer = ms.ToArray(); // Close the memory stream. ms.Close(); // Return the encrypted byte array. // Convert to Base64 so that we can write it into text file return Convert.ToBase64String(buffer); }
解密如下 :
過程並不複雜, 看註解應該就能了解. 創建一個記憶體流, 包裝成密碼服務提供者, 對它做寫入/讀取.
還剩一件事, 靜態方法GetValidKeyFromString(key, l_CryptoProvider), 程式碼如下 :
我假設你給定的金鑰長度小於或等於預設合法金鑰長度. 如果你給的金鑰長度比較長, 那就直接用你的金鑰. 如果你的金鑰較短, 這返法就會把金鑰不斷重覆讓它增長到合法長度為止, 就好像”我是金鑰我是金鑰…”. KeySize屬性會告訴你預設合法金鑰長度. 你可以發現我用base64編碼把密件做包裝, 這不是必需的, 我這樣做只是以防我要把密件寫到文字儲存器, 例如應用程式組態.
public static byte[] GetValidKeyFromString(string keyString, SymmetricAlgorithm cryptoProvider) { // Get the string as Byte using Unicode since Unicode character is 8bit // and also .NET support Unicode by default byte[] l_keySeed = System.Text.Encoding.Unicode.GetBytes(keyString); int l_seedLength = l_keySeed.Length; int l_validKeySize = cryptoProvider.KeySize / 8; byte[] l_validKey = new byte[l_validKeySize]; for(int index = 0; index<l_validKeySize; index++) { l_validKey[index] = l_keySeed[index % l_seedLength]; } return l_validKey; }
public static string DecryptFromString(string CypherText, string key, string initialVector) { string val = string.Empty; if (!string.IsNullOrEmpty(CypherText)) { // Create a memory stream to the passed buffer. // Convert from base64 back to binary first byte[] l_CypherByte = Convert.FromBase64String(CypherText); MemoryStream ms = new MemoryStream(l_CypherByte); DESCryptoServiceProvider l_CryptoProvider = new DESCryptoServiceProvider(); byte[] l_key = GetValidKeyFromString(key, l_CryptoProvider); byte[] l_initialVector = System.Text.Encoding.Unicode.GetBytes(initialVector); // Create a CryptoStream using the memory stream and the // CSP DES key. CryptoStream encStream = new CryptoStream(ms, l_CryptoProvider.CreateDecryptor(l_key, l_initialVector), CryptoStreamMode.Read); // Create a StreamReader for reading the stream. StreamReader sr = new StreamReader(encStream); // Read the stream as a string. val = sr.ReadLine(); // Close the streams. sr.Close(); encStream.Close(); ms.Close(); } return val; }