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

How does postgresql's crypt() function know that a password matches a stored one?

我正在学习使用 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” "$2a$06$.lub5s4Eqz4.epcg5zW4KervErzw//uARn8F2gchj2wM11ok.MJLK" 对于 hashResult "$2a$06$.lub5s4Eqz4.epcg5zW4KervErzw//uARn8F2gchj2wM11ok.MJLK" for authenticationPassword

为什么 authenticationPasswordhashResult 一样,我期待它用 hashResult 作为盐再次散列它。

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

P.S : 我知道如何使用 storing/retrieving 密码的功能,但我不明白它是如何做到的。

感谢您的帮助,

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

诀窍是当一个新密码被散列时(不是在验证它时)引擎会为它选择一个全新的随机盐,所以它几乎不可能从散列结果中猜出它。

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

public.crypt('password', 'a$.lub5s4Eqz4.epcg5zW4Ke')
public.crypt('password', 'a$.lub5s4Eqz4.epcg5zW4KervErzw//uARn8F2gchj2wM11ok.MJLK')
public.crypt('password', 'a$.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