¡Bienvenido! ¿Eres nuevo en Zcash?
The Zcash network is young, but evolving quickly! Sign up and we'll be in touch with monthly highlights on ecosystem growth, network development and how to get started with Zcash!

Idioma

Criptografía de emparejamientos en Rust

Sean Bowe | Jul 06, 2016

La criptografía de emparejamientos es un interesante campo de investigación y un componente esencial del zkSNARKs de Zcash ─que prueba que las transacciones son válidas sin que los usuarios necesiten revelar información privada. A principios de este año también utilizamos zkSNARKs para hacer el primer pago contingente con conocimiento-cero de Bitcoin!

Uno de nuestros objetivos mientras avanzamos es explicar mejor cómo funcionan estas herramientas y hacerlas más accesibles al público. Como primer paso, estamos comenzando el desarrollo de una biblioteca de criptografía de emparejamientos para Rust llamada "bn". La criptografía de emparejamientos es importante para zkSNARKs, pero ¿qué es exactamente?

Curvas Elípticas

Las construcciones regulares de curva elíptica como secp256k1 ─utilizada en Bitcoin─ están diseñadas para cosas tales como las firmas digitales. Los puntos de la curva forman un grupo cíclico: pueden ser sumados y multiplicados por escalares. Se cree que es imposible encontrar el multiplicando dado un punto multiplicador y el punto del producto; a esto se le llama el "problema de logaritmo discreto de la curva elíptica".

Esta asimetría (la facilidad de la multiplicación y la dificultad de la operación inversa) se utiliza para fabricar una serie de herramientas y protocolos útiles. El intercambio de claves Diffie-Hellman es un ejemplo sencillo: Alice multiplica la clave pública de Bob por su clave privada (escalar), y viceversa, para encontrar un secreto compartido en presencia de un eavesdropper, o escucha furtivo.

Este protocolo de intercambio de claves puede extenderse a tres partes, pero requiere dos rondas: para las partes A, B y C, A obtiene el secreto compartido al hacer que B envíe su clave pública a C, el cual la multiplica por su clave privada y envía el resultado a A, quien puede entonces inferir el secreto compartido multiplicándolo por su clave privada.

Criptografía de emparejamientos

La criptografía de emparejamientos es una extensión de estos conceptos. Ahora imagina que tenemos dos grupos cíclicos: \(G_{1}\) y \(G_{2}\), escritos aditivamente, y un mapeo a un tercer grupo cíclico de la forma e: \(G_{1} \times G_{2} \rightarrow G_{T}\), donde \(G_{T}\) es escrito multiplicativamente. Si este mapeo es bilineal, entonces:

\(e(a g_{1}, b g_{2}) = e(g_{1}, g_{2})^{ab}\) donde \(a\) y \(b\) son escalares y \(g_{1}\) y \(g_{2}\) son generadores para sus respectivos grupos.

Esencialmente, una multiplicación escalar de uno de los dos primeros elementos de un grupo es equivalente a una potenciación del elemento final del grupo.

Protocolo de Acuerdo de Clave de Joux

Vamos a aplicar la criptografía de emparejamientos al escenario anterior de intercambio de claves de tres partes. Usando emparejamientos, podemos realizar el intercambio en una ronda. Cada parte \(P\) publica su clave pública \(P^{pk} = (P^{sk} g_{1}, P^{sk} g_{2})\) y mantiene su clave privada \(P^{sk}\) en secreto. Todas las partes \(A, B, C\) pueden calcular el mismo secreto compartido usando la función de emparejamiento bilineal:

Alice Calcula Bob Calcula Carol Calcula
\(e(B_{1}^{pk}, C_{2}^{pk})^{A^{sk}}\) \(e(C_{1}^{pk}, A_{2}^{pk})^{B^{sk}}\) \(e(A_{1}^{pk}, B_{2}^{pk})^{C^{sk}}\)
Todos ellos equivalentes a \(e(g_{1}, g_{2})^{A^{sk} B^{sk} C^{sk}}\)

O, si prefieres código, echa un vistazo a un ejemplo de nuestra nueva biblioteca:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// Generar claves privadas
let alice_sk = Scalar::random(rng);
let bob_sk = Scalar::random(rng);
let carol_sk = Scalar::random(rng);

// Generar claves públicas en G1 y G2
let (alice_pk1, alice_pk2) = (G1::one() * &alice_sk, G2::one() * &alice_sk);
let (bob_pk1, bob_pk2) = (G1::one() * &bob_sk, G2::one() * &bob_sk);
let (carol_pk1, carol_pk2) = (G1::one() * &carol_sk, G2::one() * &carol_sk);

// Cada parte calcula el secreto compartido
let alice_ss = pairing(&bob_pk1, &carol_pk2) ^ &alice_sk;
let bob_ss = pairing(&carol_pk1, &alice_pk2) ^ &bob_sk;
let carol_ss = pairing(&alice_pk1, &bob_pk2) ^ &carol_sk;

assert!(alice_ss == bob_ss && bob_ss == carol_ss);

bn

La caja "bn" es una biblioteca en lenguaje Rust para realizar estas operaciones de emparejamiento usando una construcción criptográfica diseñada por nuestros científicos en [BCGTV14]. Utiliza una curva elíptica Barreto-Naehrig puesta a punto para su uso en zkSNARKs. La biblioteca es nueva e incompleta y no debería ser usada en software de producción, pero es un buen paso adelante en nuestro objetivo de hacer que este nuevo tipo de criptografía sea más ampliamente entendido y más fácil de usar.

Echa un vistazo a la caja bn en github o en crates.io! Y siéntete libre de unirte a nuestro Slack o suscríbete a las notificaciones por correo electrónico de nuestro equipo!