diff --git a/specs/signature-envelope-cose.md b/specs/signature-envelope-cose.md index d56e78a..d8d54fe 100644 --- a/specs/signature-envelope-cose.md +++ b/specs/signature-envelope-cose.md @@ -36,7 +36,7 @@ Signature Manifest Example } } ``` -## Detached Blob Signature Storage +## Blob Signature Storage For detached signatures associated with arbitrary blobs, a COSE signature envelope will be stored on the file system as a binary file with `cose` as the file extension. diff --git a/specs/signature-envelope-jws.md b/specs/signature-envelope-jws.md index 3efd585..2c742ea 100644 --- a/specs/signature-envelope-jws.md +++ b/specs/signature-envelope-jws.md @@ -35,7 +35,7 @@ Signature Manifest Example } ``` -## Detached Signature Storage +## Blob Signature Storage For detached signatures associated with arbitrary blobs, a JWS signature envelope will be stored on the file system as a binary file with `jws` as the file extension. diff --git a/specs/signature-specification.md b/specs/signature-specification.md index 2d6a356..1334311 100644 --- a/specs/signature-specification.md +++ b/specs/signature-specification.md @@ -3,8 +3,8 @@ This document provides the following details for Notary Project signature: - **[Signature Envelope](#signature-envelope)**: Describes the structure of the Notary Project signature. -- **[OCI Signatures](#storage)**: Describes how signatures are stored and retrieved from an OCI registry. -- **[Detached Signatures](#storage)**: Describes how detached signatures of Blobs are stored on file system. +- **[OCI Signatures](#storage)**: Describes how signatures for OCI artifacts are stored and retrieved from an OCI registry. +- **[Blob Signatures](#storage)**: Describes how detached signatures for signed Blobs are stored on file system. ## Signature Envelope @@ -38,7 +38,7 @@ The Notary Project signature payload is a JSON document with media type `applica - Descriptor MUST contain `mediaType`, `digest`, and `size` fields. - `digest` MUST be in the format of `:`. Example: `sha256:2f3a23b6373afb134ddcd864be8e037e34a662d090d33ee849471ff73c873345` - SHA-256, SHA-384, SHA-512 are the only allowed digest algorithms. - - `mediaType` can be any arbitrary media type that the user chooses to describe the blob. An example can be `application/octet-stream` + - `mediaType` can be any arbitrary media type that the user provides to describe the blob. An example can be `application/octet-stream` - `size` MUST be the raw size of the blob in bytes. - Blob descriptors MAY optionally contain `annotations` and if present it MUST follow the [annotation rules][annotation-rules]. @@ -219,9 +219,9 @@ Each Notary Project signature refers to a signature envelope blob. An OCI artifact can have multiple signatures, implementations of the Notary Project signature specification uses annotations of the signature manifest to filter relevant signatures based on the applicable trust policy. The Notary Project signature manifest's `io.cncf.notary.x509chain.thumbprint#S256` annotation key MUST contain the list of SHA-256 fingerprints of certificate and certificate chain used for signing. -## Detached Signatures +## Blob Signatures -The Notary Project facilitates signing of arbitrary blobs and generating detached signatures. These detached signatures can be conveyed via any preferred medium and verified on the receiving end. The Notary Project's detached signature is a self-contained binary file encompassing the signature envelope. The file extension can either be 'jws' or 'cose', indicating the signature envelope format. +The Notary Project facilitates signing arbitrary blobs using detached signatures. These detached signatures can be transported via any preferred medium and verified on the receiving end. A detached signature refers to a signature that is not embedded within (and therefore does not modify) the original blob, instead it consists of a detached signature envelope with a signature over the unique representation of the blob (i.e. blob's digest). The file extension can either be 'jws' or 'cose', indicating the signature envelope format. ![Signature storage inside file system](../media/detached-signature-specification.svg) @@ -246,7 +246,7 @@ For ECDSA equivalent NIST curves and ANSI curves can be found at [RFC4492 Append ### Algorithm Selection -The signing certificate's public key algorithm and size MUST be used to determine the signature algorithm. Below are the only supported Signature Algorithms in the Notary project. +The signing certificate's public key algorithm and size MUST be used to determine the signature algorithm. Notary Project supports the following Signature Algorithms. | Public Key Algorithm | Key Size (bits) | Signature Algorithm | | -------------------- | --------------- | ------------------------------- | @@ -360,7 +360,7 @@ Whereas, the Notary Project signatures that contain critical extended attributes Similarly, Notation compliant plugin vendors should be aware that usage of extended signed attributes which are marked critical in signature will have implications on portability of the signature. ### Detached Signature Portability -Notary Project detached signatures provide the maximum portability as there are no requirements on storage or transport medium. Users can can store and transport their blobs and associated detached signatures however they like. +Notary Project detached signatures provide the maximum portability as there are no requirements on storage or transport medium. Users can can store and transport their blobs and associated detached signatures as required. ### Guidelines for implementations of the Notary Project signature specification diff --git a/specs/signing-and-verification-workflow.md b/specs/signing-and-verification-workflow.md index ba2b4ed..b290619 100644 --- a/specs/signing-and-verification-workflow.md +++ b/specs/signing-and-verification-workflow.md @@ -1,6 +1,6 @@ # Signing and Verification Workflow -This document describes the workflow of signing and verifying artifacts likes OCI images and arbitrary blobs. +This document describes workflows for signing and verifying OCI artifacts and arbitrary blobs. ## OCI artifact signing workflow @@ -86,16 +86,16 @@ The user wants to sign an arbitrary blob with a detached signature. 1. Verify that the signing certificate is valid and satisfies [certificate requirements](./signature-specification.md#certificate-requirements). 1. Verify that the signing algorithm satisfies [algorithm requirements](./signature-specification.md#signature-algorithm-requirements). 1. Generate signature. - 1. Generate signature using signature formats specified in [supported signature envelopes](./signature-specification.md#supported-signature-envelopes). Also, as part of this step, the user-defined/supplied custom attributes should be added to the annotations of the signature's descriptor. + 1. Generate signature using a signature format specified in [supported signature envelopes](./signature-specification.md#supported-signature-envelopes). Also, as part of this step, the user-defined/supplied custom attributes should be added to the annotations of the signature payload. 1. If the user wants to timestamp the signature, obtain an [RFC-3161](https://datatracker.ietf.org/doc/html/rfc3161.html) compliant timestamp for the signature generated in the previous step. Otherwise, continue to the next step. 1. Verify that the timestamp signing certificate satisfies [certificate requirements](./signature-specification.md#certificate-requirements). 1. Verify that the timestamp signing algorithm satisfies [algorithm requirements](./signature-specification.md#signature-algorithm-requirements). 1. Embed timestamp to the signature envelope. -1. **Save the signature envelope:** Save the signature envelope generated in the previous step to a file. +1. **Save the signature envelope:** Save the signature envelope generated in the previous step to a file. File extension should be the original blob file name plus `.sig.jws` for JWS signatures and `.sig.cose` for COSE signatures. ## Arbitrary blob verification workflow -The user wants to consume an arbitrary blob only if if was signed by a trusted publisher and the signature associated with the blob is valid. +The user wants to consume an arbitrary blob only if it was signed by a trusted publisher and the signature associated with the blob is valid. ### Verification Prerequisites @@ -111,5 +111,5 @@ The user wants to consume an arbitrary blob only if if was signed by a trusted p 1. Verify the signature envelope using trust-store and trust-policy as mentioned in [signature evaluation](./trust-store-trust-policy.md#signature-evaluation) section. 1. If the signature verification fails, exit. 1. Construct the blob payload as defined in [`signature specification`](./signature-specification.md#payload) -1. Compare the payload derived from the above step with the payload present in the signature envelope. Fail signature verification if there is mismatch. -1. Calculate the digest of the blob using the digest algorithm specified at `targetArtifact.payload.digest` and make sure the blob digest matches the digest present in the `targetArtifact.payload.digest`. If the digests are equal, signature verification is considered successful +1. Calculate the digest of the blob using the digest algorithm specified at `targetArtifact.payload.digest` and make sure the blob digest matches the digest present in `targetArtifact.payload.digest`. Fail signature verification if there is a mismatch. +1. Verify blob's media type and size match the values present in `targetArtifact.payload`. If they match, signature verification is considered successful. \ No newline at end of file diff --git a/specs/trust-store-trust-policy.md b/specs/trust-store-trust-policy.md index b6e1af2..30d8c30 100644 --- a/specs/trust-store-trust-policy.md +++ b/specs/trust-store-trust-policy.md @@ -60,7 +60,7 @@ Any additional sub directories under a named store and certificates in it are ig ## Trust Policy -Users who consume signed artifacts from OCI registries or signed arbitrary blobs with detached signatures use trust policies to specify trusted identities that signed the artifacts, and level of signature verification to enforce. The trust policy is a JSON document. +Users who consume signed artifacts from OCI registries, or signed arbitrary blobs stored on file system, use trust policies to specify trusted identities that signed the artifacts, and level of signature verification to enforce. The trust policy is a JSON document. **NOTE**: Support for verifying signed arbitrary blob has been added in policy version 1.1. While the policy version 1.1 can be used for verifying both signed OCI artifacts as well as signed arbitrary blobs, policy version 1.0 can only be used for verifying signed OCI artifacts. @@ -104,8 +104,16 @@ Policy version 1.1 made below changes over version 1.0 Note: Version 1.0 does not support verifying signed arbitrary blobs. See [Version 1.1](#version-1.1) for that. +### Migrating a trust policy from 1.0 to 1.1 + +1. Update the version value from `1.0` to `1.1` +2. Rename `registryScopes` key to `scopes` +3. Prefix each of the values under `scopes` with either `oci:` or `blob:` depending on whether the scope is for OCI artifacts and arbitrary blobs + ### Trust Policy Examples +#### Trust Policy in version 1.1 for OCI artifacts + 1. Trust policy for a simple scenario where ACME Rockets consumes only the OCI artifacts signed by their own CI/CD. Any third party artifacts consumed by ACME Rockets are also signed and vetted by their CI/CD. ```jsonc @@ -191,7 +199,31 @@ Note: Version 1.0 does not support verifying signed arbitrary blobs. See [Versio } ``` -3.Trust policy in version 1.0 for a scenario where ACME Rockets consumes some OCI artifacts signed by Wabbit Networks and some signed by ACME Rockets. +#### Trust Policy in version 1.0 for OCI artifacts + +1. Trust policy for a simple scenario where ACME Rockets consumes only the OCI artifacts signed by their own CI/CD. Any third party artifacts consumed by ACME Rockets are also signed and vetted by their CI/CD. + +```jsonc +{ + "version": "1.0", + "trustPolicies": [ + { + // Policy for all artifacts, from any OCI registry location. + "name": "wabbit-networks-images", // Name of the policy. + "registryScopes": [ "*" ], // The registry artifacts to which the policy applies. + "signatureVerification": { // The level of verification - strict, permissive, audit, skip. + "level" : "audit" + }, + "trustStores": ["ca:acme-rockets"], // The trust stores that contains the X.509 trusted roots. + "trustedIdentities": [ // Identities that are trusted to sign the artifact. + "x509.subject: C=US, ST=WA, L=Seattle, O=acme-rockets.io, OU=Finance, CN=SecureBuilder" + ] + } + ] +} +``` + +2.Trust policy for a scenario where ACME Rockets consumes some OCI artifacts signed by Wabbit Networks and some signed by ACME Rockets. ```jsonc { @@ -254,7 +286,9 @@ Note: Version 1.0 does not support verifying signed arbitrary blobs. See [Versio } ``` -4. Trust policy for the scenario where ACME Rockets consumes arbitrary blobs signed by Wabbit Networks and some signed by ACME Rockets. +#### Trust Policy for Blobs + +1. Trust policy for the scenario where ACME Rockets consumes arbitrary blobs signed by Wabbit Networks and some signed by ACME Rockets. ```jsonc { @@ -384,7 +418,7 @@ Signature verification levels provide defined behavior for each validation e.g. The scope `oci:*` or `blob:*` is called a global scope. The trust policy with global scope applies when a more specific scope is not available. There can only be one trust policy with a global scope of either kind (`oci:*` or `blob:*`). - +- A policy can contain either `oci:` scopes or `blob:` scopes, but not both. ##### Policy Version 1.0 - Each trust policy MUST contain scope property `registryScopes` and the scope collection MUST contain at least one value. @@ -464,7 +498,7 @@ Notary Project allows user to execute custom validations during verification usi 1. **Identify applicable trust policy** 1. For OCI artifacts, use [the artifact URI as the policy selector](#selecting-a-trust-policy-based-on-oci-artifact-uri-as-the-scope) and select the policy with matching scope from `scopes` (in policy version 1.0, use `registryScopes` field). 2. For Blob artifacts, use [the scope value provided by the verifier](#selecting-a-trust-policy-based-on-blob-scope) as the policy selector and select the policy with matching scope from `scopes`. - 1. If an applicable trust policy for the artifact URI cannot be found, fail signature verification. + 1. If an applicable trust policy for the blob cannot be found, fail signature verification. 1. **Proceed based on signature verification level** 1. If `signatureVerification` level is set to `skip` in the trust policy, return success. 1. For all other `signatureVerification` levels, `strict`, `permissive` and `audit`, perform each of the validation defined in the next sections - `integrity`, `authenticity`, `trusted timestamp`, `expiry` and `revocation`. @@ -480,6 +514,9 @@ Notary Project allows user to execute custom validations during verification usi 1. Get the signing certificate from the parsed [signature envelope](https://github.com/notaryproject/notaryproject/blob/7b7d283038/signature-specification.md#signature-envelope). 1. Determine the signing algorithm(hash+encryption) from the signing certificate and validate that the signing algorithm satisfies [algorithm requirements](./signature-specification.md#signature-algorithm-requirements) 1. Using the public key of the signing certificate and signing algorithm identified in the previous step, validate the integrity of the signature envelope. + 1. Verify signature `payload` + 1. Verify the signature envelope's `payload` matches the source [`payload`](./signature-specification.md#payload) that is getting verified. Make sure the artifact's digest, media type and size match the ones present in the signature envelope. + 1. Additionally for Blob artifacts, calculate the digest of the blob using the digest algorithm specified at `targetArtifact.payload.digest` and make sure the digests match. 1. **Validate Authenticity.** 1. For the applicable trust policy, **validate trust store and identities:** 1. Validate that the signature envelope contains a complete certificate chain that starts from a code signing certificate and terminates with a root certificate. Also, validate that code signing certificate satisfies [certificate requirements](./signature-specification.md#certificate-requirements). @@ -510,10 +547,7 @@ Notary Project allows user to execute custom validations during verification usi 1. **Validate Revocation Status:** 1. Validate signing identity(certificate and certificate chain) revocation status using [certificate revocation evaluation](#certificate-revocation-evaluation) section as per `signingIdentityRevocation` setting in trust-policy. 1. Perform extended validation using the applicable (if any) plugin. -1. Verify signature `payload` - 1. Verify the signature envelope's `payload` matches the source [`payload`](./signature-specification.md#payload) that is getting verified. - 1. For Blob artifacts, calculate the digest of the blob using the digest algorithm specified at `targetArtifact.payload.digest` and make sure the digests match. -1. If present, verify user metadata/custom annotations match the signature attributes. +1. If present, verify the user provided metadata/custom annotations match the signed attributes present in the signature envelope. 1. If all the steps are completed without critical failures then the signatures is successfully verified. ### Certificate Revocation Evaluation