跳转到内容

密码与密钥管理规范

密码存储、密钥轮换


[Requirement] 用户密码必须使用不可逆哈希存储,禁止明文、禁止可逆加密。

算法是否推荐说明
Argon2id推荐(首选)抗 GPU 暴力破解,可调内存/时间参数
bcrypt推荐成熟稳定,内置盐值,work factor 可调
scrypt可选内存难函数,抗 ASIC
SHA-256 + 盐不推荐速度太快,易被 GPU 暴力破解
MD5 / SHA-1禁止已被破解,不安全

[Standard] 推荐使用 Argon2id,参数:内存 64MB、迭代 3 次、并行度 4;或 bcrypt,cost factor ≥ 12。

[Requirement] 每个密码使用独立随机盐(≥ 16 字节),盐与哈希值一起存储,禁止全局共用一个盐。

[Standard] bcrypt / Argon2 内部已自动生成并存储盐,无需手动处理。

# bcrypt 示例
import bcrypt
 
def hash_password(password: str) -> str:
    salt = bcrypt.gensalt(rounds=12)
    hashed = bcrypt.hashpw(password.encode(), salt)
    return hashed.decode()
 
def verify_password(password: str, hashed: str) -> bool:
    return bcrypt.checkpw(password.encode(), hashed.encode())
# Argon2 示例
from argon2 import PasswordHasher
 
ph = PasswordHasher(time_cost=3, memory_cost=65536, parallelism=4)
 
def hash_password(password: str) -> str:
    return ph.hash(password)
 
def verify_password(password: str, hashed: str) -> bool:
    try:
        return ph.verify(hashed, password)
    except Exception:
        return False

[Standard] 密码长度 ≥ 8 位,建议包含大小写字母、数字、特殊字符中至少 3 种;禁止弱密码(如 123456、password、连续/重复字符)。

[Caution] 不要强制定期改密码(NIST 已不建议),改为检测是否出现在泄露密码库(HIBP)中。

[Requirement] 密码哈希比较使用恒定时间比较(bcrypt/argon2 库内置),禁止用 == 比对哈希字符串,防止时序攻击。


密钥类型示例存储方式访问方式
主密钥(KEK)加密数据密钥的根密钥KMS / HSM,永不离开硬件通过 KMS API 调用
数据密钥(DEK)加密业务数据的密钥加密后存数据库 / 配置由 KEK 解密后使用
应用密钥AppSecret、API Key加密存配置中心 / 环境变量运行时解密
签名密钥JWT 签名密钥、HMAC 密钥KMS / 加密配置运行时加载

[Requirement] 禁止把密钥硬编码在代码、Git 仓库、Docker 镜像中;必须通过环境变量、配置中心(加密)或 KMS 注入。

[Requirement] 生产环境密钥存储于 KMS(如 AWS KMS、阿里云 KMS、HashiCorp Vault)或 HSM,开发/测试环境用本地加密配置文件(如 .env 加 .gitignore)。

[Standard] 密钥按环境隔离(dev / staging / prod 不同密钥),禁止跨环境复用。

# 配置中心加密配置示例(密钥由 KMS 加密后存储)
database:
  host: db.prod.internal
  username: app_user
  password: ENC(AWSCiphertextBlob:AQICAHg...)  # KMS 加密后的密文
jwt:
  secret: ENC(vault:secret/jwt/prod)

[Standard] 应用通过 IAM 角色 / 服务身份从 KMS 获取密钥,密钥不落盘到应用容器,仅在内存中使用。

[Caution] 禁止在日志、异常堆栈、错误信息中输出密钥。


密钥类型轮换周期方式
JWT 签名密钥90 天新旧密钥并存一段时间,平滑过渡
AppSecret / API Key90~180 天生成新密钥 → 双写 → 切换 → 旧密钥过期
数据加密密钥(DEK)180 天重新加密数据(re-encrypt)
主密钥(KEK)1 年KMS 自动轮换
TLS 证书90 天(Let’s Encrypt)自动续期

[Standard] 密钥轮换采用双密钥并行策略:新密钥生效后,旧密钥保留一段时间(一般 1 个轮换周期)用于兼容,确认无流量后再废弃。

1. 生成新密钥并存入 KMS
2. 配置新密钥为"生效中",旧密钥为"待废弃"
3. 应用同时支持新旧密钥(读取时依次尝试)
4. 监控旧密钥使用量,降为 0 后标记为"废弃"
5. 废弃密钥保留 30 天备查,然后彻底删除

[Requirement] 发生密钥泄露事件时,立即触发应急轮换:生成新密钥 → 配置生效 → 旧密钥立即失效(不保留并行期)→ 审计影响范围。


[Requirement] 密钥访问遵循最小权限原则:只有需要解密的服务才能调用 KMS 解密,其他服务只能加密(或完全无权限)。

[Standard] KMS 密钥策略限制:哪些 IAM 角色可以 Decrypt、哪些可以 Encrypt、哪些可以管理密钥。

[Requirement] 禁止开发人员直接访问生产密钥;如需查看,走审批流程,通过临时凭证访问并记录审计日志。

[Caution] 禁止在 IM、邮件、文档中传递生产密钥;密钥传递使用一次性加密链接(如 1Password、Vault)。

[Requirement] CI 流水线集成密钥扫描工具(如 gitleaks、trufflehog、detect-secrets),阻止包含密钥的代码提交。

# gitleaks 扫描示例
gitleaks detect --source . --redact --verbose

[Requirement] 如发现密钥已提交到 Git,必须立即轮换该密钥,并清理 Git 历史(git filter-repo 或 BFG)。


[Requirement] KMS 的所有密钥操作(Create、Encrypt、Decrypt、Rotate、Disable)必须记录审计日志,保留 ≥ 1 年。

[Standard] 审计日志包含:操作时间、操作者(IAM 主体)、操作类型、密钥 ID、调用来源 IP、结果。

[Standard] 对以下行为触发告警:

  • 非工作时间的密钥访问
  • 大量解密操作(可能是批量窃取数据)
  • 密钥管理操作(创建、删除、轮换)
  • 来自非常规 IP 的访问

[Requirement] 密码修改、重置、登录失败等操作记录审计日志,包含用户 ID、时间、IP、结果,便于事后追溯。

[Caution] 审计日志中禁止记录密码明文或哈希值。