哈希和腌制混乱

时间:2015-01-02 17:36:12

标签: encryption hash

我已经阅读了很多关于哈希和盐渍密码的内容。我知道哈希是如何工作的,这一切都很容易,但我感到困惑的是腌制。

如果我将密码哈希并加密并将其粘贴到数据库中,如何在用户尝试登录时使用密码检查该密码。当然因为盐是完全随机的,所以几乎不可能再次获得盐以便能够匹配数据库

实施例

//On create account.
hash(password + randomSalt) to the Database

//On log-in
hash(password + differentRandomSalt) compare to Database

2 个答案:

答案 0 :(得分:2)

使用您散列的每个密码生成固定长度的随机散列。然后将该盐与计算的哈希结合存储到一个数据库列中。

当用户想要登录时,您从数据库中提取salt-part并且可以匹配结果。

示例:

var salt = GenerateSecureRandom(16) // generates e.g. 0x42552241
var saltedHash = Hash(salt + password)

登录方案:

var saltedHash = GetSaltedHashFromDatabase()
var salt = GetFirstBytes(saltedHash)     // 0x42552241
var hash = GetRemainingBytes(saltedHash) // 0x47111337
var match = IsMatch(hash, salt, userInput)

数据库条目可能如下所示(其中=是salt,*是哈希):

0x4255224147111337
  ========********

对于(更多)更多详细信息,请查看:https://crackstation.net/hashing-security.htm

答案 1 :(得分:1)

对于每个不同的用户/密码组合,盐是随机的。对于相同的用户/密码组合,它不是随机的。如果是这种情况,那么您将无法验证密码,正如您已经发现的那样。如果使用足够安全的随机数生成器生成足够大的盐,则甚至无法验证密码。盐的想法是防止彩虹表攻击,以及如果密码相同,为不同的用户创建不同的密码哈希。

salt通常与用户名和密码哈希一起存储在数据库中。它可以成为包含salt和密码哈希的特殊构造的一部分,也可以存储在单独的列中。有时,密码哈希实际上是一个特殊的字符串,包含需要解析的某种格式的盐和哈希(使用十六进制或base64编码),但它也可能只是一个二进制值,只包含一个静态大小的盐和静态大小的散列。

示例bcrypt字符串是:

$2a$12$QyrjMQfjgGIb4ymtdKQXIewDBqhA3eNppF8qOrMhidnEbzNvmHqhy

,其构造方式如此SO answer

设定:

  1. 找到用户
  2. 收到&验证旧密码(见下文)
  3. 收到新密码
  4. 生成随机盐
  5. 从密码和盐计算哈希
  6. 储存盐&用户
  7. 在数据库中散列

    验证

    1. 找到用户
    2. 接收密码
    3. 检索盐和用户哈希
    4. 计算哈希以验证密码和盐
    5. 比较并返回结果
    6. 通常,出于安全原因,您应该尝试进行时间常数比较,即使这不是密码哈希的问题。此外,通常不区分未知用户和错误密码,只是为了避免向攻击者提供信息。

      构造密码散列方案是有意义的,它允许更新迭代量,散列大小,散列函数等。