有没有办法在没有彩虹表的情况下反转哈希?

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) = xhash(b) = x,a并且b是彼此的碰撞.因此,我们需要做的就是找到一个碰撞(相信它或不相信比找到确切的输入更容易,因为技术上有无限数量的输入可以给出特定的输出).输入密码大小时,通常碰撞是原始密码.

找到此冲突的最简单方法是使用预先计算的哈希列表(通常称为彩虹表).基本上你需要做的就是在表格中查找哈希,看原文是否存在.如果是这样,你就完成了(那很简单).

通常添加盐来对抗彩虹表.这是因为如果用户输入1234他们的密码,并且您使用abcdefghijklmnop原始的盐,1234abcdefgjhijklmnop那么在彩虹表中出现的可能性要小得多.因此添加强盐可以防止预先计算的彩虹表.

蛮力

但是,如果您这样做,则会引起严重关注hash(pass + salt).它不容易受到预先计算的彩虹表的影响,但它很容易受到暴力破坏的影响.原因是加密哈希函数(例如sha1,md5,sha256等)设计得很快.他们的传统角色是签名,所以他们需要快速有用.但是,在密码存储中,这是一个弱点.使用现代GPU,攻击者可以在几个小时内蛮力(只是尝试每个可能的密码排列)一个简单的盐哈希(有关详细信息,请参阅我的博客文章)...

最好的预防

最好的预防有两个特点:

  1. 预先计算一个值表(彩虹表)并不容易

  2. 散列单个值并不快(不容易暴力).

事实证明,使用哈希函数有一种简单的方法.简单地迭代它并使输出依赖于大量的散列函数:

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)

注意:

这些都不会保护用户免受非常弱的密码.如果他们输入字典单词或通用密码,攻击者仍然可能会破解它.然而,他们会增加对中等强度密码的防御......

更多阅读: