¿Qué criterios debe cumplir una dirección de Ethereum válida? ¿Es solo un número aleatorio en hexadecimal? ¿O debe derivarse de una manera específica, de acuerdo con algunos algoritmos criptográficos? ¿Qué algoritmos y estándares se utilizan para generar el par de claves?
Recientemente me llamó la atención este artículo que es mucho más profundo y técnico que mi versión más accesible a continuación. También lo guía a través de cómo generar uno por su cuenta. Lo recomiendo mucho: https://kobl.one/blog/create-full-ethereum-keypair-and-address/
Cree una clave privada aleatoria (64 caracteres (hexadecimales) / 256 bits / 32 bytes)
Derivar la clave pública de esta clave privada (128 caracteres (hexadecimales) / 512 bits / 64 bytes)
Derive la dirección de esta clave pública. (40 caracteres (hexadecimales) / 160 bits / 20 bytes)
Aunque mucha gente llama a la dirección clave pública, en realidad no es el caso en Ethereum. Hay una clave pública separada que actúa como un intermediario que nunca verá, a menos que busque un archivo JSON de billetera de preventa.
La clave privada tiene 64 caracteres hexadecimales. Cada cadena de 64 hexadecimales es, hipotéticamente, una clave privada de Ethereum (vea el enlace en la parte superior para saber por qué esto no es totalmente exacto) que accederá a una cuenta. Si planea generar una nueva cuenta, debe asegurarse de que estén sembradas con un RNG adecuado. Una vez que tengas esa cadena...
Esto es difícil y más allá de mí. Hay algo con el algoritmo de firma digital de curva elíptica (ECDSA) y esas cosas. Pero al final terminas con una clave pública de 64 bytes.
Comience con la clave pública (128 caracteres / 64 bytes)
Tome el hash Keccak-256 de la clave pública. Ahora debería tener una cadena de 64 caracteres / 32 bytes. (nota: SHA3-256 eventualmente se convirtió en el estándar, pero Ethereum usa Keccak)
Tome los últimos 40 caracteres/20 bytes de esta clave pública (Keccak-256). O, en otras palabras, suelte los primeros 24 caracteres/12 bytes. Estos 40 caracteres/20 bytes son la dirección. Cuando tiene el prefijo 0x, se convierte en 42 caracteres.
Dirección: una dirección de Ethereum representa una cuenta. Para EOA, la dirección se obtiene como los últimos 20 bytes de la clave pública que controla la cuenta, por ejemplo, `cd2a3d9f938e13cd947ec05abc7fe734df8dd826. Este es un formato hexadecimal (notación de base 16), que a menudo se indica explícitamente agregando 0x a la dirección. Web3.js y las funciones de la consola aceptan direcciones con o sin este prefijo, pero por motivos de transparencia recomendamos su uso. Dado que cada byte de la dirección está representado por 2 caracteres hexadecimales, una dirección prefijada tiene 42 caracteres. Varias aplicaciones y API también están destinadas a implementar el nuevo esquema de dirección habilitado para suma de verificación introducido en la billetera Mist Ethereum a partir de la versión 0.5.0. - Documentos de Homestead
Clave privada: un número entero positivo seleccionado aleatoriamente (representado como una matriz de bytes de longitud 32 en formato big-endian) en el rango [1, secp256k1n − 1]
. - Papel Amarillo
Espacio de clave privada:
Aquí hay algunos ejemplos de código, basados en la curva elíptica secp256k1 utilizada por ethereum, como otros han señalado para que la clave de 256 bits sea válida, debe ser más pequeña que el parámetro de la curva, n
que también es un valor de 256 bits que puede escribirse en formato hexadecimal como:0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
Comprobación de errores:
Varias bibliotecas producirán errores si intenta introducir una clave privada en ellas que sea mayor que n
, como un mecanismo de verificación de errores (es decir, Exception: Invalid privkey
) Consulte esta respuesta relacionada con ejemplos para obtener más detalles.
Parámetros de curva relacionados:
Podemos llamar a la clave privada s
para denotarla como un exponente secreto, ya que este valor se envuelve alrededor de la curva usando el parámetro g
(usando la multiplicación escalar) que denota un punto generador público que es como una constante universal que todos conocen y usan, para poder generar su clave pública a partir de s
.
Por lo tanto g
, permanece público, pero s
debe mantenerse en secreto para que la billetera ethereum permanezca segura, después de derivar su dirección ethereum de su clave pública.
La clave pública se puede representar en formato comprimido con un total de 33 bytes de longitud, o sin comprimir como 64 bytes, y generalmente se indica con un prefijo inicial 0x02 para claves públicas comprimidas, pero la longitud de la cadena es un mejor indicador ya que el prefijo es no también visible o presente dependiendo del paso y la implementación.
Derivación de claves criptográficamente seguras:
La forma en que s
se selecciona también es muy importante en términos de su seguridad criptográfica. En otras palabras, no es recomendable elegir este exponente secreto usted mismo o idear algún tipo de método inteligente como lo haría para una contraseña (también conocida como billetera cerebral), ya que innumerables métodos de este tipo se han utilizado durante décadas para descifrar secretos utilizando varios algoritmos y software de computadora, como los que se usan para descifrar contraseñas.
Por lo tanto, el exponente secreto debe generarse utilizando un generador de números pseudoaleatorios criptográficamente seguro (CSPRNG) como la API de criptografía del WorldWideWeb Consortium (W3C) ( divulgación: soy uno de los 12 contribuyentes a esa especificación en Github ), de modo que es mucho menos probable que un atacante pueda predecir ese valor, ya que los bits aleatorios que componen ese número provienen de varios lugares de su dispositivo local y de procesos que no transmiten esos datos de entropía en línea (asumiendo que el software que usted está usando es seguro junto con un CSPRNG seguro).
Ejemplo de código Python:
Usando Python 3, hay un CSPRNG en la biblioteca de secretos que puede ser tan fácil como ejecutar los siguientes comandos en orden desde el intérprete IDLE o un archivo .py después de importar la biblioteca de secretos:
secrets.randbits(256)
El comando anterior producirá un número binario de 256 bits que se puede usar como clave privada si es menor que el valor de n
, pero deberá formatearse como un objeto de bytes en el ejemplo de implementación de Python a continuación usando la eth-keys
biblioteca de la Repositorio Github de la Fundación Ethereum (el siguiente ejemplo puede requerir la instalación de la sha3
biblioteca ( pip install pysha3hashlib
) que contiene Keccak, si no está presente en la biblioteca predeterminada ):
import secrets
import sha3
import eth_keys
from eth_keys import keys
private_key = str(hex(secrets.randbits(256))[2:])
private_key_bytes = bytes.fromhex(private_key)
public_key_hex = keys.PrivateKey(private_key_bytes).public_key
public_key_bytes = bytes.fromhex(str(public_key_hex)[2:])
Keccak256_of_public_key_bytes = sha3.keccak_256(public_key_bytes).hexdigest()
public_address = keys.PublicKey(public_key_bytes).to_address()
print('\n Private_key:',private_key,
'\n Private_key_bytes:',private_key_bytes,
'\n Public_key_hex:',public_key_hex,
'\n Public_key_bytes:',public_key_bytes,
'\n Full_Keccak_digest:',Keccak256_of_public_key_bytes,
'\n Ethereum address:',public_address)
Salida de ejemplo del código anterior (no se debe usar en la red principal, solo por ejemplo)
Private_key: 7231bfb75a41481965e391fb6d4406b6c356d20194c5a88935151f05136d2f2e
Private_key_bytes: b'r1\xbf\xb7ZAH\x19e\xe3\x91\xfbmD\x06\xb6\xc3V\xd2\x01\x94\xc5\xa8\x895\x15\x1f\x05\x13m/.'
Public_key_hex: 0x013e81c4a44c5303b11452f649be9427b75605339d8eba90f8e99cc401a8bd4f7494e0d0740bcc0282af75f9bd4571ed493a05ed02f1b968a45a46f4d77be149
Public_key_bytes: b"\x01>\x81\xc4\xa4LS\x03\xb1\x14R\xf6I\xbe\x94'\xb7V\x053\x9d\x8e\xba\x90\xf8\xe9\x9c\xc4\x01\xa8\xbdOt\x94\xe0\xd0t\x0b\xcc\x02\x82\xafu\xf9\xbdEq\xedI:\x05\xed\x02\xf1\xb9h\xa4ZF\xf4\xd7{\xe1I"
Full_Keccak_digest: 3f54dd68163875b594cfdc8e8a2250aafb31638b19a83caa49d1ee61089dcb4b
Ethereum address: 0x8a2250aafb31638b19a83caa49d1ee61089dcb4b
Seis pasos desde la clave privada hasta la dirección de Ethereum
Como se puede ver en la implementación anterior que escribí, los seis pasos para pasar de la clave privada a la dirección de ethereum se pueden resumir de la siguiente manera:
Dependencias alternativas:
Además de la biblioteca open-ssl a la que se hace referencia en el artículo que señaló @tayvano, otras bibliotecas que se pueden usar para calcular direcciones públicas de curvas elípticas incluyen la biblioteca ecdsa Python y la biblioteca secp256k1 de Bitcoin escrita en C, aunque esta última contendrá herramientas para formatear direcciones de bitcoin que son totalmente diferentes a las direcciones de ethereum debido a los pasos de formateo y diferentes algoritmos hash y métodos de codificación, incluso si la clave privada subyacente y la clave pública son las mismas, como ejemplo.
Nota: Finalmente, es importante realizar pruebas para asegurarse de que una dirección generada no solo sea válida, sino que la clave privada subyacente utilizada en el proceso sea válida para firmar transacciones (es decir, si un usuario crea un resumen hash de la matriz de bytes tratada como una cadena en lugar de un objeto de bytes que conducirá a un resumen de hash incorrecto y, por lo tanto, a una dirección incorrecta para la clave subyacente).
Ejemplo : una de esas herramientas de verificación de direcciones (suma de verificación) de la biblioteca eth-keys es el siguiente comando: keys.PublicKey().to_checksum_address()
que usa los bytes de la clave pública (es decir, pasar la variable public_key_bytes
al primer paréntesis se vería así en el programa anterior keys.PublicKey(public_key_bytes).to_checksum_address()
para asegurarse de que la dirección calculada es correcta). Esta es la razón por la que usar bibliotecas existentes puede ser más seguro que escribir el código desde cero.
PS Las respuestas y los ejemplos no pretenden ser exhaustivos de todos los riesgos/pasos.
n
, consulte: eips.ethereum.org/EIPS/eip-1271 : "Si su biblioteca genera firmas maleables, como s
valores en el rango superior, calcule un nuevo valor s con 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1
y voltear v
de 27
a 28
o viceversa. Si su biblioteca también genera firmas con 0
/ 1
para v
en lugar de 27
/ 28
, agregue 27
a v
para aceptar estas firmas maleables también".Las direcciones de Ethereum son hashes de una clave pública. Entonces, para generar uno, primero debe generar una clave privada (consulte: ¿Cuál es el enfoque para calcular una dirección Ethereum a partir de una clave privada de 256 bits? ) La clave privada es aleatoria, pero la clave pública y, por lo tanto, su hash utilizado como dirección es no al azar
Para verificar una dirección y, por lo tanto, conocer el formato, consulte ¿Cómo puedo verificar si una dirección de Ethereum es válida?
Si alguien está buscando una solución JS:
const Web3 = require('web3')
const web3 = new Web3()
const elliptic = require('elliptic')
const ec = new elliptic.ec('secp256k1')
function pubKeyToAddress(compressedPubkey) {
let keyPair = ec.keyFromPublic(compressedPubkey, 'hex')
// remove '04' then add prefix '0x'
let pubkey = '0x' + keyPair.getPublic(false, 'hex').substr(2)
let address = trimFirst12Bytes(web3.utils.keccak256(pubkey))
return web3.utils.toChecksumAddress(address)
}
unction trimFirst12Bytes(hexString) {
return '0x'.concat(hexString.substr(hexString.length - 40))
}
Aquí hay un paquete de python alojado en PyPI: eth_address_dump
Volcar la dirección eth de la clave privada:
$ echo "0x6ee825aafad19a0d759e1e0ba61d0c523b7b23038998a92d7904458b91667105" | eth_address_dump
private_key = 0x6ee825aafad19a0d759e1e0ba61d0c523b7b23038998a92d7904458b91667105
public_key = 0xaa3e0b3f86053c2aaa08d6f6398e18f76100e0d675680228b000c252e4393e9fe85fc162e43d721533736d79c102139d3035d2d9251ccf809bc5bddb81cc6563
compressed_public_key = 0x03aa3e0b3f86053c2aaa08d6f6398e18f76100e0d675680228b000c252e4393e9f
address = 0xF7dcf60AebA077461862d51b77d6d804C06E0073
Volcar la dirección eth de las palabras mnemotécnicas:
$ echo "olympic wine chicken argue unaware bundle tunnel grid spider slot spell need" | eth_address_dump
mnemonic = olympic wine chicken argue unaware bundle tunnel grid spider slot spell need
private_key = 0x6ee825aafad19a0d759e1e0ba61d0c523b7b23038998a92d7904458b91667105
public_key = 0xaa3e0b3f86053c2aaa08d6f6398e18f76100e0d675680228b000c252e4393e9fe85fc162e43d721533736d79c102139d3035d2d9251ccf809bc5bddb81cc6563
compressed_public_key = 0x03aa3e0b3f86053c2aaa08d6f6398e18f76100e0d675680228b000c252e4393e9f
address = 0xF7dcf60AebA077461862d51b77d6d804C06E0073
Volcar la dirección eth de la clave pública comprimida:
$ echo "0x03aa3e0b3f86053c2aaa08d6f6398e18f76100e0d675680228b000c252e4393e9f" | eth_address_dump
public_key = 0xaa3e0b3f86053c2aaa08d6f6398e18f76100e0d675680228b000c252e4393e9fe85fc162e43d721533736d79c102139d3035d2d9251ccf809bc5bddb81cc6563
compressed_public_key = 0x03aa3e0b3f86053c2aaa08d6f6398e18f76100e0d675680228b000c252e4393e9f
address = 0xF7dcf60AebA077461862d51b77d6d804C06E0073
Primero se genera una clave privada aleatoria de 64 caracteres (hexadecimales) (256 bits/32 bytes).
A continuación, se deriva una clave pública de 128 caracteres (hexadecimales) (512 bits/64 bytes) a partir de la clave privada generada mediante el algoritmo de firma digital de curva elíptica ( ECDSA ).
A continuación, se aplica la función hash Keccak-256 a la clave pública para obtener una cadena hash de 64 caracteres (256 bits/32 bytes). Los últimos 40 caracteres de esta cadena con el prefijo 0x se convierten en la dirección final de Ethereum. (Nota: 0x en la codificación indica que el número/cadena está escrito en hexadecimal).
Nota: Para obtener una explicación matemática más detallada pero simple de estos pasos, lea este artículo muy útil . Si quieres profundizar más en el concepto, lee este libro .
Ejemplo de código Python simple usando el módulo eth_account
from eth_account import Account
acc = Account.create(password_string)
prv = acc.key
pub = Account._parsePrivateKey(prv).public_key
addr = acc.address
Nicolás Massart
Nicolás Massart
q9f
paula livingstone