Qué garantiza una firma digital (y qué no)
Una firma digital es un mecanismo criptográfico para probar dos cosas sobre un mensaje (documento, binario, manifiesto, token, etc.):
- Integridad: el contenido firmado no ha cambiado desde que se firmó.
- Autoría (autenticidad criptográfica): quien posee la clave privada correspondiente a la clave pública verificada generó la firma.
Una firma no garantiza por sí sola:
- Confidencialidad: firmar no cifra. Cualquiera puede leer el contenido si se distribuye en claro.
- Identidad “humana” o legal: la firma prueba posesión de una clave, no “quién es” esa persona/empresa, salvo que exista un sistema de identidad (p. ej., certificados y una cadena de confianza) que vincule la clave a una entidad.
- Autorización: que una firma sea válida no implica que el firmante tenga permisos para esa acción en tu sistema.
- Ausencia de malware: un binario puede estar perfectamente firmado y ser malicioso si el firmante lo es o si su clave fue comprometida.
Firmas modernas en la práctica: Ed25519, ECDSA y RSA-PSS
Ed25519 (EdDSA sobre Curve25519)
- Ventajas: rápida, firmas pequeñas, diseño moderno, menos “perillas” peligrosas (no depende de un nonce aleatorio por firma), muy buena opción por defecto cuando controlas ambos extremos.
- Compatibilidad: excelente en software moderno, pero puede ser limitada en ciertos HSM antiguos, stacks legacy o entornos que solo aceptan RSA/ECDSA.
- Uso típico: firma de artefactos (supply chain), tokens internos, sistemas distribuidos, Git/SSH modernos.
ECDSA (p. ej., P-256)
- Ventajas: ampliamente soportada en TLS, HSM, PKI corporativa y ecosistemas existentes.
- Riesgos operativos: requiere un nonce por firma correcto (aleatorio o determinístico). Si se reutiliza o se filtra, puede comprometer la clave privada.
- Uso típico: certificados TLS en infra existente, integraciones con hardware/PKI que no soportan Ed25519.
RSA-PSS
- Ventajas: muy compatible; RSA-PSS es la variante moderna recomendada frente a RSA “clásico” (PKCS#1 v1.5) para firmas.
- Coste: claves y firmas más grandes; rendimiento inferior a curvas elípticas en muchos escenarios.
- Uso típico: compatibilidad máxima (clientes antiguos, appliances), PKI heredada, ciertos requisitos regulatorios/organizacionales.
Criterios para escoger (guía rápida)
| Necesidad | Recomendación | Notas |
|---|---|---|
| Controlas cliente y servidor, stack moderno | Ed25519 | Menos errores operativos; excelente para firma de artefactos y tokens internos. |
| Debes integrarte con PKI/TLS corporativo existente | ECDSA P-256 o RSA-PSS | Depende del soporte del CA/HSM y de clientes. |
| Compatibilidad con clientes legacy | RSA-PSS | Evita PKCS#1 v1.5 si puedes; valida soporte real de PSS. |
| Uso en HSM con soporte limitado | Lo que soporte el HSM | Prioriza seguridad operacional: rotación, control de acceso, auditoría. |
Flujo mental correcto: firmar y verificar
Qué se firma realmente
En sistemas reales casi nunca se firma “un archivo tal cual” sin más. Se firma una representación canónica o un digest del contenido, junto con metadatos relevantes (algoritmo, versión, claims, etc.). Errores comunes aparecen cuando dos partes no comparten exactamente la misma canonicalización.
Verificación: pasos mínimos
- 1) Obtener el mensaje exacto que se supone firmado (o su forma canónica).
- 2) Obtener la firma y el algoritmo esperado.
- 3) Obtener la clave pública correcta (o un certificado que la contenga).
- 4) Verificar la firma y fallar en cerrado si algo no cuadra.
- 5) Aplicar política: ¿esta clave/certificado está autorizado para este tipo de firma? (separar autenticación de autorización).
Certificados X.509, CA y cadena de confianza
Qué es un certificado X.509
Un certificado X.509 es un documento firmado (por una CA u otra entidad) que vincula una clave pública con una identidad y atributos. Contiene, entre otros:
- Subject: identidad del titular (p. ej., un dominio o entidad).
- Subject Public Key Info: la clave pública.
- Issuer: quién lo emitió (la CA).
- Validez: notBefore / notAfter.
- Extensiones: usos permitidos (Key Usage / Extended Key Usage), SAN (Subject Alternative Name), políticas, etc.
CA y cadena de confianza
Una CA (Certificate Authority) firma certificados. La verificación se hace construyendo una cadena desde el certificado presentado hasta una raíz confiable (trust anchor) instalada en el sistema (SO, navegador, runtime, o un trust store corporativo).
- Escuche el audio con la pantalla apagada.
- Obtenga un certificado al finalizar.
- ¡Más de 5000 cursos para que explores!
Descargar la aplicación
En términos prácticos, “confiar” en un certificado significa: confío en que la CA aplicó un proceso aceptable para emitirlo y en que las reglas del ecosistema (revocación, auditoría, transparencia, etc.) reducen el riesgo.
Validación correcta de certificados (checklist)
- Construcción de cadena: el certificado debe encadenar a una raíz confiable.
- Nombre/identidad: para TLS, validar SAN (DNS/IP) contra el host esperado. No usar CN como fallback si tu stack ya no lo soporta.
- Validez temporal: notBefore/notAfter con reloj confiable.
- Usos permitidos: Key Usage / EKU deben permitir el propósito (p. ej., serverAuth para servidor TLS; codeSigning para firma de código).
- Algoritmos: rechazar algoritmos obsoletos o tamaños inseguros según tu política.
- Revocación: considerar OCSP/CRL según criticidad (ver sección siguiente).
Revocación: qué es, qué falla y cómo usarla con realismo
Qué significa revocar
Revocar un certificado es publicar que ya no debe considerarse válido antes de su fecha de expiración (por compromiso de clave, emisión errónea, cambio de estado, etc.). Los mecanismos típicos son:
- CRL (Certificate Revocation List): lista firmada y publicada periódicamente.
- OCSP (Online Certificate Status Protocol): consulta en línea del estado.
Limitaciones prácticas
- Disponibilidad: si el verificador no puede consultar OCSP/CRL, muchos entornos “fallan en abierto” por compatibilidad, reduciendo la efectividad.
- Latencia y privacidad: OCSP puede filtrar qué sitios visitas si se consulta directamente.
- Staleness: CRL/OCSP pueden estar desactualizados; hay ventanas de exposición.
Guía práctica: si tu entorno lo permite, habilita OCSP stapling en servidores TLS para mejorar privacidad y disponibilidad. Para escenarios de alta criticidad (p. ej., firma de código interna), considera mecanismos adicionales: certificados de corta vida, listas de denegación internas, y rotación rápida.
Pinning: útil, pero fácil de romper
Qué es pinning
Pinning es restringir qué claves públicas/certificados se aceptan para una identidad, en lugar de confiar en cualquier cadena válida a una raíz del sistema. Se usa para reducir el riesgo de CAs comprometidas o emisión indebida.
Advertencias importantes
- Riesgo de bloqueo: si “pineas” una sola clave y la pierdes/expira, puedes dejar clientes sin posibilidad de conectarse.
- Rotación: debes planificar pins de respaldo (p. ej., dos claves válidas) y un proceso de actualización seguro.
- Entornos: en apps móviles o agentes, el pinning es más viable que en navegadores generales. Evita pinning rígido si no controlas el ciclo de actualización.
Patrón recomendado: pinning a SPKI (hash de la clave pública) con al menos un pin de backup y ventanas de transición.
Casos prácticos
1) Firma de artefactos: paquetes, contenedores y releases
Objetivo: asegurar que lo que despliegas/instalas es exactamente lo que publicó tu pipeline o proveedor, y que no fue modificado en tránsito o en el registro.
Patrón A: firmar un manifiesto de hashes
En vez de firmar cada archivo, se crea un manifiesto con hashes y metadatos, se firma el manifiesto y se distribuye junto con los artefactos.
artifact-manifest.json (ejemplo conceptual) = { version, artifacts: [{name, sha256, size}], buildInfo }Pasos (pipeline):
- 1) Genera el manifiesto con hashes de cada artefacto.
- 2) Firma el manifiesto con una clave dedicada de firma de releases (idealmente en HSM/KMS o con controles fuertes).
- 3) Publica artefactos + manifiesto + firma.
- 4) En despliegue/cliente: descarga, verifica firma del manifiesto, luego verifica hashes de artefactos.
Controles recomendados:
- Separar claves: una para CI, otra para releases; minimizar quién puede firmar “producción”.
- Registrar qué commit/build firmó qué artefacto (trazabilidad).
- Rotación planificada y revocación/denylist interna para claves comprometidas.
Patrón B: firma de contenedores en registro
En ecosistemas de contenedores, se acostumbra firmar la imagen por digest (contenido inmutable). Buenas prácticas:
- Firmar el digest (no el tag), porque el tag es mutable.
- Verificar firma en admisión (p. ej., en Kubernetes con políticas) antes de ejecutar.
- Asociar identidad del firmante a una política: “solo imágenes firmadas por X pueden entrar a prod”.
2) Firma de documentos (PDF, contratos, reportes)
Objetivo: detectar modificaciones y atribuir la firma a una identidad (normalmente mediante certificados).
Puntos clave:
- Necesitas canonicalización y un formato de firma estándar del documento (p. ej., PAdES/CAdES/XAdES según el caso). Evita “firmas caseras” pegando una firma base64 al final del archivo.
- La verificación debe incluir cadena de confianza y propósito (EKU) del certificado.
- Si el documento debe ser verificable a largo plazo, considera sellos de tiempo y evidencias (LTV), según tu marco.
Guía paso a paso (genérica) para un flujo interno de firma de documentos
- 1) Define el formato: qué bytes exactos se firman (canonicalización/estructura).
- 2) Selecciona algoritmo: Ed25519 si es interno y controlado; ECDSA/RSA-PSS si dependes de PKI existente.
- 3) Emite/gestiona certificados para firmantes (o claves internas con un directorio de confianza).
- 4) Firma en un servicio central (evita distribuir claves privadas a múltiples clientes).
- 5) Verifica en el consumidor: firma + cadena + validez + revocación (según criticidad) + política de quién puede firmar qué tipo de documento.
3) Firma de tokens (JWT/JWS u otros)
Objetivo: emitir tokens que el receptor pueda validar sin consultar al emisor en cada petición (aunque a veces se combina con introspección).
Qué firmar y cómo evitar errores
- Firmar el token completo (header+payload) con un estándar como JWS.
- Incluir claims que eviten reuso indebido:
iss,aud,exp,nbf,iat, y un identificadorjtisi necesitas detección de replay. - Validar estrictamente: algoritmo esperado (no aceptar “none”), issuer, audience, ventanas de tiempo y clock skew controlado.
Selección de algoritmo en tokens
- EdDSA (Ed25519): excelente si tu librería/infra lo soporta para JWS; simple y robusto.
- ES256 (ECDSA P-256): muy común en OIDC/JWT; cuidado con implementaciones y canonicalización/base64url.
- PS256 (RSA-PSS): buena compatibilidad en ecosistemas empresariales; tokens más grandes.
Errores frecuentes (y cómo evitarlos)
1) Reutilización o mala gestión de claves
- Reutilizar la misma clave para múltiples propósitos (TLS, firma de código, tokens) amplía el impacto de un compromiso.
- Copiar claves privadas entre entornos (dev/staging/prod) rompe el aislamiento.
- Falta de rotación: claves “eternas” hacen que cualquier filtración sea catastrófica.
Mitigación: separación por propósito (y por entorno), inventario de claves, rotación programada, y almacenamiento en KMS/HSM cuando sea viable.
2) Verificación incompleta de certificados
- Aceptar un certificado “porque está firmado” sin validar SAN, EKU, cadena y validez.
- Desactivar validaciones para “arreglar” un problema de entorno (p. ej.,
verify=false) y olvidarlo en producción. - Confiar en cualquier certificado del sistema cuando en realidad necesitas un trust store corporativo o pinning.
Mitigación: usar validadores estándar del sistema/librería, añadir tests de integración (cert expirado, CA no confiable, SAN incorrecto), y políticas explícitas de trust store.
3) Confundir “autenticado” con “autorizado”
Ejemplo típico: “el token está bien firmado, entonces puede acceder”. La firma solo prueba que el token fue emitido por una clave confiable. La autorización requiere evaluar permisos (roles/scopes/ACL), contexto y políticas.
Checklist mínimo en un API gateway/servicio:
- Autenticación: verificar firma,
iss,aud,exp, etc. - Autorización: verificar scopes/roles y reglas de negocio (p. ej., el usuario puede acceder a este recurso).
- Auditoría: registrar sujeto, emisor,
jti, decisión y motivo.
Guía práctica: diseñar una solución de firma y confianza en 8 pasos
Define el objeto firmado: ¿archivo, manifiesto, digest, token? Especifica canonicalización y versión.
Define el verificador: ¿quién verifica (cliente, servidor, pipeline, cluster)? ¿En qué lenguaje/stack?
Elige algoritmo por compatibilidad: Ed25519 si puedes; si dependes de PKI/TLS/HSM legacy, ECDSA o RSA-PSS.
Diseña identidad: ¿basta con una lista de claves públicas confiables o necesitas X.509 con CA?
Define trust anchors: qué raíces/keys se confían y cómo se distribuyen/actualizan.
Planifica rotación y revocación: caducidades cortas cuando sea posible, proceso de emergencia, y cómo reaccionan verificadores.
Aplica política de autorización: qué firmantes pueden firmar qué (release/prod, tipo de documento, scope de token).
Prueba casos negativos: firma inválida, cert expirado, SAN incorrecto, cadena incompleta, algoritmo inesperado, token con
audincorrecto.