Timestamp Authority (TSA)
TCPDF-Next Pro incluye un cliente de Time Stamp Authority RFC 3161 de grado producción (TsaClient) y un helper DocumentTimestamp que incrusta firmas /DocTimeStamp para flujos de trabajo PAdES B-LTA.
TsaClient
Uso básico
use Yeeefang\TcpdfNext\Pro\Tsa\TsaClient;
$tsa = new TsaClient(url: 'https://freetsa.org/tsr');
$token = $tsa->timestamp($pdfHash);Con autenticación
Algunos servidores TSA corporativos requieren credenciales:
$tsa = new TsaClient(
url: 'https://tsa.corporate.example/rfc3161',
username: 'api-user',
password: 'api-secret',
);Construcción de TimeStampReq RFC 3161
El cliente construye una estructura ASN.1 TimeStampReq conforme al estándar para cada solicitud:
- MessageImprint -- Digest SHA-256 de los datos a firmar con timestamp.
- Nonce -- Valor aleatorio criptográfico de 64 bits para prevenir ataques de repetición.
- CertReq -- Establecido en
truepara que la TSA incluya su certificado de firma en la respuesta.
// The hash must be raw binary (32 bytes for SHA-256)
$hash = hash('sha256', $documentBytes, binary: true);
$token = $tsa->timestamp($hash, algorithm: 'sha256');Verificación de nonce
Después de recibir el TimeStampResp, el cliente automáticamente:
- Analiza el
TSTInfode la respuesta. - Extrae el nonce del
TSTInfo. - Lo compara con el nonce enviado en la solicitud.
- Lanza
TsaNonceMismatchExceptionsi difieren.
try {
$token = $tsa->timestamp($hash);
} catch (\Yeeefang\TcpdfNext\Pro\Tsa\TsaNonceMismatchException $e) {
// Nonce mismatch -- possible MITM or replay attack
log_security_event($e->getMessage());
}Validación de PKIStatus
El cliente valida el campo PKIStatus en cada respuesta:
| Código | Significado | Comportamiento del cliente |
|---|---|---|
0 | granted | Token aceptado |
1 | grantedWithMods | Token aceptado con advertencia registrada |
2 | rejection | Se lanza TsaRejectedException |
3 | waiting | No soportado; se lanza excepción |
4 | revocationWarning | Token aceptado con advertencia registrada |
5 | revocationNotification | Se lanza TsaCertRevokedException |
DNS Pinning (protección SSRF)
Para prevenir Server-Side Request Forgery, puedes anclar el hostname de la TSA a una dirección IP específica. El cliente usa CURLOPT_RESOLVE para eludir la resolución DNS por completo:
$tsa = new TsaClient(
url: 'https://tsa.corporate.example/rfc3161',
);
// Pin the hostname to a known IP -- DNS is never queried
$tsa->pinDns('tsa.corporate.example', '203.0.113.42', port: 443);Esto es crítico en entornos donde la URL de la TSA proviene de entrada del usuario o configuración externa y no debe resolver a direcciones de red internas.
mTLS (Mutual TLS)
Los servidores TSA corporativos frecuentemente requieren autenticación con certificado de cliente. Pasa tu certificado de cliente y clave privada:
$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',
);El handle cURL subyacente se configura con CURLOPT_SSLCERT, CURLOPT_SSLKEY y CURLOPT_SSLCERTPASSWD.
DocumentTimestamp (B-LTA)
DocumentTimestamp agrega una firma /DocTimeStamp al PDF, que es el paso final en un flujo de trabajo PAdES B-LTA. Este timestamp cubre todo el documento incluyendo todas las firmas previas y el 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);Resumen del flujo de trabajo B-LTA
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) <-- DocumentTimestampServidores TSA populares
| Proveedor | URL | Auth | Notas |
|---|---|---|---|
| FreeTSA | https://freetsa.org/tsr | Ninguna | Gratuito; adecuado para testing |
| Sectigo | https://timestamp.sectigo.com | Ninguna | Grado producción; tier gratuito |
| DigiCert | https://timestamp.digicert.com | Ninguna | Ampliamente confiable |
| GlobalSign | https://timestamp.globalsign.com/tsa/r6advanced1 | Ninguna | SHA-256 por defecto |
| Personalizado / Empresarial | Varía | Basic, mTLS, Bearer | Usa pinDns() + clientCertificate() |
TIP
Para documentos PAdES B-LTA en producción, usa un proveedor TSA cuyo certificado raíz esté en la Adobe Approved Trust List (AATL). Esto asegura que los timestamps sean reconocidos por Adobe Acrobat sin configuración manual de confianza.