Saltar al contenido

Esta página todavía no está disponible en español. Estás viendo la versión en inglés.

Development

When an RFC test vector isn't the RFC's test vector

Por Victor Da Luz
securitytestingdev-logfreetoolbox

I was building freetoolbox.net’s TOTP code generator, the client-side tool that computes the same 6-digit codes an authenticator app shows. TOTP is RFC 6238, layered on HOTP (RFC 4226), and the whole thing lives or dies on getting HMAC-SHA1 and a truncation step exactly right. Getting it “close” isn’t good enough, since a wrong code is indistinguishable from a right one until you actually try to log in with it.

The obvious move was to fetch both RFCs, grab their published test vectors, and write the test suite against those known-correct values. So I did, and got back a table of results that looked completely normal, until I read the hex strings closely. Several of the truncated-hash entries were seven characters long instead of eight, things like “82fef30” and “4e5b397”. A truncated SHA1 byte string doesn’t come in odd lengths. Something had mangled the numbers on the way out.

I don’t think this was a scraping bug so much as a compression bug: the fetch tool summarizes what it reads, and summarizing a table of hex digits is exactly the kind of task where an LLM will confidently drop a character and never notice, because the result still looks like a hex string. It’s the same failure mode I’ve hit before, a web search returning a wrong pricing formula that read as perfectly reasonable prose. Except here the input wasn’t prose, it was supposed to be exact.

So I didn’t use the fetched numbers. I opened Node, imported crypto, and implemented HMAC-SHA1 plus RFC 4226’s dynamic truncation by hand, then ran it against the RFC’s own worked inputs to see if my numbers matched what the fetch had returned. Where they didn’t, I trusted the computation, not the summary. That gave me 23 verified vectors across RFC 4226, RFC 6238, and RFC 4648’s base32 encoding, all recomputed from a real implementation instead of copied from a possibly-corrupted table.

The test suite that shipped is anchored to those recomputed values, not the original fetch. If I’d trusted the summary, the tool’s tests would have quietly locked in wrong numbers, and nothing about the article or the UI would have caught it, since a subtly wrong TOTP implementation still produces a plausible-looking 6-digit code every 30 seconds. It just wouldn’t match what a real authenticator app computes for the same secret.

The lesson generalizes past this one tool. Any time a task needs an exact value from a spec, a hex constant, a pricing formula, a cited number, don’t trust an AI-summarized fetch of the source. Recompute it, or find the number stated as plain text in the primary source, and treat disagreement as a reason to trust your own computation over the summary.

Lecturas relacionadas

Development

El error que en realidad era el depurador

El error de recorte móvil en todo el sitio que no existía: Chrome headless limita en silencio a un piso de 500px y recorta la captura al ancho que se haya pedido.

Leer
Development

El bug detrás del bug

Un widget de GitHub roto llevaba a una demo del proyecto original en pausa, y de paso apareció una CSP fijada por hash invalidada en silencio por un arreglo de accesibilidad de una línea.

Leer

También te podría ser útil

RackNerd

RackNerd VPS

Alojamiento VPS económico para servicios ligeros que funcionan de forma continua.

Como afiliado de RackNerd, obtengo ingresos por las compras que califican.

Más información
Airalo

eSIM Airalo

eSIM de datos local para viajes - sin necesidad de cambiar una SIM física.

Este es mi enlace de referido de Airalo. Obtienes un descuento en tu primer eSIM y yo obtengo crédito de Airalo para el mío.

Más información
Proton

Proton VPN

VPN comercial con filtrado NetShield e interruptor de apagado automático.

Como socio de Proton, obtengo ingresos por las compras que califican de los servicios de privacidad y seguridad de Proton (Pass, Mail, VPN, Drive).

Más información