github.com/venafi-iw/cosign@v1.3.4/README.md (about)

     1  # cosign
     2  
     3  Container Signing, Verification and Storage in an OCI registry.
     4  
     5  [![Go Report Card](https://goreportcard.com/badge/github.com/sigstore/cosign)](https://goreportcard.com/report/github.com/sigstore/cosign)
     6  [![e2e-tests](https://github.com/sigstore/cosign/actions/workflows/e2e_tests.yml/badge.svg)](https://github.com/sigstore/cosign/actions/workflows/e2e_tests.yml)
     7  
     8  Cosign aims to make signatures **invisible infrastructure**.
     9  
    10  Cosign supports:
    11  
    12  * Hardware and KMS signing
    13  * Bring-your-own PKI
    14  * Our free OIDC PKI ([Fulcio](https://github.com/sigstore/fulcio))
    15  * Built-in binary transparency and timestamping service ([Rekor](https://github.com/sigstore/rekor))
    16  
    17  ![intro](images/intro.gif)
    18  
    19  ## Info
    20  
    21  `Cosign` is developed as part of the [`sigstore`](https://sigstore.dev) project.
    22  We also use a [slack channel](https://sigstore.slack.com)!
    23  Click [here](https://join.slack.com/t/sigstore/shared_invite/zt-mhs55zh0-XmY3bcfWn4XEyMqUUutbUQ) for the invite link.
    24  
    25  ## Installation
    26  
    27  For Homebrew, Arch, Nix, GitHub Action, and Kubernetes installs see the [installation docs](https://docs.sigstore.dev/cosign/installation).
    28  
    29  For Linux and macOS binaries see the [GitHub release assets](https://github.com/sigstore/cosign/releases/latest).
    30  
    31  ## Developer Installation
    32  
    33  If you have Go 1.16+, you can setup a development environment:
    34  
    35      $ git clone https://github.com/sigstore/cosign
    36      $ cd cosign
    37      $ go install ./cmd/cosign
    38      $ $(go env GOPATH)/bin/cosign
    39  
    40  ## Quick Start
    41  
    42  This shows how to:
    43  
    44  * generate a keypair
    45  * sign a container image and store that signature in the registry
    46  * find signatures for a container image, and verify them against a public key
    47  
    48  See the [Usage documentation](USAGE.md) for more commands!
    49  
    50  See the [FUN.md](FUN.md) documentation for some fun tips and tricks!
    51  
    52  NOTE: you will need access to a container registry for cosign to work with.
    53  [ttl.sh](https://ttl.sh) offers free, short-lived (ie: hours), anonymous container image
    54  hosting if you just want to try these commands out.
    55  
    56  ### Generate a keypair
    57  
    58  ```shell
    59  $ cosign generate-key-pair
    60  Enter password for private key:
    61  Enter again:
    62  Private key written to cosign.key
    63  Public key written to cosign.pub
    64  ```
    65  
    66  ### Sign a container and store the signature in the registry
    67  
    68  ```shell
    69  $ cosign sign --key cosign.key dlorenc/demo
    70  Enter password for private key:
    71  Pushing signature to: index.docker.io/dlorenc/demo:sha256-87ef60f558bad79beea6425a3b28989f01dd417164150ab3baab98dcbf04def8.sig
    72  ```
    73  
    74  The cosign command above prompts the user to enter the password for the private key.
    75  The user can either manually enter the password, or if the environment variable `COSIGN_PASSWORD` is set then it is used automatically.
    76  
    77  
    78  ### Verify a container against a public key
    79  
    80  This command returns `0` if *at least one* `cosign` formatted signature for the image is found
    81  matching the public key.
    82  See the detailed usage below for information and caveats on other signature formats.
    83  
    84  Any valid payloads are printed to stdout, in json format.
    85  Note that these signed payloads include the digest of the container image, which is how we can be
    86  sure these "detached" signatures cover the correct image.
    87  
    88  ```shell
    89  $ cosign verify --key cosign.pub dlorenc/demo
    90  The following checks were performed on these signatures:
    91    - The cosign claims were validated
    92    - The signatures were verified against the specified public key
    93  {"Critical":{"Identity":{"docker-reference":""},"Image":{"Docker-manifest-digest":"sha256:87ef60f558bad79beea6425a3b28989f01dd417164150ab3baab98dcbf04def8"},"Type":"cosign container image signature"},"Optional":null}
    94  ```
    95  
    96  ## `Cosign` is 1.0!
    97  
    98  This means the core feature set of `cosign` is considered ready for production use.
    99  This core set includes:
   100  
   101  ### Key Management
   102  
   103  * fixed, text-based keys generated using `cosign generate-key-pair`
   104  * cloud KMS-based keys generated using `cosign generate-key-pair -kms`
   105  * keys generated on hardware tokens using the PIV interface using `cosign piv-tool`
   106  * Kubernetes-secret based keys generated using `cosign generate-key-pair k8s://namespace/secretName`
   107  
   108  ### Artifact Types
   109  
   110  * OCI and Docker Images
   111  * Other artifacts that can be stored in a container registry, including:
   112    * Tekton Bundles
   113    * Helm Charts
   114    * WASM modules
   115    * (probably anything else, feel free to add things to this list)
   116  * Text files and other binary blobs, using `cosign sign-blob`
   117  
   118  ### What ** is not ** production ready?
   119  
   120  While parts of `cosign` are stable, we are continuing to experiment and add new features.
   121  The following feature set is not considered stable yet, but we are committed to stabilizing it over time!
   122  
   123  #### Anything under the `COSIGN_EXPERIMENTAL` environment variable
   124  
   125  * Integration with the `Rekor` transparency log
   126  * Keyless signatures using the `Fulcio` CA
   127  
   128  #### Formats/Specifications
   129  
   130  While the `cosign` code for uploading, signing, retrieving, and verifying several artifact types is stable,
   131  the format specifications for some of those types may not be considered stable yet.
   132  Some of these are developed outside of the `cosign` project, so we are waiting for them to stabilize first.
   133  
   134  These include:
   135  
   136  * The SBOM specification for storing SBOMs in a container registry
   137  * The In-Toto attestation format
   138  
   139  ## Working with Other Artifacts
   140  
   141  OCI registries are useful for storing more than just container images!
   142  `Cosign` also includes some utilities for publishing generic artifacts, including binaries, scripts, and configuration files using the OCI protocol.
   143  
   144  This section shows how to leverage these for an easy-to-use, backwards-compatible artifact distribution system that integrates well with the rest of Sigstore.
   145  
   146  ### Blobs
   147  
   148  You can publish an artifact with `cosign upload blob`:
   149  
   150  ```shell
   151  $ echo "my first artifact" > artifact
   152  $ cosign upload blob -f artifact gcr.io/dlorenc-vmtest2/artifact
   153  Uploading file from [artifact] to [gcr.io/dlorenc-vmtest2/artifact:latest] with media type [text/plain; charset=utf-8]
   154  File is available directly at [us.gcr.io/v2/dlorenc-vmtest2/readme/blobs/sha256:b57400c0ad852a7c2f6f7da4a1f94547692c61f3e921a49ba3a41805ae8e1e99]
   155  us.gcr.io/dlorenc-vmtest2/readme@sha256:4aa3054270f7a70b4528f2064ee90961788e1e1518703592ae4463de3b889dec
   156  ```
   157  
   158  Your users can download it from the "direct" url with standard tools like curl or wget:
   159  
   160  ```shell
   161  $ curl -L gcr.io/v2/dlorenc-vmtest2/artifact/blobs/sha256:97f16c28f6478f3c02d7fff4c7f3c2a30041b72eb6852ca85b919fd85534ed4b > artifact
   162  ```
   163  
   164  The digest is baked right into the URL, so they can check that as well:
   165  
   166  ```shell
   167  $ curl -L gcr.io/v2/dlorenc-vmtest2/artifact/blobs/sha256:97f16c28f6478f3c02d7fff4c7f3c2a30041b72eb6852ca85b919fd85534ed4b | shasum -a 256
   168  97f16c28f6478f3c02d7fff4c7f3c2a30041b72eb6852ca85b919fd85534ed4b  -
   169  ```
   170  
   171  You can sign it with the normal `cosign sign` command and flags:
   172  
   173  ```shell
   174  $ cosign sign --key cosign.key gcr.io/dlorenc-vmtest2/artifact
   175  Enter password for private key:
   176  Pushing signature to: gcr.io/dlorenc-vmtest2/artifact:sha256-3f612a4520b2c245d620d0cca029f1173f6bea76819dde8543f5b799ea3c696c.sig
   177  ```
   178  #### sget
   179  
   180  We also include the `sget` command for safer, automatic verification of signatures and integration with our binary transparency log, Rekor.
   181  
   182  To install `sget`, if you have Go 1.16+, you can directly run:
   183  
   184      $ go install github.com/sigstore/cosign/cmd/sget@latest
   185  
   186  and the resulting binary will be placed at `$GOPATH/bin/sget` (or `$GOBIN/sget`, if set).
   187  
   188  Just like `curl`, `sget` can be used to fetch artifacts by digest using the OCI URL.
   189  Digest verification is automatic:
   190  
   191  ```shell
   192  $ sget us.gcr.io/dlorenc-vmtest2/readme@sha256:4aa3054270f7a70b4528f2064ee90961788e1e1518703592ae4463de3b889dec > artifact
   193  ```
   194  
   195  You can also use `sget` to fetch contents by tag.
   196  Fetching contents without verifying them is dangerous, so we require the artifact be signed in this case:
   197  
   198  ```shell
   199  $ sget gcr.io/dlorenc-vmtest2/artifact
   200  error: public key must be specified when fetching by tag, you must fetch by digest or supply a public key
   201  
   202  $ sget --key cosign.pub us.gcr.io/dlorenc-vmtest2/readme > foo
   203  
   204  Verification for us.gcr.io/dlorenc-vmtest2/readme --
   205  The following checks were performed on each of these signatures:
   206    - The cosign claims were validated
   207    - Existence of the claims in the transparency log was verified offline
   208    - The signatures were verified against the specified public key
   209    - Any certificates were verified against the Fulcio roots.
   210  ```
   211  
   212  The signature, claims and transparency log proofs are all verified automatically by sget as part of the download.
   213  
   214  `curl | bash` isn't a great idea, but `sget | bash` is less-bad.
   215  
   216  #### Tekton Bundles
   217  
   218  [Tekton](https://tekton.dev) bundles can be uploaded and managed within an OCI registry.
   219  The specification is [here](https://tekton.dev/docs/pipelines/tekton-bundle-contracts/).
   220  This means they can also be signed and verified with `cosign`.
   221  
   222  Tekton Bundles can currently be uploaded with the [tkn cli](github.com/tekton/cli), but we may add this support to
   223  `cosign` in the future.
   224  
   225  ```shell
   226  $ tkn bundle push us.gcr.io/dlorenc-vmtest2/pipeline:latest -f task-output-image.yaml
   227  Creating Tekton Bundle:
   228          - Added TaskRun:  to image
   229  
   230  Pushed Tekton Bundle to us.gcr.io/dlorenc-vmtest2/pipeline@sha256:124e1fdee94fe5c5f902bc94da2d6e2fea243934c74e76c2368acdc8d3ac7155
   231  $ cosign sign --key cosign.key us.gcr.io/dlorenc-vmtest2/pipeline:latest
   232  Enter password for private key:
   233  tlog entry created with index: 5086
   234  Pushing signature to: us.gcr.io/dlorenc-vmtest2/demo:sha256-124e1fdee94fe5c5f902bc94da2d6e2fea243934c74e76c2368acdc8d3ac7155.sig
   235  ```
   236  
   237  #### WASM
   238  
   239  Web Assembly Modules can also be stored in an OCI registry, using this [specification](https://github.com/solo-io/wasm/tree/master/spec).
   240  
   241  Cosign can upload these using the `cosign wasm upload` command:
   242  
   243  ```shell
   244  $ cosign upload wasm -f hello.wasm us.gcr.io/dlorenc-vmtest2/wasm
   245  $ cosign sign --key cosign.key us.gcr.io/dlorenc-vmtest2/wasm
   246  Enter password for private key:
   247  tlog entry created with index: 5198
   248  Pushing signature to: us.gcr.io/dlorenc-vmtest2/wasm:sha256-9e7a511fb3130ee4641baf1adc0400bed674d4afc3f1b81bb581c3c8f613f812.sig
   249  ```
   250  
   251  #### In-Toto Attestations
   252  
   253  Cosign also has built-in support for [in-toto](https://in-toto.io) attestations.
   254  The specification for these is defined [here](https://github.com/in-toto/attestation).
   255  
   256  You can create and sign one from a local predicate file using the following commands:
   257  
   258  ```shell
   259  $ cosign attest --predicate <file> --key cosign.key <image>
   260  ```
   261  
   262  All of the standard key management systems are supported.
   263  Payloads are signed using the DSSE signing spec, defined [here](https://github.com/secure-systems-lab/dsse).
   264  
   265  To verify:
   266  
   267  ```shell
   268  $ cosign verify-attestation --key cosign.pub <image>
   269  ```
   270  
   271  ## Detailed Usage
   272  
   273  See the [Usage documentation](USAGE.md) for more commands!
   274  
   275  ## Hardware-based Tokens
   276  
   277  See the [Hardware Tokens documentation](TOKENS.md) for information on how to use `cosign` with hardware.
   278  
   279  ## Keyless
   280  
   281  🚨 🚨 🚨 See [here](KEYLESS.md) for info on the experimental Keyless signatures mode. 🚨 🚨 🚨
   282  
   283  ## Registry Support
   284  
   285  `cosign` uses [go-containerregistry](https://github.com/google/go-containerregistry) for registry
   286  interactions, which has generally excellent compatibility, but some registries may have quirks.
   287  
   288  Today, `cosign` has been tested and works against the following registries:
   289  
   290  * AWS Elastic Container Registry
   291  * GCP's Artifact Registry and Container Registry
   292  * Docker Hub
   293  * Azure Container Registry
   294  * JFrog Artifactory Container Registry
   295  * The CNCF distribution/distribution Registry
   296  * GitLab Container Registry
   297  * GitHub Container Registry
   298  * The CNCF Harbor Registry
   299  * Digital Ocean Container Registry
   300  * Sonatype Nexus Container Registry
   301  * Alibaba Cloud Container Registry
   302  * Red Hat Quay Container Registry 3.6+
   303    - Note: Cosign does not work with the Quay.io hosted service
   304  
   305  We aim for wide registry support. To `sign` images in registries which do not yet fully support [OCI media types](https://github.com/sigstore/cosign/blob/main/SPEC.md#object-types), one may need to use `COSIGN_DOCKER_MEDIA_TYPES` to fall back to legacy equivalents. For example:
   306  ```shell
   307  COSIGN_DOCKER_MEDIA_TYPES=1 cosign sign --key cosign.key legacy-registry.example.com/my/image
   308  ```
   309  
   310  Please help test and file bugs if you see issues!
   311  Instructions can be found in the [tracking issue](https://github.com/sigstore/cosign/issues/40).
   312  
   313  ## Rekor Support
   314  _Note: this is an experimental feature_
   315  
   316  To publish signed artifacts to a Rekor transparency log and verify their existence in the log
   317  set the `COSIGN_EXPERIMENTAL=1` environment variable.
   318  
   319  ```shell
   320  $ COSIGN_EXPERIMENTAL=1 cosign sign --key cosign.key dlorenc/demo
   321  $ COSIGN_EXPERIMENTAL=1 cosign verify --key cosign.pub dlorenc/demo
   322  ```
   323  
   324  `cosign` defaults to using the public instance of rekor at [rekor.sigstore.dev](https://rekor.sigstore.dev).
   325  To configure the rekor server, use the -`rekor-url` flag
   326  
   327  ## Caveats
   328  
   329  ### Intentionally Missing Features
   330  
   331  `cosign` only generates ECDSA-P256 keys and uses SHA256 hashes.
   332  Keys are stored in PEM-encoded PKCS8 format.
   333  However, you can use `cosign` to store and retrieve signatures in any format, from any algorithm.
   334  
   335  ### Unintentionally Missing Features
   336  
   337  `cosign` will integrate with transparency logs!
   338  See https://github.com/sigstore/cosign/issues/34 for more info.
   339  
   340  `cosign` will integrate with even more transparency logs, and a PKI.
   341  See https://github.com/sigStore/fulcio for more info.
   342  
   343  `cosign` will also support The Update Framework for delegations, key discovery and expiration.
   344  See https://github.com/sigstore/cosign/issues/86 for more info!
   345  
   346  ### Things That Should Probably Change
   347  
   348  #### Payload Formats
   349  
   350  `cosign` only supports Red Hat's [simple signing](https://www.redhat.com/en/blog/container-image-signing)
   351  format for payloads.
   352  That looks like:
   353  
   354  ```json
   355  {
   356      "critical": {
   357             "identity": {
   358                 "docker-reference": "testing/manifest"
   359             },
   360             "image": {
   361                 "Docker-manifest-digest": "sha256:20be...fe55"
   362             },
   363             "type": "cosign container image signature"
   364      },
   365      "optional": {
   366             "creator": "Bob the Builder",
   367             "timestamp": 1458239713
   368      }
   369  }
   370  ```
   371  **Note:** This can be generated for an image reference using `cosign generate <image>`.
   372  
   373  I'm happy to switch this format to something else if it makes sense.
   374  See https://github.com/notaryproject/nv2/issues/40 for one option.
   375  
   376  
   377  #### Registry Details
   378  
   379  `cosign` signatures are stored as separate objects in the OCI registry, with only a weak
   380  reference back to the object they "sign".
   381  This means this relationship is opaque to the registry, and signatures *will not* be deleted
   382  or garbage-collected when the image is deleted.
   383  Similarly, they **can** easily be copied from one environment to another, but this is not
   384  automatic.
   385  
   386  Multiple signatures are stored in a list which is unfortunately "racy" today.
   387  To add a signature, clients orchestrate a "read-append-write" operation, so the last write
   388  will win in the case of contention.
   389  
   390  ##### Specifying Registry
   391  `cosign` will default to storing signatures in the same repo as the image it is signing.
   392  To specify a different repo for signatures, you can set the `COSIGN_REPOSITORY` environment variable.
   393  
   394  This will replace the repo in the provided image like this:
   395  ```
   396  $ export COSIGN_REPOSITORY=gcr.io/my-new-repo
   397  $ gcr.io/dlorenc-vmtest2/demo -> gcr.io/my-new-repo/demo:sha256-DIGEST.sig
   398  ```
   399  So the signature for `gcr.io/dlorenc-vmtest2/demo` will be stored in `gcr.io/my-new-repo/demo:sha256-DIGEST.sig`.
   400  
   401  
   402  ## Signature Specification
   403  
   404  `cosign` is inspired by tools like [minisign](https://jedisct1.github.io/minisign/) and
   405  [signify](https://www.openbsd.org/papers/bsdcan-signify.html).
   406  
   407  Generated private keys are stored in PEM format.
   408  The keys encrypted under a password using scrypt as a KDF and nacl/secretbox for encryption.
   409  
   410  They have a PEM header of `ENCRYPTED COSIGN PRIVATE KEY`:
   411  
   412  ```
   413  -----BEGIN ENCRYPTED COSIGN PRIVATE KEY-----
   414  ...
   415  -----END ENCRYPTED COSIGN PRIVATE KEY-----
   416  ```
   417  
   418  Public keys are stored on disk in PEM-encoded standard PKIX format with a header of `PUBLIC KEY`.
   419  ```
   420  -----BEGIN PUBLIC KEY-----
   421  MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELigCnlLNKgOglRTx1D7JhI7eRw99
   422  QolE9Jo4QUxnbMy5nUuBL+UZF9qqfm/Dg1BNeHRThHzWh2ki9vAEgWEDOw==
   423  -----END PUBLIC KEY-----
   424  ```
   425  
   426  ## Storage Specification
   427  
   428  `cosign` stores signatures in an OCI registry, and uses a naming convention (tag based
   429  on the sha256 of what we're signing) for locating the signature index.
   430  
   431  <p align="center">
   432    <img src="/images/signatures.dot.svg" />
   433  </p>
   434  
   435  `reg.example.com/ubuntu@sha256:703218c0465075f4425e58fac086e09e1de5c340b12976ab9eb8ad26615c3715` has signatures located at `reg.example.com/ubuntu:sha256-703218c0465075f4425e58fac086e09e1de5c340b12976ab9eb8ad26615c3715.sig`
   436  
   437  Roughly (ignoring ports in the hostname): `s/:/-/g` and `s/@/:/g` to find the signature index.
   438  
   439  See [Race conditions](#race-conditions) for some caveats around this strategy.
   440  
   441  Alternative implementations could use transparency logs, local filesystem, a separate repository
   442  registry, an explicit reference to a signature index, a new registry API, grafeas, etc.
   443  
   444  ### Signing subjects
   445  
   446  `cosign` only works for artifacts stored as "manifests" in the registry today.
   447  The proposed mechanism is flexible enough to support signing arbitrary things.
   448  
   449  ### KMS Support
   450  
   451  `cosign` supports using a KMS provider to generate and sign keys.
   452  Right now cosign supports Hashicorp Vault, AWS KMS, GCP KMS, Azure Key Vault and we are hoping to support more in the future!
   453  
   454  See the [KMS docs](KMS.md) for more details.
   455  
   456  ### OCI Artifacts
   457  
   458  Push an artifact to a registry using [oras](https://github.com/deislabs/oras) (in this case, `cosign` itself!):
   459  
   460  ```shell
   461  $ oras push us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact ./cosign
   462  Uploading f53604826795 cosign
   463  Pushed us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact
   464  Digest: sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef
   465  ```
   466  
   467  Now sign it! Using `cosign` of course:
   468  
   469  ```shell
   470  $ cosign sign --key cosign.key us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact@sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef
   471  Enter password for private key:
   472  Pushing signature to: us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact:sha256-551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef.sig
   473  ```
   474  
   475  Finally, verify `cosign` with `cosign` again:
   476  
   477  ```shell
   478  $ cosign verify --key cosign.pub  us-central1-docker.pkg.dev/dlorenc-vmtest2/test/artifact@sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef
   479  The following checks were performed on each of these signatures:
   480    - The cosign claims were validated
   481    - The claims were present in the transparency log
   482    - The signatures were integrated into the transparency log when the certificate was valid
   483    - The signatures were verified against the specified public key
   484    - Any certificates were verified against the Fulcio roots.
   485  
   486  {"Critical":{"Identity":{"docker-reference":""},"Image":{"Docker-manifest-digest":"sha256:551e6cce7ed2e5c914998f931b277bc879e675b74843e6f29bc17f3b5f692bef"},"Type":"cosign container image signature"},"Optional":null}
   487  ```
   488  
   489  ## FAQ
   490  
   491  ### Why not use Notary v2
   492  
   493  It's hard to answer this briefly.
   494  This post contains some comparisons:
   495  
   496  [Notary V2 and Cosign](https://medium.com/@dlorenc/notary-v2-and-cosign-b816658f044d)
   497  
   498  If you find other comparison posts, please send a PR here and we'll link them all.
   499  
   500  ### Why not use containers/image signing
   501  
   502  `containers/image` signing is close to `cosign`, and we reuse payload formats.
   503  `cosign` differs in that it signs with ECDSA-P256 keys instead of PGP, and stores
   504  signatures in the registry.
   505  
   506  ### Why not use TUF?
   507  
   508  I believe this tool is complementary to TUF, and they can be used together.
   509  I haven't tried yet, but think we can also reuse a registry for TUF storage.
   510  
   511  ### Why not use Blockchain?
   512  
   513  Just kidding. Nobody actually asked this. Don't be that person.
   514  
   515  ### Why not use $FOO?
   516  
   517  See the next section, [Requirements](#Requirements).
   518  I designed this tool to meet a few specific requirements, and didn't find
   519  anything else that met all of these.
   520  If you're aware of another system that does meet these, please let me know!
   521  
   522  ## Design Requirements
   523  
   524  * No external services for signature storage, querying, or retrieval
   525  * We aim for as much registry support as possible
   526  * Everything should work over the registry API
   527  * PGP should not be required at all.
   528  * Users must be able to find all signatures for an image
   529  * Signers can sign an image after push
   530  * Multiple entities can sign an image
   531  * Signing an image does not mutate the image
   532  * Pure-go implementation
   533  
   534  ## Future Ideas
   535  
   536  ### Registry API Changes
   537  
   538  The naming convention and read-modify-write update patterns we use to store things in
   539  a registry a bit, well, "hacky".
   540  I think they're the best (only) real option available today, but if the registry API
   541  changes we can improve these.
   542  
   543  ### Other Types
   544  
   545  `cosign` can sign anything in a registry.
   546  These examples show signing a single image, but you could also sign a multi-platform `Index`,
   547  or any other type of artifact.
   548  This includes Helm Charts, Tekton Pipelines, and anything else currently using OCI registries
   549  for distribution.
   550  
   551  This also means new artifact types can be uploaded to a registry and signed.
   552  One interesting type to store and sign would be TUF repositories.
   553  I haven't tried yet, but I'm fairly certain TUF could be implemented on top of this.
   554  
   555  ### Tag Signing
   556  
   557  `cosign` signatures protect the digests of objects stored in a registry.
   558  The optional `annotations` support (via the `-a` flag to `cosign sign`) can be used to add extra
   559  data to the payload that is signed and protected by the signature.
   560  One use-case for this might be to sign a tag->digest mapping.
   561  
   562  If you would like to attest that a specific tag (or set of tags) should point at a digest, you can
   563  run something like:
   564  
   565  ```shell
   566  $ TAG=sign-me
   567  $ DGST=$(crane digest dlorenc/demo:$TAG)
   568  $ cosign sign --key cosign.key -a tag=$TAG dlorenc/demo@$DGST
   569  Enter password for private key:
   570  Pushing signature to: dlorenc/demo:sha256-97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36.sig
   571  ```
   572  
   573  Then you can verify that the tag->digest mapping is also covered in the signature, using the `-a` flag to `cosign verify`.
   574  This example verifies that the digest `$TAG` points to (`sha256:97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36`)
   575  has been signed, **and also** that the `$TAG`:
   576  
   577  ```shell
   578  $ cosign verify --key cosign.pub -a tag=$TAG dlorenc/demo:$TAG | jq .
   579  {
   580    "Critical": {
   581      "Identity": {
   582        "docker-reference": ""
   583      },
   584      "Image": {
   585        "Docker-manifest-digest": "97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36"
   586      },
   587      "Type": "cosign container image signature"
   588    },
   589    "Optional": {
   590      "tag": "sign-me"
   591    }
   592  }
   593  ```
   594  
   595  Timestamps could also be added here, to implement TUF-style freeze-attack prevention.
   596  
   597  ### Base Image/Layer Signing
   598  
   599  Again, `cosign` can sign anything in a registry.
   600  You could use `cosign` to sign an image that is intended to be used as a base image,
   601  and include that provenance metadata in resulting derived images.
   602  This could be used to enforce that an image was built from an authorized base image.
   603  
   604  Rough Idea:
   605  * OCI manifests have an ordered list of `layer` `Descriptors`, which can contain annotations.
   606    See [here](https://github.com/opencontainers/image-spec/blob/master/manifest.md) for the
   607    specification.
   608  * A base image is an ordered list of layers to which other layers are appended, as well as an
   609    initial configuration object that is mutated.
   610    * A derived image is free to completely delete/destroy/recreate the config from its base image,
   611      so signing the config would provided limited value.
   612  * We can sign the full set of ordered base layers, and attach that signature as an annotation to
   613    the **last** layer in the resulting child image.
   614  
   615  This example manifest manifest represents an image that has been built from a base image with two
   616  layers.
   617  One additional layer is added, forming the final image.
   618  
   619  ```json
   620  {
   621    "schemaVersion": 2,
   622    "config": {
   623      "mediaType": "application/vnd.oci.image.config.v1+json",
   624      "size": 7023,
   625      "digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7"
   626    },
   627    "layers": [
   628      {
   629        "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
   630        "size": 32654,
   631        "digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0"
   632      },
   633      {
   634        "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
   635        "size": 16724,
   636        "digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b",
   637        "annotations": {
   638          "dev.cosign.signature.baseimage": "Ejy6ipGJjUzMDoQFePWixqPBYF0iSnIvpMWps3mlcYNSEcRRZelL7GzimKXaMjxfhy5bshNGvDT5QoUJ0tqUAg=="
   639        }
   640      },
   641      {
   642        "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
   643        "size": 73109,
   644        "digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736"
   645      }
   646    ],
   647  }
   648  ```
   649  
   650  Note that this could be applied recursively, for multiple intermediate base images.
   651  
   652  ### Counter-Signing
   653  
   654  Cosign signatures (and their protected payloads) are stored as artifacts in a registry.
   655  These signature objects can also be signed, resulting in a new, "counter-signature" artifact.
   656  This "counter-signature" protects the signature (or set of signatures) **and** the referenced artifact, which allows
   657  it to act as an attestation to the **signature(s) themselves**.
   658  
   659  Before we sign the signature artifact, we first give it a memorable name so we can find it later.
   660  
   661  ```shell
   662  $ cosign sign --key cosign.key -a sig=original dlorenc/demo
   663  Enter password for private key:
   664  Pushing signature to: dlorenc/demo:sha256-97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36.sig
   665  $ cosign verify --key cosign.pub dlorenc/demo | jq .
   666  {
   667    "Critical": {
   668      "Identity": {
   669        "docker-reference": ""
   670      },
   671      "Image": {
   672        "Docker-manifest-digest": "97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36"
   673      },
   674      "Type": "cosign container image signature"
   675    },
   676    "Optional": {
   677      "sig": "original"
   678    }
   679  }
   680  ```
   681  
   682  Now give that signature a memorable name, then sign that:
   683  
   684  ```shell
   685  $ crane tag $(cosign triangulate dlorenc/demo) mysignature
   686  2021/02/15 20:22:55 dlorenc/demo:mysignature: digest: sha256:71f70e5d29bde87f988740665257c35b1c6f52dafa20fab4ba16b3b1f4c6ba0e size: 556
   687  $ cosign sign --key cosign.key -a sig=counter dlorenc/demo:mysignature
   688  Enter password for private key:
   689  Pushing signature to: dlorenc/demo:sha256-71f70e5d29bde87f988740665257c35b1c6f52dafa20fab4ba16b3b1f4c6ba0e.sig
   690  $ cosign verify --key cosign.pub dlorenc/demo:mysignature
   691  {"Critical":{"Identity":{"docker-reference":""},"Image":{"Docker-manifest-digest":"71f70e5d29bde87f988740665257c35b1c6f52dafa20fab4ba16b3b1f4c6ba0e"},"Type":"cosign container image signature"},"Optional":{"sig":"counter"}}
   692  ```
   693  
   694  Finally, check the original signature:
   695  
   696  ```shell
   697  $ crane manifest dlorenc/demo@sha256:71f70e5d29bde87f988740665257c35b1c6f52dafa20fab4ba16b3b1f4c6ba0e
   698  {
   699    "schemaVersion": 2,
   700    "config": {
   701      "mediaType": "application/vnd.oci.image.config.v1+json",
   702      "size": 233,
   703      "digest": "sha256:3b25a088710d03f39be26629d22eb68cd277a01673b9cb461c4c24fbf8c81c89"
   704    },
   705    "layers": [
   706      {
   707        "mediaType": "application/vnd.oci.descriptor.v1+json",
   708        "size": 217,
   709        "digest": "sha256:0e79a356609f038089088ec46fd95f4649d04de989487220b1a0adbcc63fadae",
   710        "annotations": {
   711          "dev.sigstore.cosign/signature": "5uNZKEP9rm8zxAL0VVX7McMmyArzLqtxMTNPjPO2ns+5GJpBeXg+i9ILU+WjmGAKBCqiexTxzLC1/nkOzD4cDA=="
   712        }
   713      }
   714    ]
   715  }
   716  ```
   717  
   718  ## Security
   719  
   720  Should you discover any security issues, please refer to sigstore's [security
   721  process](https://github.com/sigstore/community/blob/main/SECURITY.md)