Foto de Steve driscoll en Unsplash
La criptografía asimétrica es uno de los inventos informáticos más importantes del siglo pasado. También se encuentra en el corazón de toda la tecnología blockchain . En esta publicación, analizaremos más a fondo cómo Ethereum utiliza el algoritmo de firma digital de curva elíptica (ECDSA) para validar el origen y la integridad de los mensajes.
Las técnicas de cifrado como ECDSA también son esenciales para extender de forma segura las cadenas de bloques existentes. Hemos visto esto en mi publicación anterior analizando intercambios descentralizados donde un DEX usa firmas en su comunicación fuera de la cadena. A medida que el ecosistema de la cadena de bloques madure, espero que veamos más extensiones de capa 2 y capa 3 de la infraestructura de cadena de bloques de bajo nivel existente.
En Ethereum, como en cualquier otro sistema de cadena de bloques, hay una clave privada y otra pública. Estas claves se generan cuando crea una nueva "cuenta" de blockchain. Mantener segura la clave privada es esencial porque cualquier copia permite el acceso al libro mayor. Las billeteras de hardware para almacenar de forma segura la clave privada se han convertido en una mejor práctica esencial.
La noción de una cuenta es un poco inapropiada, porque en términos estrictamente técnicos, solo hay claves y un libro mayor de fondos que se corresponden con esas claves. Una dirección de Ethereum o Bitcoin es esencialmente una versión codificada de la clave pública.
La criptografía de curva elíptica (ECC) y ECDSA son una versión específica de la criptografía asimétrica. Son ampliamente utilizados en la tecnología blockchain por tres razones:
ECDSA utiliza la estructura algebraica de curvas elípticas sobre campos finitos. Sin entrar en las matemáticas, requieren un conjunto de constantes para definir esta curva. Las constantes utilizadas por la mayoría de las cadenas de bloques se establecen en el estándar secp256k1 .
Ejemplo de forma de una curva elíptica
Antes de blockchain, este estándar de curva elíptica no era nada común. De hecho, la mayoría de los principales proveedores de hardware no admiten el cifrado de hardware para esta curva . Se rumorea que secp256k1 fue elegido porque tiene la menor probabilidad de que la NSA implante puertas traseras cleptográficas .
En un sistema de cadena de bloques, cualquier titular de clave puede usar su clave privada para firmar un dato. Esto da como resultado una firma. Quien obtenga la firma puede utilizarla para:
Echemos un vistazo a las funciones exactas utilizadas en Ethereum para realizar la firma:
La primera línea crea un hash SHA3 del mensaje que queremos firmar. Esto da como resultado el siguiente hash de 32 bytes (256 bits):
0x592fa743889fc7f92ac2a37bb1f5ba1daf2a5c84741ca0e0061d243a2e6707ba
Luego, la línea 2 usa JSON RPC de Ethereum para decirle a la billetera Ethereum (que controla la clave privada) que firme el mensaje en una cuenta determinada, lo que resulta en una firma. La última línea es decodificar la salida JSON RPC para que obtengamos los valores de firma V, R y S. (V es algo que se agregó para abordar cierto tipo de ataque ).
Tanto los clientes de Smart Contracts como de Ethereum tienen la capacidad de verificar las firmas ECDSA. La verificación ECDSA en Smart Contracts permite comunicaciones a prueba de manipulaciones fuera de la cadena de bloques. Hay muchos proyectos, como por ejemplo $ZRX, que dependen de esto para la comunicación fuera de la cadena.
En Solidity , un mensaje firmado se puede verificar con el siguiente código:
Este código devolverá la dirección de Ethereum (clave pública) que se utilizó para firmar el mensaje. Cualquier cambio en el hash o la firma del mensaje dará como resultado una dirección diferente a la dirección de origen.
A veces es bueno echar un vistazo bajo el capó de estas funciones, solo para que podamos obtener una comprensión más profunda. Las siguientes dos secciones siguen el código que se usa en la popular billetera Meta Mask y las entrañas internas del código Go-Ethereum Smart Contract.
Meta Mask es una extensión de Chrome que crea una experiencia de transacción fácil de usar. Los usuarios pueden enviar/recibir Ether, firmar mensajes e interactuar con Smart Contracts. También viene con un increíble zorro poligonal en 3D que sigue el cursor mientras escribes.
Las claves privadas en Meta Mask se almacenan en el almacenamiento local del navegador. Meta Mask utiliza una biblioteca externa para cifrar la información de la clave privada con una contraseña. (Usando AES-GCM).
Cuando firmamos mensajes con Meta Mask, aparece una ventana emergente que muestra el mensaje y la cuenta desde la que firmar:
Cuando examinamos el código subyacente, pasamos por las siguientes bibliotecas, la mayoría de las cuales están controladas por los desarrolladores de Meta Mask.
Algunos de los paquetes de NPM utilizados para firmar un mensaje
¡Bienvenido al maravilloso mundo de Javascript moderno!
El código JS de Ethereum más relevante para la firma es el siguiente:
Se están realizando muchas conversiones de estructura de datos, pero en la función final podemos ver cómo se obtiene la firma R, S, V llamando a la función secp256k1.sign() . Lo que nos lleva a la siguiente pieza de código fundamental dentro de la biblioteca elíptica :
Echemos un vistazo más de cerca al código de contrato antes mencionado que recupera la clave pública de la firma:
La función ecrecover() proporcionada por Solidity es en realidad un poco especial. Es uno de los pocos "contratos nativos" disponibles en los contratos inteligentes. Estos son contratos inteligentes internos en código que se pueden llamar. Aquí hay una forma alternativa de llamar a ecrecover() en el ensamblador Solidity EVM :
La función call() ejecuta el contrato en la dirección fija 3000 . Luego ejecuta el siguiente código (en el caso de la implementación go-ethereum):
Esto eventualmente llama al siguiente código C para recuperar la clave pública (usando el puntero pubkey ):