我该如何在Java中安全地存储加密密钥?

22

我有一个Java属性对象,其中包含Web服务的身份验证信息。 我需要加密这些数据,但我不知道在哪里存储加密密钥才能保持安全。

在加密这些数据和以安全方式检索它方面,有什么最佳实践吗?

使用密钥库是否有任何优势?

ws_user=username
ws_password=password
ws_url=https://www.whatever.com/myservice

似乎如果我的应用程序需要访问密钥,就没有办法“保护”它。如果我将其存储在密钥库中,它会更加隐晦,但似乎并不更安全。希望我是错的 :) - ScArcher2
这听起来像是一个引导问题。在某个链条的某个点上,您必须拥有一个密钥才能解密某些内容。即使您使用密钥库,您也需要该密钥库的密码。难道您不能更改身份验证方案吗? 此外,如果您在http://security.stackexchange.com/上提问,您可能会得到一些非常专业的回答。 - mcfinnigan
@mcfinnigan,这就是我想的。我只是想看看是否有绕过这个问题的方法。 - ScArcher2
你要么将加密密钥存储在某个地方(或将其嵌入代码中),要么就要相信存储设备是安全的。这就像先有鸡还是先有蛋的问题。 - David R Tribble
有人想把它作为答案,我会接受的吗? - ScArcher2
1
安全防护针对谁?无法防范客户端计算机的所有者。 - CodesInChaos
4个回答

11

你的问题很常见。在Linux中,用户密码存储在一个明文文件中。虽然只有密码哈希值被存储,但如果攻击者获得了访问该文件的权限,他不需要花费太多时间就可以使用离线字典攻击来发现一些密码。在这种情况下,操作系统依赖文件权限来拒绝未授权用户的访问。在你的情况下,也没有太大差别。你必须正确配置密码文件的权限,并确保服务器的物理安全。


我遇到了一个客户的安全策略要求在配置文件中加密用户名/密码的情况。虽然看起来有些荒谬,但我想在这里进行确认是否有所遗漏。 - ScArcher2
可能对Linux来说还不错,但在Windows上呢?很不幸,仍然普遍使用管理员权限进行工作。UAC已经在改善这种情况,但大多数Windows用户仍然没有意识到接受UAC权限提升请求的影响。 - Denis Itskovich

7

关键问题在于某处需要以未加密的形式保留“链的根”密码。这可以是受操作系统保护的本地文件、远程文件、源代码中的硬编码等。

唯一的解决方法是要求人类在应用程序启动时键入初始密码,但对于需要自动启动的应用程序来说显然不可能。


问题已关闭,但似乎仍在获得一些点击量,因此我想提及这个OWASP项目https://owasp.org/www-project-sidekek/。 "SideKEK提供了一种廉价的方式来保护加密主密钥(密钥加密密钥,KEK),以一种抵御一些最常见的远程文件外泄攻击的方式。" - dbreaux

5
这是一个鸡生蛋或蛋生鸡的问题。然后,您需要找到在哪里存储密钥库密码等内容......
根据您的安全要求和需求,您可以使用对称加密加密数据,并通过客户端证书身份验证从远程服务器(您的服务器)检索密码。
或者,您可以使用对称加密加密数据,并在jar中硬编码密码,这不安全但需要一些努力才能找到它,您可以委派文件系统权限来决定谁可以访问您的文件。

1

我曾经成功地使用JasyptStringEncrytor来加密属性文件中的敏感信息,以及一些内部过程来生成盐并检索密码。由于您正在使用Web服务,因此您可以使用Jasypt的Web PBE Configuration在部署时手动输入密码,甚至可以自己开发类似的解决方案。


嗨,丹,你用过Web PBE配置吗?我认为它可以解决鸡蛋问题(始终需要一个主密钥来加密文本)。它该如何设置?我有点困惑。谢谢帮忙!V. - Viktor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接