¿Cómo se generan las direcciones ethereum?

¿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?

No estoy de acuerdo con el duplicado. La pregunta no se trata de verificar si la dirección es válida, sino de cómo se construye la dirección y si sigue un formato o es simplemente aleatoria. De hecho, no es aleatorio sino el resultado de algunos procesos. El hecho de que la palabra "válida" esté en la pregunta no es un criterio, ¡no marcará todas las preguntas con la palabra "válida" como duplicadas!
@tayvano no soy el que hizo esta pregunta
Está totalmente bien que las preguntas sean editadas/mejoradas y votadas para reabrir. Aquí vamos.
Podría valer la pena mantener los comentarios que apuntan a posibles incautos, ya que tienen valor al ofrecer una perspectiva diferente a aquellos de nosotros que estamos aprendiendo.

Respuestas (6)

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/


del papel amarillo

papel amarillo

Hay tres pasos principales para obtener desde privado -> dirección:

  1. Cree una clave privada aleatoria (64 caracteres (hexadecimales) / 256 bits / 32 bytes)

  2. Derivar la clave pública de esta clave privada (128 caracteres (hexadecimales) / 512 bits / 64 bytes)

  3. 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.

1. Generación de clave privada

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...

2. Clave privada -> Clave pública

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.

3. Clave pública -> Dirección

  1. Comience con la clave pública (128 caracteres / 64 bytes)

  2. 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)

  3. 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.

Definiciones

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

¿Cuál es la lógica detrás de usar solo los últimos 20 bytes del hash?
@k26dr Cada criptografía parece hacer algo similar para mantener las direcciones únicas (para que no envíe Bitcoin a una dirección ETH, etc.). Sin embargo, no sé el motivo específico. Sin embargo, sería una gran pregunta nueva. Es poco probable que obtenga una respuesta real aquí.
@ k26dr es solo para mantener las direcciones lo más cortas posible sin correr el riesgo de tener colisiones.
Buena información: pero no explicó la suma de verificación final (opcional) para letras mayúsculas como lo hizo aquí. ethereum.stackexchange.com/a/2046/22785 Esto también es parte de la generación de direcciones públicas.
Dice aquí: ethdocs.org/en/latest/… que la clave privada está codificada con la contraseña de los usuarios, ¿esto no parece mencionarse en esta respuesta?
@MartinDawson La respuesta le dice cómo se generan las claves (y es correcta). Después de generar las claves públicas/privadas, debe almacenarlas en algún lugar seguro. Para eso está el archivo encriptado con contraseña.
@k26dr Sospecho que otra razón para acortar la dirección a 160 bits fue que los nodos p2p de Kademlia DHT son de 160 bits según la especificación y, si no recuerdo mal, los nodos de Ethereum deberían proporcionar su dirección como ID de nodo de Kademlia.
¿Existe un software oficial* de código abierto para generar simplemente las claves privadas y las claves públicas? (*Hecho por los chicos que crearon el ETH)

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, nque 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 spara 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 sdebe 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 sse 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-keysbiblioteca de la Repositorio Github de la Fundación Ethereum (el siguiente ejemplo puede requerir la instalación de la sha3biblioteca ( 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:

  1. Genere un número seguro de 256 bits con formato hexadecimal convertido en una cadena con el prefijo 0x descartado.
  2. Convierta la cadena hexadecimal generada en el paso 1 en un objeto de bytes (b"").
  3. Calcule la clave pública como hexadecimal usando el objeto de bytes de clave privada creado en el paso 2.
  4. Convierta la clave pública hexadecimal generada en el paso 3 en un objeto de bytes.
  5. Calcule el resumen hash del objeto de bytes creado en el paso 4 usando Keccak_256.
  6. Tome los 40 caracteres hexadecimales más a la derecha/últimos (160 bits finales en el lado little-endian) del resumen hash creado en el paso 5, que se convierte en la dirección ethereum derivada.

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_bytesal 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.

En el algoritmo de generación de ETH HD-Wallet (derivación de clave secundaria de la ruta m/44'/60/0/x), ¿debemos usar clave pública 'comprimida' o 'sin comprimir'?
Parece que se usa 33 bytes 'comprimidos'
Re. el comentario sobre la clave secreta relativa al parámetro de la curva elíptica n, consulte: eips.ethereum.org/EIPS/eip-1271 : "Si su biblioteca genera firmas maleables, como svalores en el rango superior, calcule un nuevo valor s con 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1y voltear vde 27a 28o viceversa. Si su biblioteca también genera firmas con 0/ 1para ven lugar de 27/ 28, agregue 27a vpara 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?

¡De acuerdo! Algunas preguntas rápidas: 1) Las claves privadas y públicas: ¿qué algoritmo de cifrado se utiliza? ¿Es lo mismo que para bitcoin? (secp256k1 ECDSA creo) 2) La dirección: Es un hash de la clave pública. ¿Qué función hash se utiliza? SHA256?
Si y si pero con keccak256. Pero debe hacer esto en otra pregunta y marcar esta como respondida si considera que la pregunta inicial está respondida.
En realidad, eran estas preguntas en el comentario las que quería responder (cómo se genera la dirección, qué algoritmos, etc.). ¡Si lo agregas a la respuesta, lo marcaré como respondido! Voy a aclarar un poco mi pregunta original.
;) Aclara tu pregunta primero. Es difícil responder claramente a preguntas que ni siquiera se hacen.
No se recomiendan las preguntas de solo enlace.
Pensé que solo era un problema para los enlaces fuera de los sitios de pila. Pero el interior debería estar bien ya que el objetivo debería ser visible si el enlace es visible. Es solo un problema para las personas que imprimen páginas web, pero nadie debería hacer eso.

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).

Fuente


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