我已经阅读了很多关于哈希和盐渍密码的内容。我知道哈希是如何工作的,这一切都很容易,但我感到困惑的是腌制。
如果我将密码哈希并加密并将其粘贴到数据库中,如何在用户尝试登录时使用密码检查该密码。当然因为盐是完全随机的,所以几乎不可能再次获得盐以便能够匹配数据库
实施例
//On create account.
hash(password + randomSalt) to the Database
//On log-in
hash(password + differentRandomSalt) compare to Database
答案 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。
设定:
验证
通常,出于安全原因,您应该尝试进行时间常数比较,即使这不是密码哈希的问题。此外,通常不区分未知用户和错误密码,只是为了避免向攻击者提供信息。
构造密码散列方案是有意义的,它允许更新迭代量,散列大小,散列函数等。