4. 密钥生命周期管理基础
JWT 的安全性并不只取决于签名算法本身,更取决于签名密钥在整个生命周期中是否被正确管理。一个使用 HS256 的系统,如果密钥是 "secret"、被硬编码进前端、在多个环境复用、三年不轮换,那么它和没有签名几乎没有区别。密钥生命周期管理要解决的正是这类问题:密钥从哪来、怎么安全地送到使用方、放在哪里、多久换一次、旧密钥怎么处理、最终如何销毁。
NIST SP 800-57 Part 1 把密钥生命周期划分为若干阶段,核心思想是:密钥不是"生成后一直用"的静态资源,而是有明确状态和时限的对象。OWASP 的 JWT 与密钥管理建议则更贴近工程实践,强调密钥强度、环境隔离、轮换机制和泄露响应。本节把两者结合,按六个阶段展开。
一、密钥生成:熵源与算法匹配
密钥生成的第一原则是使用密码学安全的随机数生成器(CSPRNG),而不是 Math.random()、时间戳或自增 ID。对于 HS256,密钥长度应至少等于哈希输出长度,即 256 位(32 字节);对于 RS256/ES256,应使用 2048 位以上 RSA 或 P-256 曲线。生成方式示例:
# 生成 32 字节 HS256 密钥(Base64 编码)
openssl rand -base64 32
# 生成 RSA 2048 私钥
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private.pem
# 生成 EC P-256 私钥
openssl ecparam -name prime256v1 -genkey -noout -out ec-private.pem
生成环境必须是受控的、离线的或受严格访问控制的主机。密钥一旦生成,应立即分配唯一标识(如 kid)和元数据:创建时间、用途、算法、所属环境、预计轮换周期。这些元数据是后续轮换和审计的基础。
二、分发:最小暴露面
密钥分发是最容易出问题的环节。常见错误包括:通过邮件发送、提交到 Git 仓库、写入前端代码、在日志中打印。正确做法是让密钥通过受控通道进入运行时:
- 使用密钥管理服务(KMS)或密钥库(Vault)动态下发,应用启动时拉取,不落盘。
- 通过环境变量或挂载的 Secret 卷注入,避免写入镜像层。
- 分发通道本身要加密并鉴权,接收方需验证来源。
OWASP 特别强调:签名密钥绝不能出现在客户端。JWT 的验证密钥(公钥)可以公开,但签名密钥(私钥/对称密钥)只能存在于服务端可信执行环境中。
三、存储:分级保护
存储策略取决于密钥敏感级别。对称密钥(HS256)和私钥(RS256/ES256)属于最高敏感级别,应存储在硬件安全模块(HSM)、KMS 或专用密钥库中,应用通过 API 调用签名操作,密钥本身不离开安全边界。次一级可用加密的配置中心或 Secret 管理系统,配合静态加密和访问审计。最低要求是:不硬编码、不进版本库、不写日志、不随镜像分发。
JWT_SECRET 写进 docker-compose.yml 并提交到仓库;或在 CI 日志中回显环境变量。这类泄露往往在很久后才被发现,且无法判断是否已被利用。四、轮换:平滑过渡的关键
轮换是指用新密钥替换旧密钥,同时保证已签发令牌仍可验证。JWT 的无状态特性使轮换变得微妙:如果直接替换密钥,所有旧令牌立即失效,用户被迫重新登录。工程上通常采用"双密钥过渡":
- 生成新密钥,分配新的
kid,加入 JWKS(JSON Web Key Set)。 - 签发端开始用新密钥签名,令牌头部携带新
kid。 - 验证端根据
kid从 JWKS 选择对应密钥,旧令牌仍用旧密钥验证。 - 等待旧令牌最大有效期(如 24 小时)过后,从 JWKS 移除旧密钥。
轮换周期没有统一标准。NIST 建议根据密钥用途和风险设定密码期(cryptoperiod),高价值密钥可短至数月,低风险可一年。OWASP 更关注"是否具备轮换能力"——即使不频繁轮换,也必须能在泄露时快速完成。下面这张图展示了双密钥过渡期间,签发与验证两侧如何按 kid 协同:
五、归档与销毁
归档针对的是已停用但可能仍需验证历史令牌的密钥。例如审计要求保留过去 90 天的令牌验证能力,则旧密钥不能立即删除,而应移入归档区:只读、禁止签发、访问受审计、设置明确的保留期限。归档密钥与活跃密钥必须物理或逻辑隔离,避免误用。
销毁是生命周期的终点。NIST 要求密钥销毁应使其不可恢复,包括覆盖存储介质、撤销 KMS 中的密钥材料、清除缓存和备份中的副本。销毁前需确认:没有未过期令牌仍依赖该密钥、没有正在进行的验证请求、归档保留期已到。销毁动作本身应记录审计日志,包含密钥 ID、销毁时间、操作人和依据。
六、NIST 与 OWASP 要点对照
| 关注点 | NIST SP 800-57 侧重 | OWASP 侧重 |
|---|---|---|
| 生成 | 规定密钥强度、密码期、状态模型 | 强调 CSPRNG、禁止弱密钥与默认密钥 |
| 分发 | 密钥传输保护、实体鉴权 | 禁止密钥进入客户端、日志、仓库 |
| 存储 | 按敏感级别分级,HSM/KMS | 环境隔离、Secret 管理、最小权限 |
| 轮换 | 设定密码期,到期必须更换 | 必须具备快速轮换与泄露响应能力 |
| 归档/销毁 | 明确保留期与不可恢复销毁 | 审计可追溯,避免僵尸密钥 |
把六个阶段串起来看,密钥治理的本质是"可控、可换、可查"。可控指生成和存储受严格保护;可换指轮换不影响业务连续性;可查指每一步都有元数据和审计记录。对 JWT 系统而言,最实用的落地起点是:立即检查是否存在硬编码密钥,建立 JWKS 端点,实现基于 kid 的双密钥轮换,并为每把密钥记录创建时间与轮换期限。做到这四点,就已经覆盖了生命周期管理中最关键的风险面。