# Protocolo `mensajesTiempo/1`

> **To whoever reads this in the future.** This is the specification of a listening post for messages from the
> future, switched on in October 2026. If you can send information backwards in time, send a signed
> `mensaje-pasado` envelope (section 3) to any relay listed by its operators, anchored to the most recent
> drand *quicknet* round you know. If it arrives before that round exists, the receiver can prove it.
> Nobody in the receiver's present can forge a future drand signature.

Este documento basta para implementar un cliente o un relay compatible sin leer el código.

## 1. Reloj: drand quicknet

| Campo | Valor |
|---|---|
| Hash de la cadena | `52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971` |
| Clave pública (G2) | `83cf0f2896adee7eb8b5f01fcad3912212c437e0073e911fb90022d3e760183c8c4b450b6a0a6c3ac6a5776a2d1064510d1fec758c921cc22b0e17e63aaf4bcb5ed66304de9cf809bd274ca73bab4af5a6e9c76a4bc09e76eae8991ef5ece45a` |
| Esquema | `bls-unchained-g1-rfc9380` (firmas en G1, 48 bytes) |
| Periodo | 3 s |
| Génesis | 1692803367 (Unix) |
| DST | `BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_` |

- `ronda(t) = floor((t − génesis) / 3) + 1`, con `t` en segundos.
- `fecha(r) = génesis + (r − 1) · 3`.
- Una baliza `{ronda, firma}` es auténtica si `BLS.verify(firma, hash_to_G1(sha256(ronda como uint64 big-endian)), clave_pública)`.
- La API pública (`https://api.drand.sh/<hash>/public/<ronda|latest>`) devuelve HTTP 425 si se pide una ronda futura.

## 2. Identidad

Una semilla de 32 bytes. Las claves salen de ella con HKDF-SHA256 (sin sal, 32 bytes):

- firma Ed25519: `info = "mensajesTiempo/1 firma"`
- cifrado X25519: `info = "mensajesTiempo/1 cifrado"`

En disco, la semilla se guarda cifrada con scrypt (N=2^15, r=8, p=1) y AES-256-GCM, a partir de una frase secreta.
**Quien tenga la semilla es esa persona a efectos del protocolo.** Así se reconoce al "yo futuro": firma con la misma clave.

## 3. El sobre

Un objeto JSON. Se firma la forma **canónica** (claves ordenadas, sin espacios, sin el campo `firma`), en UTF-8,
con Ed25519. El `id` de un sobre es `sha256(canónico(sobre completo, con firma))` en hex.

Campos comunes:

| Campo | Contenido |
|---|---|
| `protocolo` | `"mensajesTiempo/1"` |
| `tipo` | `"carta-futuro"`, `"mensaje-pasado"` o `"tarjeta"` |
| `de` | clave pública Ed25519 del autor (hex, 64) |
| `cifrado` | clave pública X25519 del autor (hex, 64), para poder contestarle |
| `alias` | nombre declarado por el autor (opcional, ≤ 60) |
| `para` | clave Ed25519 del destinatario, o `"publico"` |
| `creado` | fecha ISO que declara el autor. **No se usa como prueba.** |
| `ancla` | `{cadena, ronda, firma}`: la baliza drand más reciente que conocía el autor |
| `nonce` | 12 bytes aleatorios en hex |
| `firma` | firma Ed25519 (hex, 128) |

Tamaño máximo: 64 KiB en forma canónica.

### 3.1 `carta-futuro` (presente → futuro)

- `abrir_en`: `{ronda, fecha}`, con `ronda > ancla.ronda`.
- `contenido.modo = "tlock"` (pública) o `"tlock+sellado"` (privada).
- `contenido.datos`: armadura *age* de [tlock](https://github.com/drand/tlock) cifrada contra `abrir_en.ronda`.
  - En `tlock+sellado`, lo que va dentro de tlock es un **sobre sellado** (3.4) en base64 para el destinatario.
  - Antes de esa ronda no lo puede abrir nadie. Después, en modo sellado, solo el destinatario.

### 3.2 `mensaje-pasado` (futuro → pasado)

- `destino`: fecha ISO del pasado a la que el autor quiere llegar.
- `contenido.modo = "claro"` (datos = JSON en texto) o `"sellado"` (datos = sobre sellado en base64).

Puede incluir cualquier otra predicción en el texto. La prueba que vale es el ancla.

### 3.3 `tarjeta`

Sin contenido, siempre `para: "publico"`. Sirve para que otros conozcan tu clave de cifrado.

### 3.4 Sobre sellado

X25519 efímero + HKDF-SHA256 (`sal = efímera_pub ‖ destinatario_pub`, `info = "mensajesTiempo/1 sellado"`) + AES-256-GCM.
En base64: `efímera_pub (32) ‖ iv (12) ‖ cifrado ‖ etiqueta (16)`.

La carga en claro es `{"texto": "...", "escrito": "<ISO>"}`.

## 4. Prueba de futuro

Un receptor acepta un sobre si su estructura es válida, su firma Ed25519 corresponde a `de` y su ancla es una baliza auténtica (sección 1).

Al recibirlo, **después** de tenerlo en la mano, el receptor mide el **presente** `P`:

- `P = max(última baliza auténtica descargada, ronda(reloj local))`.
- Si no puede descargar una baliza auténtica, el sobre queda `sin-testigo` y no se afirma nada.

Con eso se clasifica:

- `anomalia` si `ancla.ronda > P + 20`. El sobre llegó antes de poder escribirse.
- `coherente` en cualquier otro caso.

Nadie puede calcular la firma de una ronda que la red no ha emitido, así que una anomalía solo tiene dos explicaciones: el mensaje viene del futuro, o la red drand está comprometida (por encima de su umbral de nodos).

### 4.1 Libro del testigo

Cada recepción se anota en un registro de solo-añadir: `{n, anterior, id, origen, presente, estado, hash}`, con
`hash = sha256(canónico(entrada sin hash))` y `anterior` = hash de la entrada previa (`"0"*64` en la primera).
Cualquier modificación rompe la cadena.

### 4.2 Límites honestos

- El testigo local prueba la anomalía **para su dueño**, que confía en su reloj y en su libro. Para convencer a terceros harían falta además el recibo firmado del relay y un sello de tiempo externo (RFC 3161 u OpenTimestamps) del registro. Eso todavía no está implementado.
- Por lo que se sabe de las curvas temporales cerradas, ninguna máquina del tiempo alcanza instantes anteriores a su construcción. Un receptor solo puede recibir algo a partir de su encendido. Cada cliente lo deja registrado en `encendido.json` con una baliza auténtica.
- Una carta tlock depende de que drand siga emitiendo hasta su ronda de apertura. drand ya retiró una red (*fastnet*) en 2024.

## 5. API de un relay

| Método y ruta | Qué hace |
|---|---|
| `POST /v1/sobres` | Cuerpo: un sobre. `201 {recibo, duplicado:false}`, `200` si ya existía, `422` si no es válido, `429` por exceso de envíos. |
| `GET /v1/sobres?desde=SEQ&para=CLAVE&limite=N` | `{registros, ultimo, mas}`. Devuelve los públicos y los dirigidos a `CLAVE` con `seq > desde`. El cliente guarda `ultimo` como cursor. |
| `GET /v1/sobres/ID` | Un registro. |
| `GET /v1/info` | Nombre, clave del relay, cadena drand, desde cuándo escucha, presente actual. |
| `GET /v1/anomalias` | Registros en los que el propio relay vio `ancla.ronda > presente + 20`. |
| `GET /protocolo` | Este documento. |

Cada registro tiene la forma `{seq, id, recibido_en, presente, recibo, sobre}`.

El `recibo` es `{relay, seq, id, recibido_en, ronda_presente, presente_verificado, firma}`, y va firmado con la clave
Ed25519 del relay sobre su forma canónica sin `firma`. Los clientes fijan esa clave la primera vez que contactan con el relay (TOFU).
