Skip to content

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 / EnumPropósito
CertificateInfoCargar certificados de firma (PEM o PKCS#12)
SignatureLevelEnum: PAdES_B_B, PAdES_B_T, PAdES_B_LT, PAdES_B_LTA
TsaClientCliente de autoridad de timestamps RFC 3161
SignatureAppearanceWidget de firma visible o invisible
OcspClientVerificación de revocación en línea RFC 6960
CrlFetcherObtención de punto de distribución CRL RFC 5280

Niveles de firma

NivelLo que incluyeValidez
B-B (Básico)Firma + certificado de firmaVálido mientras el certificado no sea revocado
B-T (Timestamp)B-B + timestamp RFC 3161Prueba que la firma existió antes de un punto en el tiempo
B-LT (Largo plazo)B-T + DSS con respuestas OCSP/CRLVerificable después de que expire el certificado
B-LTA (Archivado)B-LT + timestamp de documento + bucle de archivadoVerificable indefinidamente

Ciclo de vida de firma PAdES

Cargar certificados

Desde archivos PEM

php
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)

php
use Yeeefang\TcpdfNext\Security\Signature\CertificateInfo;

$cert = CertificateInfo::fromPkcs12(
    p12Path: '/path/to/certificate.p12',
    password: 'pkcs12-password',
);

Ejemplos de firma

php
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.

php
$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:

php
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:

php
$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).

php
$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().

Distribuido bajo la licencia LGPL-3.0-or-later.