---
# System prepended metadata

title: '[OLD] Signing and Verification Workflow'
tags: [notary]

---

# [OLD] Signing and Verification Workflow
:::danger
This is outdated and content has been moved to https://github.com/notaryproject/notaryproject/pull/122
:::


## Signing workflow

The user wants to sign a locally available OCI artifact and push it to a repository(along with signature).

### Prerequisite

- User has access to the signing certificate and private key.

### Steps

1. **Generate signature:** Using notation CLI or any other compliant signing tool, sign the OCI artifact. The signing tool should follow the following guideline.
    1. Verify that the signing certificate is valid and satisfies [certificate requirements](./signature-specification##certificate-requirements).
    1. Verify that the signing algorithm satisfies [algorithm requirements](./signature-specification#signature-algorithms).
    1. Generate signature.
        1. Generate signature using signature formats specified in [supported signature envelopes](./signature-specification#supported-signature-envelopes).
        1. Obtain an [RFC-3161](https://datatracker.ietf.org/doc/html/rfc3161.html) compliant timestamp for the signature generated in the previous step. This step is optional but recommended.
            1. Verify that the timestamp signing certificate satisfies [certificate requirements](./signature-specification##certificate-requirements).
            1. Verify that the timestamp signing algorithm satisfies [algorithm requirements](./signature-specification#signature-algorithms).
        1. Embed timestamp to the signature envelope.
1. **Push the signature envelope:** Push the signature envelope generated in the previous step to the repository.
1. **Generate signature artifact manifest:** As decribed in [signature specification](./signature-specification#storage) create the Notary v2 signature artifact manifest for the signature envelope generated in step 1.
3. **Push signature artifact manifest:** Push Notary v2 signature artifact manifest to the repository.


The user can push the OCI artifact to the repository before, after, or in between the signature generation process.

## Verification workflow

The user wants to pull OCI artifacts only if they are signed by the trusted publisher and the signature is valid.

### Prerequisites

- User has a digest of OCI artifact they want to download. If the user wants to use a tag to identify the artifact then that tag must be resolved to digest.
- User has configured [trust store and trust policy](./trust-store-trust-policy-specification.md) required for signature verification.

### Steps

1. **Get signature artifact descriptors:** Using the ORAS [Manifest Referrers API](https://github.com/oras-project/artifacts-spec/blob/main/manifest-referrers-api.md) download  Notary v2 signature artifact descriptors. The ORAS referrers API only needs artifact digest and artifact type(optional) as input. The Notary v2 signature's artifact type is `application/vnd.cncf.notary.v2.signature`.
1. **Get signature artifact manifests:** For each signature artifact descriptor, perform the following steps:
    1. **Get signature artifact manifests:** Download the Notary v2 signature's artifact manifests for the given artifact descriptor. 
    1. **Filter signature artifact manifests:**
        1. Based on the value of the `blobs->mediaType` attribute and supported signature envelope format, filter out signature manifests.
        1. Depending upon the trust-store configuration, further filter out signature manifests. why? How? **TBD**(See [signature filtering](https://hackmd.io/@pritesh/signature_filtering)).
    1. **Get and validate signatures:** On filtered Notary v2 signature artifact manifest, perform the following steps:
        1. Download the signature envelope.
        1. Validate the signature envelope using trust-store and trust-policy as mentioned in [signature evaluation](./trust-store-trust-policy-specification.md#signature-evaluation) section.
        1. If signature validation fails, skip the below steps and move to the next signature artifact descriptor(step 2.1). If all signature artifact manifests have already been processed, fail the signature verification and exit.
        1. If signature validation succeeds, compare the given digest with the signed digest present in the signature envelope's payload. If digests are equal, signature verification is considered successful. Otherwise, move to the next signature artifact descriptor(step 2.1). If all signature artifact manifests have already been processed, fail the signature verification and exit.
1. **Get OCI artifact:** Using the given digest, download the OCI artifact. This step is not in the purview of Notary v2.


---
:::info
Below sections will be copy-pasted in trust-store and trust-policy doc
:::

## Signature Evaluation

### Prerequisites

- User has configured trust-store and trust-policy.

### Steps

1. **Validate that the signature envelope format is supported.**
    1. Parse the signature envelope content based on the signature envelope type specified in the signature artifact manifest.
    1. Validate that the content type indicated by the `cty` property value of protected headers in the signature envelope is supported.
1. **Validate the signature envelope integrity.**
    1. Get the signing algorithm(hash+encryption) from the signing identity(such as a certificate) and validate that signing algorithm satisfies [algorithm requirements](./signature-specification#signature-algorithms)
    1. Get the public key from the signing identity and validate the signature envelope integrity using the public key and signing algorithm identified in the previous step.
1. **Validate the signature against trust policy and trust store.**
    1. Using the `scope` configured in trust policies, get the applicable trust policy. (Implementations might have this value precomputed, added it for completeness)
    1. For the applicable trust policy, **validate trust-store:**
        1. Validate that the signing certificate and certificate chain found in the signature envelope leads to a self-signed root and satisfies [certificate requirements](./signature-specification##certificate-requirements).
        1. For all the trust-stores configured in applicable trust-policy perform the following steps.
            1. Validate that certificate and certificate-chain lead to a trusted certificate configured in the `x509Certs` field of trust-store.
            1. If trust anchors are configured for the trust-store used in the previous step then verify that the attributes of the signing certificate match with the attributes configured in the `x509SigningCertAnchors` field of trust-store.
            1. If all of the above verification succeeds then continue to the next step else iterate over the next set of trust stores. If all of the trust stores have been evaluated then fail the signature validation and exit.
    1. **Validate trust policy:**
        1. If signature expiry is present in the signature envelope, using the local machine’s current time(in UTC) check whether the signature is expired or not. If the signature is not expired, continue to the next step. Otherwise, if `signatureExpiry` is set to `Enforce` then fail the signature validation and exit else log a warning and continue to the next step.
        1. Check for the timestamp in the signature envelope.
            1. If the timestamp exists, continue with the next step. Otherwise, store the local machine's current time(in  UTC) in variables `timeStampLowerLimit` and `timeStampUpperLimit` and continue with step 3.3.3.
            1. Validate that the timestamp hash in `TSTInfo.messageImprint` matches the hash of the signature to which the timestamp was applied.
            1. Validate that the timestamp signing certificate satisfies [certificate requirements](./signature-specification##certificate-requirements).
            1. Validate that the timestamp signing algorithm satisfies [algorithm requirements](./signature-specification#signature-algorithms).
            1. Validate the `signing-certificate`([RFC-2634](https://tools.ietf.org/html/rfc2634)) or `signing-certificate-v2`([RFC-5126](https://tools.ietf.org/html/rfc5126#section-5.7.3.2)) attribute.
            1. Check whether timestamping certificate and certificate chain are valid(not expired) or not. If timestamping certificate and certificate-chain are not expired, continue to the next step. Otherwise, if `timestampExpiry` in trust-policy is configured to `Enforce` then fail the signature validation and exit, else log a warning and continue to the next step.
            1. Validate that timestamp certificate and certificate chain leads to a trusted TSA certificate configured in trust policy.
            1. Validate timestamp certificate and certificate chain revocation status  using [certificate revocation evaluation](#certificate-revocation-evaluation) section as per `timestampRevocation` setting in trust-policy
            1. Retrieve the timestamp's generalized time from `TSTInfo.genTime`.
            1. Retrieve the timestamp's accuracy.  If the accuracy is explicitly specified in `TSTInfo.accuracy`, use that value.  If the accuracy is not explicitly specified and `TSTInfo.policy` is the baseline time-stamp policy([RFC-3628](https://tools.ietf.org/html/rfc3628#section-5.2)), use accuracy of 1 second.  Otherwise, use accuracy of 0.
            1. Calculate the timestamp range using the lower and upper limits per [RFC-3161 section 2.4.2](https://tools.ietf.org/html/rfc3161#section-2.4.2) and store the limits in variables `timeStampLowerLimit` and `timeStampUpperLimit`, respectively.
        1. Check that the time range from `timeStampLowerLimit` to `timeStampUpperLimit` timestamp is entirely within the certificate's validity period.  If the time range is entirely within the signing certificate and certificate chain's validity period, continue to the next step.  Otherwise, If `signingIdentityExpiry` in trust-policy is configured to `Enforce` then fail the signature validation and exit else log a warning and continue to the next step.
        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. If you have reached this step then treat the OCI artifact signature as a valid signature.

### Certificate Revocation Evaluation

If the certificate revocation trust-store setting is set to `skip`, skip the below steps. Otherwise, check for revocation status for certificate and certificate chain.
1. If the revocation status of any of the certificates cannot be determined(revocation unavailable) and  `signingIdentityRevocation` is set to either `enforceWithFailClose` or `warn` then log a warning and skip the below steps. Otherwise, fail the signature validation and exit.
1. If any of the certificates are revoked and `signingIdentityRevocation` is set to either `enforceWithFailOpen` or `enforceWithFailClose` then fail signature validation and exit else log a warning.


Starting from Root to leaf certificate, for each certificate in the certificate chain, perform the following steps to check its revocation status:

- If the certificate being validated doesn't include information OCSP or CRLs then no revocation check is performed and the certificate is considered valid(not revoked).
- If the certificate being validated includes either OCSP or CRL information, then the one which is present is used for revocation check.
- If both OCSP URLs and CDP URLs are present, then OCSP is preferred over CRLs. If revocation status cannot be determined using OCSP because of any reason such as unavailability then fallback to using CRLs for revocation check.

#### CRLs

There are two types of CRLs(per RFC 3280), Base CRLs and Delta CRls.

- **Base CRLs:** Contains the revocation status of all certificates that have been issued by a given CA. BaseCRLs are signed by the certificate issuing CAs.
- **Delta CRLs:** Contains only certificates that have changed status since the last base CRL was published. Delta CRLs are signed by the certificate issuing CAs.
- **Indirect CRLs:** Special Case in which BaseCRLs and Delta CRLs are not signed by the certificate issuing CAs, instead they are signed with a completely different certificate.

Notary v2 MUST support BaseCRLs and Delta CRLs. Notary v2 MAY support Indirect CRLs. Notary v2 supports only HTTP CRL URLs.

Implementations MAY add support for caching CRLs and OCSP response to improve availability, latency and avoid network overhead.

##### CRL Download

CRL download location(URL) can be obtained from the certificate's CRL Distribution Point(CDP) extension. If the certificate contains multiple CDP locations then each location download is attempted in sequential order. For each CDP location, NotaryV2 will try to download the CRL for the default threshold of 10 seconds. If the CRL cannot be downloaded within the timeout threshold the revocation result will be "revocation unavailable". The user may be able to configure this threshold.

##### Revocation Checking with CRL

To check the revocation status of a certificate against CRL, the following steps must be performed:

1. Verify the CRL signature.
1. Verify that the CRL is valid(not expired). A CRL is considered expired if the current date is after the `NextUpdate` field in the CRL.
1. Look up the certificate’s serial number in the CRL.
      1. If the certificate’s serial number is listed in the CRL, look for `InvalidityDate`. If the invalidity date is present and timestamp signature is also present then if the invalidity date is before the timestamping date, the certificate is considered revoked. If the invalidity date is not present in CRL, the certificate is considered revoked.
      1. If the CRL is expired and the certificate is listed in the CRL for any reason other than `certificate hold`, the certificate is considered revoked.
      1. If the certificate is not listed in the CRL or the revocation reason is `certificate hold`, a new CRL is retrieved if the current time is past the time in the `NextUpdate` field in the current CRL. The new CRL is then checked to determine if the certificate is revoked. If the original reason was `certificate hold`, the CRL is checked to determine if the certificate is unrevoked by looking for the `RemoveFromCRL` revocation code.

##### Revocation Checking with Delta CRLs

If a delta CRL exists for a base CRL, the `Freshest CRL` extension in the base CRL provides the URL from where the delta CRL can be downloaded. The delta CRLs have their identifying number, plus the "Delta CRL Indicator" extension indicating the version number of the base CRL that must be used with the delta CRL.

When delta CRLs are implemented, the following results can occur during revocation checking.
- If the delta CRL cannot be retrieved for some reason, the revocation result will be "revocation unavailable".
- If the delta CRL’s indicator is less than the current base CRL, the revocation result returned will be "revocation unavailable"
- To check revocation of a certificate in Delta CRLs follow steps similar to [Revocation Checking with CRL](#Revocation-Checking-with-CRL)

#### OCSP

##### OCSP Download

OCSP URLs can be obtained from the certificate's authority information access(AIA) extension as defined in [RFC-2560](https://datatracker.ietf.org/doc/html/rfc2560). Notary V2 will wait for a default threshold of 5 seconds to receive an OCSP response. If OCSP response is not available within the timeout threshold the revocation result will be "revocation unavailable". The user may be able to configure this threshold.

##### Revocation Checking with OCSP
To check the revocation status of a certificate using OCSP, the following steps must be performed.

1. Verify the signature of the OCSP response. This step also includes verifying the OSCP response signing certificate is valid and trusted. The OCSP signing certificate must be issued by the same CA as the certificate being verified or the OCSP response must be signed by the issuing CA.
2. Verify that the OCSP response is valid(not expired). A CRL is considered expired if the current date is after the `NextUpdate` field in the CRL.
3. Verify that the OCSP response indicates that the certificate is not revoked i.e `CertStatus` is `good`.
4. If `id-pkix-ocsp-nocheck`(1.3.6.1.5.5.7.48.1.5) extension is not present on the OCSP signing certificate then revocation checking must be performed using CRLs for the OCSP signing certificate.



:::info
Remove [trust-store and trust-policy evaluation diagram](https://github.com/notaryproject/notaryproject/blob/main/media/trust-store-trust-policy-evaluation.svg) as its no longer valid and its difficult to represent workflow with UML diagram.
:::

:::danger

- Now during verification, we are evaluating timestamp if present, irrespective of whether the signing certificate is expired or not. Is that fine? IMO if a user has added a timestamp to a signature they want the verification system to use that timestamp.
- As of now, we don't support multiple certificate chains leading to root. If there are multiple certificate chains leading to a trusted root, Notary V2 will randomly pick one.
  - With multiple certificate chains, we will need to validate each chain until we find a chain that is not revoked.
- Notary V2 doesn't support building certificate chain by retrieving certificates from locations specified in the authority information access extension.
:::

---

:::info
Below sections will be copy-pasted in signature-specification doc
:::

### Certificate Requirements

The signing certificate MUST meet the following minimum requirements:

- The certificate MUST be valid for the id-kp-codeSigning purpose([RFC-5280](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12)).
- The certificate MUST abide by the following key length restrictions:
  - For RSA public key, the key length MUST be 2048 bits or higher.
  - For ECDSA public key, the key length MUST be 256 bits or higher.

The timestamping certificate MUST meet the following minimum requirements:

- The certificate MUST be valid for the id-kp-timeStamping purpose([RFC-5280](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12)).
- The certificate MUST abide by the following key length restrictions:
  - For RSA public key, the key length MUST be 2048 bits or higher.
  - For ECDSA public key, the key length MUST be 256 bits or higher.

## Related Links

- [RFC 6960 - X.509 Internet Public Key Infrastructure Online Certificate Status Protocol - OCSP](https://datatracker.ietf.org/doc/html/rfc6960)
- [RFC 5280 - Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile](https://datatracker.ietf.org/doc/html/rfc5280)
- [Microsoft: Certificate Revocation and Status Checking](https://go.microsoft.com/fwlink/?LinkID=27081)

###### tags: `notary`