我已经尝试过搜索,什么都没找到(如果它们已经存在的话,不知道这些会被叫什么,所以搜索很难),所以请原谅我,如果这是愚蠢的或已经在某处已经回答过。为了论证,我说我正在使用bcrypt或某些声誉/质量的东西,当我说我正在哈希的时候。
首先,您的哈希算法是否有理由不能随密码或中间哈希值而变化?
public static byte[] myHash(byte[] input, byte[] saltA, byte[] saltB) {
return input[0] % 2 == 0
? bcrypt(bcrypt(input, saltA), saltB)
: bcrypt(bcrypt(input, saltB), saltA);
}
我觉得这不会占用太多的CPU - 它只是bcrypt的两次迭代,而且我在其他安全性讨论中提出了10次以上的迭代 - 但是如果你知道盐,那么就说bcrypt发现是完全可逆的和散列,一个unhashing现在需要两次unhashing - 一次使用saltA
,然后使用saltB
,反之亦然,给你两个候选密码,其中一个是诱饵,50%假正率(即,它重新正确的哈希,因为它的第一位是正确的偶数或奇数),需要启发式或人眼来正确识别真实的哈希,所以你至少加倍了所需的计算资源和可能需要的人力介入。但我们可以做得更好:
public static byte[] myBetterHash(byte[] input, byte[] saltA, byte[] saltB) {
byte[] curr = input;
for (int i = 0; i < 5; i++) {
switch(input[i] % 3) {
case 0: curr = bcrypt(bcrypt(bcrypt(curr, input), saltA), saltB); break;
case 1: curr = bcrypt(bcrypt(bcrypt(curr, saltB), input), saltA); break;
case 2: curr = bcrypt(bcrypt(bcrypt(curr, saltA), saltB), input); break;
}
}
return input;
}
现在,在5次迭代中每次迭代有3次不相交,产生243个候选密码,并且可能有数十个误报消除,但即使不是,那么如果你刚才那么他们必须完成243次不懈的工作完成了。此外,在后续哈希中再次将输入包含为盐使得实际上不可能进行散乱,而且需要攻击者保留一点额外的内存。也就是说,我的最后一个想法如下:
public static byte[] myBestHash(byte[] input, byte[] saltA, byte[] saltB) {
byte[] curr = input;
byte[][] arr = new byte[16][]
for (int i = 0; i < 16; i++) {
arr[i] = curr;
switch(curr[0] % 4) {
case 0: curr = bcrypt(curr, saltA); break;
case 1: curr = bcrypt(curr, saltB); break;
case 2: curr = bcrypt(curr, arr[input[i] % i]); break;
case 3: curr = bcrypt(bcrypt(curr, saltA), saltB); break;
}
}
return input;
}
现在攻击者必须处理大量的潜在攻击(3 ^ 16 =超过400万),每个都必须通过上述内存密集进行验证(它保留在16个中间哈希值,并且没有办法优化那个。)
其次,我觉得最后一个例子的内存密集度与分支盐配对,甚至可能是其中一个分支调用bcrypt两次而不是一次的事实,在某些组合中,使得图形暴力变得更难卡片通过使手头的钉子不适合他们或使这个过程浪费更多的I / O而不是正常。如果不出意外,将此方法扩展到16次迭代以后将继续膨胀RAM使用率,从而使并行化变得更加困难。想象一下,如果使用了256个迭代,并且必须为每个在攻击中泄漏的哈希保留1024个中间哈希的空间 - 如果中间哈希本身就是1024比特(= 128个字节),则每个哈希值为32kB蛮力攻击的迭代,这并不多,但它肯定会加起来至少稍微慢一点的暴力攻击者和更少的并行迭代(由于额外的内存 - 虽然32kB并不是很多现代密码破解装置,这是32GB写入内存的百万猜测,如果没有别的东西可以减慢一些额外的东西)。
那么,我是在做某事,还是这完全是愚蠢的?
答案 0 :(得分:2)
这更恰当地属于加密,但这是我的0.02美元:
您的计算略有偏差,取决于您所做的某些假设但不一定有效。
现在额外迭代的想法并不新鲜 - PBKDF2以非常类似的方式使用迭代,bcrypt
已经在内部使用迭代。
“多盐”的想法在现实中几乎没有什么收获,因为无论如何,盐通常与明文密码一起存储在明文中。
这是你认为“好吧,如果1个函数调用和1个盐是好的,然后50个迭代和2个盐更好的事情之一。这不可能有害!”但这并不是密码学的工作方式,而且这种事情可能会受到伤害,尽管在这种情况下不会;它只是浪费资源。
请不要盲目地做这种事。如果您想增加对哈希的强力字典攻击的抵抗力,请调整bcrypt
难度系数。同样,选择一种长而独特的盐,让bcrypt
做它。
答案 1 :(得分:-1)
A)对手显然准备以非常低的成本计算最常用的bcrypt()。 B)也许还准备运行N个简单的迭代,有些欺骗,比我们预期的便宜。 C)很可能无法反转散列函数。 在任何情况下,使用bcrypt()的“外部”程序都应该非常愚蠢地写入以降低强度。分支使得对手更难以使用它的标准裂缝装备:肯定是A)和B),也可能是C) - 但是在C的情况下,无论如何都存在很大的问题。
结合使用不同类型的加密散列函数,应用分支,除非应用了一些微不足道的错误,否则它不会更弱;但是对手很难应用标准的裂缝装备。如果您正在构建的基础哈希基本上存在缺陷(许多人认为如果是这种情况他们会知道它:但这只是天真的)分支可能无法解决它。但可能使破解变得更容易。在这种情况下浪费资源是好的:分支和不同的程序比“愚蠢地只是多次应用”将浪费更多的对手资源而不是诚实的资源:非常好。