Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
cosign — 容器和二进制的代码签名与透明度 | Kitploit
工具/GitHubGitHub/sigstore/cosign
身份验证与授权容器安全加密/解密工具云安全DevSecOps供应链安全容器安全 分类第 15 名DevSecOps 分类第 11 名供应链安全 分类第 6 名
6.2k785831天前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享
GitHub
sigstore/cosign

cosign

容器和二进制的代码签名与透明度

查看仓库
<p align="center">
  <img style="max-width: 100%;width: 300px;" src="https://raw.githubusercontent.com/sigstore/community/main/artwork/cosign/horizontal/color/sigstore_cosign-horizontal-color.svg" alt="Cosign logo"/>
</p>

# cosign

使用 [Sigstore](https://sigstore.dev/) 对 OCI 容器(及其他制品)进行签名!

[![Go Report Card](https://goreportcard.com/badge/github.com/sigstore/cosign)](https://goreportcard.com/report/github.com/sigstore/cosign)
[![e2e-tests](https://github.com/sigstore/cosign/actions/workflows/e2e-tests.yml/badge.svg)](https://github.com/sigstore/cosign/actions/workflows/e2e-tests.yml)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/5715/badge)](https://bestpractices.coreinfrastructure.org/projects/5715)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/sigstore/cosign/badge)](https://securityscorecards.dev/viewer/?uri=github.com/sigstore/cosign)

Cosign 旨在让签名成为**无形的基础设施**。

Cosign 支持:

* 使用 Sigstore 公益 Fulcio 证书颁发机构和 Rekor 透明日志进行“无密钥签名”(默认)
* 硬件和 KMS 签名
* 使用 cosign 生成的加密私钥/公钥对进行签名
* 在 OCI 注册表中进行容器签名、验证和存储。
* 自带 PKI

## 信息

`Cosign` 是作为 [`sigstore`](https://sigstore.dev) 项目的一部分开发的。
我们还使用一个 [slack 频道](https://sigstore.slack.com)!
点击[此处](https://join.slack.com/t/sigstore/shared_invite/zt-47srvpyn6-j8Ek5hGBwKN32IjLw8BvYA)获取邀请链接。

## 安装

有关 Homebrew、Arch、Nix、GitHub Action 和 Kubernetes 安装,请参阅[安装文档](https://docs.sigstore.dev/cosign/system_config/installation/)。

有关 Linux、macOS 和 Windows 二进制文件,请参阅 [GitHub 发布资产](https://github.com/sigstore/cosign/releases/latest)。

:rotating_light: 如果你正在从我们的 GCS 存储桶下载 cosign 的发布版本 - 请查看有关 2023 年 7 月 31 日[弃用通知](https://blog.sigstore.dev/cosign-releases-bucket-deprecation/)的更多信息 :rotating_light:

## 开发者安装

如果你有 Go 1.22+,可以设置开发环境:

```shell
$ git clone https://github.com/sigstore/cosign
$ cd cosign
$ go install ./cmd/cosign
$ $(go env GOPATH)/bin/cosign
```

## 贡献

如果您有兴趣为 `cosign` 做贡献,请阅读[贡献文档](https://github.com/sigstore/cosign/blob/main/CONTRIBUTING.md)。

Cosign 未来的开发将聚焦于下一个主要版本,该版本将基于
[sigstore-go](https://github.com/sigstore/sigstore-go)。维护者将专注于 sigstore-go 内的功能开发。
欢迎对 sigstore-go 的贡献,特别是围绕自带密钥和签名方面的贡献。
请查看[问题跟踪器](https://github.com/sigstore/sigstore-go/issues)以寻找适合新手的问题。

Cosign 2.x 是一个稳定版本,将继续定期接收功能更新和错误修复。范围较小、规模不大的 PR
最有可能被快速审查。

显著修改或破坏 API 的 PR 将不被接受。规模较大但不引入破坏性变更的 PR 可能会被接受,
但其优先级将低于 sigstore-go 中的 PR。

## Dockerfile

以下是如何通过 ghcr.io/sigstore/cosign/cosign 镜像在 Dockerfile 中安装和使用 cosign:

```shell
FROM ghcr.io/sigstore/cosign/cosign:v2.4.1 as cosign-bin

# Source: https://github.com/chainguard-images/images/tree/main/images/static
FROM cgr.dev/chainguard/static:latest
COPY --from=cosign-bin /ko-app/cosign /usr/local/bin/cosign
ENTRYPOINT [ "cosign" ]
```

## 快速开始

本节展示如何:
* 使用默认的基于身份的“无密钥签名”方法对容器镜像进行签名(更多信息请参阅[文档](https://docs.sigstore.dev/cosign/signing/overview/))
* 验证容器镜像
* 在 [Sigstore Cosign 快速入门](https://docs.sigstore.dev/quickstart/quickstart-cosign/)中探索更广泛的无密钥 blob 签名/验证流程

### 对容器进行签名并将签名存储在注册表中

请注意,你应始终基于镜像的摘要(`@sha256:...`)而非标签(`:latest`)进行签名,否则你可能会签署并非你本意的东西!

```shell
 cosign sign $IMAGE

Generating ephemeral keys...
Retrieving signed certificate...

	Note that there may be personally identifiable information associated with this signed artifact.
	This may include the email address associated with the account with which you authenticate.
	This information will be used for signing this artifact and will be stored in public transparency logs and cannot be removed later.

By typing 'y', you attest that you grant (or have permission to grant) and agree to have this information stored permanently in transparency logs.
Are you sure you would like to continue? [y/N] y
Your browser will now be opened to:
https://oauth2.sigstore.dev/auth/auth?access_type=online&client_id=sigstore&code_challenge=OrXitVKUZm2lEWHVt1oQWR4HZvn0rSlKhLcltglYxCY&code_challenge_method=S256&nonce=2KvOWeTFxYfxyzHtssvlIXmY6Jk&redirect_uri=http%3A%2F%2Flocalhost%3A57102%2Fauth%2Fcallback&response_type=code&scope=openid+email&state=2KvOWfbQJ1caqScgjwibzK2qJmb
Successfully verified SCT...
tlog entry created with index: 12086900
Pushing signature to: $IMAGE
```

Cosign 会提示你通过 OIDC 进行身份验证,届时你将使用自己的电子邮件地址登录。
在底层,cosign 会向 Fulcio 证书颁发机构申请代码签名证书。
证书的主题将与你登录时使用的电子邮件地址相匹配。
随后,Cosign 会将签名和证书存储在 Rekor 透明度日志中,并将签名与你正在签名的镜像一起上传到 OCI 注册表。


### 验证容器

要验证镜像,你需要通过 `--certificate-identity` 和 `--certificate-oidc-issuer` 标志传入预期的证书主题和证书颁发者:

```
cosign verify $IMAGE --certificate-identity=$IDENTITY --certificate-oidc-issuer=$OIDC_ISSUER
```

你也可以为证书身份和颁发者标志传入正则表达式,即 `--certificate-identity-regexp` 和 `--certificate-oidc-issuer-regexp`。

### 使用公钥验证容器

如果找到*至少一个*与公钥匹配的 `cosign` 格式的镜像签名,此命令返回 `0`。
有关其他签名格式的信息和注意事项,请参阅下面的详细用法。

任何有效的负载都会以 json 格式打印到 stdout。
请注意,这些已签名的负载包含容器镜像的摘要,这就是我们能够确信这些“分离的”签名覆盖了正确镜像的方式。

```shell
$ cosign verify --key cosign.pub $IMAGE_URI:1h
The following checks were performed on these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key
{"Critical":{"Identity":{"docker-reference":""},"Image":{"Docker-manifest-digest":"sha256:87ef60f558bad79beea6425a3b28989f01dd417164150ab3baab98dcbf04def8"},"Type":"cosign container image signature"},"Optional":null}
```

### 在气隙环境中验证容器

**注意:** 本节内容已过时。

**注意:** 大多数验证工作流需要定期从 TUF 仓库请求服务密钥。
对于使用公共实例进行签名的气隙验证,您需要从生产 TUF 仓库中获取
[受信任根](https://github.com/sigstore/root-signing/blob/main/targets/trusted_root.json) 文件。该文件的内容会未经通知而变更。如果不使用 TUF,您需要
构建自己的机制来保持此文件的气隙副本处于最新状态。

Cosign 可以通过验证 [bundle](https://github.com/sigstore/cosign/blob/main/specs/SIGNATURE_SPEC.md#properties) 来执行完全离线验证,该 bundle 通常作为镜像清单上的注解分发。
只要此注解存在,就可以进行离线验证。
此 bundle 注解在无密钥签名中始终默认包含,因此默认的 `cosign sign` 功能将包含离线验证所需的所有材料。

要在气隙环境中验证镜像,镜像和签名必须可在本地文件系统上获取。

可以使用 `cosign save` 将镜像保存到本地(注意,此步骤必须在有网络连接的情况下完成):

```
cosign initialize # This will pull in the latest TUF root
cosign save $IMAGE_NAME --dir ./path/to/dir
```

现在,在气隙环境中,可以验证此本地镜像:

```shell
cosign verify \
  --certificate-identity $CERT_IDENTITY \
  --certificate-oidc-issuer $CERT_OIDC_ISSUER \
  --offline=true \
  --new-bundle-format=false \ # for artifacts signed without the new protobuf bundle format
  --trusted-root ~/.sigstore/root/tuf-repo-cdn.sigstore.dev/targets/trusted_root.json \ # default location of trusted root
  --local-image ./path/to/dir
```

你需要传入 `$CERT_IDENTITY` 和 `$CERT_OIDC_ISSUER` 的预期值,以正确验证此镜像。
如果你使用密钥对进行签名,只要本地存在公钥材料,同样的命令即可生效:

```
cosign verify --key cosign.pub --offline --local-image ./path/to/dir
```

### 基于身份的数据块签名与验证

使用无密钥数据块签名(不带 `--key` 的 `cosign sign-blob`),并依据预期的签名者身份进行验证:

```shell
$ cosign sign-blob artifact --bundle artifact.sigstore.json --yes
$ cosign verify-blob artifact \
  --bundle artifact.sigstore.json \
  --certificate-identity "https://github.com/ORG/REPO/.github/workflows/release.yml@refs/heads/main" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com"
```

### 故障排除

如果您在使用 Cosign 时遇到问题,首先请确保您使用的是最新版本:Cosign 项目积极支持最新版本以及 v2 系列中的上一个版本。

#### 常见问题及解决方法

1. 验证失败并显示 `failed to verify timestamps: threshold not met for verified log entry integrated timestamps: 0 < 1`:您可能正在验证需要 RFC3161 时间戳支持的签名
   * 升级到最新的 Cosign 或
   * 使用 Cosign 2.6.x 时,使用 `--use-signed-timestamps`
1. 验证失败并显示 `no signatures found`:您可能正在验证需要 Rekor v2 透明日志支持的镜像签名
   * 升级到最新的 Cosign
1. 签名失败并出现 HTTP 错误:使用 Cosign 签名依赖于多个 Sigstore 服务。如果其中任何服务失败,重试可能是一种有用的解决方法——同时也欢迎针对具体失败提交 issue

#### 我的问题是其他情况

请打开一个 [issue](https://github.com/sigstore/cosign/issues/new/choose) 或在 [slack 频道](#info) 中提问。

## 处理其他工件

OCI 注册表不仅可用于存储容器镜像!
`Cosign` 还包含一些实用工具,用于使用 OCI 协议发布通用工件,包括二进制文件、脚本和配置文件。

本节展示如何利用这些工具构建一个易于使用、向后兼容的工件分发系统,并与 Sigstore 的其他部分良好集成。

有关更多信息,请参阅[文档](https://docs.sigstore.dev/cosign/signing/other_types/)。

### Blobs

您可以使用 `cosign upload blob` 发布工件:

```shell
$ echo "my first artifact" > artifact
$ BLOB_SUM=$(shasum -a 256 artifact | cut -d' ' -f 1) && echo "$BLOB_SUM"
c69d72c98b55258f9026f984e4656f0e9fd3ef024ea3fac1d7e5c7e6249f1626
$ BLOB_NAME=my-artifact-$(uuidgen | head -c 8 | tr 'A-Z' 'a-z')
$ BLOB_URI=ttl.sh/$BLOB_NAME:1h

$ BLOB_URI_DIGEST=$(cosign upload blob -f artifact $BLOB_URI) && echo "$BLOB_URI_DIGEST"
Uploading file from [artifact] to [ttl.sh/my-artifact-f42c22e0:5m] with media type [text/plain]
File [artifact] is available directly at [ttl.sh/v2/my-artifact-f42c22e0/blobs/sha256:c69d72c98b55258f9026f984e4656f0e9fd3ef024ea3fac1d7e5c7e6249f1626]
Uploaded image to:
ttl.sh/my-artifact-f42c22e0@sha256:790d47850411e902aabebc3a684eeb78fcae853d4dd6e1cc554d70db7f05f99f
```

你的用户可以使用 curl 或 wget 等标准工具从“direct”URL 下载它:

```shell
$ curl -L ttl.sh/v2/$BLOB_NAME/blobs/sha256:$BLOB_SUM > artifact-fetched
```

摘要直接嵌入在 URL 中,因此他们也可以对此进行检查:

```shell
$ cat artifact-fetched | shasum -a 256
c69d72c98b55258f9026f984e4656f0e9fd3ef024ea3fac1d7e5c7e6249f1626  -
```

你可以使用常规的 `cosign sign` 命令和标志对其进行签名:

```shell
$ cosign sign --key cosign.key $BLOB_URI_DIGEST
Enter password for private key:
Pushing signature to: ttl.sh/my-artifact-f42c22e0
```

像往常一样,请确保通过摘要引用您签名的任何镜像,以确保您不会签错对象!

#### Tekton Bundles

[Tekton](https://tekton.dev) bundles 可以上传并在 OCI registry 中管理。
规范见[此处](https://tekton.dev/docs/pipelines/tekton-bundle-contracts/)。
这意味着它们也可以使用 `cosign` 进行签名和验证。

Tekton Bundles 目前可以通过 [tkn cli](https://github.com/tektoncd/cli) 上传,但我们未来可能会将此支持添加到
`cosign` 中。

```shell
$ tkn bundle push us.gcr.io/dlorenc-vmtest2/pipeline:latest -f task-output-image.yaml
Creating Tekton Bundle:
        - Added TaskRun:  to image

Pushed Tekton Bundle to us.gcr.io/dlorenc-vmtest2/pipeline@sha256:124e1fdee94fe5c5f902bc94da2d6e2fea243934c74e76c2368acdc8d3ac7155
$ cosign sign --key cosign.key us.gcr.io/dlorenc-vmtest2/pipeline@sha256:124e1fdee94fe5c5f902bc94da2d6e2fea243934c74e76c2368acdc8d3ac7155
Enter password for private key:
tlog entry created with index: 5086
Pushing signature to: us.gcr.io/dlorenc-vmtest2/demo:sha256-124e1fdee94fe5c5f902bc94da2d6e2fea243934c74e76c2368acdc8d3ac7155.sig
```

#### WASM

Web Assembly 模块也可以存储在 OCI registry 中,使用此[规范](https://github.com/solo-io/wasm/tree/master/spec)。

Cosign 可以使用 `cosign wasm upload` 命令上传这些模块:

```shell
$ cosign upload wasm -f hello.wasm us.gcr.io/dlorenc-vmtest2/wasm
$ cosign sign --key cosign.key us.gcr.io/dlorenc-vmtest2/wasm@sha256:9e7a511fb3130ee4641baf1adc0400bed674d4afc3f1b81bb581c3c8f613f812
Enter password for private key:
tlog entry created with index: 5198
Pushing signature to: us.gcr.io/dlorenc-vmtest2/wasm:sha256-9e7a511fb3130ee4641baf1adc0400bed674d4afc3f1b81bb581c3c8f613f812.sig
```
#### eBPF

[eBPF](https://ebpf.io) 模块也可以使用此[规范](https://github.com/solo-io/bumblebee/tree/main/spec)存储在 OCI registry 中。

下面的镜像使用 `bee` 工具构建。更多信息可在[此处](https://github.com/solo-io/bumblebee/)找到

Cosign 随后可以像签署任何其他 OCI 镜像一样签署这些镜像。

```shell
$ bee build ./examples/tcpconnect/tcpconnect.c localhost:5000/tcpconnect:test
$ bee push localhost:5000/tcpconnect:test
$ cosign sign  --key cosign.key localhost:5000/tcpconnect@sha256:7a91c50d922925f152fec96ed1d84b7bc6b2079c169d68826f6cf307f22d40e6
Enter password for private key:
Pushing signature to: localhost:5000/tcpconnect
$ cosign verify --key cosign.pub localhost:5000/tcpconnect:test

Verification for localhost:5000/tcpconnect:test --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key

[{"critical":{"identity":{"docker-reference":"localhost:5000/tcpconnect"},"image":{"docker-manifest-digest":"sha256:7a91c50d922925f152fec96ed1d84b7bc6b2079c169d68826f6cf307f22d40e6"},"type":"cosign container image signature"},"optional":null}]

```

#### In-Toto 认证

Cosign 还内置支持 [in-toto](https://in-toto.io) 认证。
这些认证的规范定义在[此处](https://github.com/in-toto/attestation)。

你可以使用以下命令从本地谓词文件创建并签名一个认证:

```shell
$ cosign attest --predicate <file> --key cosign.key $IMAGE_URI_DIGEST
```

所有标准密钥管理系统均受支持。
载荷使用 DSSE 签名规范进行签名,定义见[此处](https://github.com/secure-systems-lab/dsse)。

验证方法:

```shell
$ cosign verify-attestation --key cosign.pub $IMAGE_URI
```

## 详细用法

更多信息请参阅[用法文档](https://docs.sigstore.dev/cosign/signing/overview/)。

## 基于硬件的令牌

有关如何将 `cosign` 与硬件配合使用的信息,请参阅[硬件令牌文档](https://docs.sigstore.dev/cosign/key_management/hardware-based-tokens/)。

## 注册表支持

`cosign` 使用 [go-containerregistry](https://github.com/google/go-containerregistry) 进行注册表交互,该库通常具有出色的兼容性,但某些注册表可能存在特殊情况。

目前,`cosign` 已在以下注册表上经过测试并可正常工作:

* AWS Elastic Container Registry
* GCP 的 Artifact Registry 和 Container Registry
* Docker Hub
* Azure Container Registry
* JFrog Artifactory Container Registry
* CNCF distribution/distribution Registry
* GitLab Container Registry
* GitHub Container Registry
* CNCF Harbor Registry
* Digital Ocean Container Registry
* Sonatype Nexus Container Registry
* Alibaba Cloud Container Registry
* Red Hat Quay Container Registry 3.6+ / Red Hat quay.io
* Elastic Container Registry
* IBM Cloud Container Registry
* Cloudsmith Container Registry
* CNCF zot Registry
* OVHcloud Managed Private Registry

我们力求提供广泛的注册表支持。对于尚未完全支持 [OCI 媒体类型](https://github.com/sigstore/cosign/blob/main/specs/SIGNATURE_SPEC.md)的注册表中的镜像进行 `sign` 操作时,可能需要使用 `COSIGN_DOCKER_MEDIA_TYPES` 回退到旧版等效类型。例如:

```shell
COSIGN_DOCKER_MEDIA_TYPES=1 cosign sign --key cosign.key legacy-registry.example.com/my/image@$DIGEST
```

请帮助测试并在发现问题时提交错误报告!
相关说明可在[跟踪问题](https://github.com/sigstore/cosign/issues/40)中找到。

## 注意事项

### 有意缺失的功能

`cosign` 仅生成 ECDSA-P256 密钥,并使用 SHA256 哈希,适用于临时无密钥签名和托管密钥签名。
密钥以 PEM 编码的 PKCS8 格式存储。
不过,你可以使用 `cosign` 以任意格式、任意算法存储和检索签名。

### 可能应该改变的地方

#### 载荷格式

`cosign` 仅支持 Red Hat 的[简单签名](https://www.redhat.com/en/blog/container-image-signing)
格式作为载荷。
其格式如下:

```json
{
    "critical": {
           "identity": {
               "docker-reference": "testing/manifest"
           },
           "image": {
               "Docker-manifest-digest": "sha256:20be...fe55"
           },
           "type": "cosign container image signature"
    },
    "optional": {
           "creator": "Bob the Builder",
           "timestamp": 1458239713
    }
}
```

**注意:** 可以使用 `cosign generate $IMAGE_URI_DIGEST` 为镜像引用生成此内容。

如果有意义的话,我愿意将此格式切换为其他格式。
有关一种选项,请参见 https://github.com/notaryproject/notation/issues/40。

#### 注册表详情

`cosign` 签名作为独立对象存储在 OCI 注册表中,仅与其所“签名”的对象存在弱引用关系。
这意味着这种关系对注册表而言是不透明的,并且当镜像被删除时,签名*不会*被删除或被垃圾回收。
同样,它们**可以**轻松地从一个环境复制到另一个环境,但这并非自动完成。

多个签名存储在一个列表中,遗憾的是,目前这存在竞态条件。
要添加签名,客户端会编排一个“读取-追加-写入”操作,因此在发生争用时,最后一次写入将胜出。

##### 指定注册表

`cosign` 默认会将签名存储在其所签名镜像的同一仓库中。
要为签名指定不同的仓库,可以设置 `COSIGN_REPOSITORY` 环境变量。

这将按如下方式替换所提供镜像中的仓库:

```shell
$ export COSIGN_REPOSITORY=gcr.io/my-new-repo
$ cosign sign --key cosign.key $IMAGE_URI_DIGEST
```

因此,`gcr.io/dlorenc-vmtest2/demo` 的签名将存储在 `gcr.io/my-new-repo/demo:sha256-DIGEST.sig` 中。

注意:不同的注册表可能期望“仓库”采用不同的格式。

* 要使用 [GCR](https://cloud.google.com/container-registry),像上面示例中那样,使用 `gcr.io/$REPO` 这样的注册表名称就足够了。
* 要使用 [Artifact Registry](https://cloud.google.com/artifact-registry),请指定完整的镜像名称,例如 `$LOCATION-docker.pkg.dev/$PROJECT/$REPO/$STORAGE_IMAGE`,而不仅仅是仓库。例如,

  ```shell
  $ export COSIGN_REPOSITORY=us-docker.pkg.dev/my-new-repo/demo
  $ cosign sign --key cosign.key $IMAGE_URI_DIGEST
  ```

  其中 `sha256-DIGEST` 将与
`gcr.io/dlorenc-vmtest2/demo` 的摘要匹配。仅指定像
`$LOCATION-docker.pkg.dev/$PROJECT/$REPO` 这样的仓库在 Artifact Registry 中无法工作。


## 签名规范

`cosign` 受到 [minisign](https://jedisct1.github.io/minisign/) 和
[signify](https://www.openbsd.org/papers/bsdcan-signify.html) 等工具的启发。

生成的私钥以 PEM 格式存储。
密钥使用 scrypt 作为 KDF 和 nacl/secretbox 进行加密,并受密码保护。

它们具有 `ENCRYPTED SIGSTORE PRIVATE KEY` 的 PEM 头:

```shell
-----BEGIN ENCRYPTED SIGSTORE PRIVATE KEY-----
...
-----END ENCRYPTED SIGSTORE PRIVATE KEY-----
```

公钥以 PEM 编码的标准 PKIX 格式存储在磁盘上,头部为 `PUBLIC KEY`。
```
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELigCnlLNKgOglRTx1D7JhI7eRw99
QolE9Jo4QUxnbMy5nUuBL+UZF9qqfm/Dg1BNeHRThHzWh2ki9vAEgWEDOw==
-----END PUBLIC KEY-----
```

## 存储规范

`cosign` 将签名存储在 OCI registry 中,并使用一种命名约定(基于所签名内容的 sha256 的 tag)来定位签名索引。

<p align="center">
  <img src="https://raw.githubusercontent.com/sigstore/cosign/HEAD/images/signatures.dot.svg" />
</p>

`reg.example.com/ubuntu@sha256:703218c0465075f4425e58fac086e09e1de5c340b12976ab9eb8ad26615c3715` 的签名位于 `reg.example.com/ubuntu:sha256-703218c0465075f4425e58fac086e09e1de5c340b12976ab9eb8ad26615c3715.sig`

大致上(忽略主机名中的端口):使用 `s/:/-/g` 和 `s/@/:/g` 来查找签名索引。

关于此策略的一些注意事项,请参见[竞态条件](#registry-details)。

替代实现可以使用透明日志、本地文件系统、独立的仓库 registry、对签名索引的显式引用、新的 registry API、grafeas 等。

### 签名主体

`cosign` 目前仅适用于以 registry 中的 "manifests" 形式存储的制品。
所提出的机制足够灵活,可以支持对任意内容进行签名。

### KMS 支持

`cosign` 支持使用 KMS 提供程序来生成和签名密钥。
目前 cosign 支持 Hashicorp Vault、AWS KMS、GCP KMS、Azure Key Vault,我们希望将来支持更多!

其他 KMS 提供程序可作为外部插件使用,例如 [OVHcloud KMS](https://github.com/ovh/sigstore-kms-ovhcloud)。

更多详情请参见 [KMS 文档](https://docs.sigstore.dev/cosign/key_management/overview/)。

### OCI 制品

使用 [oras](https://github.com/deislabs/oras) 将制品推送到 registry(在本例中,就是 `cosign` 本身!):

```shell
$ oras push us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact ./cosign
Uploading f53604826795 cosign
Pushed us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact
Digest: sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef
```

现在签名!当然使用 `cosign`:

```shell
$ cosign sign --key cosign.key us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact@sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef
Enter password for private key:
Pushing signature to: us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact:sha256-551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef.sig
```

最后,再次使用 `cosign` 验证 `cosign`:

```shell
$ cosign verify --key cosign.pub  us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact@sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The claims were present in the transparency log
  - The signatures were integrated into the transparency log when the certificate was valid
  - The signatures were verified against the specified public key
  - The code-signing certificate was verified using trusted certificate authority certificates

{"Critical":{"Identity":{"docker-reference":""},"Image":{"Docker-manifest-digest":"sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef"},"Type":"cosign container image signature"},"Optional":null}
```

## 常见问题

### 为什么不使用 Notary v2

这个问题很难简短回答。
这篇文章包含了一些比较:

[Notary V2 和 Cosign](https://medium.com/@dlorenc/notary-v2-and-cosign-b816658f044d)

如果你找到其他比较文章,请在这里提交 PR,我们会把它们都链接起来。

### 为什么不使用 containers/image 签名

`containers/image` 签名与 `cosign` 很接近,我们复用了载荷格式。
`cosign` 的不同之处在于它使用 ECDSA-P256 密钥而不是 PGP 进行签名,并将
签名存储在注册表中。

### 为什么不使用 TUF?

我认为这个工具是对 TUF 的补充,它们可以一起使用。
我还没有尝试过,但我认为我们也可以复用注册表来进行 TUF 存储。

## 设计要求

* 签名存储、查询或检索不依赖外部服务
* 我们力求尽可能多地支持各种注册表
* 一切都应通过注册表 API 工作
* 完全不需要 PGP。
* 用户必须能够找到镜像的所有签名
* 签名者可以在推送后对镜像进行签名
* 多个实体可以对同一个镜像进行签名
* 对镜像签名不会改变镜像本身
* 纯 Go 实现

## 未来构想

### 注册表 API 变更

我们用来在注册表中存储内容的命名约定和读-改-写更新模式有点,嗯,“hacky”。
我认为它们是当今最好(也是唯一)的真正可用选项,但如果注册表 API
发生变化,我们可以改进这些做法。

### 其他类型

`cosign` 可以对注册表中的任何内容进行签名。
这些示例展示了对单个镜像的签名,但你也可以对多平台 `Index`
或任何其他类型的制品进行签名。
这包括 Helm Charts、Tekton Pipelines,以及当前使用 OCI 注册表
进行分发的任何其他内容。

这也意味着新的制品类型可以上传到注册表并进行签名。
一个有趣的存储和签名类型是 TUF 仓库。
我还没有尝试过,但我相当确定 TUF 可以在此基础上实现。

### 标签签名

`cosign` 签名保护注册表中存储对象的摘要。
可选的 `annotations` 支持(通过 `cosign sign` 的 `-a` 标志)可用于向
被签名并由签名保护的载荷中添加额外数据。
一个用例可能是对 tag->digest 映射进行签名。

如果你想证明某个特定标签(或一组标签)应指向某个摘要,你可以
运行类似这样的命令:

```shell
$ docker push $IMAGE_URI
The push refers to repository [dlorenc/demo]
994393dc58e7: Pushed
5m: digest: sha256:1304f174557314a7ed9eddb4eab12fed12cb0cd9809e4c28f29af86979a3c870 size: 528
$ TAG=sign-me
$ cosign sign --key cosign.key -a tag=$TAG $IMAGE_URI_DIGEST
Enter password for private key:
Pushing signature to: dlorenc/demo:1304f174557314a7ed9eddb4eab12fed12cb0cd9809e4c28f29af86979a3c870.sig
```

然后你可以使用 `cosign verify` 的 `-a` 标志来验证 tag->digest 映射也包含在签名中。
此示例验证了 digest `$TAG`(指向 `sha256:1304f174557314a7ed9eddb4eab12fed12cb0cd9809e4c28f29af86979a3c870`)
已被签名,**并且** `tag` 注解的值为 `sign-me`:

```shell
$ cosign verify --key cosign.pub -a tag=$TAG $IMAGE_URI | jq .
{
  "Critical": {
    "Identity": {
      "docker-reference": ""
    },
    "Image": {
      "Docker-manifest-digest": "97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36"
    },
    "Type": "cosign container image signature"
  },
  "Optional": {
    "tag": "sign-me"
  }
}
```

时间戳也可以添加在这里,以实现 TUF 风格的冻结攻击防护。

### 基础镜像/层签名

同样,`cosign` 可以对注册表中的任何内容进行签名。
你可以使用 `cosign` 对打算用作基础镜像的镜像进行签名,
并将该来源元数据包含在生成的派生镜像中。
这可用于强制要求某个镜像是由经过授权的基础镜像构建的。

大致思路:
* OCI 清单具有一个有序的 `layer` `Descriptors` 列表,其中可以包含注解。
  有关规范,请参见[此处](https://github.com/opencontainers/image-spec/blob/master/manifest.md)。
* 基础镜像是一个有序的层列表,其他层会追加到其上,同时还有一个会被修改的初始配置对象。
  * 派生镜像可以完全删除/销毁/重建其基础镜像的配置,
    因此对配置进行签名提供的价值有限。
* 我们可以对完整的有序基础层集合进行签名,并将该签名作为注解附加到
  生成的子镜像中的**最后一个**层上。

这个示例清单表示一个由具有两个层的基础镜像构建而成的镜像。
添加了一个额外的层,形成了最终镜像。

```json
{
  "schemaVersion": 2,
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "size": 7023,
    "digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7"
  },
  "layers": [
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "size": 32654,
      "digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0"
    },
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "size": 16724,
      "digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b",
      "annotations": {
        "dev.cosign.signature.baseimage": "Ejy6ipGJjUzMDoQFePWixqPBYF0iSnIvpMWps3mlcYNSEcRRZelL7GzimKXaMjxfhy5bshNGvDT5QoUJ0tqUAg=="
      }
    },
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "size": 73109,
      "digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736"
    }
  ],
}
```

请注意,这可以递归应用,用于多个中间基础镜像。

### 副签名

Cosign 签名(及其受保护的负载)作为制品存储在注册表中。
这些签名对象也可以被签名,从而产生一个新的“副签名”制品。
这个“副签名”保护签名(或签名集合)**以及**所引用的制品,这使其能够作为对**签名本身**的证明。

在签署签名制品之前,我们首先给它起一个易于记忆的名称,以便日后查找。

```shell
$ cosign sign --key cosign.key -a sig=original $IMAGE_URI_DIGEST
Enter password for private key:
Pushing signature to: dlorenc/demo:sha256-97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36.sig
$ cosign verify --key cosign.pub dlorenc/demo | jq .
{
  "Critical": {
    "Identity": {
      "docker-reference": ""
    },
    "Image": {
      "Docker-manifest-digest": "97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36"
    },
    "Type": "cosign container image signature"
  },
  "Optional": {
    "sig": "original"
  }
}
```

<!-- TODO: https://github.com/sigstore/cosign/issues/2333 -->

现在给该签名起一个容易记住的名字,然后对其进行签名:

```shell
$ crane tag $(cosign triangulate $IMAGE_URI) mysignature
2021/02/15 20:22:55 dlorenc/demo:mysignature: digest: sha256:71f70e5d29bde87f988740665257c35b1c6f52dafa20fab4ba16b3b1f4c6ba0e size: 556
$ cosign sign --key cosign.key -a sig=counter dlorenc/demo:mysignature
Enter password for private key:
Pushing signature to: dlorenc/demo:sha256-71f70e5d29bde87f988740665257c35b1c6f52dafa20fab4ba16b3b1f4c6ba0e.sig
$ cosign verify --key cosign.pub dlorenc/demo:mysignature
{"Critical":{"Identity":{"docker-reference":""},"Image":{"Docker-manifest-digest":"71f70e5d29bde87f988740665257c35b1c6f52dafa20fab4ba16b3b1f4c6ba0e"},"Type":"cosign container image signature"},"Optional":{"sig":"counter"}}
```

最后,检查原始签名:

```shell
$ crane manifest dlorenc/demo@sha256:71f70e5d29bde87f988740665257c35b1c6f52dafa20fab4ba16b3b1f4c6ba0e
{
  "schemaVersion": 2,
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "size": 233,
    "digest": "sha256:3b25a088710d03f39be26629d22eb68cd277a01673b9cb461c4c24fbf8c81c89"
  },
  "layers": [
    {
      "mediaType": "application/vnd.oci.descriptor.v1+json",
      "size": 217,
      "digest": "sha256:0e79a356609f038089088ec46fd95f4649d04de989487220b1a0adbcc63fadae",
      "annotations": {
        "dev.sigstore.cosign/signature": "5uNZKEP9rm8zxAL0VVX7McMmyArzLqtxMTNPjPO2ns+5GJpBeXg+i9ILU+WjmGAKBCqiexTxzLC1/nkOzD4cDA=="
      }
    }
  ]
}
```

## 发布节奏

---

[Read more](https://github.com/sigstore/cosign)
下载工具