What is the best practice for securely storing passwords in Java
在Java桌面应用程序中存储密码的推荐方法是什么?
我希望用户能够只输入一次凭证,而不需要再次提示。
在个人项目中,我一直在使用首选项API,但我假设这与以纯文本形式存储(安全方面)没有什么不同。
多谢
编辑:
非常感谢你的建议。似乎有些困惑,毫无疑问,因为我可能没有把这个问题说得很清楚…
我将给出一个低血压的情况:
假设我正在为远程数据库创建一个简单的前端,它使用用户名/密码创建一个连接字符串。通常,每次启动应用程序时,都会提示用户输入用户名/密码组合。
在不需要重新输入密码的情况下(在应用程序启动时自动连接),将密码存储在用户的计算机中的最佳方法是什么?
一种"记住我"功能(我知道这本身不是一个很好的实践…)
编辑2:
谢谢大家的回答。爸?Lo Ebermann的关于手头问题的信息非常丰富,Chris Smith的链接很有趣,但我已经接受了Jeverstry的链接,因为密钥库可能是我要走的路线。
- 看看这个问题:stackoverflow.com/q/6592010/313205
- 存储在磁盘内存中?
- 请不要转到Marcelo的链接。这满是坏建议。检查答案并阅读Codahale的文章。10年前的好建议在过去的5年里变得不安全,因为我们可以通过在计算机硬件上的少量投资轻松地强制这些算法。所有符号(a-z、a-z、0-9、特殊字符)少于8个字符的sha1、md5和密码都很容易被破坏。
- +1表示非SHA1/MD5。正如我在下面发布的,一些Eejit对此感到不满。
- 您是在谈论自己的应用程序的密码,还是将密码存储到数据库或Web服务等外部系统?
- JasPy.Org
- 你首先需要描述你想保护谁。
- @codesinchaos"所有不是我们的人都是敌人。"-任何程序,除了他的应用程序,都不能获得密码。
您可以使用一个本地密钥库来存放密码而不是密钥。
编辑回答:
钥匙库非常适合您的需要。如果需要额外的保护,可以在用户启动应用程序时要求用户输入一个密码以访问所有密码。然后,您可以使用一个简单的salt-and-stretch方法(生成加密密钥)来保护存储的数据库密码,该方法使用启动应用程序时使用的一个密码。
- 这个问题有8000种观点。对于一个复杂的安全主题,您的答案有6行(最初只有一行)。你是认真的吗?像这样的问题的答案往往会有更多的赞成票(和反对票)。什么是keystore?它是如何使用的?它是Java的东西还是操作系统的东西?我希望我能对你提出的每一个问题投反对票。
- @汤姆和第225;?ZATO这是一个Java问题,密钥库是Java SSE(安全套接字扩展)的核心特性。对于这个问题的所有观点,这个答案没有多少赞成票。
- @雷斯托姆:"对于这个问题的所有观点,这个答案没有太多的赞成票。"—这就是我要指出的。
- 是的,这个答案可能会有更多的细节,并且更有用。;)
没有办法在计算机上存储一些东西,Java程序可以检索它(没有用户输入密码),但是在这个计算机上没有其他程序(运行在同一个用户的帐户中)可以检索它。
您可以尝试以某种方式对其进行加密,并将解密算法与解密密钥一起隐藏在程序中(白盒密码术),但攻击者只需在调试器中运行您的程序,就可以让它对数据进行解密。
您可以使用系统的权限系统,但如果攻击者是与您的Java程序在同一个用户帐户中运行的某些程序(如果攻击者具有root访问权限,甚至会帮助更少),那么这通常是没有帮助的。
最好的办法是将密码存储在USB存储器上,并告诉用户在使用完密码后将其取出,但如果攻击程序正在运行并在您从存储棒中读取秘密时进行观察,即使这样也无济于事。
- 是的,但解密算法可能与互联网上的时间有关,这将是一个巨大的难题。
- 如果攻击者没有根访问权,使用系统的权限可能会有所帮助。
- @ BrianMcCutchon如果攻击者也运行在与Java程序相同的用户帐户中,则两者具有相同的权限,并且可以访问相同的文件。当然,根攻击者可以访问任何人的文件。
- @ Pa?例如,如果操作系统控制哪些应用程序可以访问密码,则Loebermann不会。在macos keychain中,应用程序可以使用它创建的密码和用户明确授予它访问权限的密码。请参见:developer.apple.com/library/content/documentation/security/…
- @布赖恩·麦考肯好吧,我对苹果机的工作原理一无所知…你能将Java程序注册为"应用程序"(而不是仅仅使用"Java"解释器作为应用程序)吗?
- 您可以完全使用Maven或Ant可用的APP绑定工具之一来制作JavaMac应用程序。
不管使用哪种语言,我认为这是适用的:http://codahale.com/how-to-safety-store-a-password/
总之,使用bcrypt哈希函数。
首选项API依赖于内存实现,因此您将由JVM供应商决定。如果它是Sun/Oracle JVM,那么获取数据就很简单。但是,如果您散列它并强制执行一个合适的密码策略,它将是非常安全的。原始密码将很难确定。
- 哈希密码不允许您检索它。
- 错误:为什么要检索密码?那简直是胡说八道。
- "我希望用户能够只输入一次凭证,而不需要再次提示。"->这意味着密码将被重用。
- 我认为不清楚的一点是,操作人员似乎真的想要将密码存储到某个第三方系统中,例如,他的数据库连接字符串是安全的,以便他以后可以通过编程方式提交密码。不假定外部系统具有通过任意算法接受已散列密码的API!
- @杰弗斯特里:不-那是不对的。哈希密码被重用,而不是未哈希密码。您预先散列它,然后在每次需要验证凭据时比较散列。如果您需要与支持不同哈希算法的提供者交谈,您可以预先存储提供者或服务所需的所有变体(sha1、md5、bcrypt等)。如果他们说的是纯文本密码,那么就有一些严重的问题。
- 克里斯的问题是:"在Java桌面应用程序中存储密码的推荐方法是什么?"这与远程服务或提供者无关。
- @我已经回答过了。
- @克里斯,如果你存储密码散列,它不会解决问题,特别是如果你打算使用它们。哈希本身不受保护。恕我直言,你提出的解决方案不是解决方案。你错过了要点。
- 存储任何可以直接用于身份验证的内容将允许攻击者登录到您的位置。
- 如果是这种情况,这是一个问题,那么您应该将哈希密码存储在易失性存储(内存)中。如果它是一个攻击向量,那么不要存储密码。我认为人们正在把这个问题弄得比现在更严重:)
- 如果你的应用程序是唯一需要验证的东西(因为你可以存储/比较哈希密码,非常安全),那么存储哈希密码是可行的。但是,如果密码是另一个系统的,则需要存储原始密码。一个很好的例子就是ftp客户机:它需要存储原始密码,因为这正是它需要提供给服务器的。