diff --git a/README.md b/README.md index a44efb43..fa515326 100644 --- a/README.md +++ b/README.md @@ -4,16 +4,55 @@ A service for issuing [RFC 3161 timestamps](https://datatracker.ietf.org/doc/htm Timestamps conform to the [RFC 3628 policy](https://datatracker.ietf.org/doc/html/rfc3628). -### Prerequisites +## Security model -On MacOS, we currently require the installation of `openssl`. +[Trusted timestamping](https://en.wikipedia.org/wiki/Trusted_timestamping) is a process that has been around for some time. +It provides a timestamp record of when a documented was created or modified. + +A timestamp authority creates signed timestamps using public key infrastructure. The operator of the timestamp +authority must secure the signing key material to prevent unauthorized timestamp signing. + +A timestamp authority should also verify its own clock. We provide a configuration to periodically check the current +time against well-known NTP sources. + +## Timestamping within Sigstore + +Timestamps are a critical component of [Rekor](https://github.com/sigstore/rekor), Sigstore's signature transparency log. +Timestamps are used to verify short-lived certificates. Currently, the timestamp comes from Rekor's own internal clock, +which is not externally verifiable. Using signed timestamps issued from timestamp authorities mitigates the risk of +Rekor's clock being manipulated. + +As a artifact signer, you can: + +* Generate a signature over an artifact +* Fetch a timestamp for that signature (more below in "What to sign") +* Upload the signature, artifact hash, and certificate to Rekor (hashedrekord record type) +* Upload the timestamp to Rekor (rfc3161 record type) + * This step is important because it makes the timestamps publicly auditable + +As an artifact verifier: + +* Fetch the artifact entry from Rekor +* If the artifact was signed with a certificate, verify its expiration + * If you trust Rekor's clock, verify the certificate with the timestamp in the Rekor response + * If you trust an external timestamp authority, fetch the timestamp from Rekor, verify the + signed timestamp, and verify the certificate using the signed timestamp + +### What to sign + +For usage within Sigstore, we recommend signing over a value that is associated with an artifact. +For [Cosign](https://github.com/sigstore/cosign/), we have chosen to sign the artifact signature, +a process called "countersigning". We sign over the raw signature, not a base64-encoded value. Signing +over the signature ensures that the signature, not the artifact, was created a certain time. + +## Local development + +Prerequisite: On macOS, we currently require the installation of `openssl`. ```shell brew install openssl ``` -## Local development - To launch the server, run either: * `docker-compose up` * `make timestamp-server && ./bin/timestamp-server serve --port 3000` @@ -51,12 +90,74 @@ To fetch a timestamp with `openssl` and `curl`: ## Production deployment -To deploy to production, the timestamp authority currently supports signing with Cloud KMS. You will need to provide +To deploy to production, the timestamp authority currently supports signing with Cloud KMS or +[Tink](https://github.com/google/tink). You will need to provide a certificate chain (leaf, any intermediates, and root), where the certificate chain's purpose (extended key usage) is -for timestamping. +for timestamping. We do not recommend the file signer for production since the signing key will only be password protected. + +### Cloud KMS + +Create an asymmetric cloud KMS signing key in either GCP, AWS, Azure, or Vault, that will be used to sign timestamps. + +Generate a certificate chain, which must include a leaf certificate whose public key pairs to the private key +in cloud KMS, may include any number of intermediate certificates, and must include a root certificate. +We recommend reviewing the [code](https://github.com/sigstore/timestamp-authority/blob/main/cmd/fetch-tsa-certs/fetch_tsa_certs.go) +used to generate the certificate chain if you do not want to use GCP. If you are using GCP: +* Create a root CA with [GCP CA Service](https://cloud.google.com/certificate-authority-service). Configure lifetime, and other defaults + can remain. You will need to first create a CA pool, and then create one CA in that pool. +* Create an asymmetric signing key on KMS that will be used as an intermediate CA to sign the TSA certificate. +* Run the following: + +```shell +go run cmd/fetch-tsa-certs/fetch_tsa_certs.go \ + --intermediate-kms-resource="gcpkms://projects//locations//keyRings//cryptoKeys//versions/1" \ + --leaf-kms-resource="gcpkms://projects//locations//keyRings//cryptoKeys//versions/1" \ + --gcp-ca-parent="projects//locations//caPools/" \ + --output="chain.crt.pem" +``` + +Set `--timestamp-signer=kms`, provide the path to the chain with `--certificate-chain-path`, +and the KMS key with `--kms-key-resource`. The key should be prefixed with either `gcpkms://`, `azurekms://`, `awskms://`, or `hashivault://`. + +### Tink + +[Tink](https://github.com/google/tink) is an easy-to-use cross-language crypto library. +The timestamp authority provides a signer that uses Tink, which enables in-memory signing +with secure on-disk key storage. Instead of being password-protected, the key is encrypted +with a cloud KMS key, and decrypted on startup. + +Install [tinkey](https://github.com/google/tink/blob/master/docs/TINKEY.md) first. + +Create a symmetric cloud KMS key in either GCP, AWS, or Vault, that will be used to encrypt a +signing key that is generated locally. + +Run the following to create the local encrypted signing key, changing key URI and the key template if desired: + +```shell +tinkey create-keyset --key-template ECDSA_P384 --out enc-keyset.cfg --master-key-uri gcp-kms://path-to-key +``` + +Generate a certificate chain, which must include a leaf certificate whose public key pairs to the private key +in the Tink keyset, may include any number of intermediate certificates, and must include a root certificate. +We recommend reviewing the [code](https://github.com/sigstore/timestamp-authority/blob/main/cmd/fetch-tsa-certs/fetch_tsa_certs.go) +used to generate the certificate chain if you do not want to use GCP. If you are using GCP: +* Create a root CA with [GCP CA Service](https://cloud.google.com/certificate-authority-service). Configure lifetime, and other defaults + can remain. You will need to first create a CA pool, and then create one CA in that pool. +* Create an asymmetric signing key on KMS that will be used as an intermediate CA to sign the TSA certificate. +* Run the following: + +```shell +go run cmd/fetch-tsa-certs/fetch_tsa_certs.go \ + --intermediate-kms-resource="gcpkms://asymmetric-kms-key"\ + --tink-kms-resource="gcp-kms://tink-encryption-key"\ + --gcp-ca-parent="projects//locations//caPools/"\ + --tink-keyset-path="enc-keyset.cfg"\ + --output="chain.crt.pem" +``` -Provide the path to the chain with `certificate-chain-path`, and the KMS key with `timestamp-signer`. The key should be prefixed -with either `gcpkms://`, `azurekms://`, `awskms://`, or `hashivault://`. +To run the TSA, set `--timestamp-signer=tink`, `--tink-key-resource=`, and +`--tink-keyset-path=enc-keyset.cfg`. The key resource should be prefixed with either `gcp-kms://`, `aws-kms://`, or `hcvault://`. +If using Vault, you may also set `--tink-hcvault-token`. Provide the path to the chain with `--certificate-chain-path`. ## Security