【问题标题】:encrypting password: when it is too much?加密密码:什么时候太多了?
【发布时间】:2011-06-29 10:39:24
【问题描述】:

我正在更新我的 helper 函数库。我想知道是不是密码加密中salt太多了?

两者有什么区别:

mb_substr(sha1($str . AY_HASH), 5, 10) . mb_substr(sha1(AY_HASH . sha1($str . AY_HASH)), 5, 10) . mb_substr(md5($str . AY_HASH), 5, 10)

简单地说:

sha1(AY_HASH . sha1($str . AY_HASH))

AY_HASHsalt。我应该更喜欢哪个,如果两者都不好,最好的选择是什么?

【问题讨论】:

  • 你知道这个叫做blowfish crypt的神奇工具,除了adaptive之外,每个密码都使用不同的盐,对吧?

标签: php salt saltedhash


【解决方案1】:

应该为每个密码生成一个盐,而不是每个密码都使用一个秘密字符串。重复使用盐意味着攻击者只需为每个密码创建一个彩虹表,而不是每个密码一个。

我邀请您阅读我之前在secure hashing 上写的答案。规则很简单:

  • 对所有密码使用单一盐。每个密码使用随机生成的盐。
  • 重新散列未修改的散列(冲突问题,see my previous answer,散列需要无限输入)。
  • 不要尝试将自己的哈希算法或混合匹配算法创建到复杂的操作中。
  • 如果卡在损坏/不安全/快速哈希原语中,请使用key strengthening。这增加了攻击者计算彩虹表所需的时间。示例:

function strong_hash($input, $salt = null, $algo = 'sha512', $rounds = 20000) {
  if($salt === null) {
    $salt = crypto_random_bytes(16);
  } else {
    $salt = pack('H*', substr($salt, 0, 32));
  }

  $hash = hash($algo, $salt . $input);

  for($i = 0; $i < $rounds; $i++) {
    // $input is appended to $hash in order to create
    // infinite input.
    $hash = hash($algo, $hash . $input);
  }

  // Return salt and hash. To verify, simply
  // passed stored hash as second parameter.
  return bin2hex($salt) . $hash;
}

function crypto_random_bytes($count) {
  static $randomState = null;

  $bytes = '';

  if(function_exists('openssl_random_pseudo_bytes') &&
      (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { // OpenSSL slow on Win
    $bytes = openssl_random_pseudo_bytes($count);
  }

  if($bytes === '' && is_readable('/dev/urandom') &&
     ($hRand = @fopen('/dev/urandom', 'rb')) !== FALSE) {
    $bytes = fread($hRand, $count);
    fclose($hRand);
  }

  if(strlen($bytes) < $count) {
    $bytes = '';

    if($randomState === null) {
      $randomState = microtime();
      if(function_exists('getmypid')) {
        $randomState .= getmypid();
      }
    }

    for($i = 0; $i < $count; $i += 16) {
      $randomState = md5(microtime() . $randomState);

      if (PHP_VERSION >= '5') {
        $bytes .= md5($randomState, true);
      } else {
        $bytes .= pack('H*', md5($randomState));
      }
    }

    $bytes = substr($bytes, 0, $count);
  }

  return $bytes;
}

如果有的话,你应该使用 bcrypt,它可以适应未来。同样,I invite you to my previous answer for a more detailed example

【讨论】:

  • 使用随机盐的驱动程序到底是什么?为了检查密码的正确性,您必须将其保存。针对散列的唯一且唯一的攻击向量是有人可以访问数据库......他也可以在其中读取相关的盐......!所以也许我缺少一些东西,但据我所知,加盐的唯一优点是有人可能不会将数据库转储与彩虹表进行比较。请赐教。
  • @fyr:盐要求攻击者生成针对该特定盐定制的彩虹表。虽然生成彩虹表的成本很高,但如果您为每个密码重复使用相同的盐,攻击者只需生成一张表即可破解您的所有密码。但是,如果您为每个密码生成一个随机盐,则攻击者需要为他想要破解的每个密码生成一个彩虹表(而不是仅使用一个表来破解您的所有密码)。密钥强化会增加攻击者生成彩虹表所需的时间。
  • @fyr,如果每个用户都有自己的 salt,那么攻击者就无法为整个站点计算一个包含一个固定 salt 的表。如果每个用户都有自己的盐,那么暴力破解两个用户密码的难度将增加一倍。如果你有一万种不同的盐,难度会增加一万倍。随机生成盐是如此便宜,没有理由不这样做。
  • 没错,攻击者获得了盐的访问权限。但是现在他需要为每个盐计算一个彩虹表,如果你使用一个唯一的盐,那么他必须为每个用户做这件事。
  • @fyr:你是错的。如果你使用单一的盐,你的盐也会受到彩虹表攻击。攻击者只需注册即可。然后,知道他自己的密码并检索散列版本,他可以生成一个表来找到合适的盐。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
  • 2020-07-16
  • 1970-01-01
  • 2016-02-06
  • 2016-08-10
  • 2013-09-12
  • 1970-01-01
相关资源
最近更新 更多