.NET环境下的DPAPI加密编程

Windows的本地加密保护机制提供了简单的调用接口,密钥的生成、保护等事项一概由系统来处理,其编程接口称为DPAPI。这一加密保护机制的边界是用户登录帐户或者本地计算机系统,使用操作系统设定的加密处理过程保护数据和解密还原数据,用户无需关心密钥的来源和管理。使用 DPAPI加密本地敏感信息可以使应用程序免于处理生成和存储加密密钥这一难题。

在保护边界之外,DPAPI加密的保护的机制与强度与EFS类似。较EFS的差异是,同一用户帐户或者计算机保护范围之内,还可以使用可选乱数建立更细粒度的加密分割边界。持有与加密时相同安全令牌的进程,使用相同的可选乱数,都能够访问数据。本地计算机系统范围内加密的数据,只有系统启动后,本地运行的进程能够解密数据。这能够防止远程进程获得本地敏感数据,也能防止以本地多启动方式启动到其他操作系统实例,直接从硬盘获取所保护的数据。

可选乱数不会是一个强的保护,渗入本地计算机的恶意代码能够扫描文件获得存储的保护字,也可以通过键盘钩子截获口令派生的保护字。本地计算机范围保护的数据能够被所有能够在本机上运行的程序打开,攻击者如果能够获得计算机的物理控制,可以通过修改注册表、未加密文件等方式强行插入开机启动过程,也有获取这些加密数据的机会。所以,以谨慎的使用方式,保持计算机不被恶意代码侵袭仍然是实施有效加密的必要条件。

面对其设计的安全场景,DPAPI可以认为是一种强保护机制。Windows采用了精心设计的密钥管理机制保护所加密的数据。

.NET数据保护类是DPAPI的托管封装。由于这是操作系统提供的服务,应用程序无需添加额外的库。.NET  DPAPI有两个类,它们是ProtectedData类 和ProtectedMemory类,分别用于一般数据保护和内存区保护。

ProtectedData 类对字节数组进行加密。Windows 2000、XP 之后的系统中具有该功能。加密方法是调用静态 Protect函数,传递明文和可选乱数。解密方法是调用静态 Unprotect 方法,传递密文和加密时设定的可选乱数。应用程序可以指定加密的数据只能由同一用户帐户解密,或者指定由本地计算机上的任何帐户解密。这个范围由一个DataProtectionScope 枚举类型的参数指定,具体说明如下:

CurrentUser: 受保护的数据与当前用户关联。只有在当前用户上下文中运行的线程才可以取消数据保护。

LocalMachine :受保护的数据与计算机上下文关联。计算机中运行的任何进程都可以取消数据保护。此枚举值通常用于服务器(不受信任的用户无法访问服务器)上运行的服务器特定应用程序。

数据加密保护的代码示例:

ProtectedData.Protect( data, s_aditionalEntropy, DataProtectionScope.CurrentUser );

数据解密去保护的代码示例:

ProtectedData.Unprotect( data, s_aditionalEntropy, DataProtectionScope.CurrentUser );

ProtectedMemory是Vista以后引入的更高级一些的本地加密保护功能。它能够建立进程之间内存的加密隔离,这能够防止攻击者通过访问虚拟内存交换文件等内存搜索机制获取口令等敏感信息。使用 ProtectedMemory 类对内存中字节数组进行加密。这一加密过程会在内存中用密文代替明文,结果是即使搜索内存,都无法找到明文。ProtectedMemory加密的内存数据如果保存在硬盘的话,在计算机重启之后是不可以加密的。可以指定由当前进程加密的内存只能由当前进程解密、可以由所有进程解密,或者可以从相同的用户上下文解密,这一范围由MemoryProtectionScope 枚举类型的参数指定。 具体如下:

SameProcess:  只有与加密代码相同的进程中运行的代码才能解密。

CrossProcess: 任何进程中的任何代码均可使用 UnProtect 方法解密。

SameLogon: 只有与加密时相同的用户上下文中运行的代码才能解密。

内存加密保护的代码示例:

ProtectedMemory.Protect( secret, MemoryProtectionScope.SameLogon );

内存解密去保护的代码示例:

ProtectedMemory.Unprotect( secret, MemoryProtectionScope.SameLogon );
原文地址:https://www.cnblogs.com/kodefun/p/4875960.html