CryptContext 哈希如何知道使用什么秘密?

How does CryptContext hashing know what secret to use?

我有以下代码片段:

from passlib.context import CryptContext

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
pwd_context.hash(password)

描述的是here

我不明白的是,如果一直 returns 相同的散列密码而不考虑另一个 secret_key 来散列密码值,这怎么可能安全?

您假设它一直 returns 相同的散列密码而不考虑另一个“秘密”(嗯,这不是真正的秘密)是错误的;如果你 运行 pwd_context.hash 多次你会看到这个:

>>> from passlib.context import CryptContext
>>>
>>> pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
>>> pwd_context.hash("test")
'b[=10=]qdOrAMoK7dgySjmNbyRpOggbk.IM2vffMh8rFoITorRKabyFiElC'
>>> pwd_context.hash("test")
'b$gqaNzwTmjAQbGW/08zs4guq1xWD/g7JkWtKqE2BWo6nU1TyP37Feq'

如您所见,这两个哈希值并不相同 - 即使给定相同的密码。那么到底发生了什么?

当您不给 hash 明确的盐(您正在谈论的秘密“密钥”)时 one will be generated for you by passlib。值得指出的是,散列与加密不同,因此没有 key 可谈。相反,您会看到提到的 salt,这是一个明文值,用于确保相同的密码经过两次哈希处理后会产生不同的结果(因为您实际上是在对 salt + password 进行哈希处理)。

那么为什么我们会得到两个不同的值呢? salt 是实际 bcrypt 值的前 22 个字符。这些字段由 $ 分隔 - 2b 表示 bcrypt,12 表示 12 轮,下一个字符串是为密码存储的实际结果值(salt + resulting bcrypt hash)。此字符串的前 22 个字符是散列。

如果你给 bcrypt 一个 salt 而不是让它生成一个 salt,你就会看到这一点(我们将忽略这里可能出现的关于小填充的警告,但为了展示这个概念):

>>> pwd_context.hash("test", salt="a"*22)
'b$aaaaaaaaaaaaaaaaaaaaaOm/4kNFO.mb908CDiMw1TgDxyZeDSwum'
        ^-------------------^

如果我们明确给出相同的哈希值,结果应该是相同的(这也是您稍后验证密码的方式):

>>> pwd_context.hash("test", salt="a"*22)
'b$aaaaaaaaaaaaaaaaaaaaaOm/4kNFO.mb908CDiMw1TgDxyZeDSwum'
>>> pwd_context.hash("test", salt="a"*22)
'b$aaaaaaaaaaaaaaaaaaaaaOm/4kNFO.mb908CDiMw1TgDxyZeDSwum'

前面的哈希也是如此:

>>> pwd_context.hash("test")
'b$gqaNzwTmjAQbGW/08zs4guq1xWD/g7JkWtKqE2BWo6nU1TyP37Feq'
        ^-------------------^

这是实际生成的盐,然后与 test 一起使用来创建实际的散列:

>>> pwd_context.hash("test")
'b$gqaNzwTmjAQbGW/08zs4guq1xWD/g7JkWtKqE2BWo6nU1TyP37Feq'
                             ^------------------------------^

那么,当每个人都清楚地看到这种盐时,我们为什么要使用它呢?这使得仅扫描已知散列的散列列表变得不可能 - 因为列表中的 test 将具有与您正在比较的列表中的 test 不同的值(因为不同盐),您必须实际 测试猜测的密码及其盐,并通过散列算法运行 测试它们。 bcrypt 明确设计为使该过程需要时间,因此与仅扫描 2 亿个密码列表并在数据库中搜索已知哈希相比,您尝试破解密码所花费的时间要长得多。

当计算机变得更快时,您会怎么做?您增加 12 参数 - rounds - 这会增加散列算法的 运行 时间,希望在更长时间内保持更安全(您可以试验 rounds 参数以passlib.hash).