This repository has been archived on 2026-05-19. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
obsidian/金山办公作业/Week06/bcrypt成本因子.md
T

3.3 KiB
Raw Blame History

tags, create time
tags create time
go
security
bcrypt
password-hashing
cost-factor
2026-04-25 14:45

bcrypt 成本因子(Cost Factor)详解

概述

成本因子是 bcrypt 算法的核心参数,控制哈希计算的"难度"。它是平衡安全性和性能的关键旋钮。

什么是成本因子?

bcrypt 不是做一次哈希就完事,而是通过 多次迭代 来增加暴力破解的计算成本。成本因子(cost)就是这个迭代次数的对数指数:

实际迭代次数 = 2^cost

所以在 Go 中:

import "golang.org/x/crypto/bcrypt"

// bcrypt.DefaultCost = 10 → 2^10 = 1024 次迭代
hash, _ := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost)

不同成本因子的对比

成本值 迭代次数 单次哈希耗时 适用场景
4 16 ~1ms 本地开发、测试
8 256 ~50ms 低流量内部系统
10 1,024 ~100-300ms 生产环境默认
12 4,096 ~500ms 高安全需求
14 16,384 ~2s 极低频登录场景

💡 想一想:成本因子是不是越高越好?为什么?

答案:不是。成本越高,合法用户登录时服务器也要做同等次数的计算。过高的成本会导致登录延迟,影响用户体验,也给服务器带来不必要的负载。

如何选择合适的成本?

选择原则

目标:让单次哈希耗时在 100ms ~ 300ms 之间

这个区间意味着:

  • 对合法用户:几乎无感,登录流畅
  • 对攻击者:暴力破解速度被大幅压制(每秒只能尝试 3~10 次)

调整方式

// 生产环境手动调高
hash, _ := bcrypt.GenerateFromPassword([]byte(pwd), 12)

// 也可以手动降低(仅开发环境)
hash, _ := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.MinCost) // MinCost = 4

成本因子的"升级陷阱"

一个容易被忽视的问题:当硬件变快后,原来合适的成本因子会变得不够安全。

// 2024 年的机器比 2018 年快很多
// 当年 cost=10 是 200ms,现在可能只要 80ms

// 解决方案:用户登录时检查并升级哈希
func Login(username, password string) error {
    user := db.GetUser(username)
    bcrypt.CompareHashAndPassword(user.Hash, []byte(password))

    // 检测当前哈希的成本是否偏低
    currentCost, _ := bcrypt.Cost(user.Hash)
    if currentCost < bcrypt.DefaultCost {
        // 用更高的成本重新哈希并保存
        newHash, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
        db.UpdateHash(username, newHash)
    }
}

💡 想一想:为什么要在登录时"顺便"升级哈希,而不是批量扫描全量用户?

答案:惰性升级(lazy upgrade)避免一次性计算压力过大,且只升级活跃用户的哈希,不活跃用户的旧哈希影响较小。

最佳实践

✅ 推荐

  • 生产环境默认 bcrypt.DefaultCost(10)
  • 定期评估并逐步提升成本因子
  • 登录时惰性升级低于最低成本的哈希

❌ 避免

  • 在生产环境使用 < 10 的成本
  • 为每个用户设置不同的成本(增加复杂度且收益有限)
  • 为了追求极致安全而盲目调高到 14+

关联笔记