保护内存中的敏感数据

感觉安全方面很重要啊.看到好文章,大家分享一下了.

某些时候,我们需要在内存中保存一些非常敏感的数据,比如信用卡账号密码、软件注册码等等。那么危险随之而来,使用一些高级软件调试工具查看进程的内存数据,居心不良的人就会有机会拿到这些本该严格保密的数据。

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));
}

你可能感兴趣的:(windows,.net,Security,Microsoft)