关于身份验证:在Java代码中嵌入密码最安全的方法是什么?

What's the most secure way to embed a password inside Java code?

本问题已经有最佳答案,请猛点这里访问。

我必须在这个问题的开头说,我知道在客户机应用程序中硬编码密码是不好的做法,原因很多。关于这个问题还有其他问题。这个问题的范围更窄,并且假设身份验证凭证必须驻留在客户机应用程序的代码上,这是因为一些您无法控制的原因。

如果某些方法比其他方法更好(例如:jPaseWordField将密码存储在char数组中而不是字符串),并且如果您必须在Java应用程序中硬编码它,您可以采取什么措施来使其更难获取?

更新:

应用程序的一个实例运行在远程PC上,最终用户在该PC上拥有管理权限。凭证用于访问同一网络中的数据库,因此实际密码已经预先确定,必须在实际代码中手动输入。


.... if you had to hard code it in the Java application, what measures could you take to make it harder to be fetched?

首先,我要确保负责做出这一错误决策的管理层充分意识到这是根本的、不可挽回的不安全因素1。

然后我可能会想出一些NAFF算法,它以一种模糊的方式组装密码;例如,通过构建两个字节数组并将它们异或化在一起…分发模糊的字节码。您希望做的最好的事情就是让那些技能有限的人很难从您的代码中逆向工程密码。

(用强算法加密密码没有多大帮助,因为算法的选择和解密密钥都必须嵌入到代码中。实际上,任何您梦寐以求的方案都可以通过使用调试器在密码需要清除的地方设置一个断点而失败。)

1…即使是乔恩·斯基特也不能保证安全。

If some ways are better than others (for instance: JPasswordField stores the password in a char array instead of a String) ...

我只想指出,使用char数组在jpasswordfield等文件中保存密码的正常理由是防止坏人从核心转储或交换文件中读取密码。在这种情况下,它不会真正有帮助,因为我们必须假设您应该担心的坏人是具有系统管理访问权限的Simeone。他或她将有足够的控制权将调试程序附加到JVM并从char数组中捕获字节。


在客户端存储敏感数据(尤其是密码)是非常不安全的,因为.class文件可以很容易地进行反编译。你有没有想过让一些非对称加密的东西参与进来?像公钥/私钥对之类的?


我想最不理想的解决方案是,如果您可以使用随机元素的基于挑战的认证协议。

这样一来,不仅是密码,还包括使用密码生成正确响应的代码,这些响应需要进行反向工程。

然后它也可以是双向认证,也就是说,您的终端可以验证另一方是否也使用相同的协议/算法,以及是否有相同的密码。

最重要的是,密码永远不会通过网络发送,因此无法被嗅探。

Diffie-Helman密钥交换是一种广泛使用的协议,但如果您只希望模糊性,而不是真正的安全性,则可以随时滚动自己的简单实现。如果一切都能从字节码中进行反编译和逆向工程,那么真正的安全显然是不可能实现的,但是无论如何……:)


作为一般准则,您不应该存储密码(当然)。

如果您需要在运行时提供可用的密码,那么最佳实践(如Jez Humble在Continous Delivery Book中所提倡的)是在部署/启动时提供密码。这样,密码只能存在于人们的大脑中,而不是某个不安全的文件中。

我不知道在你的情况下这是否可行,但你应该瞄准这个目标。


我喜欢斯蒂芬的回答,但我想补充一下…

源代码的安全性也很重要。无论您使用什么方法来混淆密码,任何有权访问源代码的人都可以轻松地放置System.out.println(password)并捕获使用它的密码,或者在调试中运行代码并停止代码以检查变量。

即使没有编译,任何访问EDCOX1(1)的人都可以在调试模式下启动Java程序,并停止使用密码的程序,并检查源代码中的变量,虽然只是JAR和一些工具,但仍然是可行的。

您可以考虑让程序在需要时(通过Web服务调用或其他方式)从安全服务器获取密码,并让该服务器使用防火墙仅允许某些IP访问它(如果客户端计算机的IP已知)。它仍然不安全,但至少是一些东西。


您可以散列密码,甚至可以根据需要对其进行加密。看看这篇文章,它可能会有用。Java-从配置文件加密/解密用户名和密码