From de56f9dc1d824f6a92e1e5a97bbd7396d239214b Mon Sep 17 00:00:00 2001 From: Steve Lasker Date: Fri, 25 Mar 2022 16:38:39 -0700 Subject: [PATCH] Support for JWT and COSE envelopes Signed-off-by: Steve Lasker --- signature-envelope-cose.md | 134 +++++++++++++++++++++++++++ signature-envelope-jwt.md | 142 ++++++++++++++++++++++++++++ signature-specification.md | 184 +++++++------------------------------ 3 files changed, 307 insertions(+), 153 deletions(-) create mode 100644 signature-envelope-cose.md create mode 100644 signature-envelope-jwt.md diff --git a/signature-envelope-cose.md b/signature-envelope-cose.md new file mode 100644 index 00000000..ff21d5a8 --- /dev/null +++ b/signature-envelope-cose.md @@ -0,0 +1,134 @@ +# COSE Sign1 Envelope Serialization + +In COSE ([rfc8152](https://datatracker.ietf.org/doc/html/rfc8152)), data is stored as either payload or headers (protected and unprotected). +Notary v2 supports [COSE_Sign1_Tagged](https://datatracker.ietf.org/doc/html/rfc8152#section-4.2) as a signature envelope with some additional constraints on the header fields. + +A JWS based signature will be persisted with a blob `mediaType` of `"application/cose"` + +```jsonc +{ + "artifactType": "application/vnd.cncf.notary.v2.signature", + "blobs": [ + { + "mediaType": "application/cose", + "digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0", + "size": 32654 + } + ], + "subject": { + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "digest": "sha256:73c803930ea3ba1e54bc25c2bdc53edd0284c62ed651fe7b00369da519a3c333", + "size": 16724 + }, + "annotations": { + "io.cncf.notary.x509certs.fingerprint.sha256": "[\"B7A69A70992AE4F9FF103EBE04A2C3BA6C777E439253CE36562E6E98375068C3\" \"932EB6F5598435D4EF23F97B0B5ACB515FAE2B8D8FAC046AB813DDC419DD5E89\"]" + } +} +``` + +Unless explicitly specified as OPTIONAL, all fields are required. + +**Payload**: COSE signs the payload as defined in the [Payload](#payload) section. Detached payloads are not supported. + +**ProtectedHeaders**: Notary v2 supports the following protected headers. Other header fields can be included but will be ignored. + +``` +{ + / crit / 2: [ + / cty / 3, + 'signingtime', + 'expiry' + ], + / cty / 3: 'application/vnd.cncf.oras.artifact.descriptor.v1+json', + 'signingtime': 1234567891000, + 'expiry': 1234567891011 +} +``` + +Note: The above example is represented using the [extended CBOR diagnostic notation](https://datatracker.ietf.org/doc/html/rfc8152#appendix-C). + +- **`crit`** (*array of integers or strings*): This REQUIRED property (label: `2`) lists the headers that implementation MUST understand and process. + The array MUST contain `3` (`cty`), and `signingtime`. If `expiry` is presented, the array MUST also contain `expiry`. +- **`cty`** (*string*): The REQUIRED property content-type (label: `3`) is used to declare the media type of the secured content (the payload). +- **`signingtime`** (*datetime*): The REQUIRED property identifies the time at which the signature was generated. +- **`expiry`** (*datetime*): This OPTIONAL property contains the expiration time on or after which the signature must not be considered valid. + +**UnprotectedHeaders**: Notary v2 supports two unprotected headers: `timestamp` and `x5chain`. + +``` +{ + 'timestamp': << TimeStampToken >>, + / x5chain / 33: [ + << DER(leafCert) >>, + << DER(intermediate CACert) >>, + << DER(rootCert) >> + ] +} +``` + +Note: `<<` and `>>` are used to notate the byte string resulting from encoding the data item. + +- **`timestamp`** (*byte string*): This OPTIONAL property is used to store time stamp token. + Only [RFC3161]([rfc3161](https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.2)) compliant TimeStampToken are supported. +- **`x5chain`** (*array of byte strings*): This REQUIRED property (label: `33` by [IANA](https://www.iana.org/assignments/cose/cose.xhtml#header-parameters)) contains the list of X.509 certificate or certificate chain ([RFC5280](https://datatracker.ietf.org/doc/html/rfc5280)) corresponding to the key used to digitally sign the COSE. + The certificate containing the public key corresponding to the key used to digitally sign the COSE MUST be the first certificate. + Optionally, this header can be presented in the protected header. + +**Signature**: In COSE, signature is calculated by constructing the `Sig_structure` for `COSE_Sign1`. +The process is described below: + +1. Encode the protected header into a CBOR object as a byte string named `body_protected`. +2. Construct the `Sig_structure` for `COSE_Sign1`. + ``` + Sig_structure = [ + / context / 'Signature1', + / body_protected / << ProtectedHeaders >>, + / external_aad / h'', + / payload / << Payload >>, + ] + ``` +3. Encode `Sig_structure` into a CBOR object as a byte string named `ToBeSigned`. +4. Compute the signature on the `ToBeSigned` constructed in the previous step by using the signature algorithm defined in the corresponding header element: `alg`. + This is the value of the signature property used in the signature envelope. + +**Signature Envelope**: The final signature envelope is a `COSE_Sign1_Tagged` object, consisting of Payload, ProtectedHeaders, UnprotectedHeaders, and Signature. + +``` +18( + [ + / protected / << { + / crit / 2: [ + / cty / 3, + 'signingtime', + 'expiry' + ], + / cty / 3: 'application/vnd.cncf.oras.artifact.descriptor.v1+json', + 'signingtime': 1234567891000, + 'expiry': 1234567891011 + } >>, + / unprotected / { + 'timestamp': << TimeStampToken >>, + / x5chain / 33: [ + << DER(leafCert) >>, + << DER(intermediate CACert) >>, + << DER(rootCert) >> + ] + }, + / payload / << descriptor >>, + / signature / << sign( << Sig_structure >> ) >> + ] +) +``` + +## Signature Algorithm Requirements + +The implementation MUST support the following set of algorithms: + +1. RSASSA-PSS with SHA-256 +1. RSASSA-PSS with SHA-384 +1. RSASSA-PSS with SHA-512 +1. ECDSA on secp256r1 with SHA-256 +1. ECDSA on secp384r1 with SHA-384 +1. ECDSA on secp521r1 with SHA-512 + +For ECDSA equivalent NIST curves and ANSI curves can be found at [RFC4492 Appendix A](https://tools.ietf.org/search/rfc4492#appendix-A). diff --git a/signature-envelope-jwt.md b/signature-envelope-jwt.md new file mode 100644 index 00000000..43604747 --- /dev/null +++ b/signature-envelope-jwt.md @@ -0,0 +1,142 @@ +# JWS Signature Envelope Serialization + +JWS JSON Serialization ([RFC7515](https://datatracker.ietf.org/doc/html/rfc7515)) data is stored as either claims or headers (protected and unprotected). +Notary v2 supports JWS JSON Serialization as a signature envelope with some additional constraints on the structure of claims and headers. + +A JWS based signature will be persisted with a blob `mediaType` of `"application/jose+json"` + +```jsonc +{ + "artifactType": "application/vnd.cncf.notary.v2.signature", + "blobs": [ + { + "mediaType": "application/jose+json", + "digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0", + "size": 32654 + } + ], + "subject": { + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "digest": "sha256:73c803930ea3ba1e54bc25c2bdc53edd0284c62ed651fe7b00369da519a3c333", + "size": 16724 + }, + "annotations": { + "io.cncf.notary.x509certs.fingerprint.sha256": "[\"B7A69A70992AE4F9FF103EBE04A2C3BA6C777E439253CE36562E6E98375068C3\" \"932EB6F5598435D4EF23F97B0B5ACB515FAE2B8D8FAC046AB813DDC419DD5E89\"]" + } +} +``` + +Unless explicitly specified as OPTIONAL, all fields are required. +Also, there shouldn’t be any additional fields other than ones specified in JWSPayload, ProtectedHeader, and UnprotectedHeader. + +**JWSPayload a.k.a. Claims**: +Notary v2 is using one private claim (`notary`) and two public claims (`iat` and `exp`). +An example of the claim is described below + +```jsonc +{ + "subject": { + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "digest": "sha256:73c803930ea3ba1e54bc25c2bdc53edd0284c62ed651fe7b00369da519a3c333", + "size": 16724, + "annotations": { + "key1": "value1", + "key2": "value2", + ... + } + }, + "iat": 1234567891000, + "exp": 1234567891011 +} +``` + +The payload contains the subject manifest and other attributes that have to be integrity protected. + +- **`subject`**(*descriptor*): A REQUIRED top-level node consisting of the manifest that needs to be integrity protected. + Please refer [Payload](#payload) section for more details. +- **`iat`**(*number*): The REQUIRED property Issued-at(`iat`) identifies the time at which the signature was issued. +- **`exp`**(*number*): This OPTIONAL property contains the expiration time on or after which the signature must not be considered valid. + +To leverage JWS claims validation functionality already provided by libraries, we have defined `iat`, `exp` as top-level nodes. + +**ProtectedHeaders**: Notary v2 supports only three protected headers: `alg`, `cty`, and `crit`. + +```jsonc +{ + "alg": "RS256", + "cty": "application/vnd.cncf.notary.v2.jws.v1", + "crit":["cty"] +} +``` + +- **`alg`**(*string*): This REQUIRED property defines which algorithm was used to generate the signature. + JWS needs an algorithm(`alg`) to be present in the header, so we have added it as a protected header. +- **`cty`**(*string*): The REQUIRED property content-type(cty) is used to declare the media type of the secured content(the payload). + This will be used to version different variations of JWS signature. + The supported value is `application/vnd.cncf.notary.v2.jws.v1`. +- **`crit`**(*array of strings*): This REQUIRED property lists the headers that implementation MUST understand and process. + The value MUST be `["cty"]`. + +**UnprotectedHeaders**: Notary v2 supports only two unprotected headers: timestamp and x5c. + +```jsonc +{ + "timestamp": "", + "x5c": ["", "", ""] +} +``` + +- **`timestamp`** (*string*): This OPTIONAL property is used to store time stamp token. + Only [RFC3161]([rfc3161](https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.2)) compliant TimeStampToken are supported. +- **`x5c`** (*array of strings*): This REQUIRED property contains the list of X.509 certificate or certificate chain([RFC5280](https://datatracker.ietf.org/doc/html/rfc5280)) corresponding to the key used to digitally sign the JWS. + The certificate containing the public key corresponding to the key used to digitally sign the JWS MUST be the first certificate. + +- **`timestamp`** (*string*): This OPTIONAL property is used to store time stamp token. + Only [RFC3161]([rfc3161](https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.2)) compliant TimeStampToken are supported. +- **`x5c`** (*array of strings*): This REQUIRED property contains the list of X.509 certificate or certificate chain([RFC5280](https://datatracker.ietf.org/doc/html/rfc5280)) corresponding to the key used to digitally sign the JWS. + The certificate containing the public key corresponding to the key used to digitally sign the JWS MUST be the first certificate. + +**Signature**: In JWS signature is calculated by combining JWSPayload and protected headers. +The process is described below: + +1. Compute the Base64Url value of ProtectedHeaders. +2. Compute the Base64Url value of JWSPayload. +3. Build message to be signed by concatenating the values generated in step 1 and step 2 using '.' +`ASCII(BASE64URL(UTF8(ProtectedHeaders)) ‘.’ BASE64URL(JWSPayload))` +1. Compute the signature on the message constructed in the previous step by using the signature algorithm defined in the corresponding header element: `alg`. +1. Compute the Base64Url value of the signature produced in the previous step. + This is the value of the signature property used in the signature envelope. + +**Signature Envelope**: The final signature envelope comprises of Claims, ProtectedHeaders, UnprotectedHeaders, and signature. + +Since Notary v2 restricts one signature per signature envelope, the compliant signature envelope MUST be in flattened JWS JSON format. + +```jsonc +{ + "payload": "", + "protected": "", + "header": { + "timestamp": "", + "x5c": ["", "", ""] + }, + "signature": "Base64Url( sign( ASCII( . )))" +} +``` + +**Implementation Constraints**: Notary v2 implementation MUST enforce the following constraints on signature generation and verification: + +1. `alg` header value MUST NOT be `none` or any symmetric-key algorithm such as `HMAC`. +1. `alg` header value MUST be same as that of signature algorithm identified using signing certificate's public key algorithm and size. +1. `alg` header values for various signature algorithms: + + | Signature Algorithm | `alg` Param Value | + | ------------------------------- | ----------------- | + | RSASSA-PSS with SHA-256 | PS256 | + | RSASSA-PSS with SHA-384 | PS384 | + | RSASSA-PSS with SHA-512 | PS512 | + | ECDSA on secp256r1 with SHA-256 | ES256 | + | ECDSA on secp384r1 with SHA-384 | ES384 | + | ECDSA on secp521r1 with SHA-512 | ES512 | + +1. Only JWS JSON flattened format is supported. + See 'Signature Envelope' section. \ No newline at end of file diff --git a/signature-specification.md b/signature-specification.md index 2144cbba..da329acc 100644 --- a/signature-specification.md +++ b/signature-specification.md @@ -9,15 +9,15 @@ The document has the following sections: ## Storage This section describes how Notary v2 signatures are stored in the OCI Distribution conformant registry. -Notary v2 uses [ORAS artifact manifest](https://github.com/oras-project/artifacts-spec/blob/main/artifact-manifest.md) to store the signature in the repository. +Notary v2 uses [ORAS artifact manifest][oras-artifact-manifest] to store the signature in the repository. The media type of the signature manifest is `application/vnd.cncf.oras.artifact.manifest.v1+json`. The signature manifest has an artifact type that specifies it's a Notary V2 signature, a reference to the manifest of the artifact being signed, a blob referencing the signature, and a collection of annotations. ![Signature storage inside registry](media/signature-specification.svg) - **`artifactType`** (*string*): This REQUIRED property references the Notary version of the signature: `application/vnd.cncf.notary.v2.signature`. -- **`blobs`** (*array of objects*): This REQUIRED property contains collection of only one [artifact descriptor](https://github.com/oras-project/artifacts-spec/blob/main/descriptor.md) referencing signature envelope. - - **`mediaType`** (*string*): This REQUIRED property contains media type of signature envelope blob. The supported value is `application/cose`. +- **`blobs`** (*array of objects*): This REQUIRED property contains collection of only one [artifact descriptor][artifact-descriptor] referencing signature envelope. + - **`mediaType`** (*string*): This REQUIRED property contains media type of signature envelope blob. The currently supported values are `application/cose` and `application/jose+json`. - **`subject`** (*descriptor*): A REQUIRED artifact descriptor referencing the signed manifest, including, but not limited to image manifest, image index, oras-artifact manifest. - **`annotations`** (*string-string map*): This REQUIRED property contains metadata for the artifact manifest. It is being used to store information about the signature. @@ -25,30 +25,9 @@ The signature manifest has an artifact type that specifies it's a Notary V2 sign - **`io.cncf.notary.x509certs.fingerprint.sha256`**: A REQUIRED annotation whose value contains the list of SHA-256 fingerprint of signing certificate and certificate chain used for signature generation. The list of fingerprints is present as a JSON array string. -```json -{ - "artifactType": "application/vnd.cncf.notary.v2.signature", - "blobs": [ - { - "mediaType": "application/cose", - "digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0", - "size": 32654 - } - ], - "subject": { - "mediaType": "application/vnd.oci.image.manifest.v1+json", - "digest": "sha256:73c803930ea3ba1e54bc25c2bdc53edd0284c62ed651fe7b00369da519a3c333", - "size": 16724 - }, - "annotations": { - "io.cncf.notary.x509certs.fingerprint.sha256": "[\"B7A69A70992AE4F9FF103EBE04A2C3BA6C777E439253CE36562E6E98375068C3\" \"932EB6F5598435D4EF23F97B0B5ACB515FAE2B8D8FAC046AB813DDC419DD5E89\"]" - } -} -``` - ### Signature Discovery -The client should be able to discover all the signatures belonging to an artifact (such as image manifest) by using [ORAS Manifest Referrers API](https://github.com/oras-project/artifacts-spec/blob/main/manifest-referrers-api.md). +The client should be able to discover all the signatures belonging to an artifact (such as image manifest) by using [ORAS Manifest Referrers API][oras-artifacts-referrers]. ORAS Manifest Referrers API returns a paginated list of all artifacts belonging to a target artifact (such as container images, SBoMs). The implementation can filter Notary signature artifacts by either using ORAS Manifest Referrers API or using custom logic on the client. Each Notary signature artifact refers to a signature envelope blob. @@ -64,23 +43,27 @@ The Signature Envelope is a standard data structure for creating a signed messag A signature envelope consists of the following components: - Payload `m`: The data that is integrity protected - e.g. descriptor of the artifact being signed. -- Signed attributes `v`: The signature metadata that is integrity protected - e.g. signature expiration time, signing time, etc. -- Unsigned attributes `u`: This OPTIONAL property represents signature metadata that is not integrity protected - e.g. timestamp, certificates, etc. +- Signed attributes `v`: The signature metadata that is integrity protected - e.g. signature expiration time, creation time, etc. +- Unsigned attributes `u`: This OPTIONAL property represents signature metadata that is not integrity protected by this envelope- e.g. timestamp, certificates, etc. + We anticipate all unsigned attributes contain signed content. - Cryptographic signatures `s`: The digital signatures computed on payload and signed attributes. A signature envelope is `e = {m, v, u, s}` where `s` is signature. -Notary v2 supports [COSE_Sign1_Tagged](https://datatracker.ietf.org/doc/html/rfc8152#section-4) as signature envelope format with some additional constraints but makes provisions to support additional signature envelope format. +Notary v2 supports multiple envelope formats, including: + +- [COSE Sign1](./signature-envelope-cose.md) +- [JWT](./signature-envelope-jwt.md) ### Payload Notary v2 requires Payload to be the content **descriptor** of the subject manifest that is being signed. 1. Descriptor MUST contain `mediaType`, `digest`, `size` fields. -1. Descriptor MAY contain `annotations` and if present it MUST follow the [annotation rules](https://github.com/opencontainers/image-spec/blob/main/annotations.md#rules). Notary v2 uses annotations for storing both Notary specific and user defined signed attributes. The prefix `io.cncf.notary` in annotation keys is reserved for use in Notary v2 and MUST NOT be used outside this specification. -1. Descriptor MAY contain `artifactType` field for artifact manifests, or the `config.mediaType` for `oci.image` based manifests. +2. Descriptor MAY contain `annotations` and if present it MUST follow the [annotation rules][annotation-rules]. Notary v2 uses annotations for storing both Notary specific and user defined signed attributes. The prefix `io.cncf.notary` in annotation keys is reserved for use in Notary v2 and MUST NOT be used outside this specification. +3. Descriptor MAY contain `artifactType` field for artifact manifests, or the `config.mediaType` for `oci.image` based manifests. -Examples: The media type of the content descriptor is `application/vnd.cncf.oras.artifact.descriptor.v1+json`. +**Examples**: The media type of the content descriptor is `application/vnd.cncf.oras.artifact.descriptor.v1+json`. ```jsonc { @@ -93,7 +76,7 @@ Examples: The media type of the content descriptor is `application/vnd.cncf.oras } ``` -```json +```jsonc { "mediaType": "sbom/example", "digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0", @@ -109,128 +92,12 @@ Notary v2 requires the signature envelope to support the following signed attrib Its value should be numeric representing the number of seconds (not milliseconds) since Epoch. - **Expiration time**: The time after which signature shouldn't be considered valid. Its value should be numeric representing the number of seconds since Epoch. + The value MUST be equal or greater than the `Creation time` This is an OPTIONAL attribute. ### Unsigned Attributes - **Certificates**: The ordered collection of X.509 certificates with a signing certificate as the first entry. -- **Timestamp**: The time stamp token generated for a given signature. - Only [RFC3161](https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.2) compliant *TimeStampToken* are supported. - This is an OPTIONAL attribute. - -### Supported Signature Envelopes - -#### COSE_Sign1_Tagged - -In COSE ([rfc8152](https://datatracker.ietf.org/doc/html/rfc8152)), data is stored as either payload or headers (protected and unprotected). -Notary v2 uses [COSE_Sign1_Tagged](https://datatracker.ietf.org/doc/html/rfc8152#section-4.2) object as the signature envelope with some additional constraints on the header fields. - -Unless explicitly specified as OPTIONAL, all fields are required. - -**Payload**: COSE signs the payload as defined in the [Payload](#payload) section. Detached payloads are not supported. - -**ProtectedHeaders**: Notary v2 supports the following protected headers. Other header fields can be included but will be ignored. - -``` -{ - / crit / 2: [ - / cty / 3, - 'signingtime', - 'expiry' - ], - / cty / 3: 'application/vnd.cncf.oras.artifact.descriptor.v1+json', - 'signingtime': 1234567891000, - 'expiry': 1234567891011 -} -``` - -Note: The above example is represented using the [extended CBOR diagnostic notation](https://datatracker.ietf.org/doc/html/rfc8152#appendix-C). - -- **`crit`** (*array of integers or strings*): This REQUIRED property (label: `2`) lists the headers that implementation MUST understand and process. - The array MUST contain `3` (`cty`), and `signingtime`. If `expiry` is presented, the array MUST also contain `expiry`. -- **`cty`** (*string*): The REQUIRED property content-type (label: `3`) is used to declare the media type of the secured content (the payload). -- **`signingtime`** (*datetime*): The REQUIRED property identifies the time at which the signature was generated. -- **`expiry`** (*datetime*): This OPTIONAL property contains the expiration time on or after which the signature must not be considered valid. - -**UnprotectedHeaders**: Notary v2 supports two unprotected headers: `timestamp` and `x5chain`. - -``` -{ - 'timestamp': << TimeStampToken >>, - / x5chain / 33: [ - << DER(leafCert) >>, - << DER(intermediate CACert) >>, - << DER(rootCert) >> - ] -} -``` - -Note: `<<` and `>>` are used to notate the byte string resulting from encoding the data item. - -- **`timestamp`** (*byte string*): This OPTIONAL property is used to store time stamp token. - Only [RFC3161]([rfc3161](https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.2)) compliant TimeStampToken are supported. -- **`x5chain`** (*array of byte strings*): This REQUIRED property (label: `33` by [IANA](https://www.iana.org/assignments/cose/cose.xhtml#header-parameters)) contains the list of X.509 certificate or certificate chain ([RFC5280](https://datatracker.ietf.org/doc/html/rfc5280)) corresponding to the key used to digitally sign the COSE. - The certificate containing the public key corresponding to the key used to digitally sign the COSE MUST be the first certificate. - Optionally, this header can be presented in the protected header. - -**Signature**: In COSE, signature is calculated by constructing the `Sig_structure` for `COSE_Sign1`. -The process is described below: - -1. Encode the protected header into a CBOR object as a byte string named `body_protected`. -2. Construct the `Sig_structure` for `COSE_Sign1`. - ``` - Sig_structure = [ - / context / 'Signature1', - / body_protected / << ProtectedHeaders >>, - / external_aad / h'', - / payload / << Payload >>, - ] - ``` -3. Encode `Sig_structure` into a CBOR object as a byte string named `ToBeSigned`. -4. Compute the signature on the `ToBeSigned` constructed in the previous step by using the signature algorithm defined in the corresponding header element: `alg`. - This is the value of the signature property used in the signature envelope. - -**Signature Envelope**: The final signature envelope is a `COSE_Sign1_Tagged` object, consisting of Payload, ProtectedHeaders, UnprotectedHeaders, and Signature. - -``` -18( - [ - / protected / << { - / crit / 2: [ - / cty / 3, - 'signingtime', - 'expiry' - ], - / cty / 3: 'application/vnd.cncf.oras.artifact.descriptor.v1+json', - 'signingtime': 1234567891000, - 'expiry': 1234567891011 - } >>, - / unprotected / { - 'timestamp': << TimeStampToken >>, - / x5chain / 33: [ - << DER(leafCert) >>, - << DER(intermediate CACert) >>, - << DER(rootCert) >> - ] - }, - / payload / << descriptor >>, - / signature / << sign( << Sig_structure >> ) >> - ] -) -``` - -## Signature Algorithm Requirements - -The implementation MUST support the following set of algorithms: - -1. RSASSA-PSS with SHA-256 -1. RSASSA-PSS with SHA-384 -1. RSASSA-PSS with SHA-512 -1. ECDSA on secp256r1 with SHA-256 -1. ECDSA on secp384r1 with SHA-384 -1. ECDSA on secp521r1 with SHA-512 - -For ECDSA equivalent NIST curves and ANSI curves can be found at [RFC4492 Appendix A](https://tools.ietf.org/search/rfc4492#appendix-A). ### Algorithm Selection @@ -270,12 +137,23 @@ The **timestamping certificate** MUST meet the following minimum requirements: ## FAQ -**Q: How will Notary v2 support multiple signature envelope format?** +**Q: How will Notary v2 support multiple signature envelope formats?** -**A:** The idea is to use `mediaType` of artifact manifest's blob to identify the signature envelope type (like COSE, JWS, CMS, DSSE, etc). +**A:** The `mediaType` of artifact manifest's blob identifies the signature envelope type. The client implementation can use the aforementioned `mediaType` to parse the signature envelope. **Q: How will Notary v2 handle non-backward compatible changes to signature format?** -**A:** The Signature envelope MUST have a versioning mechanism to support non-backward compatible changes. -For [COSE_Sign1_Tagged](#cose_sign1_tagged) signature envelope it is achieved by `cty` field in ProtectedHeaders. +**A:** The Signature envelope MUST have a versioning mechanism to support non-backward compatible changes. +[COSE_Sign1_Tagged](./signature-envelope-cose.md) signature envelope versioning is achieved by the `cty` field in ProtectedHeaders. +[JWS JSON serialization](./signature-envelope-jwt.md) signature envelope versioning is achieved by the `cty` field in ProtectedHeaders. + +[annotation-rules]: https://github.com/opencontainers/image-spec/blob/main/annotations.md#rules +[artifact-descriptor]: https://github.com/oras-project/artifacts-spec/blob/main/descriptor.md +[ietf-cose]: https://datatracker.ietf.org/doc/html/rfc8152 +[ietf-cose-section-4]: https://datatracker.ietf.org/doc/html/rfc8152#section-4 +[ietf-cose-section-4.2]: https://datatracker.ietf.org/doc/html/rfc8152#section-4.2 +[ietf-cose-appendix-c]: https://datatracker.ietf.org/doc/html/rfc8152#appendix-C +[ietf-rfc3161]: https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.2 +[oras-artifact-manifest]: https://github.com/oras-project/artifacts-spec/blob/main/artifact-manifest.md +[oras-artifacts-referrers]: https://github.com/oras-project/artifacts-spec/blob/main/manifest-referrers-api.md