🇨🇴ColombiaGuía Técnica

Firma Digital para Factura Electrónica en Colombia: Certificados y XAdES-B

La firma digital es el mecanismo criptográfico que garantiza la autenticidad e integridad de cada documento electrónico en Colombia. Usa el estándar XAdES-B con certificados emitidos por entidades certificadoras acreditadas.

Ing. Carlos Méndez
Arquitecto de Software · Integraciones Fiscales LATAM
5 min lectura22 de abril de 2026

Un certificado digital con un día menos de vigencia provoca rechazo automático de todas las facturas electrónicas hasta que se renueve, y la DIAN no avísa previamente — el primer indicador es la respuesta del validador en producción. Y cuando el certificado es válido pero la firma todavía se rechaza, el problema casi siempre está en una sutileza de la canonicalización XML que ninguna librería detecta automáticamente.

Esta guía explica qué tipo de certificado se requiere en Colombia, qué autoridades pueden emitirlo, cómo se construye una firma XAdES-BES sobre un documento UBL 2.1, qué algoritmos y mecanismos de canonicalización exige la DIAN, y cuáles son los puntos donde más fallan las integraciones — desde la C14N Exclusiva hasta la rotación de certificados cerca de la fecha de vencimiento.

Qué tipo de certificado exige la DIAN

Certificado de persona jurídica vs persona natural

Para emitir facturas electrónicas en Colombia, el emisor debe contar con un certificado digital de firma electrónica emitido por una Entidad de Certificación Digital (ECD) acreditada por la ONAC. El certificado se asocia al NIT del obligado a facturar (persona jurídica) o a la cédula del contribuyente (persona natural). La DIAN no acepta certificados de propósito general o autofirmados — solo aquellos emitidos por ECDs registradas y vigentes.

ECDs acreditadas en Colombia

Las ECDs autorizadas para emitir certificados con propósito de facturación electrónica son Certicámara, Andes SCD, Gestión de Seguridad Electrónica (GSE), Onpe y algunas otras de menor uso. La vigencia típica del certificado es de uno o dos años; algunas ECDs ofrecen tres años. El costo varía pero ronda los 250.000 a 400.000 COP por año según la entidad y el tipo de uso.

Estándar XAdES-BES aplicado al documento UBL

Qué es XAdES-BES

XAdES es la extensión de XML Signature (XMLDSig) que añade campos específicos para firmas avanzadas en el contexto europeo y latinoamericano. La variante BES (Basic Electronic Signature) es la requerida por la DIAN: firma básica sin sello de tiempo agregado por una autoridad externa. La firma se incluye dentro del propio XML en el bloque ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent del documento UBL.

Estructura de la firma dentro del UBL

La firma XAdES-BES sobre un UBL contiene tres elementos principales: SignedInfo (referencias canónicas a lo firmado), SignatureValue (el hash firmado), y KeyInfo (datos del certificado firmante). Adicionalmente, los elementos qualifying-properties: SigningTime con timestamp en UTC, SigningCertificate con el hash del certificado, y SignaturePolicyIdentifier — este último apunta al policy ID definido por la DIAN.

Algoritmos y canonicalización requeridos

Algoritmos obligatorios

La DIAN exige específicamente SHA-256 para los digests de las referencias, RSA-SHA256 para la firma asimétrica, y C14N Exclusiva (Exclusive XML Canonicalization 1.0) para la canonicalización del XML. Una combinación incorrecta — por ejemplo, C14N inclusiva en lugar de exclusiva — produce una firma que matemáticamente es válida pero la DIAN rechaza al recalcularla del lado servidor.

Canonicalización: la fuente del 60% de los errores de firma

La canonicalización convierte el XML a una forma canónica antes de hashear, para que diferencias irrelevantes (espacios, orden de atributos, namespaces declarados pero no usados) no afecten el hash. C14N Exclusiva es la variante que la DIAN exige porque preserva los namespaces solo donde son necesarios. Bibliotecas como Apache Santuario (Java), xmlsec (Python), o SignedXml (C#) implementan C14N pero con valores por defecto distintos — verificar explícitamente que está usando exclusiva, no inclusiva, antes de transmitir.

SigningTime y validez temporal

El elemento SigningTime debe contener el timestamp exacto de la firma en UTC. La DIAN valida que ese timestamp esté dentro de la vigencia del certificado y dentro de una ventana razonable respecto a su servidor (no más de 24 horas en el pasado, no más de unas horas en el futuro). Servidores desincronizados producen firmas con timestamps fuera de ventana, lo que aparece como rechazo genérico de firma sin pista clara del origen.

Errores frecuentes en la firma digital

Certificado vencido sin alerta previa

La DIAN no envía notificaciones previas al vencimiento del certificado. Una vez vencido, todas las firmas se rechazan inmediatamente. La buena práctica es implementar un check automatizado que alerte 30, 15 y 5 días antes del vencimiento, integrado al monitoreo del servicio. Renovar requiere la misma ECD que emitió el original y suele tomar entre 1 y 3 días hábiles según la entidad.

Firma matemáticamente válida pero la DIAN la rechaza

Indica problema de canonicalización (C14N inclusiva en lugar de exclusiva), algoritmo de digest incorrecto (SHA-1 en lugar de SHA-256), o referencia mal construida en SignedInfo. La verificación rápida es firmar y validar localmente con xmlsec1 usando el certificado de la DIAN como confianza — si valida localmente y la DIAN sigue rechazando, el problema es del policy ID DIAN o de un campo qualifying-property requerido faltante.

Rotación de certificado sin caer en bloqueo

Al renovar el certificado, la clave técnica entregada por la DIAN no cambia, pero el certificado nuevo sí. Para una ventana corta — el momento de cambio — conviene mantener ambos certificados disponibles y rotar gradualmente. Si la rotación se hace de golpe sin haber probado el nuevo certificado en sandbox, hay riesgo de bloqueo total de la emisión en producción hasta que se diagnostica el problema.

Gestión operativa del certificado

Almacenamiento seguro del archivo privado

El certificado privado (PFX/P12) debe almacenarse cifrado en reposo. No se debe versionar en el repositorio de código bajo ninguna circunstancia, ni siquiera en repositorios privados. La práctica recomendada es usar un secret manager (AWS Secrets Manager, HashiCorp Vault, Azure Key Vault) con rotación periódica de la contraseña del PFX y acceso solo desde el servidor que ejecuta la firma.

Backup y restauración

Si el archivo PFX se pierde y no hay backup, la única vía es solicitar reemisión a la ECD, lo que toma días hábiles y bloquea la facturación durante ese tiempo. Mantener backup del PFX cifrado en al menos dos ubicaciones independientes es obligatorio operativamente. La contraseña del PFX debe almacenarse en un sistema distinto del backup, para evitar que un único punto de compromiso dé acceso a ambos.

Preguntas frecuentes

¿Cuál es la diferencia entre XAdES-BES, XAdES-EPES y XAdES-T? BES (Basic Electronic Signature) es la firma básica con datos del firmante pero sin sello de tiempo externo ni política explícita. EPES (Explicit Policy Electronic Signature) añade una referencia explícita a la política de firma. T (Timestamped) añade un sello de tiempo emitido por una Autoridad de Sello de Tiempo (TSA). La DIAN exige específicamente BES con referencia a su policy ID — formalmente es XAdES-EPES con la política de la DIAN incluida, pero comúnmente se referencia como BES en la documentación técnica. Las variantes T, X y A (con archive timestamp) no son requeridas para factura electrónica colombiana.

¿Cómo puedo validar una firma localmente antes de transmitir? Con xmlsec1 desde línea de comandos: xmlsec1 verify --trusted-pem cert-dian.pem documento_firmado.xml. Si la verificación local pasa pero la DIAN rechaza, el problema es de validación específica del policy DIAN, no de la firma matemática. En Java con Apache Santuario: instanciar XMLSignatureFactory, parsear el documento, llamar a XMLSignature.validate(). En Python con xmlsec: usar XMLSecurity.verify_signature(). Los tres deben coincidir en su resultado; si uno valida y otro no, hay diferencia en la canonicalización aplicada.

¿Qué diferencia hay entre el certificado del software y el certificado del firmante? Son dos certificados distintos en el flujo DIAN. El certificado del software (configurado al habilitar el emisor) se usa para autenticarse contra los endpoints SOAP de la DIAN — es decir, para identificar al sistema que está enviando. El certificado del firmante (típicamente el del representante legal o un certificado de persona jurídica del NIT) se usa para firmar el contenido de cada factura — es decir, para identificar al obligado a facturar. Pueden ser el mismo certificado si el sistema y el emisor son la misma entidad, pero típicamente son distintos en arquitecturas BaaS donde un proveedor tecnológico opera el sistema pero la firma debe llevar el certificado del cliente final.

¿Es posible firmar facturas sin tener el certificado físicamente en el servidor? Sí, mediante HSM (Hardware Security Module) o servicios cloud equivalentes (AWS CloudHSM, Azure Dedicated HSM, Google Cloud KMS con keys de tipo asimétrico RSA). En esas arquitecturas, la clave privada nunca sale del HSM; el servidor envía el hash a firmar y recibe la firma de vuelta. Es la opción más segura operativamente y la única viable en arquitecturas multi-tenant con auditoría regulatoria. El costo es mayor que un PFX local — desde unos cientos de dólares mensuales — pero elimina riesgo de filtración del certificado y simplifica la auditoría SOC2 o ISO 27001.