将密码存储在单独的表/数据库中并在单独的进程中管理它们是否很好?

信息安全 密码 哈希 数据库 建筑学
2021-08-21 22:07:33

我是系统架构和安全方面的新手,所以我只想检查这个计划是否有意义。我正在构建一个网络应用程序,我需要为每个用户存储一个密码。我已经阅读了大量有关散列算法、盐等的内容。我将使用 Argon2,因为它似乎是当前的推荐。我的问题涉及如何根据整体架构存储和检查哈希值。

由于使用 Argon2 的散列故意非常昂贵,因此我想在单独的模块/进程中创建一个服务,以便在需要时可以轻松地将其移动到一个或多个单独的机器上。即使它与主应用服务器位于同一台机器上,监控其 CPU 和内存使用情况以调整散列算法的成本因素也是微不足道的。

我的应用程序将向服务发送 HTTPS POST 请求以创建、更新、删除或验证密码。所有详细信息都将在请求正文中,包括纯文本密码。连接将被加密。响应将只是成功或失败的指示。

该服务将处理数据库操作、哈希密码以及比较哈希是否相等的逻辑。密码将存在于与用户不同的数据库中,因此即使攻击者转储了整个密码数据库,他们实际上仍然不知道任何人的密码,反之亦然。此外,如果我曾经为我的其他数据迁移到不同的存储解决方案,则需要进行的迁移更少,因为密码可以保持原样。

听起来不错?还是它以某种方式打开了更多我不知道的弱点?

2个回答

散列太慢意味着您需要使用更快的散列,而不是第二个过程。尝试调整 Argon2 上的参数或转移到 bcrypt(这仍然非常安全)。调整参数以使哈希值达到合理的时间(~0.2-0.4 秒),并将所有内容保持在一个进程中。

如果您愿意,您仍然可以将密码保存在第二个数据库中,以在主数据库的内容被盗时减少数据丢失,但我不确定是否需要这样做。传统观点认为,即使所有数据都被盗,bcrypt 也是安全的。现在这并不能保证,但除非你有 NSA 追随你,或者你存储的东西足以激励大部分比特币网络停止模仿并开始破解你的密码,否则我会非常满意一个合理的执行 bcrypt。

虽然这是一个安全问题,但我想让您了解另一个注意事项:

性能注意事项

在某些情况下,创建一个微 Web 服务来处理身份验证可能是一个好主意,这取决于用例。

但是,您可能要考虑建立许多 https 连接(对于许多请求)也是有代价的。在负载最小化方面(这似乎是一个问题)可能很有用,让这两个服务建立一个供多个连接使用的长寿命隧道。

关于安全考虑

  • 实际的、面向用户的 Web 服务将在此场景中充当 TLS 客户端。

    信任存储按预期工作(例如,仅信任密码服务的证书)并且密码服务的私钥以及 Web 服务的私钥保持私密,这一点极其重要。

    别的,

    • 该服务可能容易受到 MITM 攻击(尤其是在不同机器上运行时)
    • 攻击者可以直接与密码服务进行交互,可能会使用非常大的有效负载对其进行 DOS 攻击,或者能够使用间接侧信道定时攻击。
  • Web 服务和/或密码服务最好使用某种策略来确保减轻可能的定时攻击和 DOS。

此外,当然,增加的可扩展性、关注点的分离,尤其是网络分段(这些都是好的和重要的)是有代价的:实现逻辑可能会变得更加复杂,并且您可能会引入您不知道的细微问题。如果您不习惯,则尤其如此。

增加复杂性的一个例子可能是:在电子邮件更改时,谁处理经过验证的新电子邮件的实际提交以及如何处理,例如,谁有权更改跨数据库重复的数据?您想在数据库事务中启动网络 IO 吗?

至于散列函数

这里有一个关于安全地散列密码的问题,它有很好的答案。

考虑到您不需要使用前沿研究散列函数。其他的(PBKDF2、bcrypt 和 scrypt)同样适用于这个目的,你不必期望很快就会发现一个严重的问题,因为他们有时间经过仔细的同行评审。