Electrum utiliza una semilla de 12 palabras para generar un par de claves y luego genera jerárquicamente direcciones a partir de ese par de claves.
Sé cómo generar direcciones jerárquicas a partir de un par de claves, pero lo que no entiendo es cómo Electrum genera un par de claves a partir de la semilla. Entiendo que la semilla consiste en palabras que provienen de una lista de palabras de 2048 de longitud, pero después de eso no me queda claro cómo comienza a generar la secuencia de direcciones.
Me gustaría hacer la generación HD en Java/C++/Python o C#. Si puedo entender el proceso, podría reproducirlo yo mismo y generar direcciones jerárquicas a partir de una semilla.
EDITAR:
Un día después encuentro esta implementación de Java... ¡Gracias por las respuestas!
Las billeteras creadas por Electrum 1.x tienen semillas que contienen 12 palabras (24 palabras también son posibles para semillas creadas a medida ). Dada una matriz de base cero de seed_words de esa longitud, este pseudocódigo calcula master_private_key:
i = 0
while i < length(seed_words):
# convert each word into an int in the range [0,1625]
# based on the word's position in the sorted word list
seed_ints[i] = lookup_seed_word(seed_words[i])
i = i + 1
num_words = 1626
num_words2 = num_words * num_words
seed_hex_str = ""
i = 0
while i < length(seed_words):
# (hex8 converts an int into an ASCII string of
# exactly 8 zero-padded lowercase hex digits;
# % is the integer remainder operator
seed_hex_str = seed_hex_str + hex8( seed_ints[i ]
+ num_words * ( (seed_ints[i + 1] - seed_ints[i ]) % num_words )
+ num_words2 * ( (seed_ints[i + 2] - seed_ints[i + 1]) % num_words ))
i = i + 3
unstretched_seed = ascii_string_to_byte_array(seed_hex_str)
seed = byte_array() # an empty byte array
i = 0
while i < 100000:
# sha256 operates on and produces byte arrays
seed = sha256(seed + unstretched_seed)
i = i + 1
master_private_key = byte_array_to_int(seed, order=big_endian)
En caso de que se lo pregunte, parece que la razón por la que el cálculo de seed_ints parece demasiado complejo puede ser para evitar infringir una patente .
A modo de comparación, las billeteras creadas por Electrum 2.x generalmente tienen semillas que contienen 13 palabras, sin embargo, en ocasiones tendrán menos. (Es técnicamente posible construir semillas de casi cualquier longitud que se aceptarán al restaurar una billetera Electrum 2.x). Aquí está el pseudocódigo que calcula una clave privada maestra extendida BIP-32:
# Electrum 2.x doesn't separate mnemonic words with spaces in sentences for any CJK
# scripts when calculating the checksum or deriving a binary seed (even though this
# seems inappropriate for some CJK scripts such as Hiragana as used by the ja wordlist)
if language is CJK:
space = ""
else:
space = " "
seed_phrase = ""
i = 0
do:
word = seed_words[i]
normalize_unicode(word, normalization=nfkd)
remove_unicode_combining_marks(word) # e.g. accent marks
seed_phrase = seed_phrase + word
i = i + 1
if i ≥ length(seed_words):
exit-loop
seed_phrase = seed_phrase + space
seed_utf8 = unicode_to_byte_array(seed_phrase, format=utf8)
if hmac_sha512(key="Seed version", message=seed_utf8)[0] ≠ 1:
fail("invalid checksum")
stretched_seed = pbkdf2_hmac_sha512(password=seed_utf8, salt="electrum", iterations=2048, output_length=64)
seed_bytes = hmac_sha512(key="Bitcoin seed", message=stretched_seed)
private_key = byte_array_to_int(seed_bytes[0..31], order=big_endian)
chain_code_bytes = seed_bytes[32..63]
master_private_key = create_bip32_extended_private_key(private_key, chain_code_bytes)
BIP-39 , una técnica de derivación alternativa, es similar a Electrum 2.x pero no idéntica.
SR Jones
Christopher Gurnee
Christopher Gurnee
TomasV