知识卡片

Fenix's Bookstore密码存储验证的双重加盐链路

结构图卡

内容

落实[[客户端加密对防泄密无意义但对防服务端滥用密码仍有价值]]和[[保密强度 的六级递进及各自代价]]两个原则的具体实现,是一条”客户端做慢哈希、服务端 再加盐”的链路。客户端:先对明文密码做一次简单哈希(如MD5),再加一个 固定或伪动态盐值防彩虹表,最后用BCrypt这类”慢哈希函数”(通过可调节的 Cost参数控制计算轮数,例如10轮即2¹⁰次运算,把单次计算控制在0.1秒)再 哈希一次——慢哈希的意义是让暴力破解的算力成本高到不现实(按文中估算, 破解10位字母数字弱密码需要百万年级别)。这一步运算压力最大的慢哈希放在 客户端完成,服务端几乎不受影响。服务端收到客户端传来的哈希值后,用密码 学安全伪随机数生成器(CSPRNG)为这条密码单独生成一个随机盐值,把它和 客户端哈希值一起再做一次哈希(如SHA256),最终存入数据库的是”服务端 二次哈希结果+服务端随机盐值”,而非慢哈希本身——因为慢哈希本就是为了让 计算变慢,不适合放在承受大量请求的服务端重复执行。验证登录时只需重放 完全相同的两段计算,比较最终结果是否一致。这套设计让”客户端负责防暴力 破解、服务端负责防批量拖库彩虹表”的职责边界清晰分离。

结构图

flowchart LR
    P[明文密码] -->|简单哈希 MD5| H1[client_hash]
    H1 -->|加客户端固定/伪动态盐值| H2[加盐哈希]
    H2 -->|慢哈希函数 BCrypt, 高计算成本| H3[client_hash最终值, 传输给服务端]
    H3 -->|服务端CSPRNG生成随机盐值| H4[server_salt]
    H3 -->|与server_salt一起再哈希 SHA256| H5[server_hash, 存入数据库]
    H4 -->|与server_hash一并存储| DB[(数据库)]

参考来源

- 位置:《凤凰架构:构建可靠的大型分布式系统》第5章"架构安全性" 5.4.3节"密码存储和验证"(源文件:_epub-src对应OEBPS/Text/chapter69.xhtml) - 结论依据:原文以Fenix's Bookstore真实代码为例,逐步展示客户端简单哈希 +加盐+BCrypt慢哈希,以及服务端用CSPRNG生成随机盐值再做一次哈希存储的 完整链路,并说明慢哈希放客户端、快哈希放服务端的分工理由,直接支撑 本卡片的结构梳理。 - 原始内容:慢哈希函数是指执行时间可以调节的哈希函数……由于慢哈希算法 占用大量处理器资源,笔者并不推荐在服务端中采用……以上加密存储的过程 相对复杂,但是运算压力最大的过程(慢哈希)是在客户端完成的,对服务端 压力很小。