SeguridadHMACSesionesCriptografíaVerificación

El mismo formato de texto no garantiza la misma firma

Publicado el 2026-08-31 · Xiliux

Teníamos la misma sesión escrita dos veces —una copia en cada aplicación— y una librería común para dejar de duplicarla. El token se ve igual en las tres: id|version|caducidad|firma, un HMAC-SHA256 sobre la carga.

La tentación era obvia: «mismo formato de tres campos, migrar es transparente, las cookies vivas siguen valiendo». Lo dábamos por hecho.

Antes de tocar nada computamos la firma de una misma carga con las dos implementaciones y la comparamos contra el vector fijo real de la librería —un token congelado, pegado como literal en las pruebas justamente para esto—. No coincidían.

La causa no estaba en el formato. La librería, al endurecerse, había empezado a anteponer la longitud del dominio de firma al mensaje HMAC (un arreglo contra una ambigüedad de prefijo). Con el dominio vacío de una sesión normal eso ya cambia el mensaje: una firma es HMAC(carga) y la otra HMAC([8 bytes cero]‖carga). Mismo texto, firma distinta.

Consecuencia: migrar a la librería común cierra la sesión de todos los usuarios en el despliegue. No es un bug —la librería es más estricta, no menos— pero es una interrupción real que se decide y se anuncia, no que se descubre en producción.

La lección de método: una prueba de ida y vuelta —emitir y verificar con el mismo binario— mide el códec contra sí mismo. Pasa en verde aunque cambies el separador, el orden de los campos o el motor de base64… y cerraría la sesión de todo el mundo sin un solo test en rojo. Lo único que discrimina es un vector fijo: un token real congelado, verificado por el binario de hoy. Si se pone rojo, lo guardado dejó de leerse —y eso se decide, no se regenera—.

La regla que nos llevamos: la compatibilidad de una firma no se lee del formato. Se mide contra un artefacto congelado, antes de afirmar «compatible con lo ya emitido».

Preguntas frecuentes

¿Por qué no basta un test que emita y verifique el token?

Porque mide el códec contra sí mismo: emitir y verificar con el mismo binario sale coherente aunque cambies el formato, y cerraría la sesión de todos sin ponerse rojo. Hace falta un vector fijo —un token real congelado— que solo el formato correcto verifica.

¿Qué es un «prefijo de longitud del dominio»?

Al firmar dentro de un dominio (para separar, por ejemplo, una sesión de un token intermedio de 2FA) se antepone la longitud del dominio al mensaje HMAC. Sin ella, dominio‖carga es ambiguo y dos pares distintos producen la misma firma; con ella, la codificación es inyectiva.

¿Se puede migrar sin cerrar la sesión de nadie?

Sí, con una ventana de doble verificación: aceptar las dos firmas, emitir con la nueva y retirar la vieja tras la vida máxima de sesión. Elegimos el cierre único por ser más simple y no dejar código transitorio que alguien tenga que desmontar después.

← Ver más artículosCotizar un proyecto