使用DPAPI进行数据加密






3.73/5 (6投票s)
数据保护API的包装类。
Windows 数据保护
DPAPI - Data Protection Application Programming Interface;很可能是 Win32 中提供的最小 API。它只包含两个函数。
自 Windows 2000 起,Microsoft 就引入了 DPAPI。直到 Windows XP 发布,它才广为人知或得到充分文档说明。
DPAPI 是一个精心设计的机制,允许任何应用程序为其数据进行简单而强大的加密。它具有良好的恢复方法——以防密码丢失,完全支持企业或家庭使用,并且基于 Win32 下的 Cryptographic Services。
那么,它实际上做什么呢?很简单——它加密或解密一个数据块。
而且它在不要求太多设置、加密密钥、算法和其他“魔法”的情况下完成。听起来是保护敏感数据的理想功能?绝对是。虽然有一些您可以设置的选项,但即使没有它们也可以运行。
以下是一些亮点
- 用户绑定加密(使用用户凭据)
- 机器绑定加密(使用机器凭据)
- 应用程序提供的密码短语
- 可选的用户提供的密码
- 透明模式(完全没有用户界面)
- 可选的安全审计
- 基于标准——PKCS#5v2、RFC-2404、RSA 等。
MSDN 包含一篇非常精彩的 文章,解释了 DPAPI 的内部工作原理,如果您热衷于安全,绝对值得一读。
虽然 DPAPI 通常不难使用,但它有一些陷阱,您可以通过 CProtectedData
类来避免这些陷阱。
该类在需要时执行所有必要的转换(DPAPI 只接受 UNICODE 字符串),并处理数据结构的填充、内存的分配/释放等。但归根结底,它只是一个包装类。
它提供了多种重载函数来执行加密,另有函数用于解密。会对参数进行健全性检查。
用户界面
正如您在图片中看到的,CryptoAPI
提供了一些带有信息和选项的对话框给用户。它允许用户修改加密强度、选择自定义密码并查看有关要加密的数据的信息。
重要的是要记住,当用户被允许选择密码时,他们很可能会忘记它。在这种情况下,无法找回丢失的密码,数据也无法恢复。
启用 UI 时的主要对话框。
“设置安全级别...”对话框。
切换到高安全性模式将启用密码。如果您不提供描述,用户可以自己输入描述。
“详细信息...”对话框。
如何使用?
创建 CProtectedData
的实例,调用其 SetData()
成员函数,根据需要设置一些选项,最后调用 ProtectData()
或 UnprotectData()
函数之一。两者都返回一个指向 DATA_BLOB
结构的指针。DATA_BLOB
结构包含结果数据的大小和指向数据的指针。如果 cbData
成员为 0,则表示加密/解密失败,您可以调用 ::GetLastError()
来检索原因。
请注意,当您启用用户界面时,这些函数可能会失败,因为用户可以在正常情况下取消操作,而函数本应成功。
CProtectedData pd; pd.SetData(pPlainData, dwPlainDataSize); const DATA_BLOB* pData = pd.ProtectData(); if(pData->cbData) // well, use the data in pData->pbData
为了方便起见,有两个派生类 CUserProtectedData
和 CMachineProtectedData
。前者与 CProtectedData
类相同,而后者类只是设置相应的选项以使用机器凭据进行加密。它们仅用于代码整洁。
DPAPI 使用应用程序提供的可选熵数据。如果您提供熵数据,简单地说,它将被视为密码的一部分并包含在密钥生成中。换句话说,它提高了安全性。不带熵数据加密的数据也可以被任何其他应用程序解密。
为了避免内存泄漏,还有最后一件事需要您注意:当您通过向 UnprotectData()
提供一个指向 LPTSTR
变量的指针来检索加密数据中的描述字符串时,它会将描述放入该变量,并且您必须在不再需要时调用 ::LocalFree()
。
示例应用
示例应用程序展示了如何使用所有可用的选项,并执行多次完整的加密/解密周期,包含或不包含用户干预。无论如何,它不会将加密数据保存到磁盘。
兼容性
所有类都完全支持 MBCS/Unicode。示例包含了所有配置。在 VC7 下编写、编译和测试,但应也能在 VC6 及更早版本下编译。头文件会自动添加与 crypt32.lib 的链接。请记住,您需要 Windows 2000 或 Windows XP 才能使用 DPAPI。