Qué prueba —y qué no— el hash de un fichaje
En una respuesta
La cadena de hash demuestra que un registro no se ha alterado después de guardarse, y que no se ha borrado ni reordenado ninguno. No demuestra que la hora anotada sea la real, ni quién apretó el botón, ni sirve como prueba ante notario: la clave la custodia el prestador. Es control de integridad, no fe pública.
Casi todo el software de control horario dice que sus registros son «inalterables». Es una palabra grande y casi siempre falsa: los datos viven en una base de datos que alguien puede editar. Lo que sí se puede construir es algo más modesto y más útil — que cualquier alteración deje huella —, y eso tiene una definición técnica exacta, unas garantías concretas y unos límites que conviene decir en voz alta.
Esta es la especificación de cómo sellamos los fichajes en ControlHorario.digital. La publicamos entera, con sus costuras, por dos razones: para que una asesoría o una inspección puedan comprobar qué significa realmente el sello, y porque un mecanismo de integridad que solo funciona mientras nadie lo mira no es un mecanismo de integridad.
Qué se sella exactamente
Cada fichaje genera una cadena canónica: una única línea de texto construida con los campos tal y como están guardados en la base de datos, separados por barras verticales.
id | company_id | employee_id | evento | fecha_hora | meta
Por ejemplo, la entrada número 1.482 de la empresa 7, del empleado 31, a las 08:59:03:
1482|7|31|IN|2026-08-28 08:59:03|
Que se construya con los valores almacenados no es un detalle: es lo que hace el sello reproducible. Si el verificador formateara la fecha de otra manera que el sellador, obtendría un hash distinto y cantaría manipulación donde no la hay. Por eso el formato de fecha_hora es siempre Y-m-d H:i:s y el campo meta —donde va el contexto del fichaje— entra crudo, sin normalizar.
Cómo se encadena
El sello de cada fichaje es un HMAC-SHA256 que incluye el sello del fichaje anterior:
this_hash = HMAC-SHA256(clave, cadena_canónica | prev_hash)
Ese «anterior» es lo que convierte una lista de sellos sueltos en una cadena. Un sello aislado detecta que ese registro cambió. Encadenarlo detecta además tres cosas que un sello aislado no ve:
- Borrados. Si desaparece un fichaje, el siguiente apunta a un
prev_hashque ya no existe en la secuencia. - Reordenaciones. Cambiar el orden rompe los enlaces aunque cada registro por separado siga intacto.
- Inserciones. Colar un fichaje a posteriori exigiría recalcular todos los sellos posteriores.
Al verificar, recorremos los fichajes de la empresa por id ascendente y comprobamos dos cosas por cada uno: que su sello cuadra con su contenido, y que su prev_hash es exactamente el sello del anterior. Las dos tienen que cumplirse. La primera protege el contenido; la segunda, la secuencia.
Una clave por empresa
La clave con la que se firma no es la misma para todos. Se deriva de una clave maestra para cada empresa:
clave_empresa = HMAC-SHA256(clave_maestra, "company:" + company_id)
Esto compartimenta el riesgo: si se filtrara la clave de una empresa, no serviría para tocar las cadenas de las demás. Y al derivarse en el momento, no hace falta almacenar un secreto distinto por cliente, que sería un problema de custodia mayor que el que resuelve.
Qué prueba y qué no
Aquí está la parte que casi nadie escribe. Un sello criptográfico responde a una pregunta muy concreta y a ninguna más.
| Pregunta | ¿Lo responde la cadena? |
|---|---|
| ¿Se ha modificado este registro después de guardarse? | Sí. Cualquier cambio en cualquier campo sellado rompe el hash. |
| ¿Se ha borrado o reordenado algún fichaje? | Sí. El encadenado lo detecta aunque el resto esté intacto. |
| ¿La hora anotada es la hora real en que la persona entró? | No. El sello congela lo que se registró, no certifica que lo registrado fuese cierto. Si el fichaje se hizo tarde o por otra persona, sella un dato falso con la misma solidez que uno verdadero. |
| ¿Quién pulsó el botón? | No. El PIN acredita que alguien conocía ese PIN. Eso es autenticación débil, y llamarlo identidad sería mentir. |
| ¿Vale como prueba frente al propio prestador? | No por sí sola. La clave la custodiamos nosotros. Quien tiene la clave puede recalcular una cadena entera y dejarla coherente. Ver más abajo. |
El límite serio: quién tiene la clave
Este es el punto que nos parece deshonesto esquivar. Un HMAC protege frente a quien no tiene la clave: alguien con acceso a la base de datos, una consulta SQL suelta, una cuenta de administración comprometida, un empleado con permisos que no debería tener. Frente a todo eso, la cadena funciona: los datos se pueden cambiar, pero no de forma silenciosa.
No protege frente a quien sí la tiene. Nosotros la tenemos. Un proveedor que quisiera falsificar un histórico podría, técnicamente, reescribirlo y volver a sellarlo. Que no lo hagamos es una cuestión de confianza y de responsabilidad legal, no de criptografía. Cualquier fabricante que le diga que su hash le protege también de él, o no ha entendido su propio sistema o espera que usted no lo entienda.
La forma de reducir ese límite no es criptográfica sino de custodia: sacar una copia del sello fuera de nuestro alcance. Por eso cada mes se congela un sello del periodo en un cierre mensual, con el número de fichajes que abarca, y la empresa puede descargar esa acta y guardarla donde quiera — su propio correo, su gestoría, su archivo. Si un sello guardado por usted en septiembre coincide con el que calculamos hoy, ese mes no se ha tocado, y esa comprobación ya no depende de nuestra palabra. Es el mismo principio que fechar un documento enviándoselo por burofax a uno mismo.
Cómo comprobarlo sin fiarse de nosotros
Cada cierre mensual lleva un código público firmado que abre una página de verificación, accesible por QR y sin necesidad de tener cuenta. Ese código no contiene ningún secreto: solo la empresa, el mes y una firma corta que impide fabricar códigos de otras empresas. Un trabajador o un inspector pueden usarlo para confirmar que el periodo cuadra.
Si le interesa auditarlo de verdad, lo que necesita es esto:
- El listado de fichajes del periodo, con
id, empresa, empleado, evento, fecha-hora ymeta. - Los sellos:
prev_hashythis_hashde cada uno. - Reconstruir cada cadena canónica y comprobar el encadenado.
Los dos primeros salen del informe mensual. El tercero solo requiere la clave derivada de esa empresa; si su asesoría o su departamento de sistemas quiere hacer esa verificación por su cuenta, escríbanos y hablamos de cómo entregarla sin comprometer al resto de clientes.
Dos rarezas que se ven en los informes
«Eslabones en formato antiguo». Hubo una etapa en que el histórico se sellaba con la clave maestra sin derivar. Esos sellos son legítimos y su contenido está intacto; simplemente están firmados con otra clave. El verificador acepta cada eslabón si cuadra con la derivada o con la maestra, y cuenta cuántos quedan del formato viejo. No se resellan de golpe, porque resellar reescribiría hashes que ya constan en actas entregadas.
Una cadena rota nunca se repara sola. Es deliberado. Resellar automáticamente un histórico alterado recalcularía los hashes y borraría exactamente la prueba de que hubo una alteración: dejaría el sistema «verde» y destruiría la evidencia. Cuando la verificación diaria detecta una ruptura, avisa e indica el primer fichaje afectado, y ahí se queda hasta que una persona decida qué pasó.
Y respecto a la ley
El Real Decreto-ley 8/2019 obliga a llevar un registro diario de jornada y a conservarlo cuatro años a disposición de las personas trabajadoras, sus representantes y la Inspección de Trabajo. No exige firma criptográfica, ni hash, ni cadena: un registro en papel puede cumplir la norma.
Lo que aporta el sellado no es cumplimiento, es capacidad de demostrar. Ante una discrepancia sobre las horas de un mes concreto, la diferencia entre un registro que cualquiera pudo editar sin dejar rastro y otro que cuadra con un sello que la empresa guardó en su día es, en la práctica, toda. Pero es una diferencia probatoria, no un requisito legal, y quien se lo venda como «obligatorio» le está vendiendo otra cosa.