Firmas digitales (HasSecurity)
El trait HasSecurity proporciona setSignature() para firmas digitales compatibles con PAdES. TCPDF-Next soporta cuatro niveles de firma — desde básico (B-B) hasta archivado (B-LTA) — a través de PadesOrchestrator, TsaClient y los módulos LTV. Todos los métodos de firma retornan static para encadenamiento.
Referencia rápida
| Clase / Enum | Propósito |
|---|---|
CertificateInfo | Cargar certificados de firma (PEM o PKCS#12) |
SignatureLevel | Enum: PAdES_B_B, PAdES_B_T, PAdES_B_LT, PAdES_B_LTA |
TsaClient | Cliente de autoridad de timestamps RFC 3161 |
SignatureAppearance | Widget de firma visible o invisible |
OcspClient | Verificación de revocación en línea RFC 6960 |
CrlFetcher | Obtención de punto de distribución CRL RFC 5280 |
Niveles de firma
| Nivel | Lo que incluye | Validez |
|---|---|---|
| B-B (Básico) | Firma + certificado de firma | Válido mientras el certificado no sea revocado |
| B-T (Timestamp) | B-B + timestamp RFC 3161 | Prueba que la firma existió antes de un punto en el tiempo |
| B-LT (Largo plazo) | B-T + DSS con respuestas OCSP/CRL | Verificable después de que expire el certificado |
| B-LTA (Archivado) | B-LT + timestamp de documento + bucle de archivado | Verificable indefinidamente |
Ciclo de vida de firma PAdES
sequenceDiagram
participant App
participant Core
participant TSA as TSA Server
participant OCSP as OCSP Responder
App->>Core: sign(certificate, key)
Core->>Core: PAdES B-B (embedded)
Core->>TSA: RFC 3161 timestamp
TSA-->>Core: Timestamp token
Core->>Core: PAdES B-T
Core->>OCSP: Certificate check
OCSP-->>Core: OCSP response
Core->>Core: PAdES B-LT
Core->>Core: PAdES B-LTA (archive)Cargar certificados
Desde archivos PEM
use Yeeefang\TcpdfNext\Security\Signature\CertificateInfo;
$cert = CertificateInfo::fromFiles(
certPath: '/path/to/certificate.pem',
keyPath: '/path/to/private-key.pem',
password: 'key-password',
extraCerts: '/path/to/ca-chain.pem', // certificados intermedios opcionales
);Desde PKCS#12 (.p12 / .pfx)
use Yeeefang\TcpdfNext\Security\Signature\CertificateInfo;
$cert = CertificateInfo::fromPkcs12(
p12Path: '/path/to/certificate.p12',
password: 'pkcs12-password',
);Ejemplos de firma
use Yeeefang\TcpdfNext\Core\Document;
use Yeeefang\TcpdfNext\Security\Signature\CertificateInfo;
use Yeeefang\TcpdfNext\Contracts\SignatureLevel;
use Yeeefang\TcpdfNext\Security\Timestamp\TsaClient;
$cert = CertificateInfo::fromFiles(
certPath: '/path/to/certificate.pem',
keyPath: '/path/to/private-key.pem',
password: 'key-password',
);
// PAdES B-B (Básico) — solo firma
$pdf = Document::create()
->setSignature($cert, SignatureLevel::PAdES_B_B)
->addPage()
->setFont('Helvetica', '', 12)
->cell(0, 10, 'Signed document (B-B)')
->save('signed-bb.pdf');
// PAdES B-T (Timestamp) — firma + timestamp
$tsa = new TsaClient('https://freetsa.org/tsr');
$pdf = Document::create()
->setSignature($cert, SignatureLevel::PAdES_B_T, $tsa)
->addPage()
->cell(0, 10, 'Signed with timestamp (B-T)')
->save('signed-bt.pdf');
// PAdES B-LTA (Archivado) — validación a largo plazo completa
$pdf = Document::create()
->setSignature($cert, SignatureLevel::PAdES_B_LTA, $tsa)
->addPage()
->cell(0, 10, 'Archival signature (B-LTA)')
->save('signed-blta.pdf');El TsaClient soporta autenticación opcional. La verificación de nonce y el pinning DNS están habilitados por defecto para prevenir ataques de repetición y SSRF.
$tsa = new TsaClient(
url: 'https://tsa.example.com/timestamp',
user: 'tsa-user',
pass: 'tsa-password',
);Validación a largo plazo (B-LT / B-LTA)
Para los niveles B-LT y B-LTA, los datos de revocación se obtienen e incrustan automáticamente:
- OcspClient — consulta respondedores OCSP (RFC 6960) desde la extensión AIA del certificado
- CrlFetcher — descarga CRLs desde puntos de distribución (RFC 5280)
- DSS — almacena respuestas OCSP y CRLs en el Document Security Store
- VRI — datos de validación por firma (opcional, según recomendación ETSI)
B-LTA adicionalmente agrega un timestamp de documento, habilitando el bucle de archivado — el documento puede ser re-timestampeado para extender la validez indefinidamente.
Apariencia de firma
Por defecto, las firmas son invisibles. Para crear un widget de firma visible:
use Yeeefang\TcpdfNext\Security\Signature\SignatureAppearance;
$pdf = Document::create()
->setSignature($cert, SignatureLevel::PAdES_B_T, $tsa)
->setSignatureAppearance(
SignatureAppearance::visible(x: 20, y: 250, w: 80, h: 30)
)
->addPage()
->cell(0, 10, 'Document with visible signature')
->save('visible-signature.pdf');Para una firma explícitamente invisible:
$pdf->setSignatureAppearance(SignatureAppearance::invisible());Algoritmos y referencia de métodos
Algoritmos de firma a través de phpseclib3: RSA PKCS#1 v1.5 (predeterminado, mayor compatibilidad) y RSASSA-PSS (padding más fuerte, recomendado para nuevos despliegues).
$pdf->setSignature(
CertificateInfo $cert, // Certificado y clave privada
SignatureLevel $level, // B-B, B-T, B-LT, o B-LTA
?TsaClient $tsa = null, // Requerido para B-T, B-LT, B-LTA
);Retorna static para encadenamiento. La firma se aplica durante save() o output().