6

我必须先说我知道在客户端应用程序中硬编码密码是不好的做法,原因有很多。还有其他问题涉及该问题。这个问题的范围更窄,并假设身份验证凭据必须驻留在客户端应用程序的代码中,原因是您无法控制的某些原因。

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

更新:

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

4

6 回答 6

6

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

首先,我会确保负责做出这个错误决定的管理人员完全意识到这从根本上来说是不可挽回的不安全1

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

(使用强算法加密密码并没有多大帮助,因为算法的选择和解密密钥都必须嵌入到您的代码中。确实,您可以梦想的任何方案都可以通过使用调试器设置断点在密码需要明文的地方。)

1 ...即使是 Jon Skeet 也无法确保它的安全。


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

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

于 2012-12-11T13:29:49.957 回答
1

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

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

我不知道这在你的情况下是否可行,但你应该朝着这个目标努力。

于 2012-12-11T12:50:51.270 回答
1

我想最不理想的解决方案是,如果您可以拥有基于挑战的身份验证协议,其中包含随机元素。

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

那么也可以是双向认证,即你端可以验证对方也使用相同的协议/算法,也有相同的密码。

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

Diffie-Helman 密钥交换是用于此类事情的一种广泛使用的协议,但如果您只想要默默无闻而不是真正的安全性,您总是可以推出自己的简单实现。好吧,如果一切都可以从字节码反编译和逆向工程,那么真正的安全显然是遥不可及的,但无论如何...... :)

于 2012-12-11T12:56:18.087 回答
1

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

于 2012-12-11T15:35:54.137 回答
0

我喜欢斯蒂芬的回答,但我会补充......

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

即使没有编译,任何有权访问的人都jar可以在调试模式下启动 java 程序并停止使用密码的程序并检查变量,这对于源代码来说是微不足道的,但仍然可以只使用 jar 和一些工具。

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

于 2012-12-11T18:15:41.790 回答
-1

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

于 2012-12-11T12:46:09.777 回答