Electrum

Electrum 如何從種子中生成密鑰對?

  • May 1, 2015

Electrum 使用 12 個單詞的種子來生成密鑰對,然後從該密鑰對中分層生成地址。

我知道如何從密鑰對生成分層地址,但我不明白 Electrum 如何從種子生成密鑰對。我知道種子由來自 2048 長度單詞列表的單片語成,但在那之後我不清楚它是如何開始生成地址序列的。


我想在 Java/C++/Python 或 C# 中進行 HD 生成。如果我能理解這個過程,我也許可以自己重現它並從種子中生成分層地址。


編輯:

一天后,我找到了這個 Java 實現……感謝您的回答!

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

Electrum 1.x 創建的錢包有包含 12 個單詞的種子(自定義創建的種子也可以是 24 個單詞)。給定一個從零開始的具有該長度的 seed_words 數組,此虛擬碼計算 master_private_key:

i = 0
while i &lt; 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 &lt; 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 &lt; 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)

如果您想知道,似乎 seed_ints 計算看起來過於復雜的原因可能是為了避免侵犯專利

相比之下,由 Electrum 2.x 創建的錢包通常包含 13 個單詞的種子,但有時它們會更少。(在恢復 Electrum 2.x 錢包時,幾乎可以建構任何長度的種子。)這是計算 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是一種替代派生技術,與 Electrum 2.x 類似,但並不完全相同。

引用自:https://bitcoin.stackexchange.com/questions/37176