...

Text file src/github.com/sigstore/timestamp-authority/README.md

Documentation: github.com/sigstore/timestamp-authority

     1[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/sigstore/timestamp-authority/badge)](https://api.securityscorecards.dev/projects/github.com/sigstore/timestamp-authority)
     2
     3# Sigstore Timestamp Authority
     4
     5A service for issuing [RFC 3161 timestamps](https://datatracker.ietf.org/doc/html/rfc3161).
     6
     7Timestamps conform to the [RFC 3628 policy](https://datatracker.ietf.org/doc/html/rfc3628).
     8The timestamp structure conforms to the updates in [RFC 5816](https://datatracker.ietf.org/doc/rfc5816).
     9
    10## Security model
    11
    12[Trusted timestamping](https://en.wikipedia.org/wiki/Trusted_timestamping) is a process that has been around for some time.
    13It provides a timestamp record of when a document was created or modified.
    14
    15A timestamp authority creates signed timestamps using public key infrastructure. The operator of the timestamp
    16authority must secure the signing key material to prevent unauthorized timestamp signing.
    17
    18A timestamp authority should also verify its own clock. We provide a configuration to periodically check the current
    19time against well-known NTP sources.
    20
    21## Timestamping within Sigstore
    22
    23Timestamps are a critical component of [Rekor](https://github.com/sigstore/rekor), Sigstore's signature transparency log.
    24Timestamps are used to verify short-lived certificates. Currently, the timestamp comes from Rekor's own internal clock,
    25which is not externally verifiable or immutable. Using signed timestamps issued from timestamp authorities mitigates the risk of
    26Rekor's clock being manipulated.
    27
    28As a artifact signer, you can:
    29
    30* Generate a signature over an artifact
    31* Fetch a timestamp for that signature (more below in [What to sign](#what-to-sign))
    32* Upload the signature, artifact hash, and certificate to Rekor (hashedrekord record type)
    33* Upload the timestamp to Rekor (rfc3161 record type)
    34   * This step is important because it makes the timestamps publicly auditable
    35
    36As an artifact verifier:
    37
    38* Fetch the artifact entry from Rekor
    39* If the artifact was signed with a certificate, verify its expiration
    40   * If you trust Rekor's clock, verify the certificate with the timestamp in the Rekor response
    41   * If you trust an external timestamp authority, fetch the timestamp from Rekor, verify the
    42     signed timestamp, and verify the certificate using the signed timestamp
    43
    44### What to sign
    45
    46For usage within Sigstore, we recommend signing over a value that is associated with a signature.
    47For [Cosign](https://github.com/sigstore/cosign/), we have chosen to sign the artifact signature,
    48a process called "countersigning". We sign over the raw signature bytes, not a base64-encoded value. Signing
    49over the signature ensures that the signature, not the artifact, was created at a certain time.
    50
    51## Local development
    52
    53Prerequisite: On macOS, we currently require the installation of `openssl`.
    54
    55```shell
    56brew install openssl
    57```
    58
    59To launch the server, run either:
    60* `docker-compose up`
    61* `make timestamp-server && ./bin/timestamp-server serve --port 3000`
    62
    63Both of these commands launch a server with an in-memory signing key and certificate chain. **This should not
    64be used for production.**
    65
    66To fetch a timestamp with the provided `timestamp-cli`:
    67
    681. Retrieve the verification chain: `curl http://localhost:3000/api/v1/timestamp/certchain > ts_chain.pem`
    691. Create test blob to sign: `echo "myblob" > myblob`
    701. Build client: `make timestamp-cli`
    711. Fetch timestamp: `./bin/timestamp-cli --timestamp_server http://localhost:3000 timestamp --hash sha256 --artifact myblob --out response.tsr`
    721. Verify timestamp: `./bin/timestamp-cli verify --timestamp response.tsr --artifact "myblob" --certificate-chain ts_chain.pem --format json`
    731. Inspect timestamp: `./bin/timestamp-cli inspect --timestamp response.tsr --format json`
    74
    75To fetch a timestamp with `openssl` and `curl`:
    76
    771. Retrieve the verification chain: `curl http://localhost:3000/api/v1/timestamp/certchain > ts_chain.pem`
    781. Split chain into root CA certificate and "untrusted" intermediate and leaf certificates:
    79   1. Split: `csplit -s -f tmpcert- ts_chain.pem '/-----BEGIN CERTIFICATE-----/' '{*}'`
    80      * Note, on macOS, you will need to install GNU utilities with `brew install coreutils`, and use `gcsplit`
    81   1. Remove empty file: `rm tmpcert-00`
    82   1. Get root: `mv $(ls tmpcert-* | tail -1) root.crt.pem`
    83   1. Merge remaining certificates: `cat tmpcert-* > chain.crts.pem`
    84   1. Remove temp files: `rm tmpcert-*`
    851. Create test blob to sign: `echo "myblob" > myblob`
    861. Create timestamp request: `openssl ts -query -data myblob -cert -sha256 -out request.tsq`
    871. Fetch timestamp: `curl -sSH "Content-Type: application/timestamp-query" --data-binary @request.tsq http://localhost:3000/api/v1/timestamp -o response.tsr`
    881. Verify timestamp: `openssl ts -verify -in response.tsr -data "myblob" -CAfile root.crt.pem -untrusted chain.crts.pem`
    89   * Note that you will see a warning that one certificate is "not a CA cert", but this is expected, as you need to provide the TSA signing certificate
    90     in case the certificate is not included in the response. When generating the timestamp query, setting `-cert` will mandate the signing certificate
    91     is included.
    921. Inspect timestamp: `openssl ts -reply -in response.tsr -text`
    93
    94### Making a request with JSON
    95
    96If you would like to make a request for a timestamp using a JSON based request, you can do with:
    97
    98`curl -sSH "Content-Type: application/json" -d @request.json http://localhost:3000/api/v1/timestamp -o response.tsr`
    99
   100The service expects the JSON body to be in the shape:
   101
   102```
   103{
   104  "artifactHash": "<base64 encoded artifact hash>",
   105  "certificates": true,
   106  "hashAlgorithm": "sha256",
   107  "nonce": 1123343434,
   108  "tsaPolicyOID": "1.2.3.4"
   109}
   110```
   111
   112The artifact hash must be represented as a base64 encoded string.
   113
   114## Production deployment
   115
   116To deploy to production, the timestamp authority currently supports signing with Cloud KMS or
   117[Tink](https://github.com/google/tink). You will need to provide
   118a certificate chain (leaf, any intermediates, and root), where the certificate chain's purpose (extended key usage) is
   119for timestamping. We do not recommend the file signer for production since the signing key will only be password protected.
   120
   121### Cloud KMS
   122
   123Create an asymmetric cloud KMS signing key in either GCP, AWS, Azure, or Vault, that will be used to sign timestamps.
   124
   125Generate a certificate chain, which must include a leaf certificate whose public key pairs to the private key
   126in cloud KMS, may include any number of intermediate certificates, and must include a root certificate.
   127We recommend reviewing the [code](https://github.com/sigstore/timestamp-authority/blob/main/cmd/fetch-tsa-certs/fetch_tsa_certs.go)
   128used to generate the certificate chain if you do not want to use GCP. If you are using GCP:
   129* Create a root CA with [GCP CA Service](https://cloud.google.com/certificate-authority-service). Configure lifetime, and other defaults
   130  can remain. You will need to first create a CA pool, and then create one CA in that pool.
   131* Create an asymmetric signing key on KMS that will be used as an intermediate CA to sign the TSA certificate.
   132* Run the following:
   133
   134```shell
   135go run cmd/fetch-tsa-certs/fetch_tsa_certs.go \
   136  --intermediate-kms-resource="gcpkms://projects/<project>/locations/<region>/keyRings/<key-ring>/cryptoKeys/<key>/versions/1" \
   137  --leaf-kms-resource="gcpkms://projects/<project>/locations/<region>/keyRings/<leaf-key-ring>/cryptoKeys/<key>/versions/1" \
   138  --gcp-ca-parent="projects/<project>/locations/<region>/caPools/<ca-pool>" \
   139  --output="chain.crt.pem"
   140```
   141If you are not using GCP, there are many possible options but the steps for setting up the certificates could be similar to the following:
   142* create a KMS private key (for example, in the AWS KMS)
   143* use this private key to create a CSR
   144* assuming you have an external (for example, corporate etc.) Certificate Authority entity
   145that can sign the CSR, make it sign the generated CSR and produce a certificate.  Make
   146sure that the leaf certificate - the one that will be used to sign timestamping requests -
   147has the Timestamping EKU (Extended Key Usage) set and it is marked as Critical.
   148* if necessary, combine the CA, intermediate and leaf certificates into the certificate chain file.  Verify the certificate chain format with [VerifyCertChain](https://github.com/sigstore/timestamp-authority/blob/main/pkg/x509/x509.go#L35) to ensure it is compatible with
   149what the `timestamp_server` expects.
   150
   151Set `--timestamp-signer=kms`, provide the path to the chain with `--certificate-chain-path`,
   152and the KMS key with `--kms-key-resource`. The key should be prefixed with either `gcpkms://`, `azurekms://`, `awskms://`, or `hashivault://`.
   153
   154### Tink
   155
   156[Tink](https://github.com/google/tink) is an easy-to-use cross-language crypto library.
   157The timestamp authority provides a signer that uses Tink, which enables in-memory signing
   158with secure on-disk key storage. Instead of being password-protected, the key is encrypted
   159with a cloud KMS key, and decrypted on startup.
   160
   161Install [tinkey](https://github.com/google/tink/blob/master/docs/TINKEY.md) first.
   162
   163Create a symmetric cloud KMS key in either GCP, AWS, or Vault, that will be used to encrypt a
   164signing key that is generated locally.
   165
   166Run the following to create the local encrypted signing key, changing key URI and the key template if desired:
   167
   168```shell
   169tinkey create-keyset --key-template ECDSA_P384 --out enc-keyset.cfg --master-key-uri gcp-kms://path-to-key
   170```
   171
   172Generate a certificate chain, which must include a leaf certificate whose public key pairs to the private key
   173in the Tink keyset, may include any number of intermediate certificates, and must include a root certificate.
   174We recommend reviewing the [code](https://github.com/sigstore/timestamp-authority/blob/main/cmd/fetch-tsa-certs/fetch_tsa_certs.go)
   175used to generate the certificate chain if you do not want to use GCP. If you are using GCP:
   176* Create a root CA with [GCP CA Service](https://cloud.google.com/certificate-authority-service). Configure lifetime, and other defaults
   177  can remain. You will need to first create a CA pool, and then create one CA in that pool.
   178* Create an asymmetric signing key on KMS that will be used as an intermediate CA to sign the TSA certificate.
   179* Run the following:
   180
   181```shell
   182go run cmd/fetch-tsa-certs/fetch_tsa_certs.go \
   183  --intermediate-kms-resource="gcpkms://asymmetric-kms-key"\
   184  --tink-kms-resource="gcp-kms://tink-encryption-key"\
   185  --gcp-ca-parent="projects/<project>/locations/<location>/caPools/<pool-name>"\
   186  --tink-keyset-path="enc-keyset.cfg"\
   187  --output="chain.crt.pem"
   188```
   189
   190To run the TSA, set `--timestamp-signer=tink`, `--tink-key-resource=<path-to-kms-key>`, and
   191`--tink-keyset-path=enc-keyset.cfg`. The key resource should be prefixed with either `gcp-kms://`, `aws-kms://`, or `hcvault://`.
   192If using Vault, you may also set `--tink-hcvault-token`. Provide the path to the chain with `--certificate-chain-path`.
   193
   194## Security
   195
   196Should you discover any security issues, please refer to Sigstore's [security
   197process](https://github.com/sigstore/.github/blob/main/SECURITY.md).

View as plain text