Anclaje
Todo el valor del registro es una fecha. Y mientras no puedas comprobar esa fecha sin preguntarnos, es nuestra palabra.
Por eso cada día el registro publica un recibo: un fichero de texto corto con un resumen criptográfico de cada versión de cada ficha que guarda, y de cada versión de las instrucciones de cada agente. Ese recibo se sella en la cadena de bloques de Bitcoin mediante OpenTimestamps, y por separado en dos autoridades de sellado RFC 3161. Ninguna de las tres la llevamos nosotros.
A partir de ahí la fecha deja de estar en nuestras manos. Si mañana cambiáramos una fecha de registro, el recibo de ayer dejaría de cuadrar, y el recibo de ayer ya está fuera de nuestro alcance.
Qué demuestra y qué no
Sección titulada «Qué demuestra y qué no»| Demuestra | No demuestra |
|---|---|
| Que estos datos existían antes de un bloque concreto de Bitcoin | Que quien registró sea el dueño legítimo |
| Que su contenido era exactamente ese en esa fecha | Que la fecha de registro declarada sea cierta, solo que existía antes del ancla |
| Que las ediciones posteriores no borraron el historial | Nada sobre las fichas creadas después del último ancla |
Las anclas son diarias, así que entre registrar y anclar hay una ventana de hasta 24 horas en la que sigue habiendo que fiarse de nosotros. Preferimos decirlo a que lo descubras.
El recibo
Sección titulada «El recibo»Un fichero de texto plano, y esos bytes son el artefacto: no una representación de él, sino la cosa misma. Un espacio de más cambiaría su huella y rompería todas las pruebas.
TheHumanBehind registry anchor
anchor_version: 2
recipe_version: 3
cutoff_utc: 2026-08-11T03:45:00.000000Z
records: 101
versions: 128
agent_versions: 14
merkle_root: 3a02599887336f2ab822d678b50edb05bad62eff392ba826093960faaaa543cb
prev_receipt_sha256: genesis
recipe: https://thehumanbehind.com/docs/anchoring
prev_receipt_sha256 es el SHA-256 del recibo del día anterior, y encadena la
serie: un recibo no se puede sustituir sin romper todos los que vinieron después.
El primero de todos dice genesis.
records cuenta números de registro distintos, versions cuenta versiones del
contenido de las fichas y agent_versions cuenta versiones de instrucciones de
agente. El total de hojas del árbol es versions + agent_versions, que es lo
que hace falta para saber cuántas hojas tenía que haber.
Dos formatos de recibo, los dos vivos
Sección titulada «Dos formatos de recibo, los dos vivos»Las anclas del 5 al 10 de agosto de 2026 llevan el formato 1, que no tiene
línea recipe_version ni agent_versions y dice anchor_version: 1. Se
conserva byte a byte porque esos recibos ya están sellados.
Toda línea, en los dos formatos, es clave: valor, una por línea, y está pensada
para leerse por prefijo. Un lector escrito para el formato 1 encuentra dentro
de uno del 2 todo lo que ya conocía: simplemente ignora dos líneas que no había
visto nunca. Si analizas los recibos por número de línea, este es el cambio que
te va a romper.
recipe_version pasó a estar DENTRO de los bytes sellados a propósito. Hasta el
formato 2 vivía solo en una columna de nuestra base de datos. Dentro del recibo,
la sella Bitcoin.
Cada recibo se sirve para siempre en
{SITE.platformUrl}/api/v0/anchors/{"{fecha}"}.txt, y la lista de anclas, con su
bloque de Bitcoin, en {SITE.platformUrl}/api/v0/anchors.json.
La receta
Sección titulada «La receta»Esto es un contrato. Una prueba sellada hoy tiene que verificar dentro de diez años, así que nada de lo que sigue puede cambiar nunca. Si algún día hiciera falta una versión nueva, tendría su propio prefijo y la anterior seguiría funcionando siempre, para que ninguna prueba quede huérfana.
Han existido tres recetas y las tres siguen vivas. Cada ancla publica su propia
recipe_version en /api/v0/anchors.json y se verifica con la receta con la que
se selló.
| Receta | Anclas | Preimagen de la hoja |
|---|---|---|
| v1 | solo la del 5-ago-2026 | THB-ANCHOR-v1|<registry_code>|<version>|<content_hash> |
| v2 | del 6 al 10-ago-2026 | THB-ANCHOR-v2|<registry_code>|<version>|<content_hash>|<leaf_salt> |
| v3 | desde el 11-ago-2026 | THB-ANCHOR-v3|<clase>|<registry_code>|<version>|<digest>|<leaf_salt> |
1 · La hoja
Sección titulada «1 · La hoja»Desde la v3 una hoja puede acreditar dos cosas distintas, y dice cuál en el campo 2, antes que cualquier otro dato:
THB-ANCHOR-v3|record|<registry_code>|<version>|<content_hash>|<leaf_salt>
THB-ANCHOR-v3|agent|<registry_code>|<version>|<agent_sha256>|<leaf_salt>
La hoja es el SHA-256 de esos bytes, en UTF-8.
Una hoja record acredita que el contenido público de una ficha era
exactamente ese en esa versión. Una hoja agent acredita que unas
instrucciones de agente existían y eran exactamente esas, en esa versión.
La clase va dentro porque, sin ella, una prueba de instrucciones sería indistinguible de una prueba de contenido de ficha, y cualquiera podría presentar la primera como si fuera la segunda. Va en el campo 2, delante de todo valor que venga de un usuario, así que dos hojas de clases distintas siempre difieren, sea cual sea el resto.
El texto de las instrucciones no entra nunca en la hoja. Entra su huella. Por eso la prueba sobrevive incluso si algún día hay que retirar ese texto por contener datos personales: la huella, la fecha, la versión y la sal siguen ahí, y el camino de inclusión sigue verificando.
Toda hoja lleva el número de registro, y no un identificador interno, por dos motivos: los identificadores internos no tienen por qué salir de la base de datos, y tú tienes que poder recalcular tu propia hoja con lo que ya tienes. Todos los valores están en la constancia descargable de tu ficha.
El número de versión entra porque, sin él, dos versiones de la misma ficha con el mismo contenido colapsarían en una sola hoja.
leaf_salt son 16 bytes aleatorios, en hexadecimal, y es lo que hace que esto
sea privado. Cada versión tiene la suya, no sale nunca de nuestro servidor, y
recibes la tuya, y solo la tuya, dentro de tu constancia.
Está ahí porque un hash solo esconde su entrada cuando esa entrada es difícil de adivinar. Los números de registro son secuenciales y una ficha tiene pocos campos, así que una hoja sin cegar sería un compromiso sobre datos de poca entropía, y esos se atacan probando candidatos hasta que uno cuadra. Los 16 bytes aleatorios eliminan esa posibilidad: ya no hay nada que probar. Con las instrucciones pesa todavía más que con el contenido: las plantillas de prompt se repiten entre clientes, así que sin cegar serían muy adivinables.
2 · El orden
Sección titulada «2 · El orden»Ascendente por registry_code, luego por el rango de la clase (record = 0,
agent = 1), y luego por version como número.
El rango es un número y no la palabra, a propósito: agent va antes que record
en orden alfabético, así que ordenar por el literal pondría las instrucciones de
una ficha por delante de su contenido, y el orden publicado dependería de cómo se
llamen las clases.
Así que una ficha con dos versiones de contenido y dos de instrucciones aporta, en este orden:
THB-2026-00144 · record · 1
THB-2026-00144 · record · 2
THB-2026-00144 · agent · 1
THB-2026-00144 · agent · 2
Las versiones se comparan como números: como texto, la 10 caería entre la 1 y la 2.
Los números de registro se comparan como texto, por sus bytes. Hasta el 31 de
julio de 2026 el número era de ancho fijo y eso equivalía a compararlos como
números; ya no, porque el ancho pasó a ser mínimo y no fijo, así que pasadas
99.999 fichas en un año THB-2026-100000 va antes que THB-2026-99999. No pasa
nada: la regla es el orden por los bytes del código, que está bien definida y la
puede reproducir cualquiera. Esta página afirmaba que los dos órdenes eran
equivalentes, y esa frase estaba mal.
3 · El árbol
Sección titulada «3 · El árbol»Un árbol de Merkle binario. Cada nodo interior es el SHA-256 de sus dos hijos concatenados como bytes crudos, no como texto hexadecimal.
Cuando un nivel tiene un número impar de nodos, el último sube tal cual al nivel siguiente. No se duplica. Duplicarlo es lo que hace Bitcoin, y es lo que hizo posible CVE-2012-2459: duplicando, dos conjuntos de hojas distintos pueden dar la misma raíz, lo que en un registro significaría dos historias distintas detrás de una sola prueba.
La raíz del nivel más alto es el merkle_root del recibo.
4 · Tu camino de inclusión
Sección titulada «4 · Tu camino de inclusión»La constancia de tu ficha te da los hermanos que hacen falta para subir desde tu
hoja hasta la raíz, cada uno con el lado que le toca. Empieza por tu hoja y en
cada paso hashea el par en el orden indicado. Si acabas en el merkle_root de
ese recibo, tu ficha estaba en ese ancla.
El mismo código sirve para las dos clases de hoja, porque lo único que cambia es
lo que dice la preimagen. Si tu ficha es de tipo agente,
anchor.agent_instructions de tu constancia trae una entrada por cada versión
anclada de tus instrucciones, cada una con su preimagen, su sal y su camino,
todos subiendo a la misma raíz.
import hashlib
# Directo de tu proof.json: `leaf_preimage` ya viene unido, no hay nada que
# montar. Esta es una hoja de instrucciones.
preimagen = "THB-ANCHOR-v3|agent|THB-2026-00144|2|0acb5e6a…50|5051…5f"
camino = [ # tambien de tu proof.json, en orden
("b1ef4d226bd74200ffdcc71b40b0b361280c96c5005fab3c3e8cb511e4b0044e", "right"),
# ...
]
actual = hashlib.sha256(preimagen.encode()).digest()
for hermano_hex, lado in camino:
hermano = bytes.fromhex(hermano_hex)
par = hermano + actual if lado == "left" else actual + hermano
actual = hashlib.sha256(par).digest()
print(actual.hex()) # debe ser el merkle_root del recibo de ese dia
Comprobar una versión concreta
Sección titulada «Comprobar una versión concreta»Todo lo anterior demuestra dónde está una ficha hoy. Lo que suele decidir una reclamación es qué decía antes, y cuándo cambió. Las dos cosas se conservan y las dos se anclan.
Son dos series, no una
Sección titulada «Son dos series, no una»Una ficha tiene dos historiales de solo añadir, y cada uno produce sus propias hojas:
| Serie | Una versión cada vez que… | Clase de hoja |
|---|---|---|
| Contenido | cambia alguno de los ocho campos sellados | record |
| Instrucciones | se reemplazan las instrucciones de un agente | agent |
La hoja de una versión es la misma receta que acabas de leer, con el número de esa versión en el campo 4. Con las versiones antiguas no pasa nada especial: la versión 1 de una ficha es una hoja del árbol igual que la 9, y sigue estándolo en todas las anclas desde el día en que se escribió.
Recomputar la huella de una versión antigua, con un navegador y nada más
Sección titulada «Recomputar la huella de una versión antigua, con un navegador y nada más»El historial público de una ficha verificada está abierto:
curl {SITE.platformUrl}/api/v0/records/laia-torres/history.json
Cada entrada de la serie de contenido lleva el snapshot exacto que se hasheó.
Hashéalo como explica comprobar un sello y tiene
que salir el content_hash de esa versión. Sin cuenta, sin permiso y sin nada que
creerte.
La serie de instrucciones publica cuántas versiones ha habido y cuándo, y nada más. Ni el texto, que es de quien lo escribió, ni su huella: las instrucciones de un agente suelen ser plantillas que se repiten entre clientes, así que publicar el digest permitiría a cualquiera con una plantilla candidata confirmar que esa ficha la usa. Eso es un oráculo de confirmación, y es justo por lo que hubo que sustituir la receta v1. La huella viaja al dueño de la ficha, dentro de su propia constancia, y a ningún sitio más: la base de datos tampoco entrega esa columna a quien lee de forma anónima, porque una promesa que la base de datos no cumple no es una promesa.
Seguir una versión hasta Bitcoin
Sección titulada «Seguir una versión hasta Bitcoin»Para eso hace falta la hoja, la hoja necesita la sal, y las sales no son públicas nunca: si lo fueran, cegar no serviría de nada y volvería el ataque que mató a la v1.
Por eso el camino completo vive en el proof.json del dueño, que ahora lleva una
entrada por versión, en dos sitios que reflejan las dos series:
- Las versiones de contenido están en
history.versions, cada una con elsnapshotque se hasheó y un objetoleafcon lapreimageya montada, elhashde la hoja y elinclusion_path. - Las versiones de instrucciones están en
anchor.agent_instructions.versions, cada una con suleaf_preimage, suleafy suinclusion_path. Sus entradas enhistory.versionsllevanleaf: nully unproof_inque apunta aquí, para no escribir la misma prueba dos veces.
Ese fichero es del dueño y puede publicarlo donde quiera, y quien lo reciba no
necesita nada nuestro para comprobarlo: recomputa cada hoja desde su preimagen,
recorre su camino, aterriza en la raíz de Merkle del ancla, y comprueba esa raíz
contra el recibo y el .ots, que son públicos. Lo único que pones de otra persona
es el fichero.
Las versiones escritas después del último ancla salen como pending_next_anchor y
sin camino, porque de verdad todavía no están en ese árbol. Su sal y su preimagen
se entregan igualmente, para que se puedan guardar hoy y comprobar contra el ancla
de mañana.
Comprobar el ancla en sí
Sección titulada «Comprobar el ancla en sí»Dos maneras. La primera si quieres acabar en un minuto, la segunda si quieres que siga funcionando dentro de veinte años.
La fácil
Sección titulada «La fácil»Descarga el recibo y su prueba:
curl -O {SITE.platformUrl}/api/v0/anchors/2026-08-06.txt
curl -O {SITE.platformUrl}/api/v0/anchors/2026-08-06.ots
Suelta los dos ficheros en opentimestamps.org. Te dirá qué bloque de Bitcoin contiene ese recibo. El hash se calcula en tu navegador; el fichero no sale de tu máquina.
La que sobrevive a las herramientas
Sección titulada «La que sobrevive a las herramientas»Esa web funciona sobre una librería de JavaScript que no recibe un cambio funcional desde 2022. Por eso la lista de anclas publica además, para cada una, la altura del bloque de Bitcoin y el merkle root de ese bloque. Busca el bloque en cualquier explorador, compara el merkle root y ya está. Sin herramientas, sin librerías, sin depender de que una web siga existiendo.
Con el cliente de OpenTimestamps instalado, esos dos valores salen de:
ots --no-bitcoin verify 2026-08-06.txt.ots
Los tokens RFC 3161
Sección titulada «Los tokens RFC 3161»El mismo recibo, sellado por dos autoridades independientes. Se comprueban al instante, sin cadena de bloques y sin esperas:
curl -O "{SITE.platformUrl}/api/v0/anchors/2026-08-06.tsr?tsa=freetsa"
openssl ts -verify -data 2026-08-06.txt -in 2026-08-06.tsr -CAfile cacert.pem
Existen junto al ancla de Bitcoin, no en su lugar, porque las dos fallan de maneras opuestas. Si los calendarios de OpenTimestamps desaparecieran antes de completar una prueba pendiente, los tokens seguirían en pie. Si una autoridad cerrara o le comprometieran la clave, seguiría en pie Bitcoin.
Por qué tarda horas en confirmarse
Sección titulada «Por qué tarda horas en confirmarse»OpenTimestamps no pone una transacción en la cadena por cada fichero. Los
calendarios juntan miles de digests, montan un árbol y publican una sola raíz.
Así que una prueba recién hecha dice pendiente durante unas horas, hasta que esa
transacción se confirma, y el registro la completa solo cuando ocurre.
confirmed: false en la lista de anclas es sencillamente una prueba en camino:
el estado normal durante parte del día.
Privacidad
Sección titulada «Privacidad»Los calendarios nunca ven tus datos. Antes de enviar nada, el cliente añade 16 bytes aleatorios al digest y lo vuelve a hashear, así que lo que viaja es un valor opaco del que no se puede recuperar ni el recibo ni su huella.
El recibo tampoco contiene datos personales: solo conteos y una raíz.
Y los hermanos de tu camino de inclusión no revelan nada de las fichas a las que
pertenecen, porque cada hoja va cegada con su propia sal. Ese es todo el
trabajo de leaf_salt: sin 128 bits de azar que no están en ningún sitio
público, no hay candidato que probar contra un hermano, así que un camino
demuestra que tu ficha está en el árbol sin decir nada de las demás.
Lo que los conteos sí revelan, y preferimos decirlo
Sección titulada «Lo que los conteos sí revelan, y preferimos decirlo»El recibo publica cuántas fichas, cuántas versiones de contenido y cuántas versiones de instrucciones guardaba el registro ese día. Los números de registro son secuenciales y públicos, así que los totales nunca fueron un secreto, y con las hojas cegadas un conteo no confirma nada de ninguna ficha en concreto.
Pero mientras el registro sea pequeño, que agent_versions cambie de un día para
otro dice que alguien editó las instrucciones de su agente ese día. Ni quién
ni qué: el texto sigue siendo privado y la huella sigue cegada. Lo público es el
hecho y la fecha de una edición. Si eso te importa, conviene saberlo antes de
registrar, no después.