PostgreSQL的crypt()函数如何判断输入密码与存储密码匹配?
pgcrypto
crypt() 密码校验的底层实现逻辑 核心原理:基于Modular Crypt Format(MCF)的结构化字符串解析
crypt() 的第二个参数从来不是单纯的随机盐值,而是符合MCF规范的结构化字符串,函数会自动按规则解析出加密所需的所有参数,不会把传入的整个字符串当作盐处理。
你示例中用到的bcrypt算法(对应gen_salt('bf'))生成的MCF串格式为:$算法标识$成本系数$盐值+哈希密文
对应你给出的执行结果拆解:
- 生成的盐
$2a$06$.lub5s4Eqz4.epcg5zW4Ke$2a$:bcrypt算法的标识06:迭代成本系数,对应bcrypt的计算轮次为2^6=64轮.lub5s4Eqz4.epcg5zW4Ke:实际的22位随机盐值
- 最终哈希结果
$2a$06$.lub5s4Eqz4.epcg5zW4KervErzw//uARn8F2gchj2wM11ok.MJLK
前三个部分和盐完全一致,后面的rvErzw//uARn8F2gchj2wM11ok.MJLK是明文密码经过计算得到的哈希密文。
crypt() 函数的固定执行逻辑
不管第二个参数传入的是gen_salt生成的盐前缀,还是完整的存储哈希串,crypt() 都会按照统一流程执行:
- 匹配开头的
$x$格式标识,确定使用的哈希算法 - 提取成本系数参数
- 按对应算法的盐长度规则,截取指定长度的字符作为实际盐值(bcrypt固定取22位,后续字符直接忽略)
- 用提取到的算法、成本系数、盐值,对输入的明文密码做哈希计算
- 输出完整的MCF格式串:算法标识+成本系数+盐值+新计算出的哈希密文
示例中两次哈希结果一致的原因
- 第一次调用
crypt('password', generated_salt):解析出的参数为bcrypt算法、6轮成本、盐值.lub5s4Eqz4.epcg5zW4Ke,计算得到完整哈希串 - 第二次调用
crypt('password', hashResult):解析时直接忽略了hashResult末尾的哈希密文部分,提取到的算法、成本、盐值和第一次完全一致,输入的明文密码也相同,最终计算出的完整哈希串自然和存储的hashResult完全相等。
crypt() 本身不需要区分「生成新哈希」还是「校验密码」,它只负责按参数计算哈希,你只需要把计算结果和存储的哈希串做等值比较即可完成校验。
内容的提问来源于stack exchange,提问作者Varadus
相关产品推荐
相关产品推荐

