4. 签名技术选型:GPG、Sigstore/Cosign、JWT签名对比与适用场景

在CI/CD流水线中,构建产物的签名技术直接决定了完整性验证与来源可信度的根基。当前主流方案包括GPG、Sigstore/Cosign以及JWT签名,三者分别代表了传统PKI、现代无密钥基础设施和令牌化签名的不同路径。本章从技术原理、密钥管理、验证效率、合规阻断能力四个维度进行系统对比,并给出明确的场景选型建议。

核心观点:没有“最好”的签名技术,只有“最适配”流水线合规策略的选型。GPG适合遗留系统与离线环境,Sigstore/Cosign是云原生与供应链安全的首选,JWT签名则适用于短生命周期、高频率的微服务产物。

4.1 技术原理与密钥管理对比

维度 GPG Sigstore / Cosign JWT 签名
密钥模型 非对称密钥对(公钥/私钥),用户自行生成与管理 基于OIDC身份 + 临时密钥对,密钥由Fulcio CA签发 对称密钥(HMAC)或非对称密钥(RS/ES系列)
密钥生命周期 长期有效,需手动轮换与吊销 临时密钥(通常数分钟),自动轮换 由签发方控制,可短时效(如5分钟)
公钥分发 需独立部署公钥服务器或手动导入 公钥通过Rekor透明日志自动记录,无需手动分发 公钥/密钥需通过安全通道预先共享
签名内容 对文件哈希或文件本身签名 对容器镜像、blob或附件签名 对JSON Payload签名,常用于API令牌
验证依赖 本地GPG密钥环 + 公钥 Cosign CLI + Sigstore公共/私有实例 JWT库 + 预共享密钥或公钥
选型提示:GPG的密钥管理成本最高,尤其在多团队、多流水线场景下,公钥分发与吊销极易出现“孤儿密钥”。Sigstore通过透明日志解决了这一痛点,但需要依赖外部CA服务。

4.2 签名验证流程与性能特征

三种技术在流水线中的验证流程差异显著,直接影响OPA策略的阻断点设计。

  • GPG验证流程:下载产物 → 获取签名文件(.asc) → 导入公钥 → gpg --verify → 输出状态码。验证耗时约50-200ms,公钥缺失时需回退到密钥服务器查询。
  • Cosign验证流程:拉取镜像 → cosign verify → 自动查询Rekor日志 → 验证证书链 → 输出Payload。验证耗时约200-500ms,依赖网络与透明日志可用性。
  • JWT签名验证流程:解析JWT → 获取kid → 查找公钥 → 验签 → 校验exp/nbf/iss。验证耗时约1-10ms,性能最优,但需要预先缓存公钥。
性能陷阱:在流水线中,如果每批次构建产物超过1000个,GPG和Cosign的串行验证可能成为瓶颈。建议使用OPA的data.artifacts.verify_batch规则进行批量验证,而非逐个调用外部命令。

4.3 适用场景矩阵

场景特征 推荐方案 理由
遗留Java JAR/WAR签名 GPG 与现有Maven/Gradle插件兼容,离线验证成熟
容器镜像签名(Kubernetes部署) Sigstore / Cosign 原生支持OCI镜像,与Kyverno/OPA Gatekeeper集成
微服务间API令牌签名 JWT 轻量、无状态、支持短时效,适合服务网格
多团队、多仓库的供应链安全 Sigstore / Cosign 透明日志提供全局可审计性,无需逐团队分发公钥
离线/内网环境(无互联网) GPG 完全自包含,不依赖外部CA或透明日志
CI/CD流水线产物(通用二进制) Cosign(blob签名) 支持任意文件类型,验证命令统一
签名技术选型决策树 构建产物需要签名? 离线/内网环境? 云原生/互联网可达? 推荐:GPG 产物类型? 容器镜像/Blob API令牌/JSON 推荐:Sigstore/Cosign 推荐:JWT签名 决策依据:网络可达性 + 产物类型

4.4 OPA策略中的签名验证集成模式

无论选择哪种签名技术,OPA策略的验证逻辑都应遵循统一的“验证-断言-阻断”模式。以下展示三种技术对应的Rego规则片段。

4.4.1 GPG验证的Rego规则

package artifacts.signature

# 输入:构建产物元数据,包含签名指纹与公钥ID
default allow = false

allow {
    input.signature.type == "gpg"
    input.signature.key_id == "0xABCDEF1234567890"
    input.signature.verification_status == "success"
    # 可选:检查签名时间是否在证书有效期内
    input.signature.timestamp >= input.signature.key_valid_from
    input.signature.timestamp <= input.signature.key_valid_to
}

4.4.2 Cosign验证的Rego规则

package artifacts.signature

# 输入:Cosign验证输出的JSON结果
default allow = false

allow {
    input.signature.type == "cosign"
    input.signature.verified == true
    input.signature.identity.issuer == "https://.actions.githubusercontent.com"
    input.signature.identity.subject == "repo:my-org/my-repo:.github/workflows/release.yml"
    # 强制要求透明日志条目存在
    input.signature.rekor_entry != null
    input.signature.rekor_entry.inclusion_proof == true
}

4.4.3 JWT签名验证的Rego规则

package artifacts.signature

# 输入:JWT解码后的Payload与签名元数据
default allow = false

allow {
    input.signature.type == "jwt"
    input.signature.algorithm == "RS256"
    input.signature.payload.iss == "pipeline-runner@my-corp"
    input.signature.payload.exp >= time.now_ns() / 1000000000
    input.signature.payload.nbf <= time.now_ns() / 1000000000
    # 验证签名公钥指纹是否在白名单中
    input.signature.kid in data.allowed_signing_keys
}
合规阻断要点:OPA策略不应仅验证签名是否存在,还应强制检查签名身份、时效性、透明日志记录(如适用)。对于Cosign,建议将rekor_entry.inclusion_proof设为必须条件,防止签名被绕过透明日志直接验证。

4.5 选型总结与迁移建议

评估维度 GPG Sigstore / Cosign JWT 签名
安全等级 高(依赖密钥管理成熟度) 高(透明日志提供不可否认性) 中(依赖密钥安全存储)
运维复杂度 高 低(托管服务) 中
OPA集成难度 中(需解析gpg输出) 低(原生JSON输出) 低(JWT库直接解析)
供应链审计能力 弱(无全局日志) 强(Rekor透明日志) 弱(需自行审计)
推荐迁移路径 → 逐步替换为Cosign → 作为长期标准 → 保留用于API令牌场景
迁移建议:如果当前流水线已大规模使用GPG,建议采用“双签名过渡期”——在同一个构建产物上同时附加GPG签名和Cosign签名,待所有验证方完成Cosign适配后再移除GPG。OPA策略在此期间可配置为“任一签名有效即通过”,降低迁移风险。