安全存储秘密的最佳合理方式

信息安全 密码 爪哇 贮存 保密 pbkdf2
2021-08-17 12:43:45

我正在开发一个需要存储和使用机密的软件。

例如,这些秘密可以是:

  • 连接数据库的密码
  • OAuth 2.0client_credentials授权的客户端密码。

我需要将这些密码存储在某个地方(最好是在某种配置文件中)并以合理的安全性保护它们。

合理的安全性意味着:没有基于重型硬件的解决方案,例如 HSM 或复杂的基础设施(PKI,...)。

该软件采用 Java 编写,它应该运行在 Java 可以运行的任何地方(尤其是 Windows、GNU/Linux、Solaris、AIX)。

它不能依赖操作系统或特定于发行版的工具,例如 GNOME 密钥库、KDE ​​钱包或任何这些工具,除非 Java 提供了处理它们的方法(但我对此表示怀疑)。

我想在配置软件时使用对称密码术来加密秘密,并在需要时在运行时解密它们。但我不知道如何处理加密密钥。

我找到了 4 个可能的解决方案:

  1. 使用PBKDF2 (SHA256-AES256-CBC) 或普通AES256-CBC与硬编码的加密密钥和可选的一些代码混淆(使用ProGuard
    • 有一个专门的 CWE:CWE-321 - Use of Hard-coded Cryptographic Key。所以我怀疑这是解决方案。
  2. PBKDF2 (SHA256-AES256-CBC) 或普通AES256-CBC与文件系统上文件中的密钥一起使用
    • 它在文件中公开了应该通过某种方式保护的密钥
      • 加密文件系统和/或
      • 强制 ACL
      • 还要别的吗?
  3. 使用 Java 密钥库
    • Java keystore需要密码才能解锁,那么Java keystore密码存放在哪里呢?如何保护它?蛇正在吃自己的尾巴……
    • 不知何故相当于2
  4. 使用白盒密码学
    • 它已经显示出一些弱点,或多或少等同于混淆。(在选项 1 中)。
    • 我不确定 WBC 的 Java 实现是否成熟。

我见过这个问题:在 Web 应用程序中存储用户名/密码的做法

所以我的问题是:保护我的秘密数据的“最佳”合理选择是什么?

我觉得2更好,毕竟它很简单,而且密钥保护将依赖于操作系统而不是软件本身,就像OpenSSH一样,但我并不完全相信。

编辑:

PBKDF2 可以替换为任何其他密码基密钥派生算法,例如 PKCS #12 v1 密钥派生算法。

奖金:

如果我要在PBKDF2 (SHA256-AES256-CBC) 或普通AES256-CBC之间进行选择,什么是最好的?

  • 据说 PBKDF2 可以很好地保护密码,因为它“慢”。它就是为此而设计的。
  • AES256-CBC 更简单(无需像 PBKDF2 中那样对密钥进行加盐/散列/迭代密钥)
2个回答

我假设您的威胁模型是攻击者通过某种类型的网络漏洞获取访问您的网络服务器上的文件的访问权限。如果不是,您应该质疑您提出的加密策略究竟在缓解什么。

如果是,类似于 2 的选项可能是最简单的。

我会使用 AES128-CBC 作为密钥加密密钥的算法。使用 CSPRNG 生成的 128 位加密密钥,无需使用密钥拉伸算法。仅当您尝试保护用户提供的弱密码时,才需要使用 PBKDF2 等算法。如果您可以自己设置密钥,则只需确保它们是所需的位强度。

AES256 速度较慢,并且与 AES128 相比没有额外的安全性。

确保您的配置文件和密钥文件被访问控制列表锁定。

密钥文件:

<128 bit random key>

只能由自定义服务帐户读取。

配置文件:

Passwords to systems, encrypted by the key in the Key file.

只能由 Web 服务器标识读取。


确保您的 Web 服务器无法提供这些文件(例如,example.com/config.txt无法使用)。这应该工作的方式是您有一个运行进程的服务帐户。Web 服务调用此过程并要求服务为其解密配置文件密码。该服务验证只有 Web 服务器进程可以调用它。

这将保护您的机密免受系统或服务器中的任何 LFI 攻击,因为 Web 服务器用户上下文中的攻击者无权读取密钥文件或解密配置文件中的任何凭据。

它不能防止物理访问、另一个管理员级别帐户对系统的逻辑访问或任何允许调用进程的漏洞。它基本上只会防止通过网络身份(网站本身运行的用户)直接读取配置文件的文件。如果这不是一个问题,那么根本不需要加密秘密 - 它真正保护的唯一事情是可能看到配置文件的各方的随意观察。

如果您使用 Java,您不应该使用 Java KeyStore 吗?

https://docs.oracle.com/javase/7/docs/api/java/security/KeyStore.html

此类表示加密密钥和证书的存储设施。

KeyStore 管理不同类型的条目。每种类型的条目都实现了 KeyStore.Entry 接口。提供了三个基本的 KeyStore.Entry 实现:

KeyStore.PrivateKeyEntry 这种类型的条目包含一个加密的 PrivateKey,它可以选择以受保护的格式存储,以防止未经授权的访问。它还附带相应公钥的证书链。

给定实体使用私钥和证书链进行自我认证。此认证的应用程序包括签署 JAR 文件作为发布和/或许可软件的一部分的软件分发组织。

KeyStore.SecretKeyEntry 这种类型的条目包含一个加密的 SecretKey,它可以选择以受保护的格式存储,以防止未经授权的访问。

KeyStore.TrustedCertificateEntry 这种类型的条目包含属于另一方的单个公钥证书。之所以称为可信证书,是因为密钥库所有者相信证书中的公钥确实属于证书的主体(所有者)所标识的身份。

这种类型的条目可用于验证其他方。