🇨🇷Costa RicaGuía Técnica

Firma digital XAdES-BES en Costa Rica: requisitos técnicos para comprobantes electrónicos

Cómo funciona la firma digital XAdES-BES en Costa Rica, qué certificados acepta Hacienda, el proceso de firma sobre el XML del comprobante y qué errores genera una firma mal formada.

Ing. Carlos Méndez
Arquitecto de Software · Integraciones Fiscales LATAM
6 min lectura4 de septiembre de 2026

Por Ing. Carlos Méndez | 4 de septiembre de 2026

Ing. Carlos Méndez es arquitecto de software con más de 10 años integrando sistemas fiscales en América Latina. Ha liderado implementaciones de facturación electrónica en Colombia, México y Centroamérica para ISVs de mediana y gran escala.

El XML del comprobante está perfectamente formado, pasa la validación del XSD y tiene todos los campos correctos. Pero ATV sigue respondiendo con rechazo. La causa, después de dos días de debug: la firma XAdES-BES está mal posicionada dentro del documento, o el algoritmo de canonicalización no es el que Hacienda espera. La firma digital en Costa Rica no es una operación trivial de ‘firmar el archivo’ — tiene una estructura específica que el XSD no valida pero ATV sí verifica.

Esta guía explica cómo funciona XAdES-BES en el contexto de los comprobantes electrónicos de Costa Rica: el tipo de certificado requerido, el proceso de firma paso a paso, la posición de la firma dentro del XML, los algoritmos aceptados por Hacienda, y los errores más comunes que genera una firma mal formada. Al terminar, usted tendrá el conocimiento técnico para implementar o auditar el componente de firma en su sistema.

Qué es XAdES-BES y por qué lo usa Costa Rica

XAdES (XML Advanced Electronic Signatures) es un estándar europeo de firma digital sobre documentos XML, definido por ETSI. La variante BES (Basic Electronic Signature) es el nivel base del estándar: incluye la firma del contenido, el certificado del firmante, y el momento en que se generó la firma. Costa Rica adoptó XAdES-BES como estándar nacional de firma para comprobantes electrónicos por ser un estándar internacional maduro con implementaciones en múltiples lenguajes.

La firma XAdES-BES se incrusta dentro del propio documento XML, no como un archivo separado (lo que sería una firma detached). Esto significa que el XML firmado es un único archivo que contiene tanto el comprobante como la firma que lo valida. Hacienda verifica esta firma al recibir el documento.

Certificados aceptados por Hacienda Costa Rica

Jerarquía de certificación digital de Costa Rica

La Infraestructura Nacional de Certificación Digital (SINPE-BCCR) de Costa Rica tiene al Banco Central de Costa Rica (BCCR) como autoridad raíz. Bajo esa raíz operan prestadores de servicios de certificación (PSC) autorizados. Los certificados válidos para firmar comprobantes electrónicos deben encadenar hasta la raíz del BCCR.

Prestadores de Servicios de Certificación autorizados en Costa Rica (referencia, verificar lista actualizada en BCCR): • BCCR (emisor directo) • Firma Digital CR (PSC privado) • Otros PSC autorizados por MICITT Los certificados del tipo .p12 o .pfx contienen la clave privada y el certificado público. Son los que se usan en el proceso de firma.

Atributos obligatorios del certificado para firma de comprobantes

El certificado debe tener: el número de cédula del emisor en el campo Subject; el KeyUsage con Digital Signature activado; y no debe estar vencido ni revocado al momento de la firma. Hacienda verifica el estado del certificado contra la lista de revocación (CRL) o OCSP del emisor del certificado. Un certificado válido en el momento de la firma pero revocado posteriormente sigue siendo válido para ese documento.

Proceso de firma XAdES-BES: paso a paso

La firma XAdES-BES sobre un comprobante electrónico de Costa Rica sigue este proceso en orden estricto:

bash
firma-xades-bes-cr.sh
# Proceso de firma XAdES-BES — Costa Rica (pseudocódigo)

1. Canonicalizar el XML del comprobante
   Algoritmo: http://www.w3.org/TR/2001/REC-xml-c14n-20010315
   (Canonical XML 1.0 — NO usar Exclusive Canonical XML)

2. Calcular el digest del XML canonicalizado
   Algoritmo: SHA-256 (http://www.w3.org/2001/04/xmlenc#sha256)
   → DigestValue en Base64

3. Construir el bloque SignedInfo con:
   - CanonicalizationMethod
   - SignatureMethod: RSA-SHA256
   - Reference con DigestValue del paso 2

4. Firmar el bloque SignedInfo con la clave privada del certificado
   Algoritmo: RSA-SHA256 (http://www.w3.org/2001/04/xmldsig-more#rsa-sha256)
   → SignatureValue en Base64

5. Agregar el bloque KeyInfo con el certificado público en Base64

6. Agregar los elementos XAdES:
   - SignedProperties (incluyendo SigningTime y SigningCertificate)
   - Calcular digest de SignedProperties y añadirlo como Reference adicional

7. Insertar el bloque <Signature> completo dentro del XML del comprobante
   Posición: como último hijo del elemento raíz del comprobante

Posición del bloque Signature dentro del XML

La especificación de Hacienda define que el elemento <Signature> debe ser el último hijo del elemento raíz del comprobante. Para una Factura Electrónica, eso significa que debe ir justo antes del cierre de </FacturaElectronica>. Insertar la firma en otra posición resulta en rechazo sin código de error descriptivo.

xml
firma-xades-posicion.xml
<!-- Posición correcta del bloque Signature en una FE -->
<FacturaElectronica xmlns="...">
  <Clave>...</Clave>
  ...
  <ResumenFactura>...</ResumenFactura>
  <!-- La firma va AQUÍ, como último hijo -->
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="xmldsig-...">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
      <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
      <Reference URI="">
        <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
        <DigestValue>base64==</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>base64==</SignatureValue>
    <KeyInfo>...</KeyInfo>
    <Object Id="xmldsig-...-object0">
      <xades:QualifyingProperties Target="#xmldsig-...">
        <xades:SignedProperties Id="xmldsig-...-signedprops">
          <xades:SignedSignatureProperties>
            <xades:SigningTime>2026-09-04T09:00:00-06:00</xades:SigningTime>
            <xades:SigningCertificate>...</xades:SigningCertificate>
          </xades:SignedSignatureProperties>
        </xades:SignedProperties>
      </xades:QualifyingProperties>
    </Object>
  </Signature>
</FacturaElectronica>

Algoritmos requeridos por Hacienda Costa Rica

Hacienda especifica algoritmos exactos. El uso de algoritmos alternativos — aunque sean criptográficamente equivalentes o superiores — genera rechazo:

Algoritmos obligatorios para XAdES-BES en Costa Rica: • Canonicalización: Canonical XML 1.0 (NO Exclusive C14N) • Digest del contenido: SHA-256 • Algoritmo de firma: RSA-SHA256 • Tipo de firma: enveloped (incrustada en el XML, no detached) Usar SHA-1, RSA-SHA1 o cualquier variante distinta resulta en rechazo automático.

Consideraciones para ISVs con múltiples emisores

Un ISV que gestiona 50 o 500 emisores en Costa Rica enfrenta el problema de administrar un certificado .p12 por empresa, con su propia clave privada y fecha de vencimiento. Los certificados vencen anualmente (o bianualmente según el PSC). Una factura intentada con un certificado vencido es rechazada.

Las arquitecturas de gestión de certificados para ISVs multi-emisor son: custodia directa (el ISV almacena los .p12 cifrados y los carga en memoria para firmar), delegar la firma a un proveedor de API (el proveedor gestiona los certificados), o usar un Hardware Security Module (HSM) para ISVs de alto volumen. La primera opción es la más común en implementaciones propias, pero exige cifrado en reposo y políticas de acceso estrictas a las claves privadas.

Bibliotecas disponibles para firma XAdES-BES

No hay una única biblioteca oficial. Las opciones más usadas por la comunidad de desarrolladores en Costa Rica son:

Bibliotecas para firma XAdES-BES en distintos lenguajes (uso bajo responsabilidad del integrador): • Java: xades4j, Apache Santuario (xmlsec) • .NET: Microsoft.Xades, Security.Cryptography • Python: signxml + xades (combinación manual) • Node.js: xml-crypto (requiere extensión para XAdES) • PHP: xmlseclibs Ninguna de estas tiene soporte oficial de Hacienda. La implementación debe validarse contra ATVCERT antes de produccción.

Errores frecuentes de firma y cómo diagnosticarlos

La mayoría de los errores de firma en ATV no tienen códigos de error descriptivos. El diagnóstico requiere eliminar variables una por una. Los errores más comunes son:

bash
errores-firma-cr.sh
# Errores frecuentes de firma XAdES-BES en Costa Rica

1. Algoritmo de canonicalización incorrecto
   Causa: usar Exclusive C14N en lugar de Canonical XML 1.0
   Diagnóstico: revisar el atributo Algorithm de CanonicalizationMethod

2. Firma mal posicionada en el XML
   Causa: <Signature> no es el último hijo del elemento raíz
   Diagnóstico: validar el árbol DOM del XML firmado

3. Certificado con cédula incorrecta
   Causa: clave privada del certificado no coincide con el emisor del comprobante
   Diagnóstico: extraer Subject del certificado y comparar con campo Emisor.Identificacion

4. Certificado vencido al momento del envío
   Causa: no se renovó el certificado a tiempo
   Diagnóstico: verificar NotAfter del certificado vs fecha de emisión del comprobante

5. DigestValue calculado sobre el XML sin canonicalizar
   Causa: se firmó el XML raw, no el canonicalizado
   Diagnóstico: recalcular el digest sobre el XML canonicalizado y comparar

Preguntas frecuentes

¿Cuál es la diferencia entre XAdES-BES y XAdES-T en Costa Rica?

XAdES-T agrega un sello de tiempo (timestamp) de una autoridad de confianza al nivel BES. Costa Rica oficialmente requiere XAdES-BES para comprobantes electrónicos, no XAdES-T. Algunos proveedores agregan el sello de tiempo como capa adicional de seguridad, pero Hacienda no lo exige ni lo valida como requisito de aceptación.

¿Cómo puedo verificar que mi firma XAdES-BES es válida antes de enviar a Hacienda?

El ambiente ATVCERT es el mecanismo oficial de validación. Fuera de ese ambiente, se pueden usar herramientas como ETSI Conformance Checker (online) o la librería xades4j en modo de verificación. Lo útil es separar el proceso: primero validar el XML contra el XSD, luego verificar la firma con una herramienta local, y finalmente enviar a ATVCERT.

¿Qué diferencia hay entre firma enveloped y firma detached en XAdES?

En una firma enveloped, el bloque <Signature> está dentro del documento XML que firma. En una firma detached, el bloque <Signature> es un archivo separado que referencia el documento original. Costa Rica usa firma enveloped: el XML enviado a ATV es un único archivo que contiene tanto el comprobante como su firma.

¿Es posible reutilizar el mismo certificado para múltiples emisores en Costa Rica?

No. Cada certificado está vinculado a la cédula de una persona jurídica o física específica. Un certificado de la empresa A no puede usarse para firmar comprobantes de la empresa B. Hacienda verifica que la cédula del emisor en el XML coincida con la cédula del certificado utilizado para firmar.

Sobre el autor

Ing. Carlos Méndez es arquitecto de software con más de 10 años integrando sistemas fiscales en América Latina. Ha liderado implementaciones de facturación electrónica en Colombia, México y Centroamérica para ISVs de mediana y gran escala.