1

我试过搜索但什么也没找到(如果它们已经是东西,不知道这些会被称为什么,所以搜索有点困难),所以如果这是愚蠢的或者已经在某个地方回答了,请原谅我。为了争论,当我说我正在散列某些东西时,可以说我正在使用 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 已经发现它是完全可逆的, 现在需要取消哈希两次 - 一次使用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 次 unhashes,产生 243 个候选密码,可能还有几十个误报要消除,但即使没有,也必须做 243 倍于你刚刚完成的 unhashing 工作。此外,在后续哈希中再次将输入作为盐包含在内,使得实际上无法进行反哈希,而且它需要攻击者保留一点额外的内存。也就是说,我的最后一个想法如下:

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 的内存。蛮力攻击的迭代,这并不多,

那么,我是不是在做某事,或者这完全是愚蠢的?

4

2 回答 2

2

这更恰当地属于加密货币,但这是我的 0.02 美元:

您的计算略有偏差,取决于您所做的一些假设,但不一定成立。

现在,额外迭代的想法并不新鲜——PBKDF2以非常相似的方式bcrypt使用迭代,并且已经在内部使用了迭代。

“多盐”的想法在现实中几乎没有什么好处,因为盐通常以明文形式存储在明文密码旁边。

这是您认为“好吧,如果 1 个函数调用和 1 个盐是好的,那么 50 次迭代和 2 个盐更好。这不可能伤害!”的事情之一。但这不是密码学的工作原理,尽管在这种情况下不会,但这种事情可能会造成伤害;它只是浪费资源。

请不要盲目地做这种事情。如果您想增加对哈希的暴力字典攻击的抵抗力,请调整bcrypt难度系数。同样,选择一种长而独特的盐,然后bcrypt就可以了。

于 2013-10-02T03:04:12.067 回答
-1

A) 对手显然准备以非常低的成本计算最常用的 bcrypt()。B)也许还准备运行 N 次简单的迭代,但有些作弊,比我们预期的要便宜。C) 很可能无法反转散列函数。在任何情况下,使用 bcrypt() 的“外部”过程都应该非常愚蠢地编写以降低强度。分支使对手更难使用它的标准破解装备:当然对于 A) 和 B),也可能对于 C) - 但在 C) 的情况下,无论如何都会有大问题。

结合不同类型的加密散列函数,应用分支,除非应用了一些微不足道的错误,否则它不会更弱;但对手很可能更难使用标准的破解装置。如果您正在构建的基本哈希存在根本缺陷(许多人认为如果是这种情况他们会知道:但这只是天真)分支可能无法解决它。但可能会使破解变得更难而不是更容易。在这种情况下浪费资源是好的:与“愚蠢地多次应用它”相比,分支和不同的程序将比诚实的资源浪费更多的对手资源:太好了。

于 2014-07-08T23:23:16.583 回答