感覺安全方面很重要啊.看到好文章,大家分享一下了.
某些時候,我們需要在記憶體中儲存一些非常敏感的資料,比如信用卡帳號密碼、軟體註冊碼等等。那麼危險隨之而來,使用一些進階軟體調試工具查看進程的記憶體資料,居心不良的人就會有機會拿到這些本該嚴格保密的資料。
Microsoft Windows 2000 SP4 以上版本的作業系統提供了用於資料保護的 API —— DPAPI,我們可以使用 .NET Framework 2.0 提供的相互關聯類型來保護我們的資料。
下面,我們使用一個簡單的例子來說明其使用方法。Personal 類的 CreditPassword 屬性用來類比儲存使用者信用卡密碼,對於下面這樣的例子危險可想而知。
public class Personal
{
private string creditPassword;
public string CreditPassword
{
get { return creditPassword; }
set { creditPassword = value; }
}
}
好了,我們用 DPAPI 改寫這個例子。.NET Framework 2.0 提供了 ProtectedMemory 和 ProtectedData 兩個靜態類來進行這個操作。使用前我們需要添加 System.Security.dll 的引用,預設的 System.Security.Cryptography 名字空間並不包含這兩個類。using System.Security.Cryptography;
public class Personal
{
private byte[] creditPassword;
public string MyProperty
{
get
{
ProtectedMemory.Unprotect(creditPassword, MemoryProtectionScope.SameProcess);
return Encoding.Unicode.GetString(creditPassword);
}
set
{
creditPassword = Encoding.Unicode.GetBytes(value);
ProtectedMemory.Protect(creditPassword, MemoryProtectionScope.SameProcess);
}
}
}
ProtectedMemory 提供了兩個靜態方法,Protected 用來加密資料,UnProtected 解密還原資料。在改寫的例子中我們使用 byte[] 來儲存加密後的信用卡密碼,而且使用 MemoryProtectionScope 參數指定只有當前進程才能解密,安全性自然高出很多。
我們另外寫一個例子,看看 MemoryProtected.Protect 加密後的資料是什麼樣子。using System.Security.Cryptography;
static void Main(string[] args)
{
byte[] data = Encoding.Unicode.GetBytes("Credit Card Password");
// ProtectedMemory.Protect 要求位元組數組長度必須是 16 的倍數,因此我們需要調整 data 長度。
if (data.Length % 16 > 0) Array.Resize(ref data, data.Length + (16 - (data.Length % 16)));
ProtectedMemory.Protect(data, MemoryProtectionScope.SameProcess);
Console.WriteLine(Encoding.Unicode.GetString(data));
ProtectedMemory.Unprotect(data, MemoryProtectionScope.SameProcess);
// 由於我們調整了 data 的長度,因此需要刪除字串尾部的空位元組。
Console.WriteLine(Encoding.Unicode.GetString(data).TrimEnd('/0'));
}
輸出:
??亭??氶?埠?剡??????錟????
Credit Card Password
加密後的資料由亂碼組成,且能正確被還原。(多次運行或不同的機器,加密結果有所不同。)
ProtectedData 同樣提供 Protect 和 UnProtect 兩個方法,但在使用上和 ProtectedMemory 還是有所差別的。
1. ProtectedData 的兩個方法都多了一個參數 optionalEntropy,這個 byte[] 類似我們平常加密時所使用的 key,從而提供更強的安全性。
2. ProtectedData 不會改寫要操作的位元組數組,而是棄置站台來儲存加密或解密結果。
3. DataProtectionScope 枚舉提供 CurrentUser、LocalMachine 兩種限制選擇,和 MemoryProtectionScope 不同。
基於這些差異,我們使用 ProtectedMemory 保護記憶體中的資料,而使用 ProtectedData 保護寫到硬碟等儲存空間上的資料。using System.Security.Cryptography;
static void Main(string[] args)
{
byte[] key = Encoding.Unicode.GetBytes("MyKey");
byte[] data = Encoding.Unicode.GetBytes("Credit Card Password");
byte[] encBytes = ProtectedData.Protect(data, key, DataProtectionScope.CurrentUser);
Console.WriteLine(Encoding.Unicode.GetString(encBytes));
byte[] orgBytes = ProtectedData.Unprotect(encBytes, key, DataProtectionScope.CurrentUser);
Console.WriteLine(Encoding.Unicode.GetString(orgBytes));
}