1container-signature(5)(Container)            container-signature(5)(Container)
2
3
4
5Miloslav Trmač March 2017
6
7

Container signature format

9       This  document  describes the format of container signatures, as imple‐
10       mented by the github.com/containers/image/signature package.
11
12
13       Most users should be able to consume  these  signatures  by  using  the
14       github.com/containers/image/signature  package  (preferably through the
15       higher-level signature.PolicyContext interface) without having to  care
16       about  the  details  of the format described below.  This documentation
17       exists primarily for maintainers of the package and to  allow  indepen‐
18       dent reimplementations.
19
20

High-level overview

22       The  signature  provides  an end-to-end authenticated claim that a con‐
23       tainer image has been approved by a specific party (e.g. the creator of
24       the  image  as  their work, an automated build system as a result of an
25       automated build, a company IT department approving the image  for  pro‐
26       duction)  under  a specified identity (e.g. an OS base image / specific
27       application, with a specific version).
28
29
30       A container signature consists of a cryptographic signature which iden‐
31       tifies  and authenticates who signed the image, and carries as a signed
32       payload a JSON document.  The JSON document identifies the image  being
33       signed, claims a specific identity of the image and if applicable, con‐
34       tains other information about the image.
35
36
37       The signatures do not modify the container image (the layers,  configu‐
38       ration,  manifest, …); e.g. their presence does not change the manifest
39       digest used to  identify  the  image  in  docker/distribution  servers;
40       rather,  the  signatures  are  associated  with an immutable image.  An
41       image can have any number of signatures so signature distribution  sys‐
42       tems SHOULD support associating more than one signature with an image.
43
44

The cryptographic signature

46       As  distributed,  the  container  signature  is a blob which contains a
47       cryptographic signature in  an  industry-standard  format,  carrying  a
48       signed  JSON payload (i.e. the blob contains both the JSON document and
49       a signature of the JSON document; it is not a “detached signature” with
50       independent blobs containing the JSON document and a cryptographic sig‐
51       nature).
52
53
54       Currently the only defined cryptographic signature format is an OpenPGP
55       signature (RFC 4880), but others may be added in the future.  (The blob
56       does not contain metadata identifying the cryptographic signature  for‐
57       mat.  It is expected that most formats are sufficiently self-describing
58       that this is not necessary and the configured expected public key  pro‐
59       vides  another  indication of the expected cryptographic signature for‐
60       mat. Such metadata may be added in the future for newly  added  crypto‐
61       graphic signature formats, if necessary.)
62
63
64       Consumers  of container signatures SHOULD verify the cryptographic sig‐
65       nature against one or more trusted public keys (e.g. defined in a  pol‐
66       icy.json    signature   verification   policy   file   ⟨containers-pol‐
67       icy.json.5.md⟩) before parsing or processing the JSON  payload  in  any
68       way,  in particular they SHOULD stop processing the container signature
69       if the cryptographic signature verification fails, without even  start‐
70       ing to process the JSON payload.
71
72
73       (Consumers  MAY  extract  identification  of  the signing key and other
74       metadata from the cryptographic signature, and the JSON payload,  with‐
75       out  verifying  the  signature, if the purpose is to allow managing the
76       signature blobs, e.g. to list the authors and image identities of  sig‐
77       natures  associated  with  a single container image; if so, they SHOULD
78       design the output of such processing to minimize the risk of users con‐
79       sidering  the  output  trusted  or  in any way usable for making policy
80       decisions about the image.)
81
82
83   OpenPGP signature verification
84       When verifying a cryptographic signature in  the  OpenPGP  format,  the
85       consumer  MUST  verify  at least the following aspects of the signature
86       (like the github.com/containers/image/signature package does):
87
88
89              · The blob MUST be a “Signed Message” as defined RFC  4880  sec‐
90                tion  11.3.   (e.g.  it  MUST NOT be an unsigned “Literal Mes‐
91                sage”, or any other non-signature format).
92
93              · The signature MUST have been made by an expected  key  trusted
94                for the purpose (and the specific container image).
95
96              · The  signature  MUST  be correctly formed and pass the crypto‐
97                graphic validation.
98
99              · The signature MUST correctly authenticate  the  included  JSON
100                payload  (in  particular, the parsing of the JSON payload MUST
101                NOT start before the complete payload has  been  cryptographi‐
102                cally authenticated).
103
104              · The signature MUST NOT be expired.
105
106
107
108       The  consumer  SHOULD have tests for its verification code which verify
109       that signatures failing any of the above are rejected.
110
111

JSON processing and forward compatibility

113       The payload of the cryptographic signature  is  a  JSON  document  (RFC
114       7159).  Consumers SHOULD parse it very strictly, refusing any signature
115       which violates the expected format  (e.g.  missing  members,  incorrect
116       member types) or can be interpreted ambiguously (e.g. a duplicated mem‐
117       ber in a JSON object).
118
119
120       Any violations of the JSON format or of other requirements in this doc‐
121       ument  MAY  be  accepted if the JSON document can be recognized to have
122       been created by a known-incorrect implementation (see  optional.creator
123       ⟨#optionalcreator⟩ below) and if the semantics of the invalid document,
124       as created by such an implementation, is clear.
125
126
127       The top-level value of the JSON document MUST be  a  JSON  object  with
128       exactly two members, critical and optional, each a JSON object.
129
130
131       The critical object MUST contain a type member identifying the document
132       as a container signature (as defined below ⟨#criticaltype⟩) and  signa‐
133       ture  consumers MUST reject signatures which do not have this member or
134       in which this member does not have the expected value.
135
136
137       To ensure forward compatibility (allowing older signature consumers  to
138       correctly  accept  or  reject  signatures created at a later date, with
139       possible extensions to this format), consumers MUST reject  the  signa‐
140       ture if the critical object, or any of its subobjects, contain any mem‐
141       ber or data value which is unrecognized, unsupported,  invalid,  or  in
142       any  other  way  unexpected.   At a minimum, this includes unrecognized
143       members in a JSON object, or incorrect types of expected members.
144
145
146       For the same reason, consumers SHOULD accept any members with  unrecog‐
147       nized names in the optional object, and MAY accept signatures where the
148       object member is recognized but unsupported, or the value of the member
149       is  unsupported.  Consumers still SHOULD reject signatures where a mem‐
150       ber of an optional object is supported but the value is  recognized  as
151       invalid.
152
153

JSON data format

155       An example of the full format follows, with detailed description below.
156       To reiterate, consumers of  the  signature  SHOULD  perform  successful
157       cryptographic  verification,  and  MUST  reject  unexpected data in the
158       critical object, or in the top-level object, as described above.
159
160
161              {
162                  "critical": {
163                      "type": "atomic container signature",
164                      "image": {
165                          "docker-manifest-digest": "sha256:817a12c32a39bbe394944ba49de563e085f1d3c5266eb8e9723256bc4448680e"
166                      },
167                      "identity": {
168                          "docker-reference": "docker.io/library/busybox:latest"
169                      }
170                  },
171                  "optional": {
172                      "creator": "some software package v1.0.1-35",
173                      "timestamp": 1483228800,
174                  }
175              }
176
177
178
179   critical
180       This MUST be a JSON object which contains data  critical  to  correctly
181       evaluating the validity of a signature.
182
183
184       Consumers  MUST reject any signature where the critical object contains
185       any unrecognized, unsupported, invalid or in any other  way  unexpected
186       member or data.
187
188
189   critical.type
190       This  MUST be a string with a string value exactly equal to atomic con‐
191       tainer signature (three words, including the spaces).
192
193
194       Signature consumers MUST reject signatures which do not have this  mem‐
195       ber or this member does not have exactly the expected value.
196
197
198       (The  consumers  MAY  support  signatures with a different value of the
199       type member, if any is defined in the future; if so, the  rest  of  the
200       JSON  document is interpreted according to rules defining that value of
201       critical.type, not by this document.)
202
203
204   critical.image
205       This MUST be a JSON object which identifies the  container  image  this
206       signature applies to.
207
208
209       Consumers  MUST  reject  any  signature where the critical.image object
210       contains any unrecognized, unsupported, invalid or  in  any  other  way
211       unexpected member or data.
212
213
214       (Currently  only  the  docker-manifest-digest way of identifying a con‐
215       tainer image is defined; alternatives to this may  be  defined  in  the
216       future,  but existing consumers are required to reject signatures which
217       use formats they do not support.)
218
219
220   critical.image.docker-manifest-digest
221       This  MUST  be  a   JSON   string,   in   the   github.com/opencontain‐
222       ers/go-digest.Digest string format.
223
224
225       The  value  of  this  member MUST match the manifest of the signed con‐
226       tainer  image,  as  implemented  in  the  docker/distribution  manifest
227       addressing system.
228
229
230       The consumer of the signature SHOULD verify the manifest digest against
231       a fully verified signature before processing the contents of the  image
232       manifest  in  any other way (e.g. parsing the manifest further or down‐
233       loading layers of the image).
234
235
236       Implementation notes: * A single container image manifest may have sev‐
237       eral  valid  manifest digest values, using different algorithms.  * For
238       “signed” docker/distribution schema  1  ⟨https://github.com/docker/dis
239       tribution/blob/master/docs/spec/manifest-v2-1.md⟩  manifests, the mani‐
240       fest digest applies to the payload of the JSON web  signature,  not  to
241       the raw manifest blob.
242
243
244   critical.identity
245       This MUST be a JSON object which identifies the claimed identity of the
246       image (usually the purpose of the image, or the application, along with
247       a version information), as asserted by the author of the signature.
248
249
250       Consumers  MUST reject any signature where the critical.identity object
251       contains any unrecognized, unsupported, invalid or  in  any  other  way
252       unexpected member or data.
253
254
255       (Currently  only  the  docker-reference  way of claiming an image iden‐
256       tity/purpose is defined; alternatives to this may  be  defined  in  the
257       future,  but existing consumers are required to reject signatures which
258       use formats they do not support.)
259
260
261   critical.identity.docker-reference
262       This MUST be a JSON string, in the  github.com/docker/distribution/ref‐
263       erence string format, and using the same normalization semantics (where
264       e.g. busybox:latest is equivalent to docker.io/library/busybox:latest).
265       If  the  normalization semantics allows multiple string representations
266       of the claimed identity with  equivalent  meaning,  the  critical.iden‐
267       tity.docker-reference   member  SHOULD  use  the  fully  explicit  form
268       (including the full host name and namespaces).
269
270
271       The value of this member MUST match the image identity/purpose expected
272       by the consumer of the image signature and the image (again, accounting
273       for the docker/distribution/reference normalization semantics).
274
275
276       In  the  most  common  case,  this  means   that   the   critical.iden‐
277       tity.docker-reference  value  must  be equal to the docker/distribution
278       reference used to refer to or download the image.   However,  depending
279       on  the specific application, users or system administrators may accept
280       less specific matches (e.g. ignoring the tag  value  in  the  signature
281       when  pulling  the :latest tag or when referencing an image by digest),
282       or they may require critical.identity.docker-reference  values  with  a
283       completely  different namespace to the reference used to refer to/down‐
284       load the image  (e.g.  requiring  a  critical.identity.docker-reference
285       value  which identifies the image as coming from a supplier when fetch‐
286       ing it from a company-internal mirror of approved images).   The  soft‐
287       ware performing this verification SHOULD allow the users to define such
288       a policy using the policy.json signature verification policy file  for‐
289       mat ⟨containers-policy.json.5.md⟩.
290
291
292       The  critical.identity.docker-reference  value  SHOULD contain either a
293       tag or digest; in most cases, it SHOULD use a tag rather than a digest.
294       (See also the default matchRepoDigestOrExact matching semantics in pol‐
295       icy.json ⟨containers-policy.json.5.md#signedby⟩.)
296
297
298   optional
299       This MUST be a JSON object.
300
301
302       Consumers SHOULD accept any members  with  unrecognized  names  in  the
303       optional  object, and MAY accept a signature where the object member is
304       recognized but unsupported, or the value of the  member  is  valid  but
305       unsupported.   Consumers still SHOULD reject any signature where a mem‐
306       ber of an optional object is supported but the value is  recognized  as
307       invalid.
308
309
310   optional.creator
311       If  present,  this MUST be a JSON string, identifying the name and ver‐
312       sion of the software which has created the signature.
313
314
315       The contents of this string is not  defined  in  detail;  however  each
316       implementation creating container signatures:
317
318
319              · SHOULD  define  the contents to unambiguously define the soft‐
320                ware in practice (e.g. it SHOULD contain the name of the soft‐
321                ware, not only the version number)
322
323              · SHOULD  use  a build and versioning process which ensures that
324                the contents of this string (e.g. an included version  number)
325                changes whenever the format or semantics of the generated sig‐
326                nature changes in any way; it SHOULD not be possible  for  two
327                implementations  which  use a different format or semantics to
328                have the same optional.creator value
329
330              · SHOULD use a format which is reasonably easy to parse in soft‐
331                ware  (perhaps using a regexp), and which makes it easy enough
332                to recognize a range of versions of a specific  implementation
333                (e.g.  the  version of the implementation SHOULD NOT be only a
334                git hash, because they don’t have an easily defined  ordering;
335                the string should contain a version number, or at least a date
336                of the commit).
337
338
339
340       Consumers of container signatures MAY recognize specific values or sets
341       of  values  of  optional.creator (perhaps augmented with optional.time‐
342       stamp), and MAY change their processing of the signature based on these
343       values (usually to accommodate violations of this specification in past
344       versions of the signing software which cannot be fixed  retroactively),
345       as long as the semantics of the invalid document, as created by such an
346       implementation, is clear.
347
348
349       If consumers of signatures  do  change  their  behavior  based  on  the
350       optional.creator value, they SHOULD take care that the way they process
351       the signatures is not inconsistent with strictly  validating  signature
352       consumers.  (I.e. it is acceptable for a consumer to accept a signature
353       based on a specific optional.creator  value  if  other  implementations
354       would completely reject the signature, but it would be very undesirable
355       for the two kinds of implementations to accept the signature in differ‐
356       ent and inconsistent situations.)
357
358
359   optional.timestamp
360       If  present,  this  MUST  be a JSON number, which is representable as a
361       64-bit integer, and identifies the time when the signature was  created
362       as the number of seconds since the UNIX epoch (Jan 1 1970 00:00 UTC).
363
364
365
366format                             signature container-signature(5)(Container)
Impressum