• 首页
  • 狐文
  • 狐图
  • About
狐窝
OvO
  1. 首页
  2. 未分类
  3. 正文

Windows DPAPI 数据加密保护接口详解

2020年09月10日 276点热度 3人点赞 0条评论

2018-03 from--https://blog.csdn.net/xiaoqing_2014/article/details/79546957

1 什么是DPAPI

DPAPI是Windows系统级对数据进行加解密的一种接口,无需自实现加解密代码,微软已经提供了经过验证的高质量加解密算法,提供了用户态的接口,对密钥的推导,存储,数据加解密实现透明,并提供较高的安全保证。

DPAPI提供了两个用户态接口,`CryptProtectData`加密数据,`CryptUnprotectData`解密数据,加密后的数据由应用程序负责安全存储,应用无需解析加密后的数据格式。但是,加密后的数据存储需要一定的机制,因为该数据可以被其他任何进程用来解密,当然`CryptProtectData`也提供了用户输入额外`数据`来参与对用户数据进行加密的参数,但依然无法放于暴力破解。

总体来说,程序可以使用DPAPI来对自己敏感的数据进行加解密,也可持久化存储,程序或系统重启后可解密密文获取原文。如果应用程序,对此敏感数据只是暂存于内存,为了防止被黑客dump内存后进行破解,也对此数据无需进行持久化存储,微软还提供了加解密内存的接口`CryptProtectMemory`和`CryptUnprotectMemory`。加解密内存的接口,并可指定`Flag`对此内存加解密的声明周期做控制,详细见`Memory加密及优缺点`章节。

2 DPAPI的会话密钥推导

DPAPI使用的会话密钥由MasterKey和随机数的HASH推导产生,而MasterKey的保护由用户登录密码HASH,随机数,和迭代次数通过可靠的[PBKDF2](https://baike.baidu.com/item/PBKDF2)密钥推导算法生成。其中迭代次数可以修改, `MasterKeyIterationCount` 存储在 `HKEY_LOCAL_MACHINE\Software\Microsoft\Cryptography\Protect\Providers\GUID` 允许系统管理员增加此迭代计数的密钥中。但是,它不能减少到4000以下。

为了防止篡改MasterKey,它使用HMAC进行散列。DPAPI再次使用SHA-1作为HMAC和用户的密码来派生HMAC密钥。然后使用来自上面的密码派生加密密钥和Triple-DES来加密MasterKey和MasterKey的HMAC。salt和迭代计数都是非秘密值,因此与加密的MasterKey一起存储,但未加密。这允许DPAPI在给定用户密码的情况下轻松解密MasterKey。

如上图所示,会话密钥的推导使用了MasterKey,随机数,和可选的系统登录密码,用户密码推导生成。16字节的随机数,会以明文的形式存储于加密后的BLOB中,MasterKey是受推导的加密密钥保护。

3 DPAPI密钥备份恢复

恢复密钥是在用户选择从用户的控制面板创建密码重置磁盘(PRD)时生成的。首先,DPAPI生成一个2048位RSA公钥/私钥对,它是恢复密钥。然后使用公钥将当前密码加密并存储在用户的配置文件中,同时将私钥存储到PRD,PRD实际上可以是任何可移动媒体,然后从内存中移除。私钥只存储在PRD中,而其他任何地方都不存在,所以用户将PRD保存在安全的地方非常重要。

如果用户输入错误的密码,Windows会询问他们是否想要使用PRD并重置密码。如果他们选择,运行向导会提示输入新密码,并使用PRD上的私钥解密旧密码并进行更改。

 4 DPAPI接口调用

  • 对数据进行加密:

 

  1.     DATA_BLOB DataIn;
  2.     DATA_BLOB DataOut;
  3.     DATA_BLOB BlobKey;
  4.     DataIn.pbData = const_cast(cbDataIn); //明文数据
  5.     DataIn.cbData = nLen; //明文数据长度
  6.     if(key)
  7.     {
  8. BlobKey.pbData = const_cast(key); //可选用户密码
  9. BlobKey.cbData = lenKey; //可选用户密码长度
  10.     }
  11.     CRYPTPROTECT_PROMPTSTRUCT promp; //是否与用户交互输入可选的用户密码
  12.     promp.cbSize = sizeof(CRYPTPROTECT_PROMPTSTRUCT);
  13.     promp.szPrompt = L"测试加密";
  14.     promp.dwPromptFlags = CRYPTPROTECT_PROMPT_ON_PROTECT;
  15.     promp.hwndApp = NULL;
  16.     if(!CryptProtectData(&DataIn, L"敏感数据", key ? &BlobKey:NULL, NULL, &promp, 0, &DataOut))
  17.         return false;
  18.     *encLen = DataOut.cbData;            //返回密文数据长度
  19.     *encData = malloc(DataOut.cbData);
  20.     memcpy(*encData, DataOut.pbData, DataOut.cbData); //加密后数据
  21.     LocalFree(DataOut.pbData);
  • 对数据进行解密:

 

  1.    DATA_BLOB DataIn;
  2. DATA_BLOB DataOut;
  3. DATA_BLOB BlobKey;
  4. LPWSTR pDescrOut = NULL;
  5. if(key)
  6. {
  7. BlobKey.pbData = const_cast(key); //可选用户密码
  8. BlobKey.cbData = lenKey; //可选用户密码长度
  9. }
  10. DataIn.pbData = (BYTE *)const_cast<void *>(encData); //待解密数据
  11. CRYPTPROTECT_PROMPTSTRUCT promp; //是否与用户交互输入可选的用户密码
  12. promp.cbSize = sizeof(CRYPTPROTECT_PROMPTSTRUCT);
  13. DataIn.cbData = encLen; //待解密数据长度
  14. CRYPTPROTECT_PROMPTSTRUCT promp; //是否与用户交互输入可选的用户密码
  15. promp.cbSize = sizeof(CRYPTPROTECT_PROMPTSTRUCT);
  16. promp.szPrompt = L"测试解密";
  17. promp.dwPromptFlags = CRYPTPROTECT_PROMPT_ON_UNPROTECT;
  18. promp.hwndApp = NULL;
  19. if (!CryptUnprotectData(&DataIn, &pDescrOut, key ? &BlobKey:NULL, NULL, &promp, 0, &DataOut))
  20. return false;
  21. *nLen = DataOut.cbData;
  22. *cbDataIn = malloc(DataOut.cbData);
  23. memcpy(*cbDataIn, DataOut.pbData, DataOut.cbData); //解密后的数据明文
  24. LocalFree(DataOut.pbData);
  •  交互弹框提示

- 加密前提示设置加密等级

- 加密等级分类

- 加密等级设置为高时输入用户密码

- 解密时要求输入用户密码

- 输入错误的用户密码提示

5 Memory加密及优缺点

Memory加解密微软也提供了两个接口,CryptProtectMemory内存加密,CryptUnprotectMemory内存解密。一般用于即时加解密用户敏感的数据,如用户密码等。内存加解密用于防止他人在您的进程查看敏感信息,如黑客远程dump你的进程内存,分析和破解你的敏感数据。

通常,您使用CryptProtectMemory函数来加密您的进程正在运行时将要解密的敏感信息。请勿使用此功能保存稍后要解密的数据; 如果计算机重新启动,您将无法解密数据。要将加密数据保存到文件以便稍后解密,请使用CryptProtectData函数。

加解密提供了三种标志:

Flag 说明
CRYPTPROTECTMEMORY_SAME_PROCESS 只能在当前进程内加解密,进程重新运行会无法解密
CRYPTPROTECTMEMORY_CROSS_PROCESS 可以跨进行加解密,系统重启后失效
CRYPTPROTECTMEMORY_SAME_LOGON 使用相同的登录凭据来加密和解密不同进程中的内存,系统重启后失效

如果需要持存储密文数据,可选用DPAPI的接口。如果临时缓存下敏感数据,可选用对`Memory`加解密的接口。

还有一个致命的缺陷:最低系统版本要求vista及以上系统版本,所以win xp不支持该接口。

6 扩展DPAPI加密等级

  •  程序内置用户密码
  • 程序使用物理硬件信息作为用户密码
  • 结合PKI技术实现加密用户密码
  • 或者以上的组合

 

7 附录

  • 一个很好的DPAPI加解密工具
  • 微软参考资料
  • github 代码
标签: dpapi 加密 加解密
最后更新:2020年09月10日

OvO

狐狸

点赞
< 上一篇
下一篇 >
最新 热点 随机
最新 热点 随机
brave编译打包时dump_syms报错Couldn't locate EXE or DLL file 使用Windows Kits创建PE 及精简镜像 Windows精简部署相关简易内容 APC UPS SUA1000ICH 踩坑记 TrueNAS SCALE虚拟机无法 Ping主机 TrueNas Scale libvirt-sock RDMA RoCE相关资料 Linux系统修改网卡名(eth0-3) Linux系统打开SRIOV 构建android内核时DTC工具中的多个定义错误 Windows 来宾系统提示“安全删除硬件” 修改jar的三种方法(反编译jar) 如何在 Debian 10上安装和配置 VNC Openwrt内SR-IOV网卡桥接问题 Linux下编译android 时报错loadlocale.c:130 windows 查看文件夹被那个进程占用 MongoDB中的多表关联 mongodb 学习记录
selenium处理极验滑动验证码 office2016激活备份方法 Linux下查看SSD4K对齐EXT4分区开启Trim及验证的方法 Caddy文件存储位置 使用python,scrapy写(定制)爬虫的经验,资料,杂。 脑洞大开的自然语言验证码 使用OpenSsl自己CA根证书,二级根证书和颁发证书 IntelliJ IDEA 源值1.5已过时,将在未来所有版本中删除 隐藏可移动设备列表中不希望出现的硬件 oracle 12c创建可插拔数据库(PDB)与用户详解 如何查看你的VPS是什么虚拟化架构? 利用iptables防止ssh暴力破解和控制网速 ubuntu10.04等官方原版如何添加Back Track 5等其它ubuntu衍生版的源 PyCharm下打包py程序成exe linux下trash代替rm Spring mybatis 报错 jdbcUrl is required with driverClassName. 浅谈RAID和LVM Create htpasswd file for nginx (without apache)
标签聚合
密码 编译 文件 ssl 路由 e 网卡 下载 com https git linux docker http android chrome

COPYRIGHT © 2020 狐窝. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS