在 Java 代码中嵌入密码的最安全方法是啥? [复制]
Posted
技术标签:
【中文标题】在 Java 代码中嵌入密码的最安全方法是啥? [复制]【英文标题】:What's the most secure way to embed a password inside Java code? [duplicate]在 Java 代码中嵌入密码的最安全方法是什么? [复制] 【发布时间】:2012-11-29 00:41:12 【问题描述】:我必须先说我知道在客户端应用程序中硬编码密码是不好的做法,原因有很多。还有其他问题涉及该问题。此问题的范围较窄,并假设由于某些您无法控制的原因,身份验证凭据必须驻留在客户端应用程序的代码中。
如果某些方法比其他方法更好(例如:JPasswordField 将密码存储在 char 数组而不是 String 中)并且如果您必须在 Java 应用程序中对其进行硬编码,您可以采取哪些措施来使其更难被取走?
更新:
应用程序的一个实例在远程 PC 上运行,最终用户具有管理员权限。凭据用于访问同一网络中的数据库,因此实际密码已经预先确定,必须在实际代码中手动输入。
【问题讨论】:
您是否考虑过对密码进行哈希处理?也许这适用于您的用例? 您能否详细说明您的客户端应用程序是如何工作的?它运行了多少个实例?谁控制它的生命周期?密码是干什么用的? 您是否需要将密码发送到其他地方,所以您实际上需要实际密码?或者您是否从某个地方(如用户)收到密码,只需要检查它是否正确(并且可以使用哈希)? 将牛排嵌入鲨鱼嘴里最安全的方法是什么? 另一个澄清请求:密码可以硬编码,所以需要重新编译才能更改,还是必须在安装应用程序后才能更改?此外,是否可以使用编译时代码生成器生成代码给您密码,或者必须可以手动输入实际的 Java 源代码? 【参考方案1】:....如果您必须在 Java 应用程序中对其进行硬编码,您可以采取哪些措施使其更难被获取?
首先,我会确保负责做出这个错误决定的管理人员完全意识到这是从根本上和不可挽回的不安全1。
那么我可能会想出一些 naff 算法,以一种晦涩的方式组合密码;例如通过构建两个字节数组并将它们异或在一起......并分发混淆的字节码。您能做的最好的事情就是让技能有限的人难以从您的代码中对密码进行逆向工程。
(用强算法加密密码并没有多大帮助,因为算法的选择和解密密钥都必须嵌入到你的代码中。事实上,任何你能想到的方案都可以通过使用调试器来解决在需要明文的地方设置断点。)
1 ... 而且即使是 Jon Skeet 也无法确保其安全。
如果某些方式比其他方式更好(例如:JPasswordField 将密码存储在 char 数组而不是 String 中)...
我只想指出,在 JPasswordField 等中使用 char 数组保存密码的正常理由是为了防止坏人从核心转储或交换文件中读取密码。在这种情况下它并没有真正的帮助,因为我们必须假设你应该担心的坏人是具有系统管理员访问权限的 simeone。他或她将有足够的控制权将调试器附加到 JVM 并从 char 数组中捕获字节。
【讨论】:
【参考方案2】:我喜欢斯蒂芬的回答,但我会补充...
源代码的安全性也很重要。无论您使用何种方法来混淆密码,任何有权访问源代码的人都可以轻松地输入System.out.println(password)
并在使用密码的地方捕获密码,或者在调试中运行代码并暂停代码以检查变量。
即使没有编译,任何可以访问jar
的人都可以在调试模式下启动 java 程序并停止使用密码的程序并检查变量,这对源代码来说很简单,但仍然可以只使用 jar和一些工具。
您可能会考虑让程序在需要时(通过 Web 服务调用或其他方式)从安全服务器获取密码,并让该服务器使用防火墙以仅允许某些 IP 访问它(如果客户端机器是已知的)。它仍然不安全,但至少它是安全的。
【讨论】:
【参考方案3】:在客户端存储敏感数据是极其不安全的,尤其是密码,因为 .class 文件很容易被反编译。你有没有想过让一些非对称加密的东西参与进来?像公钥/私钥对或类似的东西?
【讨论】:
【参考方案4】:我想最不理想的解决方案是,如果您可以拥有基于挑战的身份验证协议,其中包含随机元素。
这样不仅是密码,也是使用密码生成正确响应的代码,需要进行逆向工程。
那么也可以是双向认证,即你端可以验证对方也使用相同的协议/算法,也有相同的密码。
最重要的是,密码永远不会通过网络发送,因此无法被嗅探。
Diffie-Helman key exchange 是一种广泛使用的协议,但如果你只想要默默无闻而不是真正的安全性,你总是可以推出自己的简单实现。好吧,如果一切都可以从字节码反编译和逆向工程,那么真正的安全显然是遥不可及的,但无论如何...... :)
【讨论】:
【参考方案5】:作为一般准则,您永远不应该存储密码(当然)。
如果您需要在运行时提供密码,最佳实践(例如 Jez Humble 在连续交付书中所倡导的)是在部署/启动时提供密码。这样,密码就可以只存在于人们的脑海中,而不是存在于某个不安全的文件中。
我不知道这在你的情况下是否可行,但你应该朝着那个方向努力。
【讨论】:
【参考方案6】:您可以散列密码,甚至可以根据需要对其进行加密。看看这篇文章,它可能会很有用。 Java - encrypt / decrypt user name and password from a configuration file
【讨论】:
这并不能解决问题,因为你马上就会遇到和原来问题一样的新问题:你要如何安全地存储解密密钥?以上是关于在 Java 代码中嵌入密码的最安全方法是啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
将 html/css/js 添加到 mysql 的最安全方法是啥?