Verificación de firmas digitales en PDF
Cómo verifica Constaia la firma electrónica PAdES de un PDF: integridad, cadena de confianza y cambios posteriores, el objeto signature, require_valid_signature y lo que todavía no comprueba.
Muchos certificados oficiales se descargan de una sede electrónica como PDF firmado: el certificado de delitos sexuales, el de antecedentes penales, los de estar al corriente con la AEAT y la Seguridad Social, la vida laboral… Esa firma es la mejor prueba de que el documento no se ha tocado. Constaia la verifica en cada PDF que analizas, sin coste adicional y sin enviar el fichero a ningún tercero.
Qué comprueba
- Que hay firma. Busca las firmas electrónicas del PDF (PAdES / CMS) y sus revisiones.
- Integridad. Recalcula el resumen de los bytes firmados y lo compara con el que va dentro de la firma. Si no coinciden, el contenido cambió y la firma está rota. Después verifica la firma criptográfica (RSA, RSA-PSS, ECDSA o Ed25519, con SHA-1 a SHA-512).
- Firmante y fecha. Lee el certificado del firmante (nombre, organización, emisor, vigencia) y la hora de firma: la del sello de tiempo si lo hay, si no la declarada en la firma. Comprueba que el certificado estaba vigente en ese momento.
- Cadena de confianza. Construye la cadena desde el certificado del firmante hasta una autoridad raíz, verificando cada eslabón, y comprueba que llega a una de la lista de confianza.
- Cambios posteriores. Si el PDF tiene revisiones añadidas después de firmarse, mira qué añaden: otra firma, datos
de validación a largo plazo (LTV) o un sello de tiempo no cuentan; cualquier otra cosa es
document_modified_after_signing.
Además, los metadatos del PDF se revisan en busca de señales de edición: un productor conocido (iLovePDF, Smallpdf,
Sejda, PDF24, Acrobat, Word, LibreOffice, Canva, Photoshop…), una fecha de modificación muy posterior a la de creación,
o una firma "heredada" de un PDF que se reescribió. Si hay indicios, llega el aviso edited_suspected en warnings y
como motivo con warning.
El objeto signature
Solo aparece en PDF (en imágenes es null):
{
"status": "valid",
"reasons": ["signature_valid"],
"signer": "SELLO ELECTRONICO DEL MINISTERIO DE JUSTICIA",
"issuer": "AC Sector Público",
"signed_at": "2026-09-28T09:14:03Z",
"trusted": true,
"trust_anchor": "AC RAIZ FNMT-RCM",
"signatures": 1
}| Campo | Descripción |
|---|---|
status | Resultado global: valid, invalid, modified, untrusted o missing. |
reasons | Códigos del resultado (ver tabla de abajo). |
signer | Nombre del firmante (CN del certificado o, si no hay, la organización). |
issuer | Autoridad que emitió el certificado del firmante. |
signed_at | Hora de la firma: la del sello de tiempo si lo hay; si no, la declarada. null si no consta. |
trusted | true si la cadena llega a la lista de confianza. |
trust_anchor | Nombre de la autoridad de la lista de confianza a la que llega la cadena. |
signatures | Número de firmas del PDF. Los demás campos se refieren a la última. |
Estados y motivos
status | Motivo en verdict.reasons | Qué significa | Sin require_valid_signature | Con require_valid_signature |
|---|---|---|---|---|
valid | signature_valid | Firma íntegra, sin cambios posteriores y de un emisor de confianza. | info | info |
invalid | signature_invalid | La firma está rota: el contenido no coincide con lo firmado o la firma criptográfica no es correcta. | error | error |
modified | document_modified_after_signing | La firma es correcta, pero el PDF se modificó después. | warning | error |
untrusted | untrusted_signer | La firma es íntegra, pero el certificado no llega a la lista de confianza. | warning | error |
missing | signature_missing | El PDF no está firmado. | warning en tipos que suelen ir firmados (signed_pdf: true); en el resto, nada | error |
Los motivos van en verdict.reasons, así que solo aparecen si envías expect. El objeto signature llega siempre.
Exigir una firma válida: require_valid_signature
curl https://api.constaia.com/v1/analyze \
-H "Authorization: Bearer $CONSTAIA_API_KEY" \
-F file=@certificado_delitos_sexuales.pdf \
-F 'options={
"expect": "es_sexual_offences_certificate",
"checks": { "require_valid_signature": true, "max_age_days": 90 }
}'Con require_valid_signature: true todo lo que no sea signature_valid lleva a invalid. Una foto, un escaneo o un
"imprimir a PDF" nunca pueden cumplirlo: pierden la firma, y el motivo es signature_missing con error. Úsalo cuando
solo aceptes el PDF original descargado de la sede; si aceptas fotos, déjalo desactivado y revisa los review.
Los tipos que se descargan firmados tienen signed_pdf: true en el catálogo:
es_sexual_offences_certificate, es_criminal_record_certificate, es_work_history,
es_aeat_tax_compliance_certificate, es_social_security_compliance_certificate, es_aeat_census_certificate,
es_aeat_tax_id_card, es_aeat_income_certificate, es_social_security_number_document y mx_rfc_certificate. En
cualquier otro PDF la firma también se verifica y aparece en signature.
Comprueba quién firmó
Una firma válida y de confianza acredita quién firmó, no que el documento sea el que esperas. Compara
signature.signer con el organismo que debería emitirlo: un PDF firmado correctamente con el certificado de otra
persona u organismo también sale valid.
Lista de confianza
La lista de confianza parte de las autoridades raíz cualificadas españolas: AC RAIZ FNMT-RCM, ACCV (ACCVRAIZ1), Firmaprofesional y ANF. De ellas cuelga la mayoría de certificados de la Administración española. Para completar la cadena se usan los certificados que trae el propio PDF y las autoridades intermedias que Constaia tenga configuradas.
Un PDF firmado por un prestador de otro país, o cuya cadena no se puede completar, da untrusted (untrusted_signer)
aunque la firma sea íntegra. Si necesitas aceptar firmas de otros prestadores, escríbenos a
hola@constaia.com.
Lo que todavía no comprueba
Próximamente: revocación (OCSP/CRL)
Constaia no consulta todavía si el certificado del firmante está revocado (OCSP ni listas de revocación CRL). Un certificado revocado después de emitirse, pero vigente por fechas, se ve como válido.
- Sin la lista de confianza europea (TSL). Solo las autoridades de la lista de confianza de Constaia cuentan como de confianza.
- Análisis de cambios heurístico. Se revisa qué añaden las revisiones posteriores a la firma, pero no se evalúan los permisos de modificación del PDF (DocMDP) de forma completa.
- No consulta el CSV. El código seguro de verificación se valida solo en formato (
csv_format); Constaia no lo consulta en la sede del emisor. - Solo el fichero original. Un escaneo, una foto o un PDF regenerado pierden la firma.
edited_suspectedes una señal para revisar, no una prueba de fraude.
En modo test
La firma y los metadatos no se simulan: se analizan sobre el fichero que envías, también con claves ck_test_. Un PDF
sin firmar de un tipo con signed_pdf: true dará signature_missing y review. Ver Modo test.
Siguientes pasos
Checks
Referencia de las opciones de checks (vigencia, antigüedad, edad, titular, firma, importes) y de las validaciones deterministas de NIF, MRZ, IBAN y facturas.
Errores
Formato de error de la API de Constaia, todos los códigos por estado HTTP, clases de error de los SDK de JavaScript y PHP y qué errores conviene reintentar.