在应用程序二进制文件中存储私有非对称密钥?

信息安全 应用安全 加密 密钥管理 二进制代码
2021-09-03 15:30:19

我想给一个守护进程风格的进程(即没有用户交互)访问一个共享的密钥,这样它就可以访问一个共享的、加密的数据文件。访问相同加密数据的用户应用程序将共享密钥存储在用户的操作系统钥匙串中(例如 OS X 钥匙串或 Gnome 钥匙圈等)。操作系统钥匙串反过来用用户的登录(或其他用户特定的)密码保护密钥。

此处的加密用于在数据在服务器和客户端之间传输公共网络时保护数据。有问题的数据是来自科学实验的原始数据。大多数是无价值的(即不太可能吸引攻击者推测性地破坏加密并浏览数据),但其中一些可能非常有价值,用户希望将其详细信息保密,直到他们选择公开共享(即保护它来自网络上的临时观察者)。如果没有科学分析,数据的价值很难确定,因此观察用户在传输未加密线路时的活动(包括查询)将为观察者提供一些关于数据价值的线索。

守护进程是系统的查询服务器。它从共享数据中读取,处理查询,并将结果集的标识符返回给客户端,然后客户端从共享存储中提取标识的数据。

我们允许将加密数据同步到用户的本地工作站/笔记本电脑,因此磁盘上的数据加密对于坚定的攻击者至多是一种滋扰。我们允许用户在本地运行查询服务器(仍然由 init.d/launchd 启动),所以我想尽我所能保护与守护进程一起存储的密钥。主要风险是确定的恶意用户能够从其系统上的守护程序中发现密钥。泄露该密钥将要求我们更改密钥、更新所有用户的密钥,然后重新加密数据库。

为守护进程存储共享密钥的最佳方式是什么?我可以将密钥放在磁盘上并加密磁盘上的文件,但是守护进程必须拥有解密该文件的密钥。这似乎等同于仅拥有原始加密数据的共享密钥。我天真的方法是将密钥存储在应用程序的二进制文件中,但我无法想象这是最好的选择。有什么建议吗?

4个回答

这很快就变成了一个“乌龟一路下跌”的问题。您只需要决定在什么时候停止加密并依赖另一种方法。我认为目标应该是阻止临时用户而不是坚定的黑客轻松获取受保护的数据。

我在需要存储数据库密码和 SSL 证书密码的 Web 应用程序中使用了类似的方法。我最终做的是使用不同的主密码在应用程序的配置文件中加密这些密码。主密码存储为应用程序启动脚本设置的环境变量。由于主密码仅在启动脚本中设置,因此很容易让单个用户访问该脚本以及使用标准 UNIX 文件权限运行它的能力。

我的想法是,否则要访问此脚本,您需要已经是 root,此时,这并不重要。如果您不能信任 root(或服务器已被黑客入侵),您可能还有其他问题。

此外,这里的默默无闻也有一点安全性,因为它的工作原理的所有细节都没有刻意记录得很好。您将不得不回溯启动脚本的工作原理,然后弄清楚使用了哪种算法,salt + plantext 的格式等等。如果您想获得数据库密码并做到这一点,我想您可能已经有了直接闯入数据库服务器。

像往常一样,最好的起点是问自己一些问题:你的威胁模型是什么?你想保护什么?你想保护它免受谁的侵害?你为什么首先使用加密货币?这些都不是从问题中清楚的。(加密不是神奇的精灵尘埃。)如果没有这些问题的答案,我们无法为您提供解决方案:正确的解决方案将取决于您想要实现的目标。

一般来说,这个问题不会有很好的解决方案。如果您希望能够在没有用户参与的情况下启动系统,则私钥将以明文形式存在于磁盘上的某个位置(或以明文形式等效)。正如其他人所建议的那样,您将很快击中“一路乌龟”。

您可以采取的一个步骤是确保私钥受到文件系统访问控制的保护:例如,root 可以读取但普通用户不能读取。

脚注:有一些复杂的方法,但它们可能不适合您的低成本环境。(1) 一种更安全的方法是将私钥存储在连接到服务器的硬件安全模块中。如果服务器受到攻击,软件就无法窃取私钥(但它仍然可以指示硬件安全模块对任意消息进行签名/解密)。(2) 更复杂的方法是使用 TPM,并将私钥锁定到特定软件。不幸的是,当前的操作系统并没有对此提供良好的支持,因此作为系统管理员来做自己将是非常具有挑战性的:它需要大量的开发人员支持。

守护进程的帐户是否没有可用的钥匙串?

为了完整起见,我们选择的解决方案是@SteveSyfuhs 和@AngerClown 答案的组合。在 OS X 上,我们使用系统钥匙串 ( /Library/Keychains/System.keychain)。在 Linux 上,我们将加密密钥存储在权限位为 400 的文件中(即仅所有者只读),由 root 拥有。