Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Add Docs
Sigstore Timestamp Authority
https://github.com/sigstore/timestamp-authority
Admin
A service for issuing RFC 3161 timestamps that conform to relevant RFC policies, crucial for
...
Tokens:
16,678
Snippets:
124
Trust Score:
8.4
Update:
3 months ago
Context
Skills
Chat
Benchmark
70.5
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Sigstore Timestamp Authority Sigstore Timestamp Authority is a service for issuing RFC 3161 compliant timestamps. It provides cryptographic proof that a document or signature existed at a specific point in time by creating signed timestamps using public key infrastructure. The service supports multiple signing backends including Cloud KMS providers (GCP, AWS, Azure, HashiCorp Vault) and Tink for secure key management, with optional NTP monitoring to verify clock accuracy. The timestamp authority is a critical component in the Sigstore ecosystem, primarily used with Rekor (Sigstore's signature transparency log) to verify short-lived certificates. By providing externally verifiable and immutable timestamps, it mitigates risks associated with clock manipulation. The authority conforms to RFC 3628 policy and RFC 5816 timestamp structure updates, supporting SHA-256, SHA-384, and SHA-512 hash algorithms while rejecting weak algorithms like SHA-1. ## REST API ### POST /api/v1/timestamp - Request a Timestamp Creates a signed RFC 3161 timestamp response for an artifact hash. Accepts either DER-encoded timestamp query or JSON format requests. ```bash # Using DER-encoded timestamp query with openssl 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 # Using JSON format request cat > request.json << 'EOF' { "artifactHash": "n4bQgYhMfWWaL-qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=", "certificates": true, "hashAlgorithm": "sha256", "nonce": 1123343434, "tsaPolicyOID": "1.3.6.1.4.1.57264.2" } EOF curl -sSH "Content-Type: application/json" \ -d @request.json \ http://localhost:3000/api/v1/timestamp \ -o response.tsr # Response: Binary timestamp response (application/timestamp-reply) # HTTP 200 or 201 depending on server configuration ``` ### GET /api/v1/timestamp/certchain - Get Certificate Chain Retrieves the PEM-encoded certificate chain used to validate timestamps issued by this authority. ```bash # Fetch the certificate chain curl http://localhost:3000/api/v1/timestamp/certchain > ts_chain.pem # Response: PEM-encoded certificate chain # -----BEGIN CERTIFICATE----- # MIIBxjCCAWygAwIBAgIUQ... # -----END CERTIFICATE----- # -----BEGIN CERTIFICATE----- # MIIBxDCCAWqgAwIBAgIUA... # -----END CERTIFICATE----- # Split chain for verification (leaf, intermediates, root) csplit -s -f tmpcert- ts_chain.pem '/-----BEGIN CERTIFICATE-----/' '{*}' rm tmpcert-00 mv $(ls tmpcert-* | tail -1) root.crt.pem cat tmpcert-* > chain.crts.pem rm tmpcert-* ``` ## Go Client Library ### GetTimestampClient - Create API Client Creates a timestamp authority client with optional configuration for user agent and content type headers. ```go package main import ( "bytes" "crypto" "fmt" "io" "os" "github.com/digitorus/timestamp" "github.com/sigstore/sigstore/pkg/cryptoutils" "github.com/sigstore/timestamp-authority/v2/pkg/client" ts "github.com/sigstore/timestamp-authority/v2/pkg/generated/client/timestamp" ) func main() { // Create client with custom options tsClient, err := client.GetTimestampClient( "http://localhost:3000", client.WithUserAgent("my-app/1.0"), client.WithContentType(client.TimestampQueryMediaType), ) if err != nil { panic(err) } // Read artifact to timestamp artifactBytes, _ := os.ReadFile("myblob") // Generate nonce for replay protection nonce, _ := cryptoutils.GenerateSerialNumber() // Create timestamp request reqOpts := ×tamp.RequestOptions{ Hash: crypto.SHA256, Certificates: true, Nonce: nonce, } requestBytes, _ := timestamp.CreateRequest(bytes.NewReader(artifactBytes), reqOpts) // Send request params := ts.NewGetTimestampResponseParams() params.Request = io.NopCloser(bytes.NewReader(requestBytes)) var respBytes bytes.Buffer _, _, err = tsClient.Timestamp.GetTimestampResponse(params, &respBytes) if err != nil { panic(err) } // Parse and validate response tsResp, _ := timestamp.ParseResponse(respBytes.Bytes()) fmt.Printf("Timestamp: %v\n", tsResp.Time) // Save response os.WriteFile("response.tsr", respBytes.Bytes(), 0600) } ``` ## Verification Library ### VerifyTimestampResponse - Verify Timestamp Response Verifies a timestamp response against an artifact using a certificate chain. Validates signature, certificate chain, nonce, OID, and hash. ```go package main import ( "fmt" "os" "github.com/sigstore/sigstore/pkg/cryptoutils" "github.com/sigstore/timestamp-authority/v2/pkg/verification" ) func main() { // Read timestamp response tsrBytes, _ := os.ReadFile("response.tsr") // Open artifact for verification artifact, _ := os.Open("myblob") defer artifact.Close() // Read certificate chain pemBytes, _ := os.ReadFile("ts_chain.pem") certs, _ := cryptoutils.UnmarshalCertificatesFromPEM(pemBytes) // Split into intermediates and root intermediateCerts := certs[0 : len(certs)-1] rootCerts := []*x509.Certificate{certs[len(certs)-1]} // Configure verification options opts := verification.VerifyOpts{ Roots: rootCerts, Intermediates: intermediateCerts, // Optional: verify specific nonce was used // Nonce: expectedNonce, // Optional: verify specific OID // OID: []int{1, 3, 6, 1, 4, 1, 57264, 2}, // Optional: verify certificate common name // CommonName: "sigstore-tsa", } // Verify timestamp ts, err := verification.VerifyTimestampResponse(tsrBytes, artifact, opts) if err != nil { panic(fmt.Sprintf("verification failed: %v", err)) } fmt.Printf("Verified timestamp: %v\n", ts.Time) fmt.Printf("Hash algorithm: %v\n", ts.HashAlgorithm) fmt.Printf("Policy OID: %v\n", ts.Policy) } ``` ### VerifyRequest - Validate Timestamp Request Validates a timestamp request before processing, checking hash algorithm strength and digest length consistency. ```go package main import ( "crypto" "fmt" "github.com/digitorus/timestamp" "github.com/sigstore/timestamp-authority/v2/pkg/verification" ) func main() { // Create a timestamp request to validate req := ×tamp.Request{ HashAlgorithm: crypto.SHA256, HashedMessage: []byte{/* 32 bytes for SHA-256 */}, Certificates: true, } // Verify the request err := verification.VerifyRequest(req) if err != nil { switch { case errors.Is(err, verification.ErrWeakHashAlg): fmt.Println("Error: SHA-1 is not allowed") case errors.Is(err, verification.ErrUnsupportedHashAlg): fmt.Println("Error: Unsupported hash algorithm") case errors.Is(err, verification.ErrInconsistentDigestLength): fmt.Println("Error: Digest length doesn't match algorithm") default: fmt.Printf("Error: %v\n", err) } return } fmt.Println("Request is valid") } ``` ## CLI Tools ### timestamp-cli timestamp - Fetch Signed Timestamp Fetches an RFC 3161 signed timestamp for an artifact from a timestamp authority server. ```bash # Build CLI make timestamp-cli # Create test artifact echo "my important data" > artifact.txt # Fetch timestamp with default options (SHA-256, nonce enabled) ./bin/timestamp-cli \ --timestamp_server http://localhost:3000 \ timestamp \ --artifact artifact.txt \ --out timestamp.tsr # Fetch timestamp with specific options ./bin/timestamp-cli \ --timestamp_server http://localhost:3000 \ timestamp \ --artifact artifact.txt \ --hash sha384 \ --nonce=true \ --certificate=true \ --tsa-policy "1.3.6.1.4.1.57264.2" \ --out timestamp.tsr # Output: # Generating a new signed timestamp # Artifact timestamped at 2024-01-15 10:30:45.123456789 +0000 UTC # Wrote timestamp response to timestamp.tsr ``` ### timestamp-cli verify - Verify Timestamp Verifies a timestamp response against an artifact using a certificate chain. ```bash # Verify using certificate chain file ./bin/timestamp-cli verify \ --artifact artifact.txt \ --timestamp timestamp.tsr \ --certificate-chain ts_chain.pem \ --format json # Verify with separate root and intermediate certificates ./bin/timestamp-cli verify \ --artifact artifact.txt \ --timestamp timestamp.tsr \ --root-certificates root.crt.pem \ --intermediate-certificates intermediate.crt.pem # Verify with additional options ./bin/timestamp-cli verify \ --artifact artifact.txt \ --timestamp timestamp.tsr \ --certificate-chain ts_chain.pem \ --nonce "12345678901234567890" \ --oid "1.3.6.1.4.1.57264.2" \ --common-name "sigstore-tsa" # Output (JSON format): # { # "TimestampPath": "timestamp.tsr", # "ParsedTimestamp": { # "Time": "2024-01-15T10:30:45Z", # "HashAlgorithm": 5, # "HashedMessage": "base64==..." # } # } ``` ### timestamp-cli inspect - Inspect Timestamp Response Parses and displays the contents of a timestamp response file. ```bash ./bin/timestamp-cli inspect \ --timestamp timestamp.tsr \ --format json # Output: # { # "TimestampResponse": { # "Time": "2024-01-15T10:30:45.123456789Z", # "HashAlgorithm": 5, # "HashedMessage": "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=", # "SerialNumber": 1234567890, # "Policy": [1,3,6,1,4,1,57264,2], # "Ordering": false, # "Nonce": 9876543210, # "Accuracy": 1000000000, # "Qualified": false, # "Certificates": [...] # } # } ``` ### timestamp-server serve - Start Server Starts the timestamp authority HTTP server with configurable signing backend and NTP monitoring. ```bash # Build server make timestamp-server # Start with in-memory signer (development only) ./bin/timestamp-server serve --port 3000 # Start with KMS signer (production) ./bin/timestamp-server serve \ --port 3000 \ --timestamp-signer kms \ --kms-key-resource "gcpkms://projects/myproj/locations/us/keyRings/ring/cryptoKeys/key/versions/1" \ --certificate-chain-path chain.crt.pem # Start with Tink signer ./bin/timestamp-server serve \ --port 3000 \ --timestamp-signer tink \ --tink-key-resource "gcp-kms://projects/myproj/locations/us/keyRings/ring/cryptoKeys/kek" \ --tink-keyset-path enc-keyset.cfg \ --certificate-chain-path chain.crt.pem # Full production configuration ./bin/timestamp-server serve \ --host 0.0.0.0 \ --port 3000 \ --scheme https \ --timestamp-signer kms \ --kms-key-resource "gcpkms://..." \ --certificate-chain-path chain.crt.pem \ --ntp-monitoring /path/to/ntp-config.yaml \ --enable-pprof=false \ --log-type prod ``` ## Certificate Generation ### fetch-tsa-certs - Generate Certificate Chain Generates an RFC 3161 compliant certificate chain for the timestamp authority using KMS keys and optional CA service. ```bash # Create certificate chain with GCP CA Service (root) and KMS keys go run cmd/fetch-tsa-certs/fetch_tsa_certs.go \ --leaf-kms-resource="gcpkms://projects/myproj/locations/us/keyRings/ring/cryptoKeys/tsa-leaf/versions/1" \ --parent-kms-resource="gcpkms://projects/myproj/locations/us/keyRings/ring/cryptoKeys/intermediate/versions/1" \ --gcp-ca-parent="projects/myproj/locations/us/caPools/tsa-pool" \ --org-name="example.com" \ --output="chain.crt.pem" # Create self-signed certificate chain (no CA service) go run cmd/fetch-tsa-certs/fetch_tsa_certs.go \ --leaf-kms-resource="gcpkms://projects/myproj/locations/us/keyRings/ring/cryptoKeys/tsa-leaf/versions/1" \ --parent-kms-resource="gcpkms://projects/myproj/locations/us/keyRings/ring/cryptoKeys/parent/versions/1" \ --parent-validity=365 \ --org-name="example.com" \ --output="chain.crt.pem" # Create chain with Tink encrypted keyset tinkey create-keyset \ --key-template ECDSA_P384 \ --out enc-keyset.cfg \ --master-key-uri "gcp-kms://projects/myproj/locations/us/keyRings/ring/cryptoKeys/kek" go run cmd/fetch-tsa-certs/fetch_tsa_certs.go \ --tink-kms-resource="gcp-kms://projects/myproj/locations/us/keyRings/ring/cryptoKeys/kek" \ --tink-keyset-path="enc-keyset.cfg" \ --parent-kms-resource="gcpkms://projects/myproj/locations/us/keyRings/ring/cryptoKeys/intermediate/versions/1" \ --gcp-ca-parent="projects/myproj/locations/us/caPools/tsa-pool" \ --org-name="example.com" \ --output="chain.crt.pem" ``` ## Signer Configuration ### NewCryptoSigner - Create Signing Backend Creates a crypto signer for the timestamp authority supporting memory, file, KMS, and Tink backends. ```go package main import ( "context" "crypto" "github.com/sigstore/timestamp-authority/v2/pkg/signer" ) func main() { ctx := context.Background() // Memory signer (development only - generates ephemeral key) memSigner, _ := signer.NewCryptoSigner(ctx, crypto.SHA256, signer.MemoryScheme, "", "", "", "", "", "") // File signer (password-protected key file) fileSigner, _ := signer.NewCryptoSigner(ctx, crypto.SHA256, signer.FileScheme, "", "", "", "", "/path/to/key.pem", "password") // KMS signer (GCP, AWS, Azure, or HashiCorp Vault) kmsSigner, _ := signer.NewCryptoSigner(ctx, crypto.SHA256, signer.KMSScheme, "gcpkms://projects/myproj/locations/us/keyRings/ring/cryptoKeys/key/versions/1", "", "", "", "", "") // AWS KMS awsSigner, _ := signer.NewCryptoSigner(ctx, crypto.SHA256, signer.KMSScheme, "awskms:///arn:aws:kms:us-east-1:123456789:key/12345678-1234-1234-1234-123456789012", "", "", "", "", "") // Tink signer (encrypted keyset with KMS KEK) tinkSigner, _ := signer.NewCryptoSigner(ctx, crypto.SHA256, signer.TinkScheme, "", "gcp-kms://projects/myproj/locations/us/keyRings/ring/cryptoKeys/kek", "enc-keyset.cfg", "", "", "") // Use signer... _ = memSigner _ = fileSigner _ = kmsSigner _ = awsSigner _ = tinkSigner } ``` ## Docker Deployment ### docker-compose - Local Development Setup Runs the timestamp authority with an in-memory signer for local development and testing. ```yaml # docker-compose.yml version: '3' services: timestamp-server: build: . ports: - "3000:3000" command: serve --port 3000 # Start with docker-compose docker-compose up # Test the service curl http://localhost:3000/api/v1/timestamp/certchain ``` ## Summary The Sigstore Timestamp Authority serves as a trusted timestamping service primarily designed for integration with the Sigstore ecosystem, particularly Rekor. It enables artifact signers to obtain cryptographic proof of when signatures were created, which is essential for verifying short-lived certificates. The service supports production deployments with enterprise-grade KMS integrations (GCP, AWS, Azure, HashiCorp Vault) and can be configured with NTP monitoring to ensure clock accuracy within acceptable thresholds. Common integration patterns include using the Go client library to programmatically request and verify timestamps, deploying the server with Cloud KMS for production signing operations, and integrating with CI/CD pipelines to timestamp build artifacts and signatures. The CLI tools provide a complete workflow for fetching, verifying, and inspecting timestamps, while the verification library enables embedding timestamp validation directly into Go applications. For Sigstore users, the typical workflow involves generating a signature, fetching a timestamp for that signature, and uploading both to Rekor for public auditability.