Vitalik Buterin: ¿Cómo protege la privacidad la tecnología zk-SNARKs?

IntermedioDec 03, 2023
Este artículo profundiza en el funcionamiento de la tecnología zk-SNARK, su aplicabilidad en aplicaciones actuales y detalla los desafíos y las capacidades potenciales de esta tecnología en escenarios del mundo real.
Vitalik Buterin: ¿Cómo protege la privacidad la tecnología zk-SNARKs?

Los zk-SNARK son una poderosa herramienta criptográfica que se ha convertido en una parte cada vez más esencial de las aplicaciones blockchain y no basadas en blockchain. Su complejidad es evidente tanto en la comprensión de cómo funcionan como en cómo pueden utilizarse eficazmente. Este artículo profundiza en cómo los zk-SNARK se adaptan a las aplicaciones actuales, proporciona ejemplos de lo que pueden y no pueden lograr y ofrece pautas generales sobre cuándo los zk-SNARK son adecuados para aplicaciones específicas. Se hará especial hincapié en su papel a la hora de garantizar la privacidad.

¿Qué son los zk-SNARK?

Imagine tener una entrada pública x, una entrada privada w y una función (pública) f(x,w) → {True,False}, que valida las entradas. Con los zk-SNARK, se puede demostrar que conocen aw, de modo que para f y x dadas, f(x,w) = True, todo sin revelar qué es realmente w. Además, los verificadores pueden autenticar la prueba mucho más rápido de lo que podrían calcular f(x,w) incluso si supieran w.

Esto dota a zk-SNARK de dos atributos: privacidad y escalabilidad. Como se mencionó, nuestros ejemplos en este artículo se centrarán principalmente en el aspecto de la privacidad.

Prueba de membresía

Supongamos que tiene una billetera Ethereum y desea demostrar que esta billetera está registrada bajo un sistema de prueba de humanidad, sin revelar quién es realmente la persona registrada. Esta función se puede describir matemáticamente como:

Entrada privada (w): su dirección A, la clave privada de su dirección k

Entrada pública (x): conjunto de direcciones de todos los perfiles de prueba de humanidad verificados {H1…Hn}

Función de verificación f(x,w):

Interprete w como un par (A, σ) yx como una lista de perfiles válida {H1…Hn}

Verifique que A sea una de las direcciones en {H1…Hn}

Confirmar privtoaddr(k) = A

Si se pasan ambas verificaciones, devuelve True. Si alguno de ellos falla, devuelve False.

El probador genera su dirección A y la clave asociada k, proporcionando w=(A,k) como entrada privada para f. Obtienen la opinión pública, que es el conjunto actual de perfiles de prueba de humanidad verificados {H1…Hn}, de la cadena. Luego ejecutan el algoritmo de prueba zk-SNARK, que (suponiendo que la entrada sea correcta) produce una prueba. Esta prueba se envía al verificador, junto con la altura del bloque donde obtuvieron la lista de perfiles verificados.

El verificador también lee la cadena, adquiere la lista {H1…Hn} de la altura especificada por el probador y verifica la prueba. Si la verificación tiene éxito, el verificador cree que el demostrador posee un perfil de prueba de humanidad verificado.

Antes de profundizar en ejemplos más complejos, recomiendo encarecidamente comprender completamente el ejemplo anterior.

Hacer que las pruebas de membresía sean más eficientes

Una desventaja del sistema de prueba antes mencionado es que el verificador debe conocer todo el conjunto de perfiles {H1…Hn}, lo que requiere O(n) tiempo para "ingresar" este conjunto en el mecanismo zk-SNARK. Este problema se puede abordar utilizando la raíz Merkle en cadena, que abarca todos los perfiles, como entrada pública (potencialmente solo la raíz estatal). Agregamos otra entrada privada, una prueba de Merkle M, confirmando que la cuenta A del probador está en la parte pertinente del árbol.

Una alternativa muy reciente y más eficiente a las pruebas de Merkle para las pruebas de membresía de ZK es Caulk. En el futuro, algunos de estos casos de uso podrían pasar a soluciones similares a Caulk.

ZK-SNARK y monedas

Proyectos como Zcash y Tornado.cash nos permiten poseer monedas que protegen la privacidad. Ahora bien, uno podría pensar que podrían utilizar las mencionadas “pruebas humanas ZK”, pero no se trata de demostrar el acceso a pruebas de perfil humano; se trata de demostrar el acceso a las monedas. Aquí radica un problema: debemos abordar tanto la privacidad como el doble gasto simultáneamente. Es decir, no deberíamos gastar la misma moneda dos veces.

Así es como lo solucionamos: cualquiera que posea una moneda tiene una “s” secreta privada. Calculan una “hoja” L=hash(s,1) localmente, que se publica en la cadena y pasa a formar parte del estado, N=hash(s,2), al que llamamos anulador. El estado se almacena en un árbol Merkle.

Para gastar una moneda, el remitente debe presentar un ZK-SNARK donde:

  • Las entradas públicas incluyen un anulador N, la raíz de Merkle actual o reciente R y una nueva hoja L' (destinada al destinatario que tiene un secreto s' pasado al remitente como L'=hash(s',1)).

  • Las entradas privadas comprenden un secreto s, una hoja L y una rama Merkle M.

La función de verificación comprueba:

  • M es una rama de Merkle válida, lo que demuestra que L es una hoja del árbol con raíz en R, donde R es la raíz de Merkle del estado actual.

  • hash(s,1)=L y hash(s,2)=N.

La transacción contiene el anulador N y la nueva hoja L'. En realidad, no probamos nada sobre L', pero está "mezclado" con la prueba para evitar modificaciones por parte de terceros durante la transacción. Para validar la transacción, la cadena verifica el ZK-SNARK y comprueba si N se ha utilizado en transacciones anteriores. Si tiene éxito, se agrega N al conjunto de anuladores gastados, dejándolo inutilizable nuevamente. L' se agrega al árbol Merkle.

Usando ZK-SNARK, vinculamos dos valores: L (que aparece en la cadena cuando se acuña la moneda) y N (que aparece cuando se gasta), sin revelar qué L se conecta a qué N. La conexión entre L y N solo es discernible cuando conoce los secretos que los genera. Cada moneda acuñada se puede usar una vez (ya que solo hay una N válida para cada L), pero la moneda específica utilizada en cada momento permanece oculta.

Esta es una primitiva crucial de comprender. Muchos mecanismos que describimos a continuación se basan en esto, aunque con propósitos variados.

Monedas con saldos arbitrarios

Lo anterior se puede extender fácilmente a monedas con saldos arbitrarios. Mantenemos el concepto de “moneda”, pero cada moneda lleva un saldo (privado). Una forma sencilla de lograr esto es que cada moneda tenga almacenamiento en cadena, no solo con la hoja L, sino también con un saldo cifrado. Cada transacción consumiría dos monedas y crearía dos nuevas, agregando dos pares (hoja, saldo cifrado) al estado. El ZK-SNARK también verifica que la suma de los saldos de entrada sea igual a la suma de los saldos de salida, y que ambos saldos de salida no sean negativos.

Anti-Denegación de Servicio ZK

Una herramienta anti-DOS intrigante: imagine que tiene alguna identidad en cadena que no se crea fácilmente; podría ser un perfil a prueba de humanos o 32 validadores de ETH, o simplemente una cuenta con un saldo de ETH distinto de cero. Podríamos crear una red peer-to-peer más resistente a DOS aceptando únicamente mensajes que demuestren que el remitente tiene un perfil. A cada perfil se le permitirían hasta 1000 mensajes por hora. Si un remitente hace trampa, su perfil se elimina de la lista. Pero, ¿cómo garantizamos la privacidad?

Primero, la configuración: sea k la clave privada del usuario y A=privtoaddr(k) la dirección correspondiente. Una lista de direcciones válidas es pública (por ejemplo, un registro en cadena). Hasta ahora, esto refleja el ejemplo de prueba humana: debes demostrar que tienes la clave privada de una dirección sin revelar cuál. Pero no sólo queremos pruebas de que está en la lista. Necesitamos un protocolo que le permita demostrar que está en la lista pero que limite sus pruebas.

Dividiremos el tiempo en períodos: cada uno de ellos durará 3,6 segundos (lo que hace 1000 períodos por hora). Nuestro objetivo es permitir que cada usuario envíe solo un mensaje por período; si envían dos en el mismo período, los atrapan. Para permitir explosiones ocasionales, pueden utilizar períodos recientes. Entonces, si un usuario tiene 500 períodos no utilizados, puede enviar 500 mensajes todos a la vez.

Protocolo

Comencemos con una versión básica que usa anuladores. Un usuario genera un anulador con (N = \text{hash}(k, e)) donde (k) es su clave y (e) es un número de época, luego lo publica con el mensaje (m). ZK-SNARK luego ofusca el (\text{hash}(m)). No se verifica nada sobre (m) en este proceso, vinculando así la prueba a un solo mensaje. Si un usuario vincula dos pruebas a dos mensajes distintos utilizando el mismo anulador, corre el riesgo de ser atrapado.

Ahora pasamos a una versión más compleja. En este escenario, el protocolo posterior revela su clave privada en lugar de simplemente confirmar si alguien ha utilizado la misma época dos veces. Nuestra técnica fundamental se basa en el principio de que "dos puntos determinan una línea". Revelar un punto en una línea revela poco, pero exponer dos puntos revela toda la línea.

Para cada época (e), elegimos una línea (L_e(x) = \text{hash}(k, e) \times x + k). La pendiente de la recta es (\text{hash}(k, e)) y la intersección con el eje y es (k), ambas desconocidas para el público. Para generar un certificado para el mensaje (m), el remitente proporciona (y = L_e(\text{hash}(m)) = \text{hash}(k, e) \times \text{hash}(m) + k ), junto con una prueba ZK-SNARK de que el cálculo de (y) es exacto.

Resumiendo, ZK-SNARK es el siguiente:

Aportes públicos:

  • ({A_1…A_n}): una lista de cuentas válidas

  • (M): El mensaje siendo validado por el certificado.

  • (E): El número de época del certificado.

  • (Y): Evaluación de la función de línea.

Entrada privada:

  • (K): Tu clave privada

Función de verificación:

  • Compruebe si (\text{privtoaddr}(k)) existe en ({A_1…A_n})

  • Confirmar (y = \text{hash}(k, e) \times \text{hash}(m) + k)

Pero ¿qué pasa si alguien usa una época dos veces? Revelarían dos valores (m_1) y (m_2) junto con sus valores de certificado (y_1 = \text{hash}(k, e) \times \text{hash}(m_1) + k) y (y_2 = \text{hash}(k, e) \times \text{hash}(m_2) + k). Luego podemos utilizar estos dos puntos para recuperar la línea y posteriormente la intersección con el eje y, que es la clave privada.

Entonces, si alguien reutiliza una época, sin darse cuenta revela su clave privada a todos. Dependiendo del contexto, esto podría llevar al robo de fondos o simplemente a difundir la clave privada e integrarla en un contrato inteligente, lo que resultaría en la eliminación de la dirección asociada.

Un sistema anti-denegación de servicio anónimo viable fuera de la cadena, adecuado para redes blockchain peer-to-peer, aplicaciones de chat y sistemas similares, no exige prueba de trabajo. El proyecto RLN se centra esencialmente en este concepto, aunque con modificaciones menores (es decir, utilizan tanto anuladores como la técnica de la línea de dos puntos, lo que simplifica la detección de casos en los que se reutiliza una época).

La mala reputación de ZK

Imagine establecer 0chan, un foro en línea como 4chan que ofrece completo anonimato (ni siquiera tiene nombres permanentes), pero con un sistema de reputación para promover contenido de mayor calidad. Un sistema de este tipo podría tener una DAO de gobernanza para señalar publicaciones que infrinjan las reglas del sistema, introduciendo un mecanismo de tres ataques.

El sistema de reputación puede atender a reputaciones positivas o negativas; sin embargo, adaptarse a la reputación negativa exige infraestructura adicional. Esto requiere que los usuarios incorporen todos los datos de reputación en sus pruebas, incluso si son negativos. Nos centraremos principalmente en este desafiante caso de uso, similar a lo que Unirep Social pretende implementar.

Publicación vinculada: Conocimientos básicos

Cualquiera puede publicar transmitiendo un mensaje en la cadena que contiene la publicación, acompañado de un ZK-SNARK. Este ZK-SNARK sirve como prueba de que (i) usted posee una identidad externa única que le otorga permiso para crear una cuenta, o (ii) ha publicado publicaciones específicas anteriormente. En concreto, ZK-SNARK funciona de la siguiente manera:

Aportes públicos:

  • Anulador, norte

  • Raíz de estado de blockchain más reciente, R

  • Contenido de la publicación ('mezclado' en la prueba para vincularlo a la publicación, sin ningún cálculo al respecto)

Entradas privadas:

  • Tu clave privada, k

  • Una identidad externa (dirección A) o el anulador, Nprev, utilizado en la publicación anterior.

  • Una prueba de Merkle, M, de que la cadena contiene A o Nprev

  • La novena publicación que has publicado usando esta cuenta.

Función de verificación:

  1. Confirme que M es una rama válida de Merkle, demostrando que (A o Nprev, lo que se proporcione) es una hoja de un árbol con raíz R.

  2. Verifique N = enc(i, k) donde enc es una función de cifrado (por ejemplo, AES).

  3. Si i=0, verifique A=privtoaddr(k); de lo contrario, verifique Nprev=enc(i−1,k).

Además de la validación de la prueba, la cadena también verifica (i) que R sea en realidad una raíz de estado reciente y (ii) que el anulador N no se haya utilizado antes. Hasta este punto, se parece a las monedas que preservan la privacidad descritas anteriormente, pero agregamos un proceso para "acuñar" nuevas cuentas y eliminamos la capacidad de "enviar" su cuenta a diferentes claves. En cambio, todos los anuladores se generan utilizando la clave original. Empleamos enc aquí para hacer reversible el anulador. Si tiene la clave k, puede descifrar cualquier anulador específico en la cadena; si el resultado es un índice válido en lugar de un galimatías aleatorio (por ejemplo, podemos simplemente verificar dec(N) < 2^64), sabrá que el anulador se generó usando la clave k.

Agregando reputación:

En este esquema, la reputación está en cadena y es explícita. Algunos contratos inteligentes tienen un método llamado addReputation, que toma el anulador liberado con una publicación y la cantidad de unidades de reputación que se agregarán o restarán como entrada.

Hemos ampliado los datos almacenados en la cadena para cada publicación. En lugar de almacenar solo el anulador N, almacenamos {N, h¯, u¯} donde:

  • h¯ = hash(h, r) donde h representa la altura del bloque de la raíz del estado a la que se hace referencia en la prueba.

  • u¯ = hash(u, r) donde u es la puntuación de reputación de la cuenta (comenzando en 0 para cuentas nuevas).

R aquí es un valor aleatorio agregado para evitar que h y u se encuentren mediante una búsqueda de fuerza bruta. En términos criptográficos, agregar R hace que el hash sea un compromiso oculto.

Supongamos que una publicación usa la raíz R y almacena {N, h¯, u¯}. Dentro de su prueba, enlaza a una publicación anterior que almacenó los datos {Nprev, h¯prev, u¯prev}. La prueba de la publicación también debe atravesar todas las entradas de reputación publicadas entre hprev y h. Para cada anulador N, la función de verificación descifra N utilizando la clave del usuario k. Si el descifrado genera un índice válido, aplica la actualización de reputación. Si el total de todas las actualizaciones de reputación es igual a δ, entonces resulta que u = uprev + δ.

Si deseamos implementar una regla de “tres strikes y estás fuera”, ZK-SNARK también aseguraría u > -3. Si queremos una regla en la que una publicación con reputación ≥ 100 reciba una etiqueta especial de "publicación de alta reputación", eso también se puede hacer.

Para mejorar la escalabilidad de este sistema, podemos dividirlo en dos tipos de mensajes: Publicaciones y RCA. Una publicación estaría fuera de la cadena, aunque requiere señalar un RCA realizado la semana pasada. Los RCA estarían en cadena y atravesarían todas las actualizaciones de reputación desde el RCA anterior del editor. De esta manera, la carga en cadena se reduce a una transacción por publicación por semana, más una transacción por cada mensaje de reputación.

Responsabilizar a los partidos centralizados

A veces, es necesario diseñar un sistema con un "operador" centralizado. Las razones de esto pueden variar: a veces es por escalabilidad y en otras es por privacidad, especialmente la privacidad de los datos en poder del operador. Por ejemplo, el sistema de votación resistente a la coerción MACI requiere que los votantes envíen sus votos en cadena, cifrados con una clave en poder de un operador centralizado. Este operador descifra todos los votos en cadena, los cuenta y muestra el resultado final. Utilizan ZK-SNARK para demostrar que todo lo que hicieron fue exacto. Esta complejidad adicional es crucial para garantizar una privacidad sólida (conocida como resistencia coercitiva): los usuarios no pueden demostrarle a nadie cómo votaron, incluso si quisieran. Gracias a blockchain y ZK-SNARK, nuestro nivel de confianza en el operador sigue siendo mínimo. Los operadores maliciosos pueden romper la resistencia coercitiva, pero como los votos se publican en la cadena de bloques, no pueden hacer trampa censurando los votos. Y como deben proporcionar un ZK-SNARK, no pueden hacer trampa calculando mal los resultados.

Combinando ZK-SNARK con MPC

Un uso más avanzado de ZK-SNARK es en cálculos donde se requieren pruebas, con entradas distribuidas entre dos o más partes, y no queremos que ninguna de las partes conozca las entradas de los demás. En un escenario bipartito, los circuitos confusos pueden cumplir requisitos de privacidad; para N partes, se pueden utilizar protocolos de cálculo multipartitas más complejos. Los ZK-SNARK se pueden integrar con estos protocolos para cálculos multipartitos verificables. Esto habilita sistemas de reputación avanzados, lo que permite a varios participantes ejecutar cálculos conjuntos sobre sus entradas privadas. Las matemáticas para lograrlo de manera efectiva aún se encuentran en sus primeras etapas.

¿Qué no podemos hacer privado?

ZK-SNARKs es muy eficaz en la creación de sistemas donde los usuarios tienen estados privados. Sin embargo, no puede mantener como privado un Estado que nadie conoce. Para que una información sea probada, el demostrador debe conocerla en texto plano. Uniswap es un ejemplo difícil de privatizar. En Uniswap, hay una "entidad" lógica central: la cuenta del proveedor de liquidez, que no pertenece a nadie, y todas las transacciones de Uniswap se realizan con esta cuenta. No puede ocultar el estado de esta cuenta ya que alguien necesita mantener este estado en texto sin formato para probarlo, y cada transacción requeriría su participación activa. Se podrían utilizar los circuitos confusos de ZK-SNARK para crear una versión centralizada, segura y privada de Uniswap, pero no está claro si los beneficios superarían los costos. Puede que ni siquiera ofrezca ningún beneficio real: los contratos deben informar a los usuarios sobre los precios de los activos, y los cambios de precios por bloque pueden revelar la actividad de las transacciones. Las cadenas de bloques pueden globalizar la información estatal y los ZK-SNARK pueden privatizarla, pero no existe un método sólido para globalizar y privatizar la información estatal simultáneamente.

Juntando las primitivas

En las secciones anteriores, vimos ejemplos de herramientas que son poderosas por derecho propio pero que también pueden servir como componentes básicos para otras aplicaciones. Los anuladores, vitales para las monedas, ahora reaparecen en otros casos de uso. La técnica del “enlace coercitivo” utilizada en la sección de reputación negativa tiene una amplia aplicación. Es muy eficaz para muchas aplicaciones en las que el “perfil” de un usuario cambia con el tiempo de formas intrincadas y se desea obligar a los usuarios a seguir las reglas del sistema preservando al mismo tiempo la privacidad. A los usuarios incluso se les podría asignar la tarea de representar su "estado" interno utilizando un árbol Merkle privado completo. La herramienta "grupo de compromiso" mencionada se puede crear con ZK-SNARK. Si ciertas aplicaciones no pueden funcionar completamente en cadena y requieren un operador centralizado, las mismas técnicas pueden mantener al operador honesto. ZK-SNARK es una herramienta potente que combina beneficios de responsabilidad y privacidad. Si bien tienen sus limitaciones, en algunos casos, los diseños de aplicaciones inteligentes pueden superar estas limitaciones. Espero ver que más aplicaciones adopten ZK-SNARK y, eventualmente, creen aplicaciones que combinen ZK-SNARK con otras formas de cifrado en los próximos años.

Descargo de responsabilidad:

  1. Este artículo está reimpreso de [Foresightnews]. Todos los derechos de autor pertenecen al autor original [Jacob Ko]. Si hay objeciones a esta reimpresión, comuníquese con el equipo de Gate Learn y ellos lo manejarán de inmediato.
  2. Descargo de responsabilidad: los puntos de vista y opiniones expresados en este artículo son únicamente los del autor y no constituyen ningún consejo de inversión.
  3. Las traducciones del artículo a otros idiomas están a cargo del equipo de Gate Learn. A menos que se mencione, está prohibido copiar, distribuir o plagiar los artículos traducidos.
Comece agora
Inscreva-se e ganhe um cupom de
$100
!
Criar conta