4. Cosign 基础操作:签名、验证与存储解析
Cosign 是 Sigstore 项目原生的容器镜像签名工具,支持对 OCI 制品进行密钥对签名、密钥less 签名(Keyless Signing)以及验证。本章将围绕 Cosign 的核心操作展开,涵盖签名生成、验证流程、签名信息查看以及签名格式与存储位置的底层原理。
前置条件: 已安装 Cosign 二进制(≥ v2.0),并拥有一个可访问的容器镜像仓库(如 Docker Hub、Harbor 或 GHCR)。本示例使用镜像
registry.example.com/app:v1 作为操作对象。
4.1 使用 Cosign 对容器镜像签名
Cosign 支持两种签名模式:密钥对签名(使用本地生成的私钥/公钥)和 Keyless 签名(基于 OIDC 身份与 Fulcio 证书)。以下分别演示两种方式。
4.1.1 密钥对签名
- 生成密钥对:
执行后会在当前目录生成cosign generate-key-paircosign.key(私钥)和cosign.pub(公钥)。私钥需设置密码保护。 - 对镜像签名:
输入私钥密码后,Cosign 会计算镜像摘要,生成签名负载并将其推送到镜像仓库。cosign sign --key cosign.key registry.example.com/app:v1
4.1.2 Keyless 签名(无密钥模式)
- 直接执行签名命令:
系统会自动打开浏览器进行 OIDC 身份认证(支持 GitHub、Google、Microsoft 等)。cosign sign registry.example.com/app:v1 - 认证完成后,Cosign 会向 Fulcio 申请短期证书,并用该证书对镜像签名,同时将签名记录上传至 Rekor 透明日志。
推荐实践: 在 CI/CD 流水线中优先使用 Keyless 签名,避免私钥管理负担;在离线或内网环境使用密钥对签名。
4.2 验证签名
验证签名是确保镜像来源可信的关键步骤。Cosign 提供 verify 命令,支持基于公钥或 Keyless 方式的验证。
4.2.1 基于公钥验证
cosign verify --key cosign.pub registry.example.com/app:v1
输出示例:
Verification for registry.example.com/app:v1 --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- The signatures were verified using the specified public key
- Any certificates were verified against the Fulcio roots.
[{"critical":{"identity":{"docker-reference":"registry.example.com/app:v1"},"image":{"docker-manifest-digest":"sha256:abc123..."},"type":"cosign container image signature"},"optional":null}]
4.2.2 Keyless 验证
cosign verify registry.example.com/app:v1
Cosign 会自动从 Rekor 日志中检索签名证书,并验证证书链是否由 Fulcio 签发,同时检查镜像摘要是否匹配。
注意: Keyless 验证要求网络能够访问 Rekor 和 Fulcio 服务。若在离线环境,需提前缓存信任根(trust root)。
4.3 查看签名信息
使用 cosign verify 输出的 JSON 格式签名信息包含以下关键字段:
| 字段 | 说明 | 示例值 |
|---|---|---|
critical.identity.docker-reference |
被签名镜像的完整引用 | registry.example.com/app:v1 |
critical.image.docker-manifest-digest |
镜像清单的 SHA256 摘要 | sha256:abc123... |
critical.type |
签名类型标识 | cosign container image signature |
optional |
可选的附加元数据(如 CI 流水线 ID) | {"build":"jenkins-123"} |
若要查看更底层的签名原始数据,可使用 cosign verify-attestation 或直接通过 OCI 仓库 API 拉取签名层。
4.4 签名格式与存储位置
Cosign 将签名作为 OCI 制品存储在镜像仓库中,遵循 cosign 签名规范。签名并不直接修改原始镜像层,而是以独立的标签或引用形式存在。
4.4.1 签名存储结构
当对 registry.example.com/app:v1 签名后,仓库中会新增以下内容:
- 签名标签:
registry.example.com/app:sha256-<digest>.sig— 存储签名负载(Base64 编码的签名值)。 - 证书标签(Keyless 模式):
registry.example.com/app:sha256-<digest>.cert— 存储 Fulcio 签发的短期证书。 - 可选的附加信息: 如
.att标签用于存储 SBOM 或 attestation 断言。
4.4.2 签名格式解析
签名负载本身是一个 JSON 结构,包含以下核心部分:
{
"payloadType": "application/vnd.dev.cosign.simplesigning.v1+json",
"payload": "eyJjcml0aWNhbCI6eyJpZGVudGl0eSI6eyJkb2NrZXItcmVmZXJlbmNlIjoicmVnaXN0cnkuZXhhbXBsZS5jb20vYXBwOnYxIn0sImltYWdlIjp7ImRvY2tlci1tYW5pZmVzdC1kaWdlc3QiOiJzaGEyNTY6YWJjMTIzLi4uIn0sInR5cGUiOiJjb3NpZ24gY29udGFpbmVyIGltYWdlIHNpZ25hdHVyZSJ9LCJvcHRpb25hbCI6bnVsbH0=",
"signatures": [
{
"keyid": "",
"sig": "MEUCIQ..."
}
]
}
payloadType:固定为application/vnd.dev.cosign.simplesigning.v1+json。payload:Base64 编码的 简单签名负载(Simple Signing Payload),包含镜像引用和摘要。signatures:签名值数组,每个元素包含keyid和sig(Base64 编码的签名结果)。
4.4.3 存储位置示意图
下图展示了 Cosign 签名在 OCI 仓库中的存储布局:
4.5 操作流程总结
以下表格对比了密钥对签名与 Keyless 签名的核心差异:
| 维度 | 密钥对签名 | Keyless 签名 |
|---|---|---|
| 身份绑定 | 基于本地公钥指纹 | 基于 OIDC 身份(邮箱、用户名) |
| 密钥管理 | 需安全存储私钥 | 无需管理长期密钥 |
| 可审计性 | 依赖公钥分发 | 依赖 Rekor 透明日志 |
| 离线支持 | 完全支持 | 需预缓存信任根 |
| 推荐场景 | 内网、离线环境 | CI/CD、公有云环境 |