To ensure the integrity and authenticity of the metadata at a specific point in time, a trusted timestamp must be applied to the metadata signature. This process, known as Timestamp Authority (TSA) confirmation, provides cryptographic proof that the data existed before a given time.
Overview
TSA signatures serve critical functions in CommonsDB:
Temporal Proof : Demonstrates when the declaration was made
Integrity : Ensures the data hasn't been modified after timestamping
Non-repudiation : Provides irrefutable proof of timing
Compliance : Meets regulatory requirements for timestamped declarations
What is a Timestamp Authority?
A Timestamp Authority (TSA) is a trusted third party that provides cryptographic timestamps. These services use RFC 3161 standard to create tamper-evident timestamps that can be verified independently.
Free TSA Service : CommonsDB documentation references FreeTSA.org as an example service. This is a free, public TSA service that can be used for testing and development purposes.
Prerequisites
Before creating TSA signatures, ensure you have:
Required Tools ✓ OpenSSL installed ✓ curl or similar HTTP client ✓ Access to a TSA service ✓ Your metadata JSON prepared Previous Steps ✓ Certificate signature created ✓ Metadata properly formatted ✓ .well-known/did.json deployed ✓ Understanding of the metadata structure
The TSA Signing Process
Step 1: Prepare Your Data
First, prepare your metadata in JSON format. This should be the same metadata used for certificate signing:
echo -n '{"data": "your json here"}' > data.json
Example with real metadata:
echo -n '{
"signature": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImp3ayI6e319.payload.signature",
"declarationMetadata": {
"publicMetadata": {
"$schema": "https://w3id.org/commonsdb/schema/0.2.0.json",
"@context": "https://w3id.org/commonsdb/context/0.2.0.json",
"iscc": "ISCC:KEC2EHPLVKPVDFVORULRVCUFXL3DZ4SA6JSDQLNOXEVYYCXR4N5IBDY",
"name": "Example Content",
"description": "Sample content description",
"mediatype": "image/jpeg",
"timestamp": 1736251200000,
"declarerId": "did:web:example.com",
"credentials": [],
"supplierMetadata": {
"rightsStatement": "https://creativecommons.org/publicdomain/mark/1.0/",
"location": "https://europeana.eu/item/123",
"creator": "John Doe"
}
},
"commonsDbRegistry": {
"iscc": "ISCC:KEC2EHPLVKPVDFVORULRVCUFXL3DZ4SA6JSDQLNOXEVYYCXR4N5IBDY",
"location": "https://europeana.eu/item/123",
"rightsStatement": "https://creativecommons.org/publicdomain/mark/1.0/",
"timestamp": 1736251200000,
"credentials": [{"proof": "eyJhbGciOiJFUzI1NiJ9..."}]
}
}
}' > data.json
Step 2: Create the Timestamp Request
Generate a hash of your data and create a timestamp request:
openssl dgst -sha256 -binary data.json | openssl ts -query -sha256 -no_nonce -out request.tsq
This command:
Creates a SHA-256 hash of your data
Generates a timestamp query request
Saves it to request.tsq
Step 3: Submit to TSA Service
Submit your timestamp request to the TSA service:
curl -H "Content-Type: application/timestamp-query" \
--data-binary @request.tsq \
http://freetsa.org/tsr > response.tsr
Alternative TSA Services : While FreeTSA is used as an example, you can use other TSA services. Commercial options include DigiCert, Sectigo, and others. Replace the URL with your preferred TSA service endpoint.
Step 4: Verify the Response
The resulting response.tsr file contains a cryptographic timestamp. You can verify it using:
openssl ts -reply -in response.tsr -text
Expected output should include:
Status: Granted
Timestamp and serial number
TSA certificate information
Complete Implementation Example
Here's a complete script that demonstrates the entire TSA signature process:
#!/bin/bash
# TSA Signature Creation Script
# Usage: ./create-tsa-signature.sh "your-json-data"
set -e
DATA = " $1 "
TIMESTAMP = $( date +%s )
WORK_DIR = "/tmp/tsa_work_ $TIMESTAMP "
# Create working directory
mkdir -p " $WORK_DIR "
cd " $WORK_DIR "
# Step 1: Prepare the data
echo -n " $DATA " > data.json
echo "✓ Data prepared"
# Step 2: Create timestamp request
openssl dgst -sha256 -binary data.json | openssl ts -query -sha256 -no_nonce -out request.tsq
echo "✓ Timestamp request created"
# Step 3: Submit to TSA
curl -H "Content-Type: application/timestamp-query" \
--data-binary @request.tsq \
http://freetsa.org/tsr > response.tsr
echo "✓ TSA response received"
# Step 4: Verify the response
if openssl ts -reply -in response.tsr -text > /dev/null 2>&1 ; then
echo "✓ TSA signature verified"
else
echo "✗ TSA signature verification failed"
exit 1
fi
# Step 5: Encode for use in JSON
TSA_SIGNATURE = $( base64 -w 0 < response.tsr )
echo "✓ TSA signature encoded"
# Output the base64 encoded signature
echo "TSA Signature (base64):"
echo " $TSA_SIGNATURE "
# Cleanup
cd /
rm -rf " $WORK_DIR "
echo "✓ Cleanup completed"
Integration with Node.js
You can also integrate TSA signature creation into your Node.js application:
const fs = require ( 'fs' );
const { execSync } = require ( 'child_process' );
const crypto = require ( 'crypto' );
class TSASignatureCreator {
constructor ( tsaUrl = 'http://freetsa.org/tsr' ) {
this .tsaUrl = tsaUrl;
}
async createTSASignature ( data ) {
const timestamp = Date. now ();
const workDir = `/tmp/tsa_work_${ timestamp }` ;
try {
// Create working directory
fs. mkdirSync (workDir, { recursive: true });
// Prepare data
const dataPath = `${ workDir }/data.json` ;
fs. writeFileSync (dataPath, JSON . stringify (data));
// Create timestamp request
const requestPath = `${ workDir }/request.tsq` ;
execSync ( `openssl dgst -sha256 -binary ${ dataPath } | openssl ts -query -sha256 -no_nonce -out ${ requestPath }` );
// Submit to TSA
const responsePath = `${ workDir }/response.tsr` ;
execSync ( `curl -H "Content-Type: application/timestamp-query" --data-binary @${ requestPath } ${ this . tsaUrl } > ${ responsePath }` );
// Read and encode response
const tsaResponse = fs. readFileSync (responsePath);
const tsaSignature = tsaResponse. toString ( 'base64' );
// Cleanup
fs. rmSync (workDir, { recursive: true , force: true });
return tsaSignature;
} catch (error) {
// Cleanup on error
if (fs. existsSync (workDir)) {
fs. rmSync (workDir, { recursive: true , force: true });
}
throw new Error ( `TSA signature creation failed: ${ error . message }` );
}
}
}
// Usage example
const tsaCreator = new TSASignatureCreator ();
const declarationData = {
signature: "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImp3ayI6e319.payload.signature" ,
declarationMetadata: {
publicMetadata: {
"$schema" : "https://w3id.org/commonsdb/schema/0.2.0.json" ,
"@context" : "https://w3id.org/commonsdb/context/0.2.0.json" ,
iscc: "ISCC:KEC2EHPLVKPVDFVORULRVCUFXL3DZ4SA6JSDQLNOXEVYYCXR4N5IBDY" ,
name: "Example Content" ,
description: "Sample content description" ,
mediatype: "image/jpeg" ,
timestamp: 1736251200000 ,
declarerId: "did:web:example.com" ,
credentials: [],
supplierMetadata: {
rightsStatement: "https://creativecommons.org/publicdomain/mark/1.0/" ,
location: "https://europeana.eu/item/123" ,
creator: "John Doe"
}
},
commonsDbRegistry: {
iscc: "ISCC:KEC2EHPLVKPVDFVORULRVCUFXL3DZ4SA6JSDQLNOXEVYYCXR4N5IBDY" ,
location: "https://europeana.eu/item/123" ,
rightsStatement: "https://creativecommons.org/publicdomain/mark/1.0/" ,
timestamp: 1736251200000 ,
credentials: [{ proof: "eyJhbGciOiJFUzI1NiJ9..." }]
}
}
};
tsaCreator. createTSASignature (declarationData)
. then ( tsaSignature => {
console. log ( 'TSA Signature created:' , tsaSignature);
})
. catch ( error => {
console. error ( 'Error creating TSA signature:' , error);
});
TSA Service Options
Free Services
FreeTSA.org : Free public TSA service (good for testing)
DigiCert Free TSA : Limited free tier available
Commercial Services
DigiCert : Enterprise-grade TSA services
Sectigo : Commercial timestamp services
GlobalSign : Professional TSA solutions
Production Considerations : For production use, consider using a commercial TSA service that offers:
SLA guarantees
Higher availability
Customer support
Audit trails
Verification and Validation
To verify a TSA signature later:
# Verify TSA signature
openssl ts -verify -in response.tsr -data data.json -CAfile tsa-ca-cert.pem
Complete Declaration Example
Here's how the final declaration with both certificate and TSA signatures looks:
const completeDeclaration = {
// Main signature for publicMetadata
signature: "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImp3ayI6e319.payload.signature" ,
tsaSignature: {
tsr: "base64-encoded-timestamp-response" ,
tsq: "base64-encoded-timestamp-request"
},
// Signatures for commonsDbRegistry (required when commonsDbRegistry is present)
commonsDbRegistrySignature: "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImp3ayI6e319.registry-payload.signature" ,
commonsDbRegistryTsaSignature: {
tsr: "base64-encoded-registry-timestamp-response" ,
tsq: "base64-encoded-registry-timestamp-request"
},
declarationMetadata: {
publicMetadata: {
"$schema" : "https://w3id.org/commonsdb/schema/0.2.0.json" ,
"@context" : "https://w3id.org/commonsdb/context/0.2.0.json" ,
iscc: "ISCC:KEC2EHPLVKPVDFVORULRVCUFXL3DZ4SA6JSDQLNOXEVYYCXR4N5IBDY" ,
name: "Example Content" ,
description: "Sample content description" ,
mediatype: "image/jpeg" ,
timestamp: 1736251200000 ,
declarerId: "did:web:example.com" ,
credentials: [
{
"@context" : [ "https://www.w3.org/ns/credentials/v2" ],
type: [ "VerifiableCredential" , "VerifiableSupplier" ],
proof: {
type: "JwtProof2020" ,
jwt: "eyJhbGciOiJFUzI1NiJ9..."
}
}
],
supplierMetadata: {
rightsStatement: "https://creativecommons.org/publicdomain/mark/1.0/" ,
location: "https://europeana.eu/item/123" ,
name: "Example Content" ,
creator: "John Doe" ,
description: "Sample content description" ,
attributionString: "John Doe, via Example Organization"
}
},
commonsDbRegistry: {
iscc: "ISCC:KEC2EHPLVKPVDFVORULRVCUFXL3DZ4SA6JSDQLNOXEVYYCXR4N5IBDY" ,
location: "https://europeana.eu/item/123" ,
rightsStatement: "https://creativecommons.org/publicdomain/mark/1.0/" ,
timestamp: 1736251200000 ,
credentials: [
{
proof: "eyJhbGciOiJFUzI1NiJ9..."
}
]
}
}
};
Troubleshooting
Common issues and solutions:
Issue Cause Solution TSA request fails Network connectivity or service down Check TSA service status and network Invalid timestamp format Incorrect OpenSSL version or parameters Verify OpenSSL version and command syntax Base64 encoding issues Line breaks in encoded output Use -w 0 flag with base64 command Response verification fails Corrupted response or wrong CA cert Re-request timestamp and verify CA certificate
Next Steps
With your TSA signature created:
Test your complete declaration with the Declaration API
Implement error handling for production use
Monitor TSA service availability and have fallback options
Set up automated certificate and TSA signature renewal
Your metadata now has both cryptographic authenticity (certificate signature) and temporal proof (TSA signature), providing complete verification capabilities for CommonsDB declarations.
Last modified on January 23, 2026