Documentación técnica · para auditores, abogados y desarrolladores

Documentación

Cómo se verifica una firma de easyFirma.

Validador de certificados, descripción del paquete probatorio, mapeo al Decreto 2364 y referencia de la API.

Sección 01

Validar un certificado.

Pegá el hash de un certificado emitido por easyFirma para consultar sus datos. Opcionalmente, subí el PDF original para verificar que su contenido no haya sido modificado desde la firma.

Arrastrá o seleccioná el PDF firmado

para verificar que no haya sido alterado

Esperando consulta

Cargá un hash o el demo para verificar un certificado.

Sección 02

El paquete probatorio.

Cada firma genera un registro estructurado y un PDF conservado. Esto es lo que un perito o abogado puede pedirnos para defender la firma en juicio.

Estructura del certificado

{
  "hash": "C0577351D464D260A8A24CAB...",
  "pdfHash": "5A4B3C2D1E9F8A...",
  "nombre": "Gabriel Valenzuela",
  "cedula": "1018273645",
  "email": "gabriel@ejemplo.co",
  "ip": "186.29.32.12",
  "timestamp": "2026-05-21T15:42:08.391Z",
  "confirmation": "ACEPTO",
  "otpVerified": true,
  "otpTimestamp": 1747867200000
}

Hash del documento

SHA-256 sobre los bytes del PDF firmado. No sobre la URL. Cualquier modificación al documento, por mínima que sea, invalida el hash.

Hash compuesto

SHA-256 sobre nombre · cédula · email · ip · timestamp · pdfHash. Es el identificador único del registro.

IP de origen

Capturada en el servidor a partir de cabeceras de conexión. No se acepta IP enviada por el cliente.

Voluntad expresa

Texto que el firmante tipea manualmente para confirmar (palabra clave o nombre). Capturado tal cual.

Código OTP

6 dígitos enviados al correo, validados con clave del servidor, expiración a 10 minutos, marcados como usados al consumirse.

Sección 03

Mapeo al Decreto 2364, art. 3.

El Decreto 2364 de 2012 define cuatro criterios de confiabilidad para una firma electrónica verificable. easyFirma cumple cada uno de la siguiente manera.

Criterio 01

Datos de creación exclusivos del firmante

Código OTP de 6 dígitos enviado únicamente al correo del firmante. Validado por HMAC-SHA256 con una clave del servidor que el cliente no conoce.

Criterio 02

Control exclusivo al momento de firmar

El OTP se tipea manualmente en pantalla. Sin magic link. Sin auto-firma. Los previewers de correo no pueden completar el flujo. El código es de uso único.

Criterio 03

Detección de alteraciones del mensaje

Hash SHA-256 calculado sobre los bytes del PDF firmado. Conservación del archivo exacto indexado por su hash. Si cambia un solo byte, el hash deja de coincidir.

Criterio 04

Detección de alteraciones de la firma

El registro completo (firmante, IP, timestamp, voluntad expresa, hash del PDF) lleva su propio hash compuesto. Modificar el registro lo invalida.

Sección 04

Integrar por API.

Flujo seguro de tres pasos: creación de una sesión de firma efímera desde tu backend, redirección del firmante usando un token seguro de un solo uso, y recepción del webhook con el certificado firmado.

1 · Crear sesión de firma (Backend)

Desde tu servidor, genera un token efímero de firma enviando una petición POST con tu clientApiKey. Nunca expongas tu API Key ni secretos en el navegador del firmante.

Petición HTTP (POST /sessions)

POST /.netlify/functions/sessions HTTP/1.1
Authorization: Bearer ef_live_k_sura_123...
Content-Type: application/json

{
  "pdfUrl": "https://sura.com.co/polizas/contrato.pdf",
  "redirectUrl": "https://sura.com.co/firma-exitosa",
  "signerHints": {
    "nombre": "Gabriel Valenzuela",
    "email": "gabriel@ejemplo.co"
  },
  "metadata": {
    "polizaId": "POL-2026-09"
  }
}

Respuesta (200 OK)

{
  "ok": true,
  "sessionToken": "ef_sess_abc123...",
  "firmUrl": "https://easyfirma.digital/firma.html?token=ef_sess_abc123...",
  "expiresAt": "2026-05-21T22:30:00.000Z"
}
Campo Descripción Tipo
pdfUrlURL pública y directa del archivo PDF a firmar.Requerido
redirectUrlURL a la cual redirigir al firmante tras firmar con éxito.Opcional
signerHints.nombreNombre completo para pre-llenar el formulario.Opcional
signerHints.emailCorreo para pre-llenar y enviar el código OTP.Opcional
metadataObjeto JSON libre para asociar identificadores internos tuyos.Opcional

2 · Redirigir al firmante

Redirige a tu usuario a la firmUrl recibida. El firmante visualizará la interfaz con el branding de tu marca configurado (nombre, logo y colores), sin exponer credenciales ni configuraciones privadas.

https://easyfirma.digital/firma.html?token=ef_sess_abc123...

Nota: Por seguridad, cada enlace de firma es de un solo uso y expira automáticamente a las 2 horas.

3 · Webhook de firma completada

Al completarse la firma, easyFirma envía un POST JSON a tu webhookUrl configurada. Si tienes un webhookSecret configurado, el cuerpo va firmado con HMAC-SHA256 en el encabezado X-EasyFirma-Signature.

Cuerpo del webhook

{
  "event": "signature.completed",
  "timestamp": 1747867200000,
  "data": {
    "transactionId": "C0577351...",
    "certificateHash": "C0577351...",
    "pdfHash": "5A4B3C2D...",
    "clientId": "sura-001",
    "metadata": { "polizaId": "POL-2026-09" },
    "firmante": {
      "nombre": "Gabriel Valenzuela",
      "cedula": "1018273645",
      "email": "gabriel@ejemplo.co",
      "ip": "186.29.32.12",
      "declaracion": "APROBAR",
      "timestamp": "2026-05-21T15:42:08.391Z"
    }
  }
}

Validar la firma (Node.js)

const crypto = require('crypto');

app.post('/webhook', (req, res) => {
  const sig = req.headers['x-easyfirma-signature'];
  const secret = process.env.EASYFIRMA_WEBHOOK_SECRET;
  
  // Calcular HMAC usando el body en bruto (raw body)
  const expected = crypto
    .createHmac('sha256', secret)
    .update(req.rawBody)
    .digest('hex');

  // Comparación en tiempo constante para evitar ataques de timing
  const match = crypto.timingSafeEqual(
    Buffer.from(sig, 'hex'),
    Buffer.from(expected, 'hex')
  );

  if (match) {
    res.sendStatus(200);
  } else {
    res.sendStatus(401);
  }
});

4 · Consultar registro de transparencia

GET por hash y ID de cliente. Retorna el log público de transparencia sin datos de carácter personal (PII). Cumple 100% con Ley 1581 (Habeas Data).

curl -X GET \
  "https://easyfirma.digital/.netlify/functions/certs?hash=C0577351...&clientId=sura-001"
← Volver a la portada