我们为什么要用“盐"?保护我们的密码? [英] Why do we use the "salt" to secure our passwords?

查看:25
本文介绍了我们为什么要用“盐"?保护我们的密码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读本教程,我遇到了以下有关加密的讨论.最后写成

<块引用>

在最后一行,我们用密码散列了盐,得到一个加密的密码实际上是不可能破解

但在我看来,同时拥有 encrypted_pa​​sswordsalt 的黑客可以像我们使用 salt.

那么,我错在哪里?

谢谢!

<块引用>

$ rails 控制台>>需要摘要">>def secure_hash(字符串)>>摘要::SHA2.hexdigest(字符串)>>结尾=>零>>密码 = "秘密"=>秘密">>加密密码 = 安全哈希(密码)=>2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b">>提交的密码=秘密"=>秘密">>encrypted_pa​​ssword == secure_hash(submitted_pa​​ssword)=>真的

这里我们定义了一个名为使用加密的secure_hash称为 SHA2 的哈希函数的一部分SHA 系列的哈希函数,我们通过摘要包含到 Ruby 中library.7 知道并不重要这些散列函数究竟是如何工作的;为了我们的目的,重要的是他们是单向的:没有计算上易于处理的方法发现

2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b是字符串的 SHA2 哈希值秘密".

不过,如果你仔细想想,我们还有一个问题:如果攻击者曾经掌握过散列密码,他还有机会发现原作.为了例如,他可以猜到我们使用SHA2,所以写一个程序将给定的哈希值与哈希值进行比较潜在密码的值:

<代码>>>哈希=2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b">>secure_hash("secede") == 哈希=>错误的>>secure_hash("second") == 哈希=>错误的>>安全哈希(秘密")==哈希=>真的

所以我们的攻击者有一个匹配——坏消息对于密码为secret"的任何用户.这种技术被称为彩虹攻击.

为了挫败潜在的彩虹攻击,我们可以使用盐,这是不同的每个用户的唯一字符串.8 一个(几乎)确保的常用方法唯一性是散列当前时间(在 UTC 中与时区无关)连同密码,这样两个只有在以下情况下,用户才会拥有相同的盐分它们的创建时间完全相同时间和密码相同.让我们看看这是如何工作的secure_hash 函数定义在上面的控制台:

<代码>>>时间.now.utc=>UTC 2010 年 1 月 29 日星期五 18:11:27>>密码 = "秘密"=>秘密">>salt = secure_hash("#{Time.now.utc}--#{password}")=>d1a3eb8c9aab32ec19cfda810d2ab351873b5dca4e16e7f57b3c1932113314c8">>encrypted_pa​​ssword = secure_hash("#{salt}--#{password}")=>69a98a49b7fd103058639be84fb88c19c998c8ad3639cfc5deb458018561c847"

在最后一行,我们用密码散列了盐,得到一个加密的密码实际上是不可能破解.(为清楚起见,散列函数的参数是经常用--分隔.)

解决方案

彩虹表的计算成本很高.没有salt,你可以建立一个可以重复使用的彩虹表,因为密码password"将始终产生相同的哈希值(md5=5f4dcc3b5aa765d61d8327deb882cf99, sha1=5baa61e4c9b93f3f0682250b6cf83,因此容易识别数据库中的密码)/p>

对于盐,您必须为遇到的每种盐计算彩虹表.一个大小合适的盐,比如 32 位(理想情况下,128 位甚至更多),意味着您必须为每个要破解的密码计算一个彩虹表,从而在很大程度上违背了它的目的.

i was reading this tutorial, and i encountered the following discussion about encryption. At the end there's written

In the last line, we’ve hashed the salt with the password, yielding an encrypted password that is virtually impossible to crack

But in my opinion an hacker who has both the encrypted_password and the salt could do the "rainbow" trick exactly as if we were using the salt.

So, where i'm wrong?

Thanks!

$ rails console
>> require 'digest'
>> def secure_hash(string)
>>   Digest::SHA2.hexdigest(string)
>> end
=> nil
>> password = "secret"
=> "secret"
>> encrypted_password = secure_hash(password)
=> "2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b"
>> submitted_password = "secret"
=> "secret"
>> encrypted_password == secure_hash(submitted_password)
=> true

Here we’ve defined a function called secure_hash that uses a cryptographic hash function called SHA2, part of the SHA family of hash functions, which we include into Ruby through the digest library.7 It’s not important to know exactly how these hash functions work; for our purposes what’s important is that they are one-way: there is no computationally tractable way to discover that

2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b is the SHA2 hash of the string "secret".

If you think about it, though, we still have a problem: if an attacker ever got hold of the hashed passwords, he would still have a chance at discovering the originals. For example, he could guess that we used SHA2, and so write a program to compare a given hash to the hashed values of potential passwords:

>> hash = "2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b"
>> secure_hash("secede") == hash
=> false
>> secure_hash("second") == hash
=> false
>> secure_hash("secret") == hash
=> true

So our attacker has a match—bad news for any users with password "secret". This technique is known as a rainbow attack.

To foil a potential rainbow attack, we can use a salt, which is a different unique string for each user.8 One common way to (nearly) ensure uniqueness is to hash the current time (in UTC to be time zone–independent) along with the password, so that two users will have the same salt only if they are created at exactly the same time and have the same password. Let’s see how this works using the secure_hash function defined in the console above:

>> Time.now.utc
=> Fri Jan 29 18:11:27 UTC 2010
>> password = "secret"
=> "secret"
>> salt = secure_hash("#{Time.now.utc}--#{password}")
=> "d1a3eb8c9aab32ec19cfda810d2ab351873b5dca4e16e7f57b3c1932113314c8"
>> encrypted_password = secure_hash("#{salt}--#{password}")
=> "69a98a49b7fd103058639be84fb88c19c998c8ad3639cfc5deb458018561c847"

In the last line, we’ve hashed the salt with the password, yielding an encrypted password that is virtually impossible to crack. (For clarity, arguments to hashing functions are often separated with --.)

解决方案

Rainbow tables are expensive to compute. Without the salt, you can build a rainbow table once that can be used repeatedly, since the password "password" will always yield the same hash (md5=5f4dcc3b5aa765d61d8327deb882cf99, sha1=5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8) and is thus easy to identify in a password database.

With a salt, you have to compute a rainbow table for each salt you encounter. A good-sized salt, say 32 bits (ideally, 128 or even more), means you have to compute a rainbow table for every password you want to crack, thus largely defeating its purpose.

这篇关于我们为什么要用“盐"?保护我们的密码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆