在 C 中从用户那里获得 *secure* 输入的最佳方式是啥?
Posted
技术标签:
【中文标题】在 C 中从用户那里获得 *secure* 输入的最佳方式是啥?【英文标题】:Which is the best way to get *secure* input from user in C?在 C 中从用户那里获得 *secure* 输入的最佳方式是什么? 【发布时间】:2018-02-03 02:10:17 【问题描述】:我正在开发一种安全密码管理器。它不会用于专业用途,而且我知道它不会像 KeePass 或其他任何东西那样安全。这只是为了我自己对如何分配安全内存、使用加密算法等的理解。
为此,我使用 libgcrypt 并使用 gcry_malloc_secure
分配内存。
我现在已经到了某种程度,我需要用户输入他的密码以进行加密/解密。
但正如我所见,任何控制台输入首先缓冲在stdin
(或argv[..]
)中,因此不在安全内存中。因此它可以“轻松”被攻击者读取。
在我的程序中发生的任何与安全相关的事情都在securemem中,希望更难阅读/窃取。
所以我的问题就像标题所述:
让用户输入数据最安全的方法是什么?
【问题讨论】:
C 中没有 no 方式,因此解决方案将取决于平台。也许看看pinentry source 可以提供一些想法。 也许这会有所帮助:Buffered and Unbuffered inputs in C. @FelixPalmen 你能解释一下为什么没有办法吗? (键盘记录器除外..)如果我将自己限制在 POSIX 上,会有解决方案吗? @KillPinguin 仅仅是因为 C 作为一种语言仅提供stdio
并且您可以禁用 stdio
流的缓冲,但无法控制操作系统正在做什么。当然有有平台特定的方式。我不确定 POSIX 是否指定了任何有用的东西,我不在那个话题中。只是认为pinentry
可能“做得对”,所以查看源可能帮助。
I see what you did, there.
【参考方案1】:
如果“安全”内存是指不会被分页到磁盘的内存,那么符合 POSIX 的 C 环境至少应该提供 mlock()。所以你可以创建一个不会被分页的缓冲区。但是您仍然必须找到一种将数据读入其中的方法,并且您可能必须在释放它之前将其归零,以避免敏感数据潜伏在进程空间中。
我想实现所需的基本方法是创建一个缓冲区,对其应用 mlock(),然后将输入的字符逐个字符读入该缓冲区。
但是,如果您使用 stdio.h 调用,您仍然会遇到自动进行的缓冲。在 Linux 上,您可以在终端级别关闭此缓冲,然后使用 ioctl() 调用逐个读取字符。像 ncurses 这样的库有自己的方式来做类似的事情。我认为在其他平台上也可以实现类似的效果,但我对它们的了解不够多,无法发表评论。
【讨论】:
老实说,我不确定安全内存到底是什么。这只是 ligcrypt 的一个选项......应该真的看看那个。我喜欢逐个字符读取输入的想法。如果我向标准输入缓冲区添加足够多的噪音,那可能会起作用。 通常“安全内存”是指不会被分页的内存。但是,有一些方法可以通过对内容进行加密来实现加密安全内存。我认为 libgcrypt 在前一种意义上使用该术语。这是 Linux 吗? 在 Linux 上,您可以(原则上)通过使用 tcsetattr() 删除 STDIN_FILENAME 上的 ICANON 属性来关闭缓冲。然后,您可以使用 FIONREAD ioctl() 调用逐个字符地读取。如果是密码,您可能还需要删除 ECHO 属性。所有这些东西都有很好的文档记录,但如果你找不到任何来源,我可以挖掘一些来源。唯一稍微不标准的部分是使用 mlock() 来防止您的数据缓冲区被分页交换。然而,我必须指出,很难绝对确定内核中没有缓冲任何内容。以上是关于在 C 中从用户那里获得 *secure* 输入的最佳方式是啥?的主要内容,如果未能解决你的问题,请参考以下文章
在用户在java中输入正确的输入之前,如何从用户那里获得输入?