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

NAME

9       container-signature - Container signature format
10
11
12

DESCRIPTION

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

High-level overview

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

The cryptographic signature

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

JSON processing and forward compatibility

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

JSON data format

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.
318
319
320       The contents of this string is not defined in detail; however each  im‐
321       plementation creating container signatures:
322
323
324              • SHOULD  define  the contents to unambiguously define the soft‐
325                ware in practice (e.g. it SHOULD contain the name of the soft‐
326                ware, not only the version number)
327
328              • SHOULD  use  a build and versioning process which ensures that
329                the contents of this string (e.g. an included version  number)
330                changes whenever the format or semantics of the generated sig‐
331                nature changes in any way; it SHOULD not be possible  for  two
332                implementations  which  use a different format or semantics to
333                have the same optional.creator value
334
335              • SHOULD use a format which is reasonably easy to parse in soft‐
336                ware  (perhaps using a regexp), and which makes it easy enough
337                to recognize a range of versions of a specific  implementation
338                (e.g.  the  version of the implementation SHOULD NOT be only a
339                git hash, because they don’t have an easily defined  ordering;
340                the string should contain a version number, or at least a date
341                of the commit).
342
343
344
345       Consumers of container signatures MAY recognize specific values or sets
346       of  values  of  optional.creator (perhaps augmented with optional.time‐
347       stamp), and MAY change their processing of the signature based on these
348       values (usually to accommodate violations of this specification in past
349       versions of the signing software which cannot be fixed  retroactively),
350       as long as the semantics of the invalid document, as created by such an
351       implementation, is clear.
352
353
354       If consumers of signatures do change their behavior based  on  the  op‐
355       tional.creator  value,  they SHOULD take care that the way they process
356       the signatures is not inconsistent with strictly  validating  signature
357       consumers.  (I.e. it is acceptable for a consumer to accept a signature
358       based on a specific optional.creator  value  if  other  implementations
359       would completely reject the signature, but it would be very undesirable
360       for the two kinds of implementations to accept the signature in differ‐
361       ent and inconsistent situations.)
362
363
364   optional.timestamp
365       If  present,  this  MUST  be a JSON number, which is representable as a
366       64-bit integer, and identifies the time when the signature was  created
367       as the number of seconds since the UNIX epoch (Jan 1 1970 00:00 UTC).
368
369
370
371signature                          Container            container-signature(5)
Impressum