替换应用程序的纯文本密码

问题描述:

我们目前正在为我们拥有的Web应用程序存储纯文本密码。替换应用程序的纯文本密码

我一直主张移动到密码哈希,但另一个开发人员说这不太安全 - 更多的密码可以匹配哈希和字典/哈希攻击会更快。

这个说法有没有道理?

绝对没有。但没关系。我之前发布过类似的回复:

这很不幸,但是人们甚至程序员都太情绪化,不容易被争论所左右。一旦他投入了自己的职位(如果你在这里发帖,他就是),你不可能单凭事实说服他。你需要做的是切换举证责任。你需要让他找出他希望能说服你的数据,并且这样做才能了解真相。不幸的是,他有现状的好处,所以你有一个艰难的道路。

+0

那里很好 - 它确实是来自OP的同事的情绪反应。解决温暖的模糊问题可能会提高硬逻辑和度量标准的效率。也许把哈希算法选择推到同事身上,让他们有更多的选择来解决问题? – 2008-09-12 14:02:36

+0

这里有一个很好的观点。我没有提到这个问题,但这是他的代码 - 他以这种方式暗示它。它现在是我的代码,所以我可以改变它unilaterly,但我宁愿让他保存脸/同意以防我需要进一步帮助理解代码... – 2008-09-12 14:15:14

我不是安全专家,但我有一种感觉,如果纯文本更安全,哈希将不存在在第一位。

+1

-1:散列法用于除密码等等。只是因为某些东西存在并不意味着它有任何价值(尽管在这种情况下是这样)。真正的解释会增加价值。 – 2009-02-03 09:19:29

绝对没有理由在web应用上保留纯文本密码。使用具有盐值的标准哈希算法(SHA-1,不是MD5!),因此不可能发生彩虹攻击。

+0

md5完全不适合密码哈希 – 2012-07-06 00:10:01

+0

我已更新回复,谢谢@ joel-coehoorn。 – qbeuek 2012-09-20 12:34:26

如果你不加盐了密码,你嫌疑人彩虹表攻击(即对一个给定的哈希有效输入预编译字典)

其他开发商应该停止谈论安全,如果你存储密码在明文和开始阅读有关安全。

碰撞是可能的,但通常不是密码应用程序的大问题(它们主要是使用散列作为验证文件完整性的方式的一个问题)。因此:使用密码(通过将Salt添加到密码*的右侧)并使用像SHA-1或SHA-256或SHA-512那样的良好散列算法。

PS:有关Hashes here的更多细节。

*我有点不确定Salt是否应该到字符串的开头或结尾。问题是,如果你有碰撞(两个输入具有相同的散列),将Salt添加到“错误”一侧不会改变产生的散列。无论如何,你不会有彩虹表的大问题,只有碰撞

我不明白你的其他开发者的东西'更多的密码可以匹配散列'。

有一个'散列攻击会更快'的说法,但前提是你不要在密码被哈希时进行腌制。通常情况下,哈希函数允许您提供一个盐,这使得使用已知哈希表浪费时间。

就我个人而言,我会说'不'。基于上述情况,以及事实上,如果你以某种方式获得明文暴露,那么对于尝试进入的人来说,腌制的散列值是没有多大价值的。散列还提供了使所有密码“看起来”相同的长度。

即,如果散列任何字符串总是导致20个字符的散列,那么如果您只有散列来查看,则不能分辨出原始密码是8个字符还是16个例如。

理论上,是的。密码可以比散列更长(更多信息),所以存在散列冲突的可能性。但是,大多数攻击都是基于字典的,碰撞的概率比成功的直接匹配小得多。

更多的密码可以匹配散列,字典/散列攻击会更快。

是和否。使用现代哈希算法,就像SHA变体一样,并且该参数非常非常周。你真的需要担心,如果这场蛮力攻击只需要352年而不是467年呢? (那里有个轶事的笑话。)要获得的价值(没有在系统上以明文形式存储密码)远远超过了你的同事的关注。

Wikipedia

一些计算机系统存储用户密码 ,用以比较的尝试 用户登录,如明文。如果 攻击者获得访问这样一个 内部密码存储区,所有密码 等等所有用户帐户将 妥协。如果某些用户对 不同系统上的帐户使用相同的密码 ,那么这些帐户也会被 损害。

更安全的系统存储在加密 保护形式各 密码,所以获得了 实际的密码仍然会 困难谁获得了对系统 内部访问探听器,而用户访问尝试 的 验证仍然有可能。

一个普通的approache只存储一个 “散列”形式的密码 密码。当在这样的系统上的 密码的用户类型,该 密码处理软件运行 通过密码散列 算法,如果从用户的条目 生成的散列值 存储在 密码数据库中的哈希值匹配时,用户是 允许访问。散列值是 ,通过将密码 散列函数应用于所提交的密码的 和通常为 盐的另一个值组成的字符串创建。 salt可防止来自 的攻击者为 常见密码构建哈希值列表。 MD5和SHA1是 经常使用的加密哈希 函数。

还有很多内容您可以阅读该页面上的主题。在我看来,在我阅读和处理过的所有内容中,散列是一个更好的场景,除非你使用一个非常小的(< 256位)算法。

有一个事实,如果你散列的东西,是的,会有碰撞,所以有可能两个不同的密码解锁相同的帐户。

从实际的角度来看,这是一个糟糕的参数 - 一个好的散列函数(md5或sha1会很好)几乎可以保证对于所有有意义的字符串,特别是短字符串,不会有冲突。即使有,两个密码匹配一个帐户也不是一个大问题 - 如果某人有能力随机猜测密码足够快以至于他们可能能够进入,那么问题就更大了。

我认为以纯文本存储密码比密码匹配中的散列冲突代表了更大的安全风险。

这取决于你对抗什么。如果攻击者拉下你的数据库(或者欺骗你的应用程序显示数据库),那么明文密码就没用了。有很多攻击依赖于说服应用程序释放它的私有数据 - SQL注入,会话劫持等。通常最好不要保留数据,而是保持散列版本,使坏人不能轻易使用它。

正如你的同事们所建议的那样,这可以通过对字典运行相同的散列算法并使用彩虹表将信息提取出来而平庸地击败。通常的解决方法是使用一个秘密盐加上额外的用户信息进行散列结果独特 - 是这样的:

String hashedPass=CryptUtils.MD5("alsdl;ksahglhkjfsdkjhkjhkfsdlsdf" + user.getCreateDate().toString() + user.getPassword); 

只要你的盐是秘密的,或者你的攻击者不知道的确切创建日期用户的记录,字典攻击将失败 - 即使他们能够拉下密码字段。

我在我的工作场所遇到了同样的问题。我做了什么来说服他哈希更安全的是编写一个SQL注入,它从我们网站的公共部分返回用户名和密码列表。它是升级的时候了作为一个主要的安全问题:)

为了防止对字典/哈希攻击一定要凑对的令牌是唯一的每个用户和静态(用户名/加入日期/ userguid效果很好)

没有什么比存储纯文本密码更安全。如果你正在使用体面的哈希算法(至少SHA-256,但即使SHA-1比没有好),那么是的,碰撞是可能的,但它并不重要,因为给定一个哈希值,不可能*计算出什么字符串散列到它。如果你用密码对用户名进行散列,那么这种可能性也会消失。

* - 在技术上不是不可能,而是“计算上不可行”

如果用户名是“格雷姆”,密码为“计算器”,然后创建一个字符串“格雷姆 - 计算器-1234”,其中1234是随机数字,然后散列它并在数据库中存储“散列输出 1234”。在验证密码时,从储值结束处获取用户名,提供的密码和数字(哈希具有固定长度,以便始终可以执行此操作)并将它们散列在一起,然后将其与哈希值进行比较存储值的一部分。

有句老话约程序员故作密码学家:)

杰夫阿特伍德对这个问题的好岗位:You're Probably Storing Passwords Incorrectly

更广泛地回复,我同意所有上述情况,散列使​​得理论上更容易以获得用户的密码,因为多个密码匹配相同的散列。但是,与访问数据库的人相比,这种情况发生的可能性要小得多。

希望你原谅我堵的解决方案我在这写的,使用客户端的JavaScript它的传输之前散列密码:http://blog.asgeirnilsen.com/2005/11/password-authentication-without.html