因為今天又有朋友問我,從我舊的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; }