Técnico › ¿Quién envió?

Firmas de anillo

Cómo demostrar "poseo una de estas claves" sin decir cuál

En resumen

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:

  1. El firmante elige un α aleatorio y calcula α·G.
  2. Calcula el desafío c = Hs(message ‖ α·G).
  3. Calcula la respuesta s = α − c·x. La firma es (c, s).
  4. El verificador reconstruye s·G + c·P = (α − cx)·G + c·x·G = α·G y comprueba que Hs(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.

P₀ (π) P₁ P₂ P₃ P₄ P₅ c₁ c₂ c₃ c₄ c₅ c₀ cᵢ₊₁ = Hs(m ‖ sᵢ·G + cᵢ·Pᵢ) π — la clave real: el único lugar donde el anillo se «cierra» usando x todos los demás sᵢ son simplemente aleatorios
  1. En la posición π de la clave real, se toma un α aleatorio y se calcula el siguiente desafío: c_{π+1} = Hs(m ‖ α·G).
  2. Para cada clave siguiente (ajena) se elige un sᵢ aleatorio y se calcula c_{i+1} = Hs(m ‖ sᵢ·G + cᵢ·Pᵢ). Así se recorre el anillo.
  3. Se vuelve a π, conociendo ya c_π. Para que el anillo se cierre hace falta s_π·G + c_π·P_π = α·G, es decir, s_π = α − c_π·x. Esto solo se puede calcular conociendo x.
  4. 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ᵢ):

c_{i+1} = Hs( m ‖ sᵢ·G + cᵢ·Pᵢ ‖ sᵢ·Hp(Pᵢ) + cᵢ·I )

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.

W_i = μ_P·P_i + μ_C·(C_i − C̃)     demostrar el conocimiento de la clave de W_π

Historia del tamaño del anillo

CuándoMínimo de miembrosComentario
20141 (sin señuelos)Herencia de CryptoNote: se permitían transacciones «0-mixin»
20163Hard fork, se prohíben los anillos sin señuelos
20175Junto con RingCT
abril de 20187Tras la investigación sobre reacciones en cadena
octubre de 201811, fijoEl tamaño del anillo pasa a ser el mismo para todos
agosto de 202216, fijoHard 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.