c++ - 读取密码后覆盖 std::cin 读取缓冲区
问题描述
从 std::cin 读取密码后
std::cout << "Password: ";
SecureString pw{}; // secure string, wipes automatically on destruction
SetConsoleEcho(false); // hide input in terminal
std::getline(std::cin, pw); // input the password
SetConsoleEcho(true); // switch echo back on
密码一直存储在 cin(堆内存)的读取缓冲区中,直到它被新输入覆盖,并且可以很容易地被 Process Hacker 等工具嗅探,或者在内存转储的情况下被写入磁盘。
有谁知道 std::cin.rdbuf() 如何被清除/覆盖,理想情况下是跨平台的?或者有没有办法避免首先使用缓冲区?
上面的代码使用 SecureString,它是使用 Crypto++ 的 AllocatorWithCleanup 实现的,它在销毁时擦除内存。SetConsoleEcho 打开/关闭控制台回显,以避免在屏幕上看到纯文本密码。
我意识到这个问题与这个问题非常相似,但已经有 10 多年了,而公认的答案实际上并没有回答这个问题。
解决方案
链接的帖子包含您需要的所有答案,不幸的是,没有一种方法可以安全地读取然后清除密码,密码被泄露的风险为 0。看
即使您立即在缓冲区上乱涂乱画,密码仍有可能写入磁盘。系统 i/o 缓冲区可能被分页到磁盘,std::cin 所在的工作内存也可能被分页到磁盘。我曾经开发过能够准确嗅出这些条件的取证软件。
此外,如果恶意行为者可以访问 PC,则可以使用键盘记录器来提取密码。
推荐阅读
- php - 可接受的子类的最大数量
- cpu-usage - 使用在线预测扩展 Google Cloud ML Engine。如何衡量节点利用率?
- java - SQLServerException: "[...] The index 1 is out of range [...]" when using NamedParameterJdbcTemplate
- c# - XamarinForms(Android)- InvalidOperationException:此操作仅对泛型类型有效。在 System.RuntimeType.GetGenericTypeDefinition()
- javascript - 如何在这样的嵌套数据中查找重复值
- unity3d - 如何知道旋转方向
- google-cloud-platform - 使用 CA 证书对设备公钥进行数字签名
- continuous-integration - 根据提交消息跳过 travis 中的脚本
- mysql - 用于汇总员工每周工作时间的 SQL 查询
- javascript - 在 javascript 中仅向数组的一个对象添加属性可以吗?