1# Cosign Signature Specifications
2
3This document aims to describe how `cosign` signs containers.
4The goal is to specify the behavior well enough to promote other implementations and enable interoperability.
5Container signatures generated with `cosign` should be verifiable in other tools, and vice-versa.
6
7This document is broken up into a few parts:
8* [Properties](#properties) details the individual components that are used to create and verify signatures.
9* [Storage](#storage) details how signatures are stored and discovered in an OCI registry.
10* [Payload](#payload) details the format of to-be-signed payloads.
11* [Signature](#signature) details the signature schemes supported.
12
13## Properties
14
15This section describes the REQUIRED and OPTIONAL properties used to sign and verify an image.
16Their layout in an OCI object is described below.
17
18* `payload` bytes
19
20 This REQUIRED property contains the contents of signed data in byte-form.
21 Because signatures are __detached__, the payload MUST contain the digest of the image it references, in a well-known location.
22 This location is dependent on the [payload format](#payloads).
23
24* `mediaType` string
25
26 This REQUIRED property contains the media type of the payload.
27
28* `signature` string
29
30 This REQUIRED property contains the base64-encoded signature.
31 This signature MUST be generated by a supported scheme.
32 For more details on supported schemes, see the [`Signature`](#signature) section below.
33
34 Example `signature`:
35 `MEYCIQDXmXWj59naoPFlLnCADIPLKgLG3LyFtKrbjpnkYiGNGgIhAJ/eNx5zr/l1MJKSFpFMjPKKr4fjh5RHEtT2DhMamZuT`
36
37* `certificate` string
38
39 This OPTIONAL property contains a [PEM-encoded](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail) x509 certificate.
40 If present, this certificate MUST embed the public key that can be used to verify the signature.
41
42 Example `certificate`:
43
44```
45-----BEGIN CERTIFICATE-----
46MIICrjCCAjSgAwIBAgIUAM4mURWUSkg06fmHmFfTmerYKaUwCgYIKoZIzj0EAwMw
47KjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0y
48MTA0MDExNTU5MDZaFw0yMTA0MDExNjE4NTlaMDoxGzAZBgNVBAoMEmRsb3JlbmNA
49Z29vZ2xlLmNvbTEbMBkGA1UEAwwSZGxvcmVuY0Bnb29nbGUuY29tMFkwEwYHKoZI
50zj0CAQYIKoZIzj0DAQcDQgAE3R0ZtpfBd3Y8DaXuB1gM8JPlhsDIEfXO/WsMJEN1
514hEn8wajX2HklqL7igZPFICv6tBUGylIHp2mTH2Nhv38mqOCASYwggEiMA4GA1Ud
52DwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAMBgNVHRMBAf8EAjAAMB0G
53A1UdDgQWBBTy3UWIop0bNrdNgSrVHHD10qSASTAfBgNVHSMEGDAWgBTIxR0AQZok
54KTJRJOsNrkrtSgbT7DCBjQYIKwYBBQUHAQEEgYAwfjB8BggrBgEFBQcwAoZwaHR0
55cDovL3ByaXZhdGVjYS1jb250ZW50LTYwM2ZlN2U3LTAwMDAtMjIyNy1iZjc1LWY0
56ZjVlODBkMjk1NC5zdG9yYWdlLmdvb2dsZWFwaXMuY29tL2NhMzZhMWU5NjI0MmI5
57ZmNiMTQ2L2NhLmNydDAdBgNVHREEFjAUgRJkbG9yZW5jQGdvb2dsZS5jb20wCgYI
58KoZIzj0EAwMDaAAwZQIwC15Gtd9F6W9lmJuoXMym9DfWlBpK5HEPak38WPXqowRp
596p+2/3jSLkFT5Nn5fuISAjEAouVlX4zH2rlkfg45HnDJax7o6ZV+E0/6BdAms44D
60Ej6T/GLK6XJSB28haSPRWB7k
61-----END CERTIFICATE-----
62```
63
64* `chain` string
65 This OPTIONAL property contains a PEM-encoded, DER-formatted, ASN.1 x509 certificate chain.
66 The `certificate` property MUST be present if this property is present.
67 This chain MAY be used by implementations to verify the `certificate` property.
68 Clients MUST validate that any certificates in the chain that are self-signed
69 or are expected to be trust anchors with an out-of-band mechanism.
70
71 Example `chain`:
72
73```
74----BEGIN CERTIFICATE-----
75MIIB+DCCAX6gAwIBAgITNVkDZoCiofPDsy7dfm6geLbuhzAKBggqhkjOPQQDAzAq
76MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIx
77MDMwNzAzMjAyOVoXDTMxMDIyMzAzMjAyOVowKjEVMBMGA1UEChMMc2lnc3RvcmUu
78ZGV2MREwDwYDVQQDEwhzaWdzdG9yZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLSy
79A7Ii5k+pNO8ZEWY0ylemWDowOkNa3kL+GZE5Z5GWehL9/A9bRNA3RbrsZ5i0Jcas
80taRL7Sp5fp/jD5dxqc/UdTVnlvS16an+2Yfswe/QuLolRUCrcOE2+2iA5+tzd6Nm
81MGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYE
82FMjFHQBBmiQpMlEk6w2uSu1KBtPsMB8GA1UdIwQYMBaAFMjFHQBBmiQpMlEk6w2u
83Su1KBtPsMAoGCCqGSM49BAMDA2gAMGUCMH8liWJfMui6vXXBhjDgY4MwslmN/TJx
84Ve/83WrFomwmNf056y1X48F9c4m3a3ozXAIxAKjRay5/aj/jsKKGIkmQatjI8uup
85Hr/+CxFvaJWmpYqNkLDGRU+9orzh5hI2RrcuaQ==
86-----END CERTIFICATE-----
87-----BEGIN CERTIFICATE-----
88MIICVTCCAT2gAwIBAgIQAUrAOaxMcCVQ6AwcDagmRzANBgkqhkiG9w0BAQsFADAh
89MR8wHQYDVQQDDBZZdWJpY28gUElWIEF0dGVzdGF0aW9uMCAXDTE2MDMxNDAwMDAw
90MFoYDzIwNTIwNDE3MDAwMDAwWjAlMSMwIQYDVQQDDBpZdWJpS2V5IFBJViBBdHRl
91c3RhdGlvbiA5YzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFfnSOVAZLOTOYRs
92n4BeD3cMYHFvtwBsK8X0yJ21NKUwJ3fvnqdq0qGeIT92zstNLEWCqP3qMkhs9sh4
93wP1tHTGjTjBMMBEGCisGAQQBgsQKAwMEAwUCBjAUBgorBgEEAYLECgMHBAYCBADH
94kP4wEAYKKwYBBAGCxAoDCAQCAwIwDwYKKwYBBAGCxAoDCQQBAzANBgkqhkiG9w0B
95AQsFAAOCAQEAVRtRFpmgFD+rQqBG92HArMQ+j1FMX23QL9Z76IhaSElmN6cjgsv3
968pJM8GL+ih6vVyCHeU6GoE9Bgj2XB02ZgkmWihnaJX2WG4VOm2dN3SqDmWFp4KLJ
97vuzVXEHWuGevwMAOsvMkmXP8HI2npaCPBmprirExbv6bxSyng4ZNHmgdzqmjYyt+
98d+ELe3xEeYYqQYx+IswHPRE5mGk/PO4hysk79mhwRNuvmygDbI8Emwvp3Pgzlgr1
99Gyp4apdU7AXEwysEQIb034aPrTlpmxh90SnTZFs2DHOvCjCPPAmoWfuQUwPhSPRb
10092pXqODWYqpW8+IRED5e42Ncu9XtDgS5Pw==
101-----END CERTIFICATE-----
102```
103
104* `bundle` string
105
106 This OPTIONAL property contains a JSON formatted `bundle` type, which can be used for offline verification.
107 Example `bundle`:
108
109```json
110{
111 "SignedEntryTimestamp": "MEUCIQDHiGUesxPpn+qRONLmKlNIVPhl9gBMnwNeIQmRkRmZVQIgRxPpuYQDZR/8lYKcEfiQn5b+7VDoJIC72ZWHO9ZCp1A=",
112 "Payload": {
113 "body": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJzcGVjIjp7ImRhdGEiOnsiaGFzaCI6eyJhbGdvcml0aG0iOiJzaGEyNTYiLCJ2YWx1ZSI6ImE0NDkyYjBlYWJkZDIzMTJmMDYzMjkwYWJkNzk3ZDlkNzFhM2FiMjhiZDY1YTJjMTg5YjBkZjBkMzliOGMzYjkifX0sInNpZ25hdHVyZSI6eyJjb250ZW50IjoiTUVRQ0lDTmRYeTNiWHAxRE1PTDZOUGZYMzVnSjI3YnpsZHdTdkNBTnd5ZE9RVWlqQWlCQWg5WlJwQ3AzYlg5eE9UbEhTR2w0cFVGd0ZtUFJJWGZpY09pRTBHM1Vzdz09IiwiZm9ybWF0IjoieDUwOSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTmxla05EUVdkRFowRjNTVUpCWjBsVVZISk9aa013YkZSSmRWSXZWR0UyWm14MWFtdFFOWHBaTDFSQlMwSm5aM0ZvYTJwUFVGRlJSRUY2UVhFS1RWSlZkMFYzV1VSV1VWRkxSWGQ0ZW1GWFpIcGtSemw1V2xNMWExcFlXWGhGVkVGUVFtZE9Wa0pCVFZSRFNFNXdXak5PTUdJelNteE5RalJZUkZSSmVBcE5SRmw1VFdwSmVFMUVaM2RPUm05WVJGUkplRTFFV1hsTmFrbDRUV3BuZDAweGIzZEJSRUphVFVKTlIwSjVjVWRUVFRRNVFXZEZSME5EY1VkVFRUUTVDa0YzUlVoQk1FbEJRazFGV1M4ck4yRktjRmRLVFhjNWVrTmljMDFrT0hOQlRUTmxSbk5OTjBSbFpFZGlXRzlNUjJ4YUwyZHBNR2h5WTBaU1NWVTRiM2NLUzBKeU1ISkVTRE5QVkZaSWJVdFVZMkV2SzIweGQxQjNTVzlZTTFGUVYycG5aMFYwVFVsSlFrdFVRVTlDWjA1V1NGRTRRa0ZtT0VWQ1FVMURRalJCZHdwRmQxbEVWbEl3YkVKQmQzZERaMWxKUzNkWlFrSlJWVWhCZDAxM1JFRlpSRlpTTUZSQlVVZ3ZRa0ZKZDBGRVFXUkNaMDVXU0ZFMFJVWm5VVlZ5WVRoTENuSnJaMjAzVGtsNFRrNXBVMkpZVG00eFdFVkxhRzFyZDBoM1dVUldVakJxUWtKbmQwWnZRVlY1VFZWa1FVVkhZVXBEYTNsVlUxUnlSR0UxU3pkVmIwY0tNQ3QzZDJkWk1FZERRM05IUVZGVlJrSjNSVUpDU1VkQlRVZzBkMlpCV1VsTGQxbENRbEZWU0UxQlMwZGpSMmd3WkVoQk5reDVPWGRqYld3eVdWaFNiQXBaTWtWMFdUSTVkV1JIVm5Wa1F6QXlUVVJPYlZwVVpHeE9lVEIzVFVSQmQweFVTWGxOYW1OMFdXMVpNMDVUTVcxT1Ixa3hXbFJuZDFwRVNUVk9WRkYxQ21NelVuWmpiVVp1V2xNMWJtSXlPVzVpUjFab1kwZHNla3h0VG5aaVV6bHFXVlJOTWxsVVJteFBWRmw1VGtSS2FVOVhXbXBaYWtVd1RtazVhbGxUTldvS1kyNVJkMHBCV1VSV1VqQlNRVkZJTDBKQ2IzZEhTVVZYWTBoS2NHVlhSak5aVjFKdlpESkdRVm95T1haYU1uaHNURzFPZG1KVVFVdENaMmR4YUd0cVR3cFFVVkZFUVhkT2NFRkVRbTFCYWtWQk1UQlVSR015Wm1oUFZrRlVNWFJzZFM4MmMzWnhSbEZ1YkRaWU9YZGhNbXRUU2t0RGJqUkZZbFJFYTNwYVJYb3lDblppUWtwb2FFZ3ZjbWRXUjFKMU5tWkJha1ZCYkhsb05uUmhZelJZVFRaS2IzVlZlRWtyTjFnelFtUTFXVXR5WlRGS1dFOWhia0ZaYW1adldHNTVUSFFLZDNCSVFWb3paVzFhY0VWa00yeHFTVEF3Vm04S0xTMHRMUzFGVGtRZ1EwVlNWRWxHU1VOQlZFVXRMUzB0TFFvPSJ9fX0sImtpbmQiOiJyZWtvcmQifQ==",
114 "integratedTime": 1624396085,
115 "logIndex": 5179,
116 "logID": "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"
117 }
118}
119```
120
121 The following are REQUIRED properties of the bundle:
122
123 - The `SignedEntryTimestamp` is a rekor-signed signature over the logIndex, body and integratedTime of the Rekor Log Entry
124 - The `Payload` consists of all fields required to verify the SET:
125 - The `body` is the body of the Rekor Log Entry
126 - The `integratedTime` is the UNIX timestamp the log entry was integrated into the transparency log
127 - The `logIndex` is the index of the log entry in the transparency log
128 - The `logID` is the SHA256 hash of the DER-encoded public key for the log at the time the entry was included in the log
129
130For instructions on using the `bundle` for verification, see [USAGE.md](../USAGE.md#verify-a-signature-was-added-to-the-transparency-log).
131
132* `rfc3161timestamp` string
133
134 This OPTIONAL property contains a JSON formatted `RFC3161Timestamp` containing the timestamp response from a
135 timestamp authority.
136
137## Storage
138
139`cosign` image signatures are stored in an OCI registry and are designed to make use of the existing specifications.
140The full specifications for the OCI formats and specifications used are available [here](https://github.com/opencontainers).
141
142### Discovery
143
144Signature object are placed in specific location in an OCI registry to enable consistent, interoperable discovery.
145
146Multiple discovery mechanisms MAY be used.
147Implementations MUST support at least the following mechanisms:
148
149* Tag-based Discovery
150
151#### Tag-based Discovery
152
153In this scheme, signatures are stored in an OCI registry in a predictable location, addressable by tag.
154The location of signatures corresponding to a specific object can be computed using the digest of the object.
155
156If the object is referenced by tag, the tag must first be resolved to a digest.
157Then the digest of the object (of the form `sha256:abcdef...`) is encoded into a tag name using the following rules:
158
159* Replace the `:` character with a `-`
160* Append the `.sig` suffix
161
162Example digest->tag mapping:
163
1641. Start with `gcr.io/dlorenc-vmtest2/demo:latest`
1652. Resolve this to a digest: `sha256:97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36`
1663. Follow the encoding rules: `sha256-97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36.sig`
1674. Signature can be found at `gcr.io/dlorenc-vmtest2/demo:sha256-97fc222cee7991b5b061d4d4afdb5f3428fcb0c9054e1690313786befa1e4e36.sig`
168
169Implementations MAY store signatures objects in the same OCI repository as the target image or a different one.
170
171### Object Types
172
173This section describes the way the properties from above are embedded into OCI objects that can be stored in a registry.
174Implementations MUST support storing signatures in at least the following object types:
175
176* [OCI Image Manifest V1](#oci-image-manifest-v1)
177
178#### OCI Image Manifest V1
179
180This section describes the way the mandatory and optional signature properties are embedded into an
181[OCI Image Manifest V1](https://github.com/opencontainers/image-spec/blob/master/manifest.md) object.
182
183Only one image manifest is created for every signed object.
184Multiple signatures can be embedded in one image manifest.
185
186##### Payload and mediaType
187
188The `payload` bytes are uploaded to an OCI registry as a `blob`, and are referenced by `digest`, `size` and `mediaType.`
189The digest is embedded into the `Image` manifest as a `layer`, via a [`Descriptor`](https://github.com/opencontainers/image-spec/blob/master/descriptor.md).
190
191The `mediaType` property for the `payload` is included in the same descriptor.
192
193Example `payload`:
194
195```json
196{
197 "schemaVersion": 2,
198 "config": {
199 "mediaType": "application/vnd.oci.image.config.v1+json",
200 <omitted for brevity>
201 },
202 "layers": [
203 {
204 "mediaType": "application/vnd.dev.cosign.simplesigning.v1+json",
205 "size": 210,
206 "digest": "sha256:1119abab63e605dcc281019bad0424744178b6f61ba57378701fe7391994c999",
207 },
208 <other layers here>
209 ]
210}
211```
212
213##### Signature
214
215The `signature` is base64-encoded and stored as an `annotation` on the layer, in the same descriptor.
216The `annotation` key is `dev.cosignproject.cosign/signature`.
217
218Example `signature`:
219
220```json
221"annotations": {
222 "dev.cosignproject.cosign/signature": "MEUCIBKI9FIC+YD3m/lWViyPxsJsbnIHj86sSbb7L3qvpEFoAiEA2ZChO/67CuAPQKJLBVsAc7bs9hBK8RpsdfjBsByGKJM="
223}
224```
225
226##### Certificate
227
228The `certificate` is stored as an `annotation` on the layer, in the same descriptor.
229The `annotation` key is `dev.cosignproject.cosign/certificate`.
230
231Example `certificate`:
232
233```json
234"annotations": {
235 "dev.sigstore.cosign/certificate": "-----BEGIN CERTIFICATE-----\nMIICrjCCAjSgAwIBAgIUAM4mURWUSkg06fmHmFfTmerYKaUwCgYIKoZIzj0EAwMw\nKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0y\nMTA0MDExNTU5MDZaFw0yMTA0MDExNjE4NTlaMDoxGzAZBgNVBAoMEmRsb3JlbmNA\nZ29vZ2xlLmNvbTEbMBkGA1UEAwwSZGxvcmVuY0Bnb29nbGUuY29tMFkwEwYHKoZI\nzj0CAQYIKoZIzj0DAQcDQgAE3R0ZtpfBd3Y8DaXuB1gM8JPlhsDIEfXO/WsMJEN1\n4hEn8wajX2HklqL7igZPFICv6tBUGylIHp2mTH2Nhv38mqOCASYwggEiMA4GA1Ud\nDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAMBgNVHRMBAf8EAjAAMB0G\nA1UdDgQWBBTy3UWIop0bNrdNgSrVHHD10qSASTAfBgNVHSMEGDAWgBTIxR0AQZok\nKTJRJOsNrkrtSgbT7DCBjQYIKwYBBQUHAQEEgYAwfjB8BggrBgEFBQcwAoZwaHR0\ncDovL3ByaXZhdGVjYS1jb250ZW50LTYwM2ZlN2U3LTAwMDAtMjIyNy1iZjc1LWY0\nZjVlODBkMjk1NC5zdG9yYWdlLmdvb2dsZWFwaXMuY29tL2NhMzZhMWU5NjI0MmI5\nZmNiMTQ2L2NhLmNydDAdBgNVHREEFjAUgRJkbG9yZW5jQGdvb2dsZS5jb20wCgYI\nKoZIzj0EAwMDaAAwZQIwC15Gtd9F6W9lmJuoXMym9DfWlBpK5HEPak38WPXqowRp\n6p+2/3jSLkFT5Nn5fuISAjEAouVlX4zH2rlkfg45HnDJax7o6ZV+E0/6BdAms44D\nEj6T/GLK6XJSB28haSPRWB7k\n-----END CERTIFICATE-----\n",
236}
237```
238
239##### Chain
240
241The `chain` is stored as an `annotation` on the layer, in the same descriptor.
242The `annotation` key is `dev.cosignproject.cosign/chain`.
243
244Example `chain`:
245
246```json
247"annotations": {
248 "dev.sigstore.cosign/chain": "-----BEGIN CERTIFICATE-----\nMIIB+DCCAX6gAwIBAgITNVkDZoCiofPDsy7dfm6geLbuhzAKBggqhkjOPQQDAzAq\nMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIx\nMDMwNzAzMjAyOVoXDTMxMDIyMzAzMjAyOVowKjEVMBMGA1UEChMMc2lnc3RvcmUu\nZGV2MREwDwYDVQQDEwhzaWdzdG9yZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLSy\nA7Ii5k+pNO8ZEWY0ylemWDowOkNa3kL+GZE5Z5GWehL9/A9bRNA3RbrsZ5i0Jcas\ntaRL7Sp5fp/jD5dxqc/UdTVnlvS16an+2Yfswe/QuLolRUCrcOE2+2iA5+tzd6Nm\nMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYE\nFMjFHQBBmiQpMlEk6w2uSu1KBtPsMB8GA1UdIwQYMBaAFMjFHQBBmiQpMlEk6w2u\nSu1KBtPsMAoGCCqGSM49BAMDA2gAMGUCMH8liWJfMui6vXXBhjDgY4MwslmN/TJx\nVe/83WrFomwmNf056y1X48F9c4m3a3ozXAIxAKjRay5/aj/jsKKGIkmQatjI8uup\nHr/+CxFvaJWmpYqNkLDGRU+9orzh5hI2RrcuaQ==\n-----END CERTIFICATE-----"
249}
250```
251
252## Payloads
253
254Implementations MUST support at least the following payload types:
255
256 * Simple Signing
257
258### Simple Signing
259
260The Simple Signing payload format is [specified here](https://github.com/containers/image/blob/a5061e5a5f00333ea3a92e7103effd11c6e2f51d/docs/containers-signature.5.md#json-data-format)
261
262The following additional semantics are applied:
263
264* The `mediaType` used to identify this payload format is: `application/vnd.dev.cosign.simplesigning.v1+json`.
265* The `critical.type` value used to identify `cosign` signatures is: `cosign container image signature`.
266* The `critical.identity.docker-reference` field is ignored.
267* Optional user-specified claims may be included in the `Optional` section.
268
269For example:
270```json
271{
272 "critical": {
273 "identity": {
274 "docker-reference": "testing/manifest"
275 },
276 "image": {
277 "Docker-manifest-digest": "sha256:20be...fe55"
278 },
279 "type": "cosign container image signature"
280 },
281 "optional": {
282 "creator": "atomic",
283 "timestamp": 1458239713
284 }
285}
286```
287
288## Signature Schemes
289
290Implementations must support at least the following schemes:
291
292* ECDSA-P256
293
294No information about the signature scheme is included in the object.
295Clients must determine the signature scheme out-of-band during the verification process.
296
297### Hashing Algorithms
298
299Signers and verifiers must know the hash algorithm used in addition to the signature scheme.
300In an attempt to avoid specifying a particular hashing algorithm, we require that digest be calculated using the SAME algorithm as the OCI registry.
301In practice, this means [sha256](https://github.com/opencontainers/image-spec/blob/master/descriptor.md#digests).
302
303When the payload is stored as a `blob` in the OCI registry, it is exposed and referenced via a [Content Addressable](https://en.wikipedia.org/wiki/Content-addressable_storage) API.
304
305Example referenced payload:
306
307```json
308{
309 "mediaType": "application/vnd.dev.cosign.simplesigning.v1+json",
310 "size": 210,
311 "digest": "sha256:1119abab63e605dcc281019bad0424744178b6f61ba57378701fe7391994c999",
312}
313```
314
315Here, `1119abab63e605dcc281019bad0424744178b6f61ba57378701fe7391994c999` is the hex-encoded digest, and the `sha256:` prefix specifies the algorithm.
316This value is already calculated and verified by both the registry and client-tooling.
317
318This means that our signatures is "linked" to a "container image" happens via two hops:
319
320`Sign(sha256(SimpleSigningPayload(sha256(Image Manifest))))`
321
322Allowing flexibility in hashing algorithms of the digital signature would only allow manipulation of the "outer" one - the image manifest
323itself is always referenced by `sha256` today.
324This means using a different hashing algorithm as part of the final signature, even one perceived as "stronger", would result in limited cryptographic benefits.
325
326Put simply: implementations MUST use the same hash algorithm used by the underlying registry to reference the payload.
327Any future algorithmic-agility will come from the storage layer as part of the OCI specification.
328
329# Rationales and Commentary
330
331This document, while labeled a `Specification`, aims to specify as few things as possible.
332Instead, we prescribe the usage of other specifications.
333
334This section contains a rationale for each choice, as well as comparisons to alternatives considered.
335
336## Payload/Attestation Format: Simple Signing
337
338We chose Simple Signing because it has the most existing usage and meets our requirements:
339
340* Critical/Optional sections
341* Extensible with more attestations
342* Cross-language serialization support
343
344### Alternatives
345
346* OCI Descriptor.
347
348 This has the fields we need, with a few problems.
349 * The annotations section is limiting with map[string]string.
350 * The `URLs` field is not meant for this use-case.
351 * No real benefit, since it's stored as a `blob` (not parsed by the registry).
352
353* Plain digest
354
355 This doesn't have any attestation/annotation support.
356
357* Something new
358
359 See above, we've tried to avoid making any new types where possible.
360
361## OCI Type - Docker Manifest/OCI Manifest
362
363We're currently using Docker but will switch to OCI.
364The format support across registries is a toss-up, but likely to improve for OCI.
365OCI supports custom media-types and has other "correctness" benefits.
366
367## Discovery - Tag Based
368
369We use the tag based mechanism because it's the only option we can think of.
370It meets the two hard requirements: works **everywhere** today and requires no extra services.
371It also does not mutate the signed object (like an attached signature or index might).
372
373Support for multiple signatures works but is racy.
374
375### Alternatives Considered
376
377Notary v1/Grafeas both require another database.
378A few other proprietary APIs exist, but they're not cross-registry.
379
380## Hash Algorithm - None!
381
382Most common signature schemes support customizable hash algorithms.
383These are typically stored with the signature for convenience, presenting a possible attack/confusion vector.
384
385We decided to pin to the registry hash algorithm.
386This removes an entire moving part without sacrificing agility.
387
388The registry/client-tooling already perform hash validation as part of the CAS.
389While their spec does not completely pin to specific algorithm, SHA256 is ubiquitous in practice.
390This means that our signed payload object references the actual image "target" by a sha-256 digest - the entire signature already relies on the strength of this algorithm.
391
392Trading off this perceived agility for the reduction in attack surface is a win.
393
394** Note **: This is only possible if we store the `payload` in a blob by itself.
395Serializing the payload and signature together in something like a JWT for storage would mean the payload is no longer directly hashed into the CAS.
396There is also a performance benefit: we can validate the signature (stored in the manifest) against the payload (stored as a blob) without fetching the blob, because the blob's digest is also present in the manifest.
397
398## Algorithms
399
400We only require ECDSA-P256 (with the SHA256 hash algorithm, see above), but will allow for other schemes.
401We will bias toward algorithms well-supported in the Go ecosystem, but will accept others.
402We will bias toward support for algorithms with wide industry adoption, API support, and hardware availability.
403
404## Compatibility
405
406We are compatible with the In-Toto [Metablock](https://in-toto.readthedocs.io/en/latest/model.html) and JWS [rfc7515](https://tools.ietf.org/html/rfc7515) formats.
407This means we can convert to these formats during verification, and from these formats during upload/signature.
408You can think of this spec as an "on-registry serialization format" for either of these specified formats.
View as plain text