postgresql 的 crypt() 函数如何知道密码与存储的密码匹配?

Posted

技术标签:

【中文标题】postgresql 的 crypt() 函数如何知道密码与存储的密码匹配?【英文标题】:How does postgresql's crypt() function know that a password matches a stored one? 【发布时间】:2021-12-05 21:19:13 【问题描述】:

我正在学习使用 pgcrypto 中的 crypt() 函数来加密我的密码并将其存储到用户表中。

但是我不明白如果我们将现有密码作为第二个参数传递,crypt 函数如何生成相同的密码。

我想了解它是如何做到的。

do $$
declare
   generated_salt text;
   hashResult text;
   authenticationPassword text;
begin
   -- select the number of actors from the actor table
   select public.gen_salt('bf')
   into generated_salt;
   
   select public.crypt('password', generated_salt)
   into hashResult;
   
   select public.crypt('password', hashResult)
   into authenticationPassword;

   -- show the number of actors
   raise notice 'Generated salt : %', generated_salt;
   raise notice 'Hash result : %', hashResult;
   raise notice 'authenticationPassword : %', authenticationPassword;
end; $$

在上面的示例中,如果我执行并存储变量的值。

我得到: generated_salt 的“$2a$06$.lub5s4Eqz4.epcg5zW4Ke” hashResult 的“$2a$06$.lub5s4Eqz4.epcg5zW4KervErzw//uARn8F2gchj2wM11ok.MJLK” authenticationPassword

的“$2a$06$.lub5s4Eqz4.epcg5zW4KervErzw//uARn8F2gchj2wM11ok.MJLK”

为什么 authenticationPasswordhashResult 相同,我原以为它会用 hashResult 作为盐再次对其进行哈希处理。

它如何判断它是否必须识别和计算相同的密码或基于盐生成新的哈希?

P.S : 我了解如何使用该功能来存储/检索密码,但我不明白它是如何做到的。

感谢您的帮助,

【问题讨论】:

【参考方案1】:

只要您使用相同的盐,生成的哈希对于每个密码将始终是相同的。这是验证密码时发生的情况。

诀窍在于,在对新密码进行哈希处理时(而不是在验证密码时),引擎会为其选择一个全新的随机盐,因此几乎不可能从哈希结果中猜出它。

【讨论】:

感谢您的回答,但仍然如此。我不明白的是,当我将它 hashResult 作为第二个参数时。 select public.crypt('password', hashResult) into authenticationPassword; 它不使用 hashResult 作为哈希来生成新密码,但它会生成相同的密码,这怎么可能,因为 hashResultgenerated_salt 价值观不同?谢谢。 请注意 generated_salt 和 hashResult 的前 29 个字符 not 有何不同?这不是巧合。【参考方案2】:

我终于明白发生了什么,crypt 函数只使用前 29 个字符(作为 salt 传递)来生成 hashOutput,所以即使你在这 29 个字符后面放了任何东西,结果也是一样的。示例:

public.crypt('password', '$2a$06$.lub5s4Eqz4.epcg5zW4Ke')
public.crypt('password', '$2a$06$.lub5s4Eqz4.epcg5zW4KervErzw//uARn8F2gchj2wM11ok.MJLK')
public.crypt('password', '$2a$06$.lub5s4Eqz4.epcg5zW4Keyadayadayadayada')

上面 3 行的结果总是 $2a$06$.lub5s4Eqz4.epcg5zW4KervErzw//uARn8F2gchj2wM11ok.MJLK 真正重要的是前 29 个字符 $2a$06$.lub5s4Eqz4.epcg5zW4Ke 和决定 29 个字符后生成什么的密码值:rvErzw//uARn8F2gchj2wM11ok.MJLK

pgcrypto 的源代码帮助我了解了幕后发生的事情:https://github.com/postgres/postgres/tree/master/contrib/pgcrypto

【讨论】:

以上是关于postgresql 的 crypt() 函数如何知道密码与存储的密码匹配?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 NODE.JS 上模拟 php crypt()

linux下c语言的crypt函数怎么用?

为啥 PHP crypt 函数使用 DES 加密算法?

crypt():没有指定盐参数。您必须使用随机生成的盐和强哈希函数来生成安全哈希 [重复]

如何在带有 sha512 的 freeBSD 上使用 crypt()?

如何让 Ubuntu 的 crypt(3) 支持 Blowfish?