A service for issuing RFC 3161 timestamps.
Timestamps conform to the RFC 3628 policy. The timestamp structure conforms to the updates in RFC 5816.
Trusted timestamping is a process that has been around for some time. It provides a timestamp record of when a document 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.
Timestamps are a critical component of 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 or immutable. Using signed timestamps issued from timestamp authorities mitigates the risk of Rekor's clock being manipulated.
As a artifact signer, you can:
As an artifact verifier:
For usage within Sigstore, we recommend signing over a value that is associated with a signature. For Cosign, we have chosen to sign the artifact signature, a process called "countersigning". We sign over the raw signature bytes, not a base64-encoded value. Signing over the signature ensures that the signature, not the artifact, was created at a certain time.
Prerequisite: On macOS, we currently require the installation of openssl
.
brew install openssl
To launch the server, run either:
docker-compose up
make timestamp-server && ./bin/timestamp-server serve --port 3000
Both of these commands launch a server with an in-memory signing key and certificate chain. This should not be used for production.
To fetch a timestamp with the provided timestamp-cli
:
curl http://localhost:3000/api/v1/timestamp/certchain > ts_chain.pem
echo "myblob" > myblob
make timestamp-cli
./bin/timestamp-cli --timestamp_server http://localhost:3000 timestamp --hash sha256 --artifact myblob --out response.tsr
./bin/timestamp-cli verify --timestamp response.tsr --artifact "myblob" --certificate-chain ts_chain.pem --format json
./bin/timestamp-cli inspect --timestamp response.tsr --format json
To fetch a timestamp with openssl
and curl
:
curl http://localhost:3000/api/v1/timestamp/certchain > ts_chain.pem
csplit -s -f tmpcert- ts_chain.pem '/-----BEGIN CERTIFICATE-----/' '{*}'
brew install coreutils
, and use gcsplit
rm tmpcert-00
mv $(ls tmpcert-* | tail -1) root.crt.pem
cat tmpcert-* > chain.crts.pem
rm tmpcert-*
echo "myblob" > myblob
openssl ts -query -data myblob -cert -sha256 -out request.tsq
curl -sSH "Content-Type: application/timestamp-query" --data-binary @request.tsq http://localhost:3000/api/v1/timestamp -o response.tsr
openssl ts -verify -in response.tsr -data "myblob" -CAfile root.crt.pem -untrusted chain.crts.pem
-cert
will mandate the signing certificate
is included.openssl ts -reply -in response.tsr -text
If you would like to make a request for a timestamp using a JSON based request, you can do with:
curl -sSH "Content-Type: application/json" -d @request.json http://localhost:3000/api/v1/timestamp -o response.tsr
The service expects the JSON body to be in the shape:
{
"artifactHash": "<base64 encoded artifact hash>",
"certificates": true,
"hashAlgorithm": "sha256",
"nonce": 1123343434,
"tsaPolicyOID": "1.2.3.4"
}
The artifact hash must be represented as a base64 encoded string.
To deploy to production, the timestamp authority currently supports signing with Cloud KMS or 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. We do not recommend the file signer for production since the signing key will only be password protected.
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 used to generate the certificate chain if you do not want to use GCP. If you are using GCP:
go run cmd/fetch-tsa-certs/fetch_tsa_certs.go \
--intermediate-kms-resource="gcpkms://projects/<project>/locations/<region>/keyRings/<key-ring>/cryptoKeys/<key>/versions/1" \
--leaf-kms-resource="gcpkms://projects/<project>/locations/<region>/keyRings/<leaf-key-ring>/cryptoKeys/<key>/versions/1" \
--gcp-ca-parent="projects/<project>/locations/<region>/caPools/<ca-pool>" \
--output="chain.crt.pem"
If you are not using GCP, there are many possible options but the steps for setting up the certificates could be similar to the following:
timestamp_server
expects.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 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 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:
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 used to generate the certificate chain if you do not want to use GCP. If you are using GCP:
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/<project>/locations/<location>/caPools/<pool-name>"\
--tink-keyset-path="enc-keyset.cfg"\
--output="chain.crt.pem"
To run the TSA, set --timestamp-signer=tink
, --tink-key-resource=<path-to-kms-key>
, 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
.
Should you discover any security issues, please refer to Sigstore's security process.