Firmas de anillo
Cómo demostrar "poseo una de estas claves" sin decir cuál
Una firma de anillo (ring signature) demuestra que el firmante conoce la clave privada de una de las n claves públicas del anillo, sin revelar cuál. Monero usa una versión vinculable: junto con la firma va una key image para que la misma salida no se pueda gastar dos veces. El esquema actual es CLSAG, con un tamaño de anillo de 16.
Primero: una firma de Schnorr simple
Para entender los anillos, veamos primero cómo demostrar el conocimiento de una clave x para P = x·G:
- El firmante elige un
αaleatorio y calculaα·G. - Calcula el desafío
c = Hs(message ‖ α·G). - Calcula la respuesta
s = α − c·x. La firma es(c, s). - El verificador reconstruye
s·G + c·P = (α − cx)·G + c·x·G = α·Gy comprueba queHs(message ‖ α·G) = c.
Sin conocer x no se puede encontrar un s para un c dado: c depende de α·G, que debe quedar fijado antes de conocer c.
La idea del anillo: cerrar la cadena de desafíos
Ahora tenemos n claves públicas P₀ … Pₙ₋₁ y conocemos la clave de solo una, digamos Pπ. El truco: cada desafío se calcula a partir del eslabón anterior, y la cadena se cierra formando un anillo.
- En la posición π de la clave real, se toma un
αaleatorio y se calcula el siguiente desafío:c_{π+1} = Hs(m ‖ α·G). - Para cada clave siguiente (ajena) se elige un
sᵢaleatorio y se calculac_{i+1} = Hs(m ‖ sᵢ·G + cᵢ·Pᵢ). Así se recorre el anillo. - Se vuelve a π, conociendo ya
c_π. Para que el anillo se cierre hace faltas_π·G + c_π·P_π = α·G, es decir,s_π = α − c_π·x. Esto solo se puede calcular conociendo x. - Firma:
(c₀, s₀, s₁, …, sₙ₋₁).
El verificador empieza en c₀, recorre cada eslabón con la misma fórmula y comprueba que vuelve al mismo c₀. Todos los eslabones parecen iguales: a partir de la firma no se puede saber dónde se produjo el «cierre».
Vinculabilidad: LSAG
Una firma de anillo simple no impide que la misma salida se gaste dos veces en anillos distintos. Por eso Monero usa una firma vinculable (linkable): el firmante publica una key image I = x·Hp(P_π) y en cada eslabón demuestra además que el mismo x conecta I y Hp(Pᵢ):
Dos usos de la misma clave dan la misma I, y la red rechaza el segundo gasto.
MLSAG → CLSAG
En RingCT hay que demostrar no una sino dos afirmaciones por cada miembro del anillo: el conocimiento de la clave de la salida y que la diferencia de compromisos compromete a cero (ver RingCT). Al principio (2017) esto se hacía con MLSAG: básicamente dos anillos pegados, con dos valores s por miembro del anillo.
En octubre de 2020 (hard fork v13) se sustituyó por CLSAG (Concise LSAG): las dos claves de una posición se combinan en una mediante una combinación lineal aleatoria con coeficientes obtenidos por hash. Un solo s por miembro del anillo. La firma pasó a ser un 25 % más pequeña y más rápida de verificar.
Historia del tamaño del anillo
| Cuándo | Mínimo de miembros | Comentario |
|---|---|---|
| 2014 | 1 (sin señuelos) | Herencia de CryptoNote: se permitían transacciones «0-mixin» |
| 2016 | 3 | Hard fork, se prohíben los anillos sin señuelos |
| 2017 | 5 | Junto con RingCT |
| abril de 2018 | 7 | Tras la investigación sobre reacciones en cadena |
| octubre de 2018 | 11, fijo | El tamaño del anillo pasa a ser el mismo para todos |
| agosto de 2022 | 16, fijo | Hard fork v15 (con Bulletproofs+ y view tags) |
¿Por qué fijo? Si cada uno eligiera el suyo, un tamaño de anillo no estándar delataría al monedero.
¿Por qué no 1000?
El tamaño de CLSAG y su tiempo de verificación crecen de forma lineal con el tamaño del anillo. Un anillo de 1000 miembros significaría ~32 KB por entrada y una sincronización de los nodos decenas de veces más lenta. Se investigaron esquemas de tamaño logarítmico (Triptych, Arcturus, Seraphis), pero al final Monero eligió la opción radical: FCMP++, donde el «anillo» es toda la blockchain.