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