签名密钥管理
概述
签名密钥(Signing Keys)是 Code Bird Cloud 中用于对 OIDC 令牌进行数字签名的核心安全组件。系统使用 ECDSA ES256 算法对 JWT 令牌(包括 Access Token、ID Token)进行签名,确保令牌的完整性和不可伪造性。资源服务器和客户端通过 JWKS(JSON Web Key Set)端点获取公钥来验证令牌的合法性。
核心概念
OIDC 令牌签名
在 OIDC/OAuth 2.1 协议中,身份提供方(Identity Provider)使用私钥对 JWT 令牌进行签名。令牌接收方(如资源服务器、前端应用)通过公开的 JWKS 端点获取对应的公钥,验证令牌签名是否有效。这一机制确保了:
- 完整性:令牌内容未被篡改
- 来源可信:令牌确实由 Code Bird Cloud 签发
- 不可否认性:签发方无法否认已签发的令牌
ES256 算法
Code Bird Cloud 使用 ECDSA(Elliptic Curve Digital Signature Algorithm)的 ES256 变体进行令牌签名:
| 属性 | 值 |
|---|---|
| 算法名称 | ES256 |
| 全称 | ECDSA using P-256 curve and SHA-256 hash |
| 密钥类型 | EC(Elliptic Curve) |
| 曲线 | P-256(secp256r1) |
与 RSA 相比,ES256 在相同安全级别下具有以下优势:
- 密钥长度更短(256 位 vs RSA 2048 位)
- 签名速度更快
- 生成的签名数据更小,有利于减少令牌体积
密钥列表
系统维护一个签名密钥列表,包含当前活跃密钥和历史保留密钥。
列表字段
| 字段 | 类型 | 说明 |
|---|---|---|
| ID | string | 密钥的唯一标识(Key ID,对应 JWT 头部的 kid 字段) |
| 密钥类型 | string | 密钥的类型(如 EC) |
| 算法 | string | 签名算法(如 ES256) |
| 状态 | string | 密钥状态:active(当前活跃)或 previous(已轮换的旧密钥) |
| JWK | object | JSON Web Key 格式的公钥数据 |
| 创建时间 | string | 密钥创建时间(ISO 8601 格式) |
状态为 active 的密钥用于签发新令牌;状态为 previous 的密钥仍用于验证旧令牌,直到这些令牌过期。
密钥轮换
密钥轮换(Key Rotation)是定期更换签名密钥的安全操作,旨在限制单一密钥的使用寿命,降低密钥泄露带来的风险。
何时执行轮换
| 场景 | 说明 |
|---|---|
| 定期轮换 | 建议每 90 天执行一次密钥轮换,作为安全最佳实践 |
| 密钥泄露 | 如果怀疑私钥可能泄露,应立即执行密钥轮换 |
| 安全合规 | 满足安全合规要求中关于密钥管理周期的规定 |
轮换流程
密钥轮换遵循以下步骤:
1. 生成新密钥
系统生成新的 ECDSA 密钥对(ES256 算法)
2. 新密钥激活
新密钥立即设为 active 状态,后续签发的令牌使用新密钥签名
3. 旧密钥保留
当前活跃密钥状态变为 previous,仍保留在 JWKS 中
使用旧密钥签发的令牌在有效期内仍可正常验证
4. 清理旧密钥
待所有使用旧密钥签发的令牌过期后,管理员可手动删除旧密钥轮换 API
POST /api/v1/signing-keys/rotate请求示例:
curl -X POST https://your-domain/api/v1/signing-keys/rotate \
-H "Authorization: Bearer <admin_token>"成功响应:
{
"code": 0,
"message": "success",
"result": {
"id": "sk_002",
"status": "active",
"algorithm": "ES256",
"created_at": "2025-06-15T08:00:00Z"
}
}建议:在业务低峰期执行密钥轮换操作,JWKS 端点会自动包含所有状态的公钥。
删除旧密钥
当旧密钥签发的所有令牌都已过期后,可以删除旧密钥以保持密钥列表整洁。
警告:删除仍有令牌在使用的密钥会导致这些令牌验证失败。删除前请确保:
- 所有使用该密钥签发的 Access Token 已过期
- 所有使用该密钥签发的 ID Token 已过期
- 所有使用该密钥签发的 Refresh Token 已过期或已被刷新
不允许删除当前状态为 active 的密钥。如果尝试删除活跃密钥,API 将返回 400 错误。
JWKS 端点
客户端和资源服务器通过 JWKS 端点获取公钥信息来验证令牌签名:
GET /.well-known/jwks.json该端点返回当前所有有效签名密钥的公钥部分(包括 active 和 previous 状态的密钥)。客户端根据令牌头部的 kid(Key ID)字段匹配对应的公钥进行验证。
JWKS 端点是公开的,不需要认证即可访问。依赖方应通过此端点动态获取公钥,而非硬编码公钥内容。
API 参考
所有管理接口均需要管理员令牌认证:
Authorization: Bearer <admin_token>
获取签名密钥列表
GET /api/v1/signing-keys返回所有签名密钥,包含当前活跃密钥和历史密钥。
轮换签名密钥
POST /api/v1/signing-keys/rotate生成新的签名密钥并设为活跃状态,当前活跃密钥变为 previous 状态。
删除签名密钥
DELETE /api/v1/signing-keys/:id删除指定的签名密钥。不允许删除当前活跃密钥。
| 路径参数 | 类型 | 说明 |
|---|---|---|
id | string | 签名密钥 ID |
详细的请求和响应格式请参阅 签名密钥 API 参考。
安全最佳实践
- 定期轮换:即使没有安全事件,也建议每季度(90 天)轮换一次签名密钥
- 及时清理:旧密钥对应的令牌全部过期后,及时删除旧密钥,减少密钥暴露面
- 访问控制:仅授权超级管理员管理签名密钥,避免密钥管理权限泄露
- 动态获取公钥:依赖方应通过
/.well-known/jwks.json端点动态获取公钥,切勿硬编码 - 监控审计:关注签名密钥相关的操作日志,确保所有密钥操作可追溯
- 应急预案:制定密钥泄露应急响应预案,确保可以在最短时间内完成密钥轮换并通知下游服务
相关文档
- 签名密钥 API 参考 -- 完整的 API 接口文档
- 审计日志 -- 查看密钥操作的审计记录
- OIDC / OAuth 2.1 基础 -- 了解令牌签名的协议背景
