Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verification Plugin spec #165

Merged
merged 14 commits into from
Jul 25, 2022
16 changes: 12 additions & 4 deletions signature-envelope-jws.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,18 @@ Example

- **[`alg`](https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.1)**(*string*): This REQUIRED header defines which signing algorithm was used to generate the signature. JWS specification defines `alg` as a required header, that MUST be present and MUST be understood and processed by verifier. The signature algorithm of the signing key (first certificate in `x5c`) is the source of truth, and during signing the value of `alg` MUST be set corresponding to signature algorithm of the signing key using [this mapping](#supported-alg-header-values) that lists the Notary v2 allowed subset of `alg` values supported by JWS. Similarly verifier of the signature MUST match `alg` with signature algorithm of the signing key to mitigate algorithm substitution attacks.
- **[`cty`](https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.10)**(*string*): The REQUIRED header content-type is used to declare the media type of the secured content (the payload). The supported value is `application/vnd.cncf.notary.payload.v1+json`.
- **`io.cncf.notary.signingTime`**(*string*): This REQUIRED header specifies the time at which the signature was generated. This is an untrusted timestamp, and therefore not used in trust decisions. Its value is a [RFC 3339][rfc3339] formatted date time, the optional fractional second ([time-secfrac][rfc3339][[1](https://datatracker.ietf.org/doc/html/rfc3339#section-5.3)]) SHOULD NOT be used.
- **`io.cncf.notary.expiry`**(*string*): This OPTIONAL header provides a “best by use” time for the artifact, as defined by the signer. Its value is a [RFC 3339][rfc3339] formatted date time, the optional fractional second ([time-secfrac][rfc3339][[1](https://datatracker.ietf.org/doc/html/rfc3339#section-5.3)]) SHOULD NOT be used.
- **[`crit`](https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.11)**(*array of strings*): This OPTIONAL header lists the headers that implementation MUST understand and process. It MUST only contain headers apart from registered headers (e.g. `alg`, `cty`) in JWS specification, therefore this header is only present when the optional `io.cncf.notary.expiry` header is present in the protected headers collection.
If present, the value MUST be `["io.cncf.notary.expiry"]`.
- **`io.cncf.notary.signingScheme`**(*string*)(critical): This REQUIRED header specifies the [Notary v2 Signing Scheme](./signing-scheme.md) used by the signature. Supported values are `notary.default.x509` and `notary.signingAuthority.x509`.
gokarnm marked this conversation as resolved.
Show resolved Hide resolved
- **`io.cncf.notary.signingTime`**(*string*): This header specifies the time at which the signature was generated. This is an untrusted timestamp, and therefore not used in trust decisions. Its value is a [RFC 3339][rfc3339] formatted date time, the optional fractional second ([time-secfrac][rfc3339][[1](https://datatracker.ietf.org/doc/html/rfc3339#section-5.3)]) SHOULD NOT be used. This claim is REQUIRED and only valid when signing scheme is `notary.default.x509`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r/ .default

- **`io.cncf.notary.authenticSigningTime`**(*string*)(critical): This header specifies the authenticated time at which the signature was generated. Its value is a [RFC 3339][rfc3339] formatted date time, the optional fractional second ([time-secfrac][rfc3339][[1](https://datatracker.ietf.org/doc/html/rfc3339#section-5.3)]) SHOULD NOT be used. This claim is REQUIRED and only valid when signing scheme is `notary.signingAuthority.x509` .
- **`io.cncf.notary.expiry`**(*string*)(critical): This OPTIONAL header provides a “best by use” time for the artifact, as defined by the signer. Its value is a [RFC 3339][rfc3339] formatted date time, the optional fractional second ([time-secfrac][rfc3339][[1](https://datatracker.ietf.org/doc/html/rfc3339#section-5.3)]) SHOULD NOT be used.
- **[`crit`](https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.11)**(*array of strings*): This OPTIONAL header lists the headers that implementation MUST understand and process. It MUST only contain headers apart from registered headers (e.g. `alg`, `cty`) in JWS specification. This header MUST contain `io.cncf.notary.signingScheme` which is a required critical header, and optionally contain `io.cncf.notary.authenticSigningTime` and `io.cncf.notary.expiry` if these critical headers are present in the signature.

## Extended Protected Headers for *Notation* Plugins

See [Extended attributes for *Notation* Plugins](./signature-specification.md#extended-attributes-for-notation-plugins) for detailed description og these headers.
gokarnm marked this conversation as resolved.
Show resolved Hide resolved

- **`io.cncf.notary.verificationPlugin`**(*string*)(critical): An OPTIONAL header that specifies the name of the verification plugin that MAY be used to verify the signature.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, why do we think we need this?
The notary client should be able to verify any signature format supported. I haven't seen where we need plugins for verification.

- **`io.cncf.notary.verificationPluginMinVersion`**(*string*)(critical): An OPTIONAL header that specifies the minimum version of the verification plugin that MUST be used to verify the signature.

## Unprotected Headers

Expand Down
29 changes: 27 additions & 2 deletions signature-specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,24 @@ Notary v2 requires the signature envelope to support the following signed attrib

#### Standard attributes

- **Signing time**: A REQUIRED claim that indicates the time at which the signature was generated. Though this claim is signed by the signing key, it’s considered unauthenticated as a signer can modify local time and manipulate this claim. More details [here](#signing-time).
- **Signing Scheme** (critical): A REQUIRED claim that defines the [Notary v2 Signing Scheme](./signing-scheme.md) used by the signature. This attribute dictates the rest of signature schema - the set of signed and unsigned attributes to be included in the signature. Supported values are `notary.default.x509` and `notary.signingAuthority.x509`.
- **Signing Time**: A claim that indicates the time at which the signature was generated. Though this claim is signed by the signing key, it’s considered unauthenticated as a signer can modify local time and manipulate this claim. More details [here](#signing-time). This claim is REQUIRED and only valid when signing scheme is `notary.default.x509` .
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r/ .default

- **Authentic Signing Time** (critical): The authenticated time at which the signature was generated. This claim is REQUIRED and only valid when signing scheme is `notary.signingAuthority.x509` . More details [here](#signing-time).
- **Expiry** (critical): An OPTIONAL claim that provides a “best by use” time for the artifact, as defined by the signer. More details [here](#expiry).
- **Content type** (critical): A REQUIRED claim that indicates the content type of the [payload](#payload). The supported value is `application/vnd.cncf.notary.payload.v1+json`. Other payload types MAY be supported in future.
- **Content Type** (critical): A REQUIRED claim that indicates the content type of the [payload](#payload). The supported value is `application/vnd.cncf.notary.payload.v1+json`. Other payload types MAY be supported in future.

#### Extended attributes

Implementations of Notary v2 signature spec MAY include additional signed attributes in the signature envelope. These attributes MAY be marked critical, i.e. the attribute MUST be understood and processed by a verifier, unknown critical attributes MUST cause signature verification to fail.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds like it would impose instability and inconsistency.
A primary goal of Notary v2 is cloud/location independence. If a user copies an image from MAR to their ecr, they shouldn't need any special Microsoft stuff to validate it.
I'm guessing you have some ideas around new headers. Can we discuss those and find a platform neutral way?

Copy link
Contributor

@sajayantony sajayantony Jul 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these the critical headers we are discussing here -

Given the statement - basically it means that a signature with a critical header will put a requirement on the client environment to have the plugin available.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the links point to how criticality of signed attributes is implemented in JWS and COSE. If an extended attribute is marked critical (not all extended attributes need to be critical) the verifier must process it either using a plugin or equivalent verification logic.


#### Extended attributes for *Notation* Plugins

This section documents extended attributes used by Notary v2 reference implementation *Notation* to support plugins. Plugins is a *Notation* concept that allows parts of signing and verification logic to be performed by an external provider. *Signing plugins* allow *Notation* to be extended for integration with remote keys remote key management services and signing services, where as *verification plugins* allow for customization of verification logic. Detailed specification for plugins can be found [here](https://github.com/notaryproject/notaryproject/blob/main/specs/plugin-extensibility.md#notation-extensibility-for-signing-and-verification). These extended attributes are documented in this spec, as other Notary V2 implementations may encounter these attributes if they verify a signature that indicated it required a verification plugin for complete signature verification.
gokarnm marked this conversation as resolved.
Show resolved Hide resolved

- **Verification Plugin** (critical): An OPTIONAL attribute that specifies the name of the verification plugin that MAY be used to verify the signature e.g. “com.example.nv2plugin”. [Notation plugin](https://github.com/notaryproject/notaryproject/blob/main/specs/plugin-extensibility.md#plugin-contract) aware implementations use this attribute to load and execute a *Notation* compliant plugin. The plugin participates in the overall signature verification workflow and performs specific steps in it.
- **Verification Plugin Minimum Version** (critical): An OPTIONAL attribute that specifies the minimum version of the verification plugin that MUST be used to verify the signature. A Notation plugin aware implementations MUST use this attribute to verify the signature with a plugin with matching or higher plugin version. The plugin MUST use [Semantic Versioning](https://semver.org/) (SemVer) to use this feature i.e the `get-plugin-metadata` plugin command MUST return a SemVer compliant version in the response. A use case for this feature is for a plugin publisher to address security bug in older plugin version, by setting the minimum version to the plugin version with fixes.

See [Guidelines for Notary v2 implementors](#guidelines-for-notary-v2-implementors) for options to handle these attributes during signature verification.

### Unsigned Attributes

Expand Down Expand Up @@ -225,6 +240,16 @@ The signing time denotes the time at which the signature was generated. A X509 c

This is an optional feature that provides a “best by use” time for the artifact, as defined by the signer. Notary v2 allows users to include an optional expiry time when they generate a signature. The expiry time is not set by default and requires explicit configuration by users at the time of signature generation. The artifact is considered expired when the current time is greater than or equal to expiry time, users performing verification can either configure their trust policies to fail the verification or even accept the artifact with expiry date in the past using policy. This is an advanced feature that allows implementing controls for user defined semantics like deprecation for older artifacts, or block older artifacts in a production environment. Users should only include an expiry time in the signed artifact after considering the behavior they expect for consumers of the artifact after it expires. Users can choose to consume an artifact even after the expiry time based on their specific needs.

### Guidelines for Notary v2 implementors
gokarnm marked this conversation as resolved.
Show resolved Hide resolved

Implementations of Notary v2, can choose to be [Notation plugin protocol](./specs/plugin-extensibility.md#plugin-contract) aware or not. If an implementation chooses to be plugin protocol aware, and it encounters the Verification Plugin and Verification Plugin minimum version attributes during signature verification, it MUST process these attributes. This involves finding the appropriate plugin and the version to use, and executing `verify-signature` plugin command with correct inputs and processing the plugin response, as per the [Verification Plugin interface](../specs/../notaryproject-specs/specs/plugin-extensibility.md#verification-extensibility).
gokarnm marked this conversation as resolved.
Show resolved Hide resolved

Alternatively, an implementation of Notary v2 can choose not to implement plugin protocol.

- The implementation MUST itself perform equivalent verification logic that is usually performed by plugin specified in the signature.
- An implementation MUST fail signature verification if it cannot perform the equivalent verification logic, as skipping the plugin equivalent verification logic will cause incorrect and inconsistent signature verification behavior.
- An implementation MAY choose to support a set of known plugin’s verification logic and fail others.

[annotation-rules]: https://github.com/opencontainers/image-spec/blob/main/annotations.md#rules
[oci-descriptor]: https://github.com/opencontainers/image-spec/blob/main/descriptor.md
[artifact-descriptor]: https://github.com/oras-project/artifacts-spec/blob/main/descriptor.md
Expand Down
73 changes: 73 additions & 0 deletions signing-scheme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Signing Scheme

Signatures are primarily used to provide a consumer of an artifact the following guarantees - integrity (the signed artifact was not tampered after signing it), and authenticity (the artifact was indeed signed by the entity who claims to have signed it). X.509 PKI based identities are commonly used to for signing artifacts. It has well established standards for issuing and representing identities (CAs and certificates) which sign artifacts, mechanism to establish authenticity using trust stores, and support for managing key lifetimes and rotation, and revocation of identities. There is interest in the community to support other ways to establish integrity and authenticity, based on other systems and techniques (Notary TUF, ledger based). These approaches also can provide different feature sets than ones traditionally provided by standard X.509 PKI based signing. E.g. TUF is geared for software update systems and provides a freshness guarantee.
gokarnm marked this conversation as resolved.
Show resolved Hide resolved

Notary v2 will initially support X.509 PKI identity based signing, but provide the flexibility for additional systems through an abstraction called Signing Scheme. The Signing Scheme covers aspects of signature generation and verification, and formalizes the feature set (guarantees) provided by the signature produced using a signing scheme. Generally it covers the following aspects, but can be extended to other aspects as required by newer systems.

*Signature creation*

1. Supported entities that can generate signatures - typically an end user generates the signature, other models can be supported using signature scheme.
1. Representation of identities - e.g. X.509 certificates are used to represent end users and entities which verify the end user’s authenticity (CAs).
gokarnm marked this conversation as resolved.
Show resolved Hide resolved
1. Signature schema - Defines the signed and unsigned attributes to be included in a signature envelope, and which attributes are required, optional and critical.

*Signature verification*

1. Mechanism to establish trust in end users and other entities (like CAs).
2. Set of guarantees available to the verifier apart from integrity and authenticity.

## Signing Scheme

Notary v2 currently defines the following Signing Schemes.

`notary.default.x509` - Defines a signing scheme that uses the traditional signing workflow in which an end user generates signatures using X.509 certificates.

`notary.signingAuthority.x509` - Defines a signing scheme in which a `signing authority` generates signatures on behalf of an end user (the signature requestor) using X.509 certificates. A trusted signing authority is defined as a third party service that is trusted both by the end user (the signature requestor) and verifying entity to generate signatures.

* A signature envelope can only specify one Signing Scheme
* When Notary supports an additional Signing Scheme
* Existing signed artifacts MUST be resigned if they need to be verified using the new signing scheme defined verification process.
* Existing clients used by verifying entity MUST be updated to newer versions that support verifying signatures that use the new signing scheme.
* The Notary verification policy language in *trustpolicy.json* MAY have breaking changes to support newer concepts/configuration elements introduced by the new signing scheme. The breaking changes are addressed by introducing new major version in the versioned *trustpolicy.json* .

## Signature Creation

The signature envelope contains `Signing Scheme` as an required and critical attribute. This attribute dictates the rest of signature schema - the set of signed and unsigned attributes to be included in the signature.

Both `notary.default.x509` and `notary.signingAuthority.x509` signing schemes use the similar signature schema (set of signed and unsigned attributes) with the following differences.

* `notary.default.x509` MUST use a countersignature from trusted source to determine authentic signing time (timestamp). This is supported through the the Timestamp signature unsigned attribute in the signature envelope. Currently Notary V2 uses a [RFC3161](ietf-rfc3161) compliant TSA signature for this purpose.

* `notary.signingAuthority.x509` MUST use a timestamp attribute that is generated by a signing service as part of the original signature itself to determine authenticated signing time (timestamp). This is supported through the *Authentic Signing time* attribute in the signature envelope.

## Signature Verification

Signature verification requires that a `Signing Scheme` attribute is present in the signature and it’s treated as critical i.e. the attribute MUST be understood and processed by the verifier. For the JWS signature format, the
attribute name is `io.cncf.notary.signingScheme` , with supported values `notary.default.x509` and `notary.signingAuthority.x509` . Any other value will fail signature verification i.e when Notary supports an additional Signing Scheme, clients (like *notation*) MUST be updated to a version that supports the new signing scheme.

### Trust Stores

Each *Signing Scheme* defines the set of trust store types (e.g. CA) that it uses for signature verification.

`notary.default.x509`

* Uses trusts store types Certificate Authority (CA) and Timestamping Authority (TSA) during signature verification. The signature is verified against the trust store of type CA, and the *Timestamp signature* is verified against the trust store of type TSA (to determine the signing time).
* For signature verification to be successful
* The verifying entity’s trust store MUST contain the trusted root certificates under named trust stores of type CA (`{CONFIG}/notation/truststore/x509/ca`) and TSA(`{CONFIG}/notation/truststore/x509/tsa`)
* The named trust stores MUST be specified in *trustpolicy.json*. E.g. *trustPolicy.trustStore* with value of `ca:acme-rockets,tsa:acme-tsa`.

`notary.signingAuthority.x509`

* Uses trusts store type Signing Authority during signature verification. The signature is verified against the trust store of type Signing Authority. The signing time is determined using the *Authentic Signing time* attribute in the signature envelope, and does not rely on a seperate TSA generated Timestamp signature.
* For signature verification to be successful
* The verifying entity’s trust store MUST contain the trusted root certificates under named trust stores of type CA (`{CONFIG}/notation/truststore/x509/signingAuthority`).
* The named trust stores MUST be specified in *trustpolicy.json*. E.g. *trustPolicy.trustStore* with value of `signingAuthority:foobar` .

## FAQ

*Q:* What is the relationship of Signing Scheme with Signature Envelope format?
*A:* Signing Scheme aims to be agnostic of the Signature Envelope format. A given signing scheme can be implemented through any signature envelope format (such as JWS or COSE) as long as it can support the required signature schema used by the signing scheme.

*Q:* Why trust store for Signing Authority (`x509/signingAuthority`) is distinct from trust store for Certificate Authority (`x509/ca`), why can’t they share the same trust store?
*A:* Signing Authority is a different type of trusted entity as compared to Certificate Authority (CA) or Timestamping Authority (TSA) which are much widely used. A CA is trusted for verifying the identity of a signing entity (end user) and issuing it a certificate, whereas a TSA is trusted to generate authentic timestamp. In contrast, an SA is trusted for generating signatures on behalf of a signing entity (end user) and also to generate authentic timestamp. If we use a shared trust store for CA and SA roots, an end user can self generate a signature with signing scheme `notary.signingAuthority.x509` and misrepresent themselves as a signing authority that would have ideally generated the signature. A verifying entity places certain trust in a signing authority - like the ability to generate authentic timestamp, and have uniform policies related to signature generation process, which aren't available when an end user generates a signature themselves.
gokarnm marked this conversation as resolved.
Show resolved Hide resolved

[ietf-rfc3161]: https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.2
Loading