Timestamp Authority (TSA)
TCPDF-Next Pro ships a production-grade RFC 3161 Timestamp Authority client (TsaClient) and a DocumentTimestamp helper that embeds /DocTimeStamp signatures for PAdES B-LTA workflows.
TsaClient
Basic Usage
use Yeeefang\TcpdfNext\Pro\Tsa\TsaClient;
$tsa = new TsaClient(url: 'https://freetsa.org/tsr');
$token = $tsa->timestamp($pdfHash);With Authentication
Some enterprise TSA servers require credentials:
$tsa = new TsaClient(
url: 'https://tsa.enterprise.example/rfc3161',
username: 'api-user',
password: 'api-secret',
);RFC 3161 TimeStampReq Construction
The client builds a standards-compliant TimeStampReq ASN.1 structure for every request:
- MessageImprint -- SHA-256 digest of the data to be timestamped.
- Nonce -- Cryptographically random 64-bit value to prevent replay attacks.
- CertReq -- Set to
trueso the TSA includes its signing certificate in the response.
// The hash must be raw binary (32 bytes for SHA-256)
$hash = hash('sha256', $documentBytes, binary: true);
$token = $tsa->timestamp($hash, algorithm: 'sha256');Nonce Verification
After receiving the TimeStampResp, the client automatically:
- Parses the
TSTInfofrom the response. - Extracts the nonce from the
TSTInfo. - Compares it against the nonce sent in the request.
- Throws
TsaNonceMismatchExceptionif they differ.
try {
$token = $tsa->timestamp($hash);
} catch (\Yeeefang\TcpdfNext\Pro\Tsa\TsaNonceMismatchException $e) {
// Nonce mismatch -- possible MITM or replay attack
log_security_event($e->getMessage());
}PKIStatus Validation
The client validates the PKIStatus field in every response:
| Code | Meaning | Client Behavior |
|---|---|---|
0 | granted | Token accepted |
1 | grantedWithMods | Token accepted with warning logged |
2 | rejection | TsaRejectedException thrown |
3 | waiting | Not supported; exception thrown |
4 | revocationWarning | Token accepted with warning logged |
5 | revocationNotification | TsaCertRevokedException thrown |
DNS Pinning (SSRF Protection)
To prevent Server-Side Request Forgery, you can pin the TSA hostname to a specific IP address. The client uses CURLOPT_RESOLVE to bypass DNS resolution entirely:
$tsa = new TsaClient(
url: 'https://tsa.enterprise.example/rfc3161',
);
// Pin the hostname to a known IP -- DNS is never queried
$tsa->pinDns('tsa.enterprise.example', '203.0.113.42', port: 443);This is critical in environments where the TSA URL originates from user input or external configuration and must not resolve to internal network addresses.
mTLS (Mutual TLS)
Enterprise TSA servers frequently require client certificate authentication. Pass your client certificate and private key:
$tsa = new TsaClient(
url: 'https://tsa.bank.example/timestamp',
);
$tsa->clientCertificate(
certPath: '/etc/pki/tsa-client.pem',
keyPath: '/etc/pki/tsa-client.key',
keyPassword: 'client-key-pass',
);The underlying cURL handle is configured with CURLOPT_SSLCERT, CURLOPT_SSLKEY, and CURLOPT_SSLCERTPASSWD.
DocumentTimestamp (B-LTA)
DocumentTimestamp adds a /DocTimeStamp signature to the PDF, which is the final step in a PAdES B-LTA workflow. This timestamp covers the entire document including all previous signatures and the DSS (Document Security Store).
use Yeeefang\TcpdfNext\Pro\Tsa\DocumentTimestamp;
use Yeeefang\TcpdfNext\Pro\Tsa\TsaClient;
$tsa = new TsaClient(url: 'https://freetsa.org/tsr');
$stamper = new DocumentTimestamp(
tsaClient: $tsa,
hashAlgorithm: 'sha256',
);
// Apply the document timestamp (incremental save)
$stamper->apply($document);B-LTA Workflow Summary
1. Sign document (PAdES B-B)
2. Add signature timestamp (PAdES B-T)
3. Embed DSS (OCSP + CRL) (PAdES B-LT)
4. Add /DocTimeStamp (PAdES B-LTA) <-- DocumentTimestampPopular TSA Servers
| Provider | URL | Auth | Notes |
|---|---|---|---|
| FreeTSA | https://freetsa.org/tsr | None | Free; suitable for testing |
| Sectigo | https://timestamp.sectigo.com | None | Production-grade; free tier |
| DigiCert | https://timestamp.digicert.com | None | Widely trusted |
| GlobalSign | https://timestamp.globalsign.com/tsa/r6advanced1 | None | SHA-256 default |
| Custom / Enterprise | Varies | Basic, mTLS, Bearer | Use pinDns() + clientCertificate() |
TIP
For production PAdES B-LTA documents, use a TSA provider whose root certificate is in the Adobe Approved Trust List (AATL). This ensures timestamps are recognized by Adobe Acrobat without manual trust configuration.