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.
Primitivas criptográficas
Sección titulada «Primitivas criptográficas»Move, a través del adaptador de Aptos, abarca varias herramientas criptográficas fundamentales:
- 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.
- 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.
- 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.
- Pruebas de Conocimiento Cero (ZKP) – Estas técnicas criptográficas permiten a una parte demostrar que una relación se satisface sobre una declaración pública sin revelar el testigo secreto 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:
- 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.
- 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.
- 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.
Funciones hash criptográficas
Sección titulada «Funciones hash criptográficas»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 hash | Tamaño hash (bits) | Costo por hashear 1KiB (en unidades internas de gas) | Seguridad de resistencia a colisiones (bits) |
---|---|---|---|
Keccak256 | 256 | 1,001,600 | 128 |
SHA2-256 | 256 | 1,084,000 | 128 |
SHA2-512 | 512 | 1,293,600 | 256 |
SHA3-256 | 256 | 1,001,600 | 128 |
SHA3-512 | 512 | 1,114,000 | 256 |
RIPEMD160 | 160 | 1,084,000 | 80 (débil) |
Blake2b-256 | 256 | 342,200 | 128 |
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.
Verificación de firmas digitales
Sección titulada «Verificación de firmas digitales»Los desarrolladores ahora pueden usar una API segura por tipo para verificar muchas clases de firmas digitales en Move:
Esquema de firma | Curva | Tamaño de firma (bytes) | Tamaño de PK (bytes) | Malleabilidad | Suposiciones | Pros | Desventajas |
---|---|---|---|---|---|---|---|
ECDSA | secp256k1 | 64 | 64 | Sí | GGM | Adopción amplia | Prueba de seguridad |
Ed25519 | Edwards 25519 | 64 | 32 | No | DLA, ROM | Rápido | Subtleties |
MultiEd25519 | Edwards 25519 | No | DLA, ROM | Fácil de adoptar | Tamaño de firma grande | ||
MinPK BLS | BLS12-381 | 96 | 48 | No | CDH, ROM | Versátil | Verificación más lenta |
MinSig BLS | BLS12-381 | 48 | 96 | No | CDH, ROM | Versátil | Verificació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:
- 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.
- 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.
- Facilidad de implementación
- Aunque teóricamente sólido, protocolos complejos pueden ser desafiantes de implementar en la práctica.
- Ejemplo: Aunque existen protocolos -de- 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.
- Aunque teóricamente sólido, protocolos complejos pueden ser desafiantes de implementar en la práctica.
- 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.
- Dependiendo de las necesidades de tu dapp, podrías priorizar una eficiencia sobre otra.
- 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, , puede ser maullada en una firma diferente pero aún válida, , para el mismo mensaje .
- Es esencial considerar las suposiciones subyacentes y posibles vulnerabilidades de un esquema de firma.
- 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 -de- de BLS son muy simples de implementar.
- 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.
Aritmética de curvas elípticas
Sección titulada «Aritmética de curvas elípticas»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:
- Ristretto255, a través de
aptos_std::ristretto255
- BLS12-381, a través de
aptos_std::crypto_algebra
yaptos_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:
- Rollups de validez – Consulta el ejemplo del verificador de
groth16
zkSNARK. - Juegos basados en aleatoriedad – Consulta el ejemplo del verificador de
drand
. - Aplicaciones de privacidad – Consulta el ejemplo de
veiled_coin
(#veiled-coins).
Aritmética de Ristretto255
Sección titulada «Aritmética de Ristretto255»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:
- Protocolos -de-conocimiento cero – Consulta el ejemplo de
veiled_coin
(#veiled-coins). - Cifrado ElGamal – Consulta
aptos_std::ristretto255_elgamal
- Comités de Pedersen – Consulta
aptos_std::ristretto255_pedersen
- 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.
Aritmética de curva elíptica genérica
Sección titulada «Aritmética de curva elíptica genérica»¿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:
- Verificando pruebas de Groth16 zkSNARK sobre cualquier curva
- Verificando aleatoriedad desde el beacon
drand
Construyendo aplicaciones criptográficas poderosas
Sección titulada «Construyendo aplicaciones criptográficas poderosas»Monedas veladas
Sección titulada «Monedas veladas»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.
Verificador de Groth16 zkSNARK
Sección titulada «Verificador de Groth16 zkSNARK»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