存储未散列密码的理想方式

信息安全 加密 密码
2021-09-03 23:49:37

我正在与一个明显不了解安全性的第 3 方供应商打交道 - 要从我的后端访问他们的 API,我必须为每批请求提供第 3 方服务的最终用户 ID/用户/密码。

我正在与他们斗争,至少要实现某种基于可撤销令牌的身份验证,但与此同时,我必须处理这个问题(至少他们使用 HTTPS ......嘘)。

我必须定期进行身份验证以同步数据,并且必须在没有最终用户干预的情况下进行同步,因此这基本上意味着 BE 必须以可逆格式存储凭据。我还不够天真以明文形式存储它,但即使我在数据库中加密它,密钥也不会离锁很远,可以这么说。

如果他们没有存储大量机密数据,我就不会那么担心,但这绝对是值得保护的数据。有小费吗?

笔记:

  • 密码将存储在分布式数据库中。数据库本身是相当安全的。泄露的唯一真正机会是开发人员直接访问数据的凭据之一泄漏,或者是严重的编程事故。
  • 供应商的 API 不允许以编程方式更改密码,因此不能选择轮换密码。

对后端源代码的访问可能会被锁得很紧。将私钥存储在源中并收工是否合理?

2个回答

您真正希望的最好的方法是使用本地操作系统提供的任何功能来存储“秘密”。这意味着Windows上的DPAPI 、MacOS X 上的Keychain ......使用它来存储用户密码或包含用户密码的加密文件的一些解密密钥。操作系统级别的功能可能比您在应用程序级别可以更直接地访问硬件,因此,提供可能更强(不那么弱)的攻击者保护。此外,您不能因为使用了“操作系统推荐”的方法来存储机密而受到指责。

如果客户端计算机完全被盗,您仍然必须假设攻击者能够恢复用户密码。可能的缓解措施包括在客户端计算机上使用自动锁定功能以及硬盘加密(但这超出了您作为应用程序编写者的能力范围,并且人类用户可能不喜欢这个想法)。自动锁定意味着攻击者很难(不是不可能,但很难)在机器仍在运行的情况下搞乱它,而硬盘加密意味着重新启动机器将攻击者永久锁定在存储的秘密之外(磁盘加密每次机器启动时都必须输入密码)。

这在处理第三方 API 时并非闻所未闻。即使它们为您提供了“令牌”而不是密码,这些令牌也可以有效地让您访问该帐户(尽管在许多情况下它们在某些方面受到限制),因此需要小心保护它们。我知道的解决方案:

  1. 将用户名/密码存储在源代码中。由于这很容易,人们一直都这样做。但是,这让我感到紧张:理想情况下,您的代码处于源代码控制中,因此任何有权访问该代码的人都将拥有凭据。

  2. 将其存储在配置文件中(理想情况下具有有限的权限,因此未经身份验证的用户无法读取等)。我个人觉得这比#1 稍微好一点,因为理想情况下应该只有很少的副本。

  3. 将其存储在 RAM 中,并在启动或需要时从用户或通过网络获取密码。这可能是最安全的,但要么给用户带来不便,要么需要“加密凭据”服务。

我认为对于大多数应用程序,配置文件解决方案(#2)是合理的,假设您为该帐户生成一个不会在其他任何地方重用的随机密码,并且系统本身是相当安全的。对于真正重要的事情,您可能希望沿着仅将凭据存储在内存中的路径。

我最近使用这种方法为服务器提供了数据库中关键数据的加密密钥。这意味着如果服务器重新启动,有人必须手动输入密码,但这也意味着如果有人带着磁盘离开,他们就不会得到数据。