Wie macht Electrum aus einem Seed ein Schlüsselpaar?

Electrum verwendet einen Seed von 12 Wörtern, um ein Schlüsselpaar zu generieren, und generiert dann hierarchisch Adressen aus diesem Schlüsselpaar.

Ich weiß, wie man hierarchische Adressen aus einem Schlüsselpaar generiert, aber was ich nicht verstehe, ist, wie Electrum ein Schlüsselpaar aus dem Seed generiert. Ich verstehe, dass der Seed aus Wörtern besteht, die aus einer Wortliste mit einer Länge von 2048 stammen, aber danach ist mir unklar, wie er beginnt, die Abfolge von Adressen zu generieren.


Ich möchte die HD-Generierung entweder in Java / C++ / Python oder C# durchführen. Wenn ich den Prozess verstehe, kann ich ihn möglicherweise selbst reproduzieren und hierarchische Adressen aus einem Seed generieren.


BEARBEITEN:

Einen Tag später finde ich diese Java-Implementierung ... Danke für die Antworten!

https://github.com/harningt/atomun-mnemonic

Antworten (1)

Wallets, die von Electrum 1.x erstellt wurden, haben Seeds mit 12 Wörtern (24 Wörter sind auch für benutzerdefinierte Seeds möglich ). Bei einem nullbasierten Array von Seed_words dieser Länge berechnet dieser Pseudocode den 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)

Falls Sie sich fragen, scheint der Grund, warum die Seed_ints-Berechnung übermäßig komplex aussieht, darin zu liegen, ein Patent nicht zu verletzen .

Zum Vergleich: Brieftaschen, die von Electrum 2.x erstellt wurden, haben normalerweise Samen mit 13 Wörtern, gelegentlich haben sie jedoch weniger. (Technisch ist es möglich, Seeds nahezu beliebiger Länge zu konstruieren, die beim Wiederherstellen einer Electrum 2.x-Brieftasche akzeptiert werden.) Hier ist der Pseudocode, der einen erweiterten privaten BIP-32-Hauptschlüssel berechnet:

# 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 , eine alternative Ableitungstechnik, ist Electrum 2.x ähnlich, aber nicht identisch.

"seed = sha256 (seed + unstretched_seed)" oder seed = sha256 (seed) + sha256 (unstretched_seed)) "? Ich kenne keine SHA256-Methode, die zwei Byte-Arrays verwendet.
Du hast recht, das tut es nicht. Das '+' sollte eine Verkettung vermitteln. IOW, der ursprüngliche unstetched_seed wird an das Ergebnis des letzten sha256 angehängt, bevor sein Hash in jeder Iteration genommen wird. Ein konkreteres Beispiel finden Sie hier: github.com/gurnec/btcrecover/blob/…
@MrJones FYI Ich habe einen Fehler im Pseudocode von Electrum 1.x behoben: num_words war falsch. Das tut mir leid.
Ich bestätige die Sache mit der Patentvermeidung