⏱️ Lectura: 14 min

Podés demostrarle a un banco que sos mayor de edad sin decirle tu fecha de nacimiento exacta, o probarle a un servidor que conocés una contraseña sin enviarla nunca por la red. Esa es la promesa de las pruebas de conocimiento cero (zero-knowledge proofs o ZKP), un protocolo criptográfico que convierte la confianza en algo verificable matemáticamente, sin que quien te verifica aprenda nada más que el hecho de que tu afirmación es cierta.

📑 En este artículo
  1. TL;DR
  2. ¿Qué es una prueba de conocimiento cero y por qué importa?
    1. Las tres propiedades que definen un ZKP
  3. La analogía clásica: la cueva de Ali Baba
  4. Cómo funciona por dentro: el protocolo de Schnorr
  5. De interactivo a no interactivo: la transformación de Fiat-Shamir
  6. zk-SNARKs y zk-STARKs: la generación moderna
  7. Cómo empezar: tu primer circuito con circom y snarkjs
  8. Casos de uso reales
  9. Tabla comparativa: zk-SNARKs vs zk-STARKs vs Bulletproofs
  10. Errores comunes y buenas prácticas
  11. Profundizando: circuitos aritméticos y curvas elípticas
  12. Preguntas frecuentes
    1. ¿Un ZKP puede demostrar cualquier tipo de afirmación?
    2. ¿Zero-knowledge es lo mismo que anonimato?
    3. ¿Necesito hardware especial para generar una prueba?
    4. ¿Qué es exactamente el trusted setup y por qué preocupa?
    5. ¿Los zk-STARKs reemplazan a los zk-SNARKs?
    6. ¿Puedo practicar sin usar una blockchain real?
  13. Referencias

El concepto nació en 1985 con un paper de Shafi Goldwasser, Silvio Micali y Charles Rackoff, documentado hoy en la entrada de Wikipedia sobre pruebas de conocimiento cero, pero recién en la última década pasó de la teoría pura a producción: blockchains, sistemas de identidad digital y esquemas de cómputo verificable la usan todos los días.

TL;DR

  • Entendés las tres propiedades de toda prueba de conocimiento cero: completitud, solidez y conocimiento cero.
  • Sabés simular en Python el protocolo interactivo de Schnorr, la base histórica de los ZKP modernos.
  • Podés instalar circom y snarkjs y generar tu primera prueba zk-SNARK desde cero, con los comandos exactos.
  • Distinguís cuándo conviene un zk-SNARK, un zk-STARK o un Bulletproof según el caso de uso.
  • Identificás el riesgo del trusted setup en Groth16 y por qué los zk-STARKs lo evitan.
  • Reconocés los errores más comunes al diseñar circuitos aritméticos para pruebas de conocimiento cero.
  • Sabés dónde se usan hoy en producción: Zcash, rollups de Ethereum y verificación de identidad.

¿Qué es una prueba de conocimiento cero y por qué importa?

Una prueba de conocimiento cero es un protocolo entre dos partes: quien prueba (el prover) y quien verifica (el verifier). El prover quiere convencer al verifier de que conoce un dato secreto, o de que una afirmación es verdadera, sin revelar ese dato ni ningún detalle adicional. Importa porque separa dos cosas que normalmente van juntas: demostrar algo y exponerlo.

En sistemas tradicionales, demostrar que sabés una contraseña significa enviarla (o un hash de ella) al servidor. Con pruebas de conocimiento cero, demostrás que la conocés sin que el servidor la vea nunca, ni siquiera cifrada. Eso reduce la superficie de ataque: si el servidor se filtra, no hay contraseñas que robar.

Las tres propiedades que definen un ZKP

  • Completitud: si la afirmación es verdadera y ambas partes siguen el protocolo, el verifier siempre queda convencido.
  • Solidez (soundness): si la afirmación es falsa, ningún prover deshonesto puede convencer al verifier, salvo con probabilidad despreciable.
  • Conocimiento cero: el verifier no aprende nada más que ‘la afirmación es verdadera’: ni el secreto, ni cómo se calculó.

La analogía clásica: la cueva de Ali Baba

La forma más simple de entender una prueba de conocimiento cero es la cueva de Ali Baba, publicada en 1989 por Jean-Jacques Quisquater y otros autores para explicar el concepto sin matemática. Imaginá una cueva circular con una sola entrada y una puerta mágica en el fondo que solo se abre con una palabra secreta, dividiendo el túnel en dos caminos, A y B.

Peggy (el prover) entra por cualquiera de los dos caminos mientras Victor (el verifier) espera afuera sin ver cuál eligió. Victor grita qué camino quiere que Peggy use para salir. Si Peggy conoce la palabra secreta, cruza la puerta y sale siempre por el camino pedido, sin importar cuál haya elegido al entrar. Si no la conoce, solo acierta la mitad de las veces. Repitiendo el experimento veinte veces, la probabilidad de que Peggy mienta y aun así acierte todas cae a menos de una en un millón, y Victor nunca escuchó la palabra secreta.

Ilustración conceptual de una cueva circular usada para explicar pruebas de conocimiento cero
La analogía de la cueva de Ali Baba se publicó en 1989 para explicar el concepto sin matemática. Foto de Carlos Torres en Unsplash

Cómo funciona por dentro: el protocolo de Schnorr

El primer protocolo de conocimiento cero práctico con matemática real, no solo una analogía, es el protocolo de identificación de Schnorr, basado en el problema del logaritmo discreto: dado y = g^x mod p, es computacionalmente difícil recuperar x aunque conozcas y, g y p.

El protocolo tiene tres pasos, calcados de la cueva de Ali Baba: compromiso, reto y respuesta.

sequenceDiagram
    participant P as Prover
    participant V as Verifier
    P->>V: compromiso t = g^r mod p
    V-->>P: reto aleatorio c
    P->>V: respuesta s = r + c*x
    Note over P,V: V verifica g^s = t * y^c sin conocer x

Podés simular el protocolo completo con Python puro, sin librerías externas, usando un primo chico solo con fines didácticos (en producción se usan primos de cientos de bits o curvas elípticas):

import random

p = 23  # primo pequeno solo para el ejemplo
g = 5   # generador
x = 6   # el secreto de Peggy (el prover)
y = pow(g, x, p)  # y = g^x mod p, esto es publico

# 1. Peggy elige un numero aleatorio y envia el compromiso
r = random.randint(1, p - 2)
t = pow(g, r, p)

# 2. Victor (el verificador) envia un reto aleatorio
c = random.randint(0, 1)

# 3. Peggy responde segun el reto
s = (r + c * x) % (p - 1)

# 4. Victor verifica sin conocer x
lhs = pow(g, s, p)
rhs = (t * pow(y, c, p)) % p
print("Valido:", lhs == rhs)

El script calcula y = g^x mod p como valor público (el equivalente a la puerta mágica), genera un compromiso t, recibe un reto binario c y produce una respuesta s. La verificación final, g^s = t * y^c mod p, se cumple si y solo si Peggy conoce x, sin que ese valor aparezca en ningún mensaje enviado. Corré el script varias veces: vas a ver que Valido: True se imprime siempre que el secreto x es correcto.

De interactivo a no interactivo: la transformación de Fiat-Shamir

El protocolo de Schnorr necesita que Victor esté presente y mande un reto en vivo, poco práctico para una blockchain donde miles de nodos verifican la misma prueba sin coordinarse. La transformación de Fiat-Shamir reemplaza el reto aleatorio del verifier por el hash del compromiso: c = H(t). El prover no puede predecir el hash antes de generar t, así que sigue sin poder hacer trampa, pero ahora la prueba es un solo mensaje que cualquiera verifica después, sin diálogo.

Esa idea, sustituir interacción por una función hash, es la base de casi todos los zk-SNARKs y zk-STARKs que se usan hoy en producción.

zk-SNARKs y zk-STARKs: la generación moderna

Un zk-SNARK (succinct non-interactive argument of knowledge) traduce una afirmación arbitraria, no solo ‘conozco x tal que y = g^x’, a un circuito aritmético: una red de sumas y multiplicaciones sobre un campo finito. Ese circuito se compila a un formato llamado R1CS (rank-1 constraint system), y sobre él corre un esquema como Groth16, descrito en el paper original de Jens Groth, que produce pruebas de tamaño constante sin importar qué tan grande sea el circuito.

El costo de esa compacidad es el trusted setup: antes de poder probar o verificar nada, hace falta una ceremonia que genera parámetros aleatorios específicos de cada circuito. Si esos valores intermedios (‘toxic waste’) no se destruyen, alguien podría fabricar pruebas falsas que igual pasan la verificación.

Los zk-STARKs, impulsados por StarkWare, evitan por completo el trusted setup: usan solo funciones hash, resistentes a computadoras cuánticas, en vez de curvas elípticas emparejadas. A cambio, las pruebas STARK pesan más que un Groth16 y tardan más en verificarse on-chain.

Los Bulletproofs son una tercera familia: tampoco necesitan trusted setup, generan pruebas de tamaño logarítmico respecto al circuito y son la base de las transacciones confidenciales de Monero. Su desventaja es que verificarlas es más lento que un SNARK, porque comprimen menos el trabajo del verifier.

flowchart TD
    A["Circuito circom"] --> B["Compilacion a R1CS"]
    B --> C["Trusted setup"]
    C --> D["Clave de prueba (zkey)"]
    D --> E["snarkjs genera el proof"]
    E --> F["Verificador comprueba proof.json"]
flowchart LR
    A["Pruebas de conocimiento cero"] --> B["Interactivas"]
    A --> C["No interactivas (NIZK)"]
    C --> D["zk-SNARKs"]
    C --> E["zk-STARKs"]
    C --> F["Bulletproofs"]
pragma circom 2.0.0;

include "circomlib/circuits/poseidon.circom";

template ConoceSecreto() {
    signal input secreto;
    signal output hash;

    component poseidon = Poseidon(1);
    poseidon.inputs[0] <== secreto;
    hash <== poseidon.out;
}

component main = ConoceSecreto();

Este circuito, escrito en circom, declara una señal de entrada privada llamada secreto y calcula su hash con Poseidon, una función hash diseñada para ser barata dentro de un circuito aritmético. La señal hash queda pública: cualquiera verifica que el prover conoce un secreto que produce ese hash, sin que el secreto se revele en ningún momento.

Cómo empezar: tu primer circuito con circom y snarkjs

Para pasar de la teoría a una prueba real necesitás tres herramientas: el compilador circom, la librería snarkjs y un archivo de ceremonia (ptau) para el trusted setup. La documentación oficial de circom cubre la sintaxis completa del lenguaje; snarkjs genera y verifica las pruebas a partir del circuito compilado. Los pasos son estos:

npm install -g circom snarkjs

circom conoce_secreto.circom --r1cs --wasm --sym

snarkjs groth16 setup conoce_secreto.r1cs pot12_final.ptau conoce_secreto_0000.zkey

snarkjs zkey export verificationkey conoce_secreto_0000.zkey verification_key.json

snarkjs groth16 prove conoce_secreto_0000.zkey witness.wtns proof.json public.json

snarkjs groth16 verify verification_key.json public.json proof.json

El resultado esperado del último comando es la línea [INFO] snarkJS: OK! en la terminal: confirma que proof.json es válido para las entradas públicas de public.json, sin que snarkjs necesite conocer el valor de secreto en ningún momento de la verificación.

💡 Tip: probá siempre tu circuito con snarkjs en modo local, sin publicarlo on-chain, antes de generar la clave de verificación final: cualquier cambio en el circuito invalida la clave anterior.
Diagrama de flujo de un circuito aritmético transformándose en una prueba zk-SNARK
Cada circuito nuevo exige repetir el trusted setup en Groth16. Foto de Nubelson Fernandes en Unsplash

Casos de uso reales

Zcash, lanzada en 2016, fue la primera criptomoneda en usar zk-SNARKs en producción para ocultar el monto y las direcciones de una transacción sin dejar de permitir que la red verifique que nadie está creando dinero de la nada.

Ethereum agregó el precompilado necesario para verificar pruebas basadas en la curva BN254 mediante EIP-197, lo que abarató verificar un zk-SNARK dentro de un contrato inteligente y habilitó a los rollups actuales (zkSync, StarkNet, Polygon zkEVM) a comprimir miles de transacciones en una sola prueba publicada on-chain.

  • Identidad digital: apps de verificación de edad o ciudadanía que prueban un atributo del documento sin exponer el documento completo.
  • Cómputo delegado verificable: un cliente le pide un cálculo pesado a un servidor no confiable y solo necesita verificar la prueba, mucho más barata que repetir el cálculo original.

Tabla comparativa: zk-SNARKs vs zk-STARKs vs Bulletproofs

OpciónCuándo usarlaVentajaLimitación
zk-SNARKs (Groth16)Verificación on-chain barata, circuito fijo y establePrueba de tamaño constante y verificación muy rápidaRequiere trusted setup por cada circuito
zk-STARKsCuando no querés depender de una ceremonia de setup ni de curvas elípticasSin trusted setup, resistente a computadoras cuánticasPruebas más pesadas y verificación on-chain más cara
BulletproofsTransacciones confidenciales con montos, sin necesidad de verificación ultra rápidaSin trusted setup, pruebas de tamaño logarítmicoVerificación más lenta que un SNARK

Errores comunes y buenas prácticas

  • Reusar el trusted setup entre circuitos distintos: cada circuito necesita su propia ceremonia; mezclar circuitos con una clave ajena invalida las garantías de seguridad.
  • Confundir zero-knowledge con anonimato total: la prueba oculta el secreto, pero metadatos como la IP o el momento del envío pueden seguir identificando al prover.
  • Subestimar el tiempo de generar la prueba: crear un proof es mucho más costoso en CPU y memoria que verificarlo; diseñar circuitos gigantes sin medir el proving time es el error más común en producción.
  • No versionar el hash del circuito junto con la clave de verificación: si el circuito cambia y la verification key queda vieja, las pruebas nuevas fallan la verificación sin explicación clara.
⚠️ Ojo: en zk-SNARKs con Groth16, cada circuito necesita su propio trusted setup. Si los parámetros aleatorios de esa ceremonia (el llamado ‘toxic waste’) no se destruyen, quien los conserve puede falsificar pruebas válidas sin conocer el secreto real.

Profundizando: circuitos aritméticos y curvas elípticas

Por dentro, un circuito aritmético para zk-SNARKs trabaja sobre un campo finito: un conjunto de números donde suma y multiplicación se calculan módulo un primo grande, para que el resultado siempre quede dentro del mismo rango. Cada restricción del circuito se expresa como una ecuación de la forma a * b = c sobre ese campo, y el conjunto completo de restricciones forma el R1CS mencionado antes.

Esquemas como Groth16 usan emparejamientos bilineales (bilinear pairings) sobre curvas elípticas para comprimir la verificación de miles de restricciones en unas pocas operaciones. La curva más usada en Ethereum es BN254 (también llamada alt_bn128), la misma que EIP-197 agregó como precompilado nativo.

💭 Clave: verificar una prueba zk-SNARK es casi siempre más barato computacionalmente que repetir el cálculo original: por eso los rollups pagan por publicar pruebas en Ethereum en lugar de reejecutar cada transacción on-chain.

📖 Resumen en Telegram: Ver resumen

Tu próximo paso: instalá circom y snarkjs, compilá el circuito ConoceSecreto de este artículo y corré los cinco comandos de la sección ‘Cómo empezar’ hasta ver snarkJS: OK! en tu propia terminal.

Preguntas frecuentes

¿Un ZKP puede demostrar cualquier tipo de afirmación?

En teoría sí, siempre que la afirmación pueda expresarse como un circuito aritmético o una relación verificable en tiempo polinomial. En la práctica, traducir un problema complejo a ese formato es el trabajo más difícil del diseño.

¿Zero-knowledge es lo mismo que anonimato?

No. Zero-knowledge garantiza que el verifier no aprende el secreto usado en la prueba, pero no oculta automáticamente quién genera la transacción ni otros metadatos: eso depende del sistema completo, no solo de la prueba.

¿Necesito hardware especial para generar una prueba?

No es obligatorio, pero generar pruebas zk-SNARK es intensivo en CPU y memoria; circuitos grandes se benefician de más núcleos y RAM. Verificar la prueba, en cambio, es rápido incluso en un navegador.

¿Qué es exactamente el trusted setup y por qué preocupa?

Es una ceremonia donde se generan parámetros aleatorios necesarios para protocolos como Groth16. Si alguien conserva esos valores en vez de destruirlos, puede fabricar pruebas falsas que igual pasan la verificación.

¿Los zk-STARKs reemplazan a los zk-SNARKs?

No los reemplazan, compiten en distintos trade-offs: los STARKs evitan el trusted setup y resisten computadoras cuánticas, pero generan pruebas más pesadas que un SNARK como Groth16.

¿Puedo practicar sin usar una blockchain real?

Sí. circom y snarkjs corren completamente en local: podés compilar circuitos, generar y verificar pruebas sin publicar nada on-chain ni gastar gas.

Referencias

  • Wikipedia: Zero-knowledge proof: historia y definición formal del concepto desde el paper de 1985.
  • Zcash: zk-SNARKs technology: cómo Zcash usa zk-SNARKs para transacciones privadas en producción.
  • Documentación oficial de circom: sintaxis del lenguaje para escribir circuitos aritméticos.
  • Repositorio de snarkjs en GitHub: herramienta para generar y verificar pruebas zk-SNARK.
  • EIP-197: precompilado de Ethereum para verificar emparejamientos sobre la curva BN254.

📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @programacion donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.

Imagen destacada: Foto de FlyD en Unsplash

Categorías: SeguridadTutoriales

Clara Vásquez

Analista de ciberseguridad enfocada en vulnerabilidades críticas, zero-days y amenazas emergentes. Cubre CVEs de alto impacto, análisis de malware, incidentes de ransomware y tendencias de seguridad para LATAM.

0 Comentarios

Deja un comentario

Marcador de posición del avatar

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.