1container-signature(5) format container-signature(5)
2
3
4
5Miloslav Trmač March 2017
6
7
9 container-signature - Container signature format
10
11
12
14 This document describes the format of container signatures, as imple‐
15 mented by the github.com/containers/image/signature package.
16
17
18 Most users should be able to consume these signatures by using the
19 github.com/containers/image/signature package (preferably through the
20 higher-level signature.PolicyContext interface) without having to care
21 about the details of the format described below. This documentation
22 exists primarily for maintainers of the package and to allow indepen‐
23 dent reimplementations.
24
25
27 The signature provides an end-to-end authenticated claim that a con‐
28 tainer image has been approved by a specific party (e.g. the creator of
29 the image as their work, an automated build system as a result of an
30 automated build, a company IT department approving the image for pro‐
31 duction) under a specified identity (e.g. an OS base image / specific
32 application, with a specific version).
33
34
35 A container signature consists of a cryptographic signature which iden‐
36 tifies and authenticates who signed the image, and carries as a signed
37 payload a JSON document. The JSON document identifies the image being
38 signed, claims a specific identity of the image and if applicable, con‐
39 tains other information about the image.
40
41
42 The signatures do not modify the container image (the layers, configu‐
43 ration, manifest, …); e.g. their presence does not change the manifest
44 digest used to identify the image in docker/distribution servers;
45 rather, the signatures are associated with an immutable image. An im‐
46 age can have any number of signatures so signature distribution systems
47 SHOULD support associating more than one signature with an image.
48
49
51 As distributed, the container signature is a blob which contains a
52 cryptographic signature in an industry-standard format, carrying a
53 signed JSON payload (i.e. the blob contains both the JSON document and
54 a signature of the JSON document; it is not a “detached signature” with
55 independent blobs containing the JSON document and a cryptographic sig‐
56 nature).
57
58
59 Currently the only defined cryptographic signature format is an OpenPGP
60 signature (RFC 4880), but others may be added in the future. (The blob
61 does not contain metadata identifying the cryptographic signature for‐
62 mat. It is expected that most formats are sufficiently self-describing
63 that this is not necessary and the configured expected public key pro‐
64 vides another indication of the expected cryptographic signature for‐
65 mat. Such metadata may be added in the future for newly added crypto‐
66 graphic signature formats, if necessary.)
67
68
69 Consumers of container signatures SHOULD verify the cryptographic sig‐
70 nature against one or more trusted public keys (e.g. defined in a pol‐
71 icy.json signature verification policy file ⟨containers-pol‐
72 icy.json.5.md⟩) before parsing or processing the JSON payload in any
73 way, in particular they SHOULD stop processing the container signature
74 if the cryptographic signature verification fails, without even start‐
75 ing to process the JSON payload.
76
77
78 (Consumers MAY extract identification of the signing key and other
79 metadata from the cryptographic signature, and the JSON payload, with‐
80 out verifying the signature, if the purpose is to allow managing the
81 signature blobs, e.g. to list the authors and image identities of sig‐
82 natures associated with a single container image; if so, they SHOULD
83 design the output of such processing to minimize the risk of users con‐
84 sidering the output trusted or in any way usable for making policy de‐
85 cisions about the image.)
86
87
88 OpenPGP signature verification
89 When verifying a cryptographic signature in the OpenPGP format, the
90 consumer MUST verify at least the following aspects of the signature
91 (like the github.com/containers/image/signature package does):
92
93
94 • The blob MUST be a “Signed Message” as defined RFC 4880 sec‐
95 tion 11.3. (e.g. it MUST NOT be an unsigned “Literal Mes‐
96 sage”, or any other non-signature format).
97
98 • The signature MUST have been made by an expected key trusted
99 for the purpose (and the specific container image).
100
101 • The signature MUST be correctly formed and pass the crypto‐
102 graphic validation.
103
104 • The signature MUST correctly authenticate the included JSON
105 payload (in particular, the parsing of the JSON payload MUST
106 NOT start before the complete payload has been cryptographi‐
107 cally authenticated).
108
109 • The signature MUST NOT be expired.
110
111
112
113 The consumer SHOULD have tests for its verification code which verify
114 that signatures failing any of the above are rejected.
115
116
118 The payload of the cryptographic signature is a JSON document (RFC
119 7159). Consumers SHOULD parse it very strictly, refusing any signature
120 which violates the expected format (e.g. missing members, incorrect
121 member types) or can be interpreted ambiguously (e.g. a duplicated mem‐
122 ber in a JSON object).
123
124
125 Any violations of the JSON format or of other requirements in this doc‐
126 ument MAY be accepted if the JSON document can be recognized to have
127 been created by a known-incorrect implementation (see optional.creator
128 ⟨#optionalcreator⟩ below) and if the semantics of the invalid document,
129 as created by such an implementation, is clear.
130
131
132 The top-level value of the JSON document MUST be a JSON object with ex‐
133 actly two members, critical and optional, each a JSON object.
134
135
136 The critical object MUST contain a type member identifying the document
137 as a container signature (as defined below ⟨#criticaltype⟩) and signa‐
138 ture consumers MUST reject signatures which do not have this member or
139 in which this member does not have the expected value.
140
141
142 To ensure forward compatibility (allowing older signature consumers to
143 correctly accept or reject signatures created at a later date, with
144 possible extensions to this format), consumers MUST reject the signa‐
145 ture if the critical object, or any of its subobjects, contain any mem‐
146 ber or data value which is unrecognized, unsupported, invalid, or in
147 any other way unexpected. At a minimum, this includes unrecognized
148 members in a JSON object, or incorrect types of expected members.
149
150
151 For the same reason, consumers SHOULD accept any members with unrecog‐
152 nized names in the optional object, and MAY accept signatures where the
153 object member is recognized but unsupported, or the value of the member
154 is unsupported. Consumers still SHOULD reject signatures where a mem‐
155 ber of an optional object is supported but the value is recognized as
156 invalid.
157
158
160 An example of the full format follows, with detailed description below.
161 To reiterate, consumers of the signature SHOULD perform successful
162 cryptographic verification, and MUST reject unexpected data in the
163 critical object, or in the top-level object, as described above.
164
165
166 {
167 "critical": {
168 "type": "atomic container signature",
169 "image": {
170 "docker-manifest-digest": "sha256:817a12c32a39bbe394944ba49de563e085f1d3c5266eb8e9723256bc4448680e"
171 },
172 "identity": {
173 "docker-reference": "docker.io/library/busybox:latest"
174 }
175 },
176 "optional": {
177 "creator": "some software package v1.0.1-35",
178 "timestamp": 1483228800,
179 }
180 }
181
182
183
184 critical
185 This MUST be a JSON object which contains data critical to correctly
186 evaluating the validity of a signature.
187
188
189 Consumers MUST reject any signature where the critical object contains
190 any unrecognized, unsupported, invalid or in any other way unexpected
191 member or data.
192
193
194 critical.type
195 This MUST be a string with a string value exactly equal to atomic con‐
196 tainer signature (three words, including the spaces).
197
198
199 Signature consumers MUST reject signatures which do not have this mem‐
200 ber or this member does not have exactly the expected value.
201
202
203 (The consumers MAY support signatures with a different value of the
204 type member, if any is defined in the future; if so, the rest of the
205 JSON document is interpreted according to rules defining that value of
206 critical.type, not by this document.)
207
208
209 critical.image
210 This MUST be a JSON object which identifies the container image this
211 signature applies to.
212
213
214 Consumers MUST reject any signature where the critical.image object
215 contains any unrecognized, unsupported, invalid or in any other way un‐
216 expected member or data.
217
218
219 (Currently only the docker-manifest-digest way of identifying a con‐
220 tainer image is defined; alternatives to this may be defined in the fu‐
221 ture, but existing consumers are required to reject signatures which
222 use formats they do not support.)
223
224
225 critical.image.docker-manifest-digest
226 This MUST be a JSON string, in the github.com/opencontainers/go-di‐
227 gest.Digest string format.
228
229
230 The value of this member MUST match the manifest of the signed con‐
231 tainer image, as implemented in the docker/distribution manifest ad‐
232 dressing system.
233
234
235 The consumer of the signature SHOULD verify the manifest digest against
236 a fully verified signature before processing the contents of the image
237 manifest in any other way (e.g. parsing the manifest further or down‐
238 loading layers of the image).
239
240
241 Implementation notes: * A single container image manifest may have sev‐
242 eral valid manifest digest values, using different algorithms. * For
243 “signed” docker/distribution schema 1 ⟨https://github.com/docker/dis‐
244 tribution/blob/master/docs/spec/manifest-v2-1.md⟩ manifests, the mani‐
245 fest digest applies to the payload of the JSON web signature, not to
246 the raw manifest blob.
247
248
249 critical.identity
250 This MUST be a JSON object which identifies the claimed identity of the
251 image (usually the purpose of the image, or the application, along with
252 a version information), as asserted by the author of the signature.
253
254
255 Consumers MUST reject any signature where the critical.identity object
256 contains any unrecognized, unsupported, invalid or in any other way un‐
257 expected member or data.
258
259
260 (Currently only the docker-reference way of claiming an image iden‐
261 tity/purpose is defined; alternatives to this may be defined in the fu‐
262 ture, but existing consumers are required to reject signatures which
263 use formats they do not support.)
264
265
266 critical.identity.docker-reference
267 This MUST be a JSON string, in the github.com/docker/distribution/ref‐
268 erence string format, and using the same normalization semantics (where
269 e.g. busybox:latest is equivalent to docker.io/library/busybox:latest).
270 If the normalization semantics allows multiple string representations
271 of the claimed identity with equivalent meaning, the critical.iden‐
272 tity.docker-reference member SHOULD use the fully explicit form (in‐
273 cluding the full host name and namespaces).
274
275
276 The value of this member MUST match the image identity/purpose expected
277 by the consumer of the image signature and the image (again, accounting
278 for the docker/distribution/reference normalization semantics).
279
280
281 In the most common case, this means that the critical.identity.docker-
282 reference value must be equal to the docker/distribution reference used
283 to refer to or download the image. However, depending on the specific
284 application, users or system administrators may accept less specific
285 matches (e.g. ignoring the tag value in the signature when pulling the
286 :latest tag or when referencing an image by digest), or they may re‐
287 quire critical.identity.docker-reference values with a completely dif‐
288 ferent namespace to the reference used to refer to/download the image
289 (e.g. requiring a critical.identity.docker-reference value which iden‐
290 tifies the image as coming from a supplier when fetching it from a com‐
291 pany-internal mirror of approved images). The software performing this
292 verification SHOULD allow the users to define such a policy using the
293 policy.json signature verification policy file format ⟨containers-pol‐
294 icy.json.5.md⟩.
295
296
297 The critical.identity.docker-reference value SHOULD contain either a
298 tag or digest; in most cases, it SHOULD use a tag rather than a digest.
299 (See also the default matchRepoDigestOrExact matching semantics in pol‐
300 icy.json ⟨containers-policy.json.5.md#signedby⟩.)
301
302
303 optional
304 This MUST be a JSON object.
305
306
307 Consumers SHOULD accept any members with unrecognized names in the op‐
308 tional object, and MAY accept a signature where the object member is
309 recognized but unsupported, or the value of the member is valid but un‐
310 supported. Consumers still SHOULD reject any signature where a member
311 of an optional object is supported but the value is recognized as in‐
312 valid.
313
314
315 optional.creator
316 If present, this MUST be a JSON string, identifying the name and ver‐
317 sion of the software which has created the signature (identifying the
318 low-level software implementation; not the top-level caller).
319
320
321 The contents of this string is not defined in detail; however each im‐
322 plementation creating container signatures:
323
324
325 • SHOULD define the contents to unambiguously define the soft‐
326 ware in practice (e.g. it SHOULD contain the name of the soft‐
327 ware, not only the version number)
328
329 • SHOULD use a build and versioning process which ensures that
330 the contents of this string (e.g. an included version number)
331 changes whenever the format or semantics of the generated sig‐
332 nature changes in any way; it SHOULD not be possible for two
333 implementations which use a different format or semantics to
334 have the same optional.creator value
335
336 • SHOULD use a format which is reasonably easy to parse in soft‐
337 ware (perhaps using a regexp), and which makes it easy enough
338 to recognize a range of versions of a specific implementation
339 (e.g. the version of the implementation SHOULD NOT be only a
340 git hash, because they don’t have an easily defined ordering;
341 the string should contain a version number, or at least a date
342 of the commit).
343
344
345
346 Consumers of container signatures MAY recognize specific values or sets
347 of values of optional.creator (perhaps augmented with optional.time‐
348 stamp), and MAY change their processing of the signature based on these
349 values (usually to accommodate violations of this specification in past
350 versions of the signing software which cannot be fixed retroactively),
351 as long as the semantics of the invalid document, as created by such an
352 implementation, is clear.
353
354
355 If consumers of signatures do change their behavior based on the op‐
356 tional.creator value, they SHOULD take care that the way they process
357 the signatures is not inconsistent with strictly validating signature
358 consumers. (I.e. it is acceptable for a consumer to accept a signature
359 based on a specific optional.creator value if other implementations
360 would completely reject the signature, but it would be very undesirable
361 for the two kinds of implementations to accept the signature in differ‐
362 ent and inconsistent situations.)
363
364
365 optional.timestamp
366 If present, this MUST be a JSON number, which is representable as a
367 64-bit integer, and identifies the time when the signature was created
368 as the number of seconds since the UNIX epoch (Jan 1 1970 00:00 UTC).
369
370
371
372signature Container container-signature(5)