Saltearse al contenido

Criptografía

La criptografía juega un papel integral en garantizar la seguridad, integridad, confidencialidad e inmutabilidad de los datos en los sistemas blockchain. El adaptador de Aptos para Move proporciona a los desarrolladores una variedad de primitivas criptográficas para satisfacer esta necesidad. Este documento profundiza en las funcionalidades criptográficas ofrecidas por Move en Aptos y explica los principios que impulsan su diseño.

Move, a través del adaptador de Aptos, abarca varias herramientas criptográficas fundamentales:

  1. Funciones Hash Criptográficas – Algoritmos que producen una salida de tamaño fijo (hash) a partir de datos de entrada de tamaño variable. Las funciones soportadas incluyen SHA2-256, SHA3-256, Keccak256 y Blake2b-256.
  2. Verificación de Firmas Digitales – Algoritmos para firmar un mensaje y así asegurar su integridad, autenticar al remitente, garantizar la no repudio, o cualquier combinación de estos. Los esquemas de firma soportados incluyen Ed25519, ECDSA y BLS.
  3. Aritmética de Curvas Elípticas – Las curvas elípticas son uno de los bloques de construcción de primitivas criptográficas avanzadas, como firmas digitales, cifrado de clave pública o compartición verificable de secretos. Las curvas soportadas incluyen Ristretto255 y BLS12-381.
  4. Pruebas de Conocimiento Cero (ZKP) – Estas técnicas criptográficas permiten a una parte demostrar que una relación R(x;w)R(x; w) se satisface sobre una declaración pública xx sin revelar el testigo secreto ww que la hace válida. Actualmente, soportamos verificación de ZKP Groth16 y verificación de pruebas de rango ZK Bulletproofs.

Tres principios fundamentales guían el diseño e integración de las extensiones criptográficas de Aptos en Move:

  1. Uso Económico de Gas – Se busca minimizar los costos de gas para los desarrolladores de Move implementando primitivas clave como funciones nativas de Move. Por ejemplo, consulta el módulo para firmas BLS sobre curvas elípticas BLS12-381.
  2. APIs Seguras por Tipo – Asegurando que las APIs sean resistentes a errores comunes, la seguridad de tipos mejora la confiabilidad del código y promueve un proceso de desarrollo eficiente. Por ejemplo, consulta el módulo de firmas Ed25519.
  3. Empoderamiento de Desarrolladores – En casos donde no hay funciones nativas disponibles, empoderamos a los desarrolladores para construir sus propias primitivas criptográficas sobre bloques abstractos como campos finitos y grupos abelianos. Consulta el módulo aptos_std::crypto_algebra para más información.

Continúa leyendo para profundizar un poco más y descubrir algunas de las complejidades detrás de estas extensiones, así como la gama de aplicaciones que habilitan. Para una comprensión más completa de este tema, consulta el código de los módulos Move de criptografía.

Los desarrolladores ahora pueden usar más funciones hash criptográficas en Move a través del módulo aptos_std::aptos_hash:

Función hashTamaño hash (bits)Costo por hashear 1KiB (en unidades internas de gas)Seguridad de resistencia a colisiones (bits)
Keccak2562561,001,600128
SHA2-2562561,084,000128
SHA2-5125121,293,600256
SHA3-2562561,001,600128
SHA3-5125121,114,000256
RIPEMD1601601,084,00080 (débil)
Blake2b-256256342,200128

Todas las funciones hash tienen las mismas propiedades de seguridad (por ejemplo, unidireccionalidad, resistencia a colisiones, etc.), pero sus niveles de seguridad son diferentes.

Algunas de estas funciones pueden usarse para interoperabilidad con otras cadenas (por ejemplo, verificar pruebas de Merkle de Ethereum vía aptos_std::aptos_hash::keccak256). Otras, tienen menores costos de gas, como aptos_std::aptos_hash::blake2b_256. En general, una mayor variedad de funciones hash da a los desarrolladores libertad adicional tanto en seguridad como en interoperabilidad con otros sistemas criptográficos fuera de la cadena.

Los desarrolladores ahora pueden usar una API segura por tipo para verificar muchas clases de firmas digitales en Move:

Esquema de firmaCurvaTamaño de firma (bytes)Tamaño de PK (bytes)MalleabilidadSuposicionesProsDesventajas
ECDSAsecp256k16464GGMAdopción ampliaPrueba de seguridad
Ed25519Edwards 255196432NoDLA, ROMRápidoSubtleties
MultiEd25519Edwards 255194+t644 + t \cdot 64n32n \cdot 32NoDLA, ROMFácil de adoptarTamaño de firma grande
MinPK BLSBLS12-3819648NoCDH, ROMVersátilVerificación más lenta
MinSig BLSBLS12-3814896NoCDH, ROMVersátilVerificación más lenta

Los módulos de firma digital anterior pueden usarse para construir contratos inteligentes basados en firmas, mecanismos de reclamación de airdrops seguros o cualquier mecanismo de control de acceso basado en firmas digitales para dapps.

La elección correcta de un esquema de firma en tu dapp podría depender de muchos factores:

  1. Compatibilidad hacia atrás
    • Si tu dapp’s base de usuarios principalmente usa un mecanismo de firma particular, sería prudente apoyar ese mecanismo para facilitar la transición y la adopción.
      • Ejemplo: Si los usuarios principalmente firman usando Ed25519, sería una elección lógica.
  2. Facilidad de implementación
    • Aunque teóricamente sólido, protocolos complejos pueden ser desafiantes de implementar en la práctica.
      • Ejemplo: Aunque existen protocolos tt-de-nn de umbral para Ed25519, su intrincidad en el lado del firmante podría impulsar a los desarrolladores a MultiEd25519 debido a su implementación de firma más directa.
  3. Eficiencia
    • Dependiendo de las necesidades de tu dapp, podrías priorizar una eficiencia sobre otra.
      • Tamaño de firma vs. tamaño de clave pública: Algunas aplicaciones podrían priorizar un pie de firma más pequeño, mientras que otras podrían enfatizar una clave pública compacta.
      • Velocidad de firma vs. velocidad de verificación: Para ciertas dapps, la velocidad de firma podría ser más crucial, mientras que para otras, la verificación rápida de la firma podría ser la prioridad.
  4. Análisis de seguridad
    • Es esencial considerar las suposiciones subyacentes y posibles vulnerabilidades de un esquema de firma.
      • Ejemplo: La seguridad de ECDSA está probada bajo suposiciones fuertes como el Modelo de Grupo Genérico (GGM).
      • Consideraciones de malleabilidad: Algunos esquemas de firma son susceptibles a la malleabilidad, donde una firma válida, σ\sigma, puede ser maullada en una firma diferente pero aún válida, σ\sigma, para el mismo mensaje mm.
  5. Versatilidad
    • La adaptabilidad y flexibilidad de los esquemas de firma son importantes para considerar, por lo que podrías adecuarte a las necesidades criptográficas de tu dapp.
      • Ejemplo: Los esquemas de firma de umbral tt-de-nn de BLS son muy simples de implementar.

Mientras que las funciones hash y verificación de firmas deberían proporcionar suficiente funcionalidad para la mayoría de las aplicaciones, algunas aplicaciones requerirán criptografía más poderosa. Normalmente, los desarrolladores de tales aplicaciones tendrían que esperar hasta que su funcionalidad criptográfica deseada se implemente eficientemente como una función nativa de Move en el marco de Move de Aptos. En lugar de eso, exponemos bloques de construcción básicos que los desarrolladores pueden usar para implementar sus propias primitivas criptográficas directamente en el lenguaje Move y lo hacen eficientemente.

Específicamente, actualmente exponemos operaciones de aritmética de curva elíptica en dos grupos de curvas elípticas populares y sus campos finitos asociados:

  1. Ristretto255, a través de aptos_std::ristretto255
  2. BLS12-381, a través de aptos_std::crypto_algebra y aptos_std::bls12381_algebra

Estos módulos soportan operaciones de bajo nivel como:

  • multiplicación escalar de puntos de curva elíptica
  • multiplicaciones escalares múltiples (MSMs)
  • emparejamientos
  • suma, multiplicación, inversión escalar
  • hash a un escalar o a un punto
  • y muchas más

Ejemplos de aplicaciones poderosas que se pueden construir encima incluyen:

  1. Rollups de validez – Consulta el ejemplo del verificador de groth16 zkSNARK.
  2. Juegos basados en aleatoriedad – Consulta el ejemplo del verificador de drand.
  3. Aplicaciones de privacidad – Consulta el ejemplo de veiled_coin (#veiled-coins).

El módulo aptos_std::ristretto255 proporciona soporte para la aritmética de curvas elípticas en la popular curva Ristretto255. Una de las principales ventajas de Ristretto255 es que es un grupo de orden de primo (a diferencia de la curva Edwards 25519), lo que elimina los ataques de subgrupo pequeño en sistemas criptográficos superiores construidos encima. Además, la serialización de Ristretto255 es canónica y la deserialización solo acepta codificaciones canónicas, lo que elimina problemas de malleabilidad en protocolos superiores.

Este módulo ha resultado útil para implementar varias primitivas criptográficas:

  1. Protocolos Σ\Sigma-de-conocimiento cero – Consulta el ejemplo de veiled_coin (#veiled-coins).
  2. Cifrado ElGamal – Consulta aptos_std::ristretto255_elgamal
  3. Comités de Pedersen – Consulta aptos_std::ristretto255_pedersen
  4. Pruebas de rango ZK Bulletproofs[^bulletproofs] – Consulta aptos_std::ristretto255_bulletproofs

¿Tienes ideas para un sistema criptográfico para construir encima de ristretto255? Un primitivo popular que podrías construir fácilmente sería el esquema de firma schnorrkel, que es una versión endurecida de firmas de Schnorr sobre grupos Ristretto255.

¿Qué es mejor que una curva? Más curvas!

El módulo aptos_std::crypto_algebra proporciona operaciones de aritmética de curva elíptica para cualquier curva elíptica soportada, incluyendo curvas de emparejamiento. Como consecuencia, los desarrolladores de Move pueden implementar un sistema criptográfico de forma genérica sobre cualquier curva que sea o que vaya a ser soportada en el futuro. Comparado con fijar una curva particular en el código (por ejemplo, implementando contra el módulo Ristretto255), este enfoque proporciona más flexibilidad y reduce el tiempo de desarrollo al migrar a una curva diferente.

Aunque actualmente el módulo crypto_algebra solo soporta aritmética sobre curvas BLS12-381 (a través de los tipos marcadores declarados en aptos_std::bls12381_algebra), más curvas serán soportadas en el futuro (por ejemplo, BN254, Ristretto255, BLS12-377, BW6-761, secp256k1, secp256r1).

Como ejemplo, un desarrollador de Move puede implementar el popular esquema de firma de Boneh-Lynn-Shacham (BLS) de forma genérica sobre cualquier curva usando parámetros de tipo para el tipo de curva en su implementación:

use std::option;
use aptos_std::crypto_algebra::{eq, pairing, one, deserialize, hash_to};
/// Ejemplo de una función de verificación de firma BLS que funciona sobre cualquier tripleta de grupos de emparejamiento
/// `Gr1`, `Gr2`, `GrT` donde las firmas están en `Gr1` y las PKs en `Gr2`.
/// Los puntos se serializan usando el formato en `FormatG1` y `FormatG2` y el método de hash es `HashMethod`.
///
/// ADVERTENCIA: Este ejemplo es de tipo inseguro y probablemente no sea una buena opción para el código de producción.
public fun bls_verify_sig<Gr1, Gr2, GrT, FormatG1, FormatG2, HashMethod>(
dst: vector<u8>,
signature: vector<u8>,
message: vector<u8>,
public_key: vector<u8>): bool
{
let sig = option::extract(&mut deserialize<Gr1, FormatG1>(&signature));
let pk = option::extract(&mut deserialize<Gr2, FormatG2>(&public_key));
let hash = hash_to<Gr1, HashMethod>(&dst, &message);
// Verifica si $e(H(m), pk) = e(sig, g_2)$, donde $g_2$ genera $\mathbb{G}_2$
eq(
&pairing<Gr1, Gr2, GrT>(&hash, &pk),
&pairing<Gr1, Gr2, GrT>(&sig, &one<Gr2>())
)
}

Usando la función bls_verify_sig genérica de arriba, los desarrolladores pueden verificar firmas BLS sobre cualquier de las curvas soportadas (de emparejamiento). Por ejemplo, uno puede verificar MinSig BLS firmas sobre curvas BLS12-381 llamando a la función anterior con los tipos marcadores BLS12-381 correctos como sus argumentos de tipo:

use aptos_std::bls12381_algebra::{
G1, G2, Gt, FormatG1Compr, FormatG2Compr, HashG1XmdSha256SswuRo
};
// Aborta con código 1 si la firma MinSig BLS sobre la curva BLS12-381 falla la verificación.
assert(
bls_verify_sig<G1, G2, Gt, FormatG1Compr, FormatG2Compr, HashG1XmdSha256SswuRo>(
dst, signature, message, public_key
),
1
);

Para más casos de uso del módulo crypto_algebra, consulta algunos ejemplos de Move:

  1. Verificando pruebas de Groth16 zkSNARK sobre cualquier curva
  2. Verificando aleatoriedad desde el beacon drand

Construyendo aplicaciones criptográficas poderosas

Sección titulada «Construyendo aplicaciones criptográficas poderosas»

El ejemplo de veiled_coin demuestra cómo usar los módulos Ristretto255 mencionados arriba para agregar una capa razonable de confidencialidad a los saldos y transacciones de monedas.

Específicamente, los usuarios pueden velar su saldo, manteniéndolo oculto para todos, incluidos los validadores. Además, un usuario puede enviar una transacción velada que oculte la cantidad de la transacción para todos, incluidos los validadores. Una advertencia importante es que las transacciones veladas no ocultan las identidades del remitente o destinatario.

El ejemplo de groth16 demuestra cómo verificar pruebas de Groth16 zkSNARK[^groth16], que son las pruebas de conocimiento cero más cortas, rápidas de verificar y de propósito general. Importante, como se explicó arriba, esta implementación es genérica sobre cualquier curva, lo que la hace muy fácil de usar para los desarrolladores de Move con sus curvas favoritas (soportadas).

Verificando aleatoriedad desde el beacon drand

Sección titulada «Verificando aleatoriedad desde el beacon drand»

El ejemplo de drand muestra cómo verificar aleatoriedad pública desde el beacon de aleatoriedad de drand. Esta aleatoriedad puede usarse en juegos o cualquier otro contrato inteligente basado en azar. Damos un ejemplo simple de una lotería implementada sobre la aleatoriedad de drand en lottery.move.

Otra aplicación que se puede construir encima de drand es el cifrado con bloqueo de tiempo[^tlock], que permite a los usuarios cifrar información de forma que solo pueda ser descifrada en un bloque futuro. Actualmente no tenemos una implementación, ¡pero animamos al lector a escribir una!

[^bulletproofs]: bulletproofs: Bulletproofs: Short Proofs for Confidential Transactions and More; por B. Bünz y J. Bootle y D. Boneh y A. Poelstra y P. Wuille y G. Maxwell; en 2018 IEEE Symposium on Security and Privacy