Hug*_*ota 6 php security hash rainbowtable password-hash
可能重复:
md5解码.他们是怎么做到的?
这个页面表明,由于我们现在拥有巨大的处理能力,可以颠倒像md5()和sha1()这样的哈希算法.在这一点上,我认为只有彩虹表才有可能.我错了吗?
如果Rainbow Tables是唯一的方法,有人可以如何反转用盐制作的哈希?
irc*_*ell 15
那么,这个问题一般是与本课题的重复.但是,要回答您的确切问题:
在这一点上,我认为只有彩虹表才有可能.我错了吗?
从技术上讲,是的,你错了.在给定足够的处理能力的情况下,没有哈希函数是不可恢复的.关键点在于它需要多少处理能力,在大多数情况下,这比你想象的要大得多.原因是可能值的数量在散列循环的每个阶段以指数方式增加.对于MD5,每个阶段(其中有64个)会将可能性的数量乘以10 ^ 77(很多零).因此,要成功地扭转了MD5,你不得不尝试真正大量可能的排列(背的包络的计算显示了10 ^ 4932尝试量级上的某个地方).使用今天创建的最快的超级计算机(大约8 petaflops,或每秒8x10 ^ 15浮点运算),你正在寻找大约10 ^ 4908 年来逆转它.顺便提一下,现在是宇宙年龄的2.5x10 ^ 4898倍.真的,这是一个超出我们人类理解能力的巨大数字......
这是一个绝对最好的案例情况.
从技术上讲,它可以逆转.但实际上,不是不是.
如果Rainbow Tables是唯一的方法,有人可以如何反转用盐制作的哈希?
问题是没有人需要扭转它.他们只需找到一个碰撞.基本上,碰撞是两个输入,导致相同的输出.所以如果hash(a) = x
和hash(b) = x
,a
并且b
是彼此的碰撞.因此,我们需要做的就是找到一个碰撞(相信它或不相信比找到确切的输入更容易,因为技术上有无限数量的输入可以给出特定的输出).输入密码大小时,通常碰撞是原始密码.
找到此冲突的最简单方法是使用预先计算的哈希列表(通常称为彩虹表).基本上你需要做的就是在表格中查找哈希,看原文是否存在.如果是这样,你就完成了(那很简单).
通常添加盐来对抗彩虹表.这是因为如果用户输入1234
他们的密码,并且您使用abcdefghijklmnop
原始的盐,1234abcdefgjhijklmnop
那么在彩虹表中出现的可能性要小得多.因此添加强盐可以防止预先计算的彩虹表.
蛮力
但是,如果您这样做,则会引起严重关注hash(pass + salt)
.它不容易受到预先计算的彩虹表的影响,但它很容易受到暴力破坏的影响.原因是加密哈希函数(例如sha1,md5,sha256等)设计得很快.他们的传统角色是签名,所以他们需要快速有用.但是,在密码存储中,这是一个弱点.使用现代GPU,攻击者可以在几个小时内蛮力(只是尝试每个可能的密码排列)一个简单的盐哈希(有关详细信息,请参阅我的博客文章)...
最好的预防
最好的预防有两个特点:
预先计算一个值表(彩虹表)并不容易
散列单个值并不快(不容易暴力).
事实证明,使用哈希函数有一种简单的方法.简单地迭代它并使输出依赖于大量的散列函数:
var result = password + salt;
for (var i = 0; i < 10000000; i++) {
result = hash(result + salt);
}
Run Code Online (Sandbox Code Playgroud)
关键是通过人为地减慢和使用盐,你可以使它抵抗预先计算和暴力强迫.
事实证明,有2个标准算法可以做到这一点(好吧,使用原则).
最好的一个是Blowfish hash(bcrypt),它实际上并没有使用哈希原语函数,而是使用Blowfish密码的密钥派生循环.它可以通过PHP获得crypt()
.要使用它:
$hash = crypt($password, '$2a$07$' . $salt . '$');
Run Code Online (Sandbox Code Playgroud)
并验证它
$hash == crypt($password, $hash);
Run Code Online (Sandbox Code Playgroud)
另一种方法(稍微不太优选)是PBKDF2.要用PHP编程:
function pbkdf2($hashFunc, $password, $salt, $iterations, $length = 32) {
$size = strlen(hash($hashFunc, '', true));
$len = ceil($length / $size);
$result = '';
for ($i = 1; $i <= $len; $i++) {
$tmp = hash_hmac($hashFunc, $salt . pack('N', $i), $password, true);
$res = $tmp;
for ($j = 1; $j < $iterations; $j++) {
$tmp = hash_hmac($hashFunc, $tmp, $password, true);
$res ^= $tmp;
}
$result .= $res;
}
return substr($result, 0, $length);
}
Run Code Online (Sandbox Code Playgroud)
注意:
这些都不会保护用户免受非常弱的密码.如果他们输入字典单词或通用密码,攻击者仍然可能会破解它.然而,他们会增加对中等强度密码的防御......
更多阅读: