InicioTraazzaGuías › La huella de Verifactu

Guía técnica

Qué es la huella encadenada de Verifactu y cómo se calcula

La huella es lo que hace que los registros de Verifactu sean inalterables: un hash SHA-256 que incluye la huella del registro anterior, de modo que alterar una factura pasada rompe toda la cadena.

Guía técnica · Integridad y trazabilidad

La idea: una cadena de hashes

Cada registro de facturación calcula un hash SHA-256 sobre un conjunto fijo de sus campos, concatenados en un orden concreto con el formato Campo=valor&Campo=valor&…. La clave es que ese cálculo incluye la huella del registro anterior. Así, los registros quedan enlazados como los eslabones de una cadena.

Por qué eso lo hace inalterable

Si alguien modifica una factura ya emitida, su huella cambia. Y como esa huella entraba en el cálculo de la siguiente, y la siguiente en la próxima… toda la cadena posterior deja de cuadrar. Es el mecanismo antifraude que persigue el reglamento: no se puede borrar o alterar una factura «por en medio» sin dejar rastro.

Detalles que importan

  • El algoritmo es SHA-256 y el resultado se representa en hexadecimal en mayúsculas.
  • El orden de los campos y el formato son fijos: un cambio mínimo produce una huella distinta.
  • El primer registro de la cadena se marca como tal; los siguientes referencian al anterior.

En Traazza, la huella está validada al carácter contra los tres ejemplos oficiales de la AEAT (alta, alta encadenada y anulación). El valor coincide exactamente con el de referencia.

En código

python
from traazza.modelos import Emisor, Cadena, LineaDesglose

cadena = Cadena(Emisor("89890001K", "EMPRESA SL"))
f1 = cadena.alta(num_serie="2026/1", fecha_expedicion="01-01-2026",
    tipo_factura="F2", cuota_total="21.00", importe_total="121.00",
    descripcion_operacion="Venta", desglose=[LineaDesglose("100","21","21")])
f2 = cadena.alta(num_serie="2026/2", fecha_expedicion="01-01-2026",
    tipo_factura="F2", cuota_total="21.00", importe_total="121.00",
    descripcion_operacion="Venta", desglose=[LineaDesglose("100","21","21")])

print(f1.huella)               # primer registro
print(f2.huella_anterior == f1.huella)  # True: encadenado

El punto delicado: persistir la cadena

En producción tu programa arranca y para. Si cada vez creas una cadena nueva vacía, marcará cada factura como «primer registro» y la AEAT devolverá el error 2007. La solución es guardar la huella del último registro y arrancar la siguiente cadena desde ahí.

Edu García
Edu García Desarrollador Full Stack en Sevilla y autor de Traazza, la librería open source de Verifactu en Python. Lo que escribo aquí sale de integrar Verifactu de verdad contra los sistemas de la AEAT, con sus errores reales incluidos. edugarciadev.com · GitHub