在Java代码中嵌入密码最安全的方法是什么?

我必须在这个问题前面说,我知道在客户端应用程序中对密码进行硬编码是不好的做法,原因有很多。 处理该问题还有其他问题。 此问题的范围较窄,并假设validation凭据必须驻留在客户端应用程序的代码上,原因可能是您无法控制的一些原因。

如果某些方法比其他方法更好(例如:JPasswordField将密码存储在char数组而不是String中),并且如果您必须在Java应用程序中对其进行硬编码,那么您可以采取哪些措施来使其更难被提取?

更新:

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

….如果您必须在Java应用程序中对其进行硬编码,您可以采取哪些措施来使其更难获取?

首先,我会确定管理层负责做出这个错误决定的人完全清楚这是从根本上和不可靠的不安全 1

然后我可能会想到一些以晦涩的方式组装密码的naff算法; 例如,通过构建两个字节数组并将它们XOR一起…并分发混淆的字节码。 您可以希望做的最好的事情是让技能有限的人难以对代码中的密码进行反向工程。

(使用强大的算法加密密码将无济于事,因为算法和解密密钥的选择都必须嵌入到您的代码中。实际上,任何您可以梦想的方案都可以通过使用调试器来设置密码需要明确的断点。)

1 ……甚至Jon Skeet都无法确保安全。


如果某些方法比其他方法更好(例如:JPasswordField将密码存储在char数组而不是String中)…

我只想指出,使用char数组在JPasswordField等中保存密码的正常原因是为了防止坏人从核心转储或交换文件中读取密码。 在这种情况下它不会真正有用,因为我们必须假设坏人有足够的控制权来将调试器连接到JVM并从char数组中捕获字节。

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

如果您需要在运行时提供密码,最佳实践(例如,Jez Humble的Continous Delivery一书中提倡的那样)是在部署/启动时提供密码。 这样,密码只能驻留在人们的脑海中而不是某个不安全的文件中。

我不知道你的情况是否可行,但你应该以此为目标。

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

这样,它不仅仅是密码,它也是使用密码生成正确响应的代码,需要进行逆向工程。

然后它也可以是双向身份validation,也就是说您可以validation对方是否也使用相同的协议/算法并且也具有相同的密码。

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

Diffie-Helman密钥交换是一种广泛使用的协议,但是如果你只想要默默无闻,而不是真正的安全性,你可以随时使用自己的简单实现。 好吧,如果一切都可以从字节码反编译和反向设计,那么真正的安全性显然无法实现,但无论如何…… 🙂

在客户端存储敏感数据非常不安全,特别是密码,因为.class文件可以很容易地反编译。 你有没有考虑过涉及一些非对称加密的东西? 像公钥/私钥对或类似的东西?

我喜欢斯蒂芬的答案,但我会补充……

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

即使没有编译,任何有权访问jar都可以在调试模式下启动java程序,并暂停使用密码的程序并检查变量,使用源代码进行微不足道的操作,但仍然可以使用jar和一些工具。

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

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