Provided by: golang-github-containers-image_5.29.2-2_all bug

NAME

       container-signature - Container signature format

DESCRIPTION

       This  document  describes  the  format  of  container  signatures,  as  implemented by the
       github.com/containers/image/signature package.

       Most   users   should   be   able   to   consume   these   signatures   by    using    the
       github.com/containers/image/signature   package   (preferably   through  the  higher-level
       signature.PolicyContext interface) without having to care about the details of the  format
       described  below.   This documentation exists primarily for maintainers of the package and
       to allow independent reimplementations.

High-level overview

       The signature provides an end-to-end authenticated claim that a container image  has  been
       approved  by  a  specific party (e.g. the creator of the image as their work, an automated
       build system as a result of an automated build, a  company  IT  department  approving  the
       image  for  production)  under  a  specified  identity  (e.g.  an OS base image / specific
       application, with a specific version).

       A  container  signature  consists  of  a  cryptographic  signature  which  identifies  and
       authenticates  who signed the image, and carries as a signed payload a JSON document.  The
       JSON document identifies the image being signed, claims a specific identity of  the  image
       and if applicable, contains other information about the image.

       The signatures do not modify the container image (the layers, configuration, manifest, …);
       e.g. their presence does not change the manifest digest used  to  identify  the  image  in
       docker/distribution  servers;  rather,  the  signatures  are  associated with an immutable
       image.  An image can have any number  of  signatures  so  signature  distribution  systems
       SHOULD support associating more than one signature with an image.

The cryptographic signature

       As distributed, the container signature is a blob which contains a cryptographic signature
       in an industry-standard format, carrying a signed JSON payload  (i.e.  the  blob  contains
       both  the  JSON  document  and  a  signature  of  the JSON document; it is not a “detached
       signature” with independent  blobs  containing  the  JSON  document  and  a  cryptographic
       signature).

       Currently  the  only  defined  cryptographic signature format is an OpenPGP signature (RFC
       4880), but others may be added in  the  future.   (The  blob  does  not  contain  metadata
       identifying  the  cryptographic  signature  format.  It  is expected that most formats are
       sufficiently self-describing that this is not necessary and the configured expected public
       key  provides  another  indication  of  the  expected cryptographic signature format. Such
       metadata may be added in the future for newly added cryptographic  signature  formats,  if
       necessary.)

       Consumers of container signatures SHOULD verify the cryptographic signature against one or
       more trusted public keys (e.g. defined in a policy.json signature verification policy file
       ⟨containers-policy.json.5.md⟩)  before  parsing or processing the JSON payload in any way,
       in particular they SHOULD stop processing the container  signature  if  the  cryptographic
       signature verification fails, without even starting to process the JSON payload.

       (Consumers  MAY  extract  identification  of  the  signing key and other metadata from the
       cryptographic signature, and the JSON payload, without verifying  the  signature,  if  the
       purpose  is  to  allow  managing  the  signature blobs, e.g. to list the authors and image
       identities of signatures associated with a single container  image;  if  so,  they  SHOULD
       design  the output of such processing to minimize the risk of users considering the output
       trusted or in any way usable for making policy decisions about the image.)

   OpenPGP signature verification
       When verifying a cryptographic signature in the OpenPGP format, the consumer  MUST  verify
       at     least     the     following     aspects     of     the    signature    (like    the
       github.com/containers/image/signature package does):

              • The blob MUST be a “Signed Message” as defined RFC 4880 section 11.3.   (e.g.  it
                MUST  NOT be an unsigned “Literal Message”, a “Cleartext Signature” as defined in
                RFC 4880 section 7, or any other non-signature format).

              • The signature MUST have been made by an expected key trusted for the purpose (and
                the specific container image).

              • The signature MUST be correctly formed and pass the cryptographic validation.

              • The   signature  MUST  correctly  authenticate  the  included  JSON  payload  (in
                particular, the parsing of the JSON payload MUST NOT start  before  the  complete
                payload has been cryptographically authenticated).

              • The signature MUST NOT be expired.

       The  consumer  SHOULD  have  tests  for its verification code which verify that signatures
       failing any of the above are rejected.

JSON processing and forward compatibility

       The payload of the cryptographic signature is  a  JSON  document  (RFC  7159).   Consumers
       SHOULD  parse  it very strictly, refusing any signature which violates the expected format
       (e.g. missing members, incorrect member types) or can be interpreted ambiguously  (e.g.  a
       duplicated member in a JSON object).

       Any  violations  of  the  JSON  format  or  of  other requirements in this document MAY be
       accepted if the JSON document can be recognized to have been created by a  known-incorrect
       implementation  (see  ⟨#optionalcreator⟩  below)  and  if  the  semantics  of  the invalid
       document, as created by such an implementation, is clear.

       The top-level value of the JSON document MUST be a JSON object with exactly  two  members,
       critical and optional, each a JSON object.

       The  critical  object  MUST  contain a type member identifying the document as a container
       signature  (as  defined  below  ⟨#criticaltype⟩)  and  signature  consumers  MUST   reject
       signatures  which  do  not  have  this  member  or  in which this member does not have the
       expected value.

       To ensure forward compatibility (allowing older signature consumers to correctly accept or
       reject  signatures  created  at  a  later  date, with possible extensions to this format),
       consumers MUST reject the signature if the critical object,  or  any  of  its  subobjects,
       contain  any  member  or data value which is unrecognized, unsupported, invalid, or in any
       other way unexpected.  At a minimum, this includes unrecognized members in a JSON  object,
       or incorrect types of expected members.

       For  the  same  reason, consumers SHOULD accept any members with unrecognized names in the
       optional object, and MAY accept signatures where  the  object  member  is  recognized  but
       unsupported,  or  the  value  of the member is unsupported.  Consumers still SHOULD reject
       signatures where a member of an optional object is supported but the value  is  recognized
       as invalid.

JSON data format

       An  example  of  the  full format follows, with detailed description below.  To reiterate,
       consumers of the signature SHOULD perform successful cryptographic verification, and  MUST
       reject  unexpected  data  in the critical object, or in the top-level object, as described
       above.

       {
           "critical": {
               "type": "atomic container signature",
               "image": {
                   "docker-manifest-digest": "sha256:817a12c32a39bbe394944ba49de563e085f1d3c5266eb8e9723256bc4448680e"
               },
               "identity": {
                   "docker-reference": "docker.io/library/busybox:latest"
               }
           },
           "optional": {
               "creator": "some software package v1.0.1-35",
               "timestamp": 1483228800,
           }
       }

   critical
       This MUST be a JSON object which  contains  data  critical  to  correctly  evaluating  the
       validity of a signature.

       Consumers  MUST  reject any signature where the critical object contains any unrecognized,
       unsupported, invalid or in any other way unexpected member or data.

   critical.type
       This MUST be a string with a string value exactly  equal  to  atomic  container  signature
       (three words, including the spaces).

       Signature  consumers  MUST  reject signatures which do not have this member or this member
       does not have exactly the expected value.

       (The consumers MAY support signatures with a different value of the type member, if any is
       defined  in  the  future; if so, the rest of the JSON document is interpreted according to
       rules defining that value of critical.type, not by this document.)

   critical.image
       This MUST be a JSON object which identifies the container image this signature applies to.

       Consumers  MUST  reject  any  signature  where  the  critical.image  object  contains  any
       unrecognized, unsupported, invalid or in any other way unexpected member or data.

       (Currently  only  the  docker-manifest-digest  way  of  identifying  a  container image is
       defined; alternatives to this may be defined in the future,  but  existing  consumers  are
       required to reject signatures which use formats they do not support.)

   critical.image.docker-manifest-digest
       This  MUST  be  a  JSON  string,  in the github.com/opencontainers/go-digest.Digest string
       format.

       The value of this member MUST match  the  manifest  of  the  signed  container  image,  as
       implemented in the docker/distribution manifest addressing system.

       The  consumer  of the signature SHOULD verify the manifest digest against a fully verified
       signature before processing the contents of the image manifest  in  any  other  way  (e.g.
       parsing the manifest further or downloading layers of the image).

       Implementation  notes: * A single container image manifest may have several valid manifest
       digest values, using different algorithms.  * For “signed”  docker/distribution  schema  1
       ⟨https://github.com/docker/distribution/blob/master/docs/spec/manifest-v2-1.md⟩ manifests,
       the manifest digest applies to the payload of the JSON  web  signature,  not  to  the  raw
       manifest blob.

   critical.identity
       This MUST be a JSON object which identifies the claimed identity of the image (usually the
       purpose of the image, or the application, along with a version information),  as  asserted
       by the author of the signature.

       Consumers  MUST  reject  any  signature  where  the  critical.identity object contains any
       unrecognized, unsupported, invalid or in any other way unexpected member or data.

       (Currently only the docker-reference way of claiming an image identity/purpose is defined;
       alternatives  to this may be defined in the future, but existing consumers are required to
       reject signatures which use formats they do not support.)

   critical.identity.docker-reference
       This MUST be a JSON string, in the github.com/docker/distribution/reference string format,
       and  using  the  same  normalization semantics (where e.g. busybox:latest is equivalent to
       docker.io/library/busybox:latest).  If the normalization semantics allows multiple  string
       representations    of    the    claimed    identity    with    equivalent   meaning,   the
       critical.identity.docker-reference member SHOULD use the fully  explicit  form  (including
       the full host name and namespaces).

       The value of this member MUST match the image identity/purpose expected by the consumer of
       the image signature and the image (again, accounting for the docker/distribution/reference
       normalization semantics).

       In the most common case, this means that the critical.identity.docker-reference value must
       be equal to the docker/distribution reference used to refer  to  or  download  the  image.
       However,  depending on the specific application, users or system administrators may accept
       less specific matches (e.g. ignoring the tag value  in  the  signature  when  pulling  the
       :latest   tag   or   when   referencing   an   image  by  digest),  or  they  may  require
       critical.identity.docker-reference values with a completely  different  namespace  to  the
       reference  used to refer to/download the image (e.g. requiring a critical.identity.docker-
       reference value which identifies the image as coming from a supplier when fetching it from
       a  company-internal mirror of approved images).  The software performing this verification
       SHOULD  allow  the  users  to  define  such  a  policy  using  the  policy.json  signature
       verification policy file format ⟨containers-policy.json.5.md⟩.

       The  critical.identity.docker-reference  value  SHOULD  contain either a tag or digest; in
       most  cases,  it  SHOULD  use  a  tag  rather  than  a  digest.   (See  also  the  default
       ⟨containers-policy.json.5.md#signedby⟩.)

   optional
       This MUST be a JSON object.

       Consumers  SHOULD  accept  any members with unrecognized names in the optional object, and
       MAY accept a signature where the object member is recognized but unsupported, or the value
       of the member is valid but unsupported.  Consumers still SHOULD reject any signature where
       a member of an optional object is supported but the value is recognized as invalid.

   optional.creator
       If present, this MUST be a JSON string, identifying the name and version of  the  software
       which  has  created  the signature (identifying the low-level software implementation; not
       the top-level caller).

       The contents of this string is not defined in detail; however each implementation creating
       container signatures:

              • SHOULD define the contents to unambiguously define the software in practice (e.g.
                it SHOULD contain the name of the software, not only the version number)

              • SHOULD use a build and versioning process which ensures that the contents of this
                string (e.g. an included version number) changes whenever the format or semantics
                of the generated signature changes in any way; it SHOULD not be possible for  two
                implementations  which  use  a  different  format  or  semantics to have the same
                optional.creator value

              • SHOULD use a format which is reasonably easy to parse in software (perhaps  using
                a  regexp),  and which makes it easy enough to recognize a range of versions of a
                specific implementation (e.g. the version of the  implementation  SHOULD  NOT  be
                only  a  git hash, because they don’t have an easily defined ordering; the string
                should contain a version number, or at least a date of the commit).

       Consumers of container signatures MAY recognize specific  values  or  sets  of  values  of
       optional.creator  (perhaps  augmented  with  optional.timestamp),  and  MAY  change  their
       processing of the signature based on these values (usually to  accommodate  violations  of
       this  specification  in  past  versions  of  the  signing  software  which cannot be fixed
       retroactively), as long as the semantics of the invalid document, as created  by  such  an
       implementation, is clear.

       If  consumers  of signatures do change their behavior based on the optional.creator value,
       they SHOULD take care that the way they process the signatures is  not  inconsistent  with
       strictly  validating signature consumers.  (I.e. it is acceptable for a consumer to accept
       a signature based on a specific optional.creator  value  if  other  implementations  would
       completely  reject  the  signature,  but it would be very undesirable for the two kinds of
       implementations to accept the signature in different and inconsistent situations.)

   optional.timestamp
       If present, this MUST be a JSON number, which is representable as a  64-bit  integer,  and
       identifies the time when the signature was created as the number of seconds since the UNIX
       epoch (Jan 1 1970 00:00 UTC).