Mastering Bitcoinを読む Chapter4 Mnemonic Code

f:id:yzono:20150127111518j:plain

はじめに

今回はMnemonic Code、Mnemonic Code Wordsについて書きます。

目次

  • Mnemonic Code Wordsとは
  • Mnemonic Code Converter
  • Mnemonic Code Wordsの作り方

Mnemonic Code Wordsとは

Mnemonic Code Words

Mnemonic Code Wordsは128ビット〜256ビットの数値を人間が分かりやすいように12〜24の単語で表現したものです。

以下は128ビットのエントロピーの例です。

Entropy input (128 bits) : 0c1e24e5917779d297e14d45f14e1a1a

Mnemonic (12 words) : army van defense carry jealous true garbage claim echo media make crunch

Mnemonic CodeはPBKDF2により何度もハッシュされて512ビットのseedを生成します。seedはDeterministic walletの作成、秘密鍵の作成に利用されます。BIP39で提案されており、Draftステータスですが多くのWalletで採用されており、有志により日本語版のMnemonic Codeも開発されています。

Mnemonic Code Converter

Mnemonic Codeを体験したい場合は、Mnemonic Code Converterが便利です。画面を開いて"Generate Random Mnemonic"ボタンをクリックしてください。12単語のMnemoni Codeが表示されます。

f:id:yzono:20150127111314p:plain

Mnemonic Code Wordsの作り方

Mnemonic Code Wordsは以下プロセスで生成されます。

1. Create a random sequence (entropy) of 128 to 256 bits.
2. Create a checksum of the random sequence by taking the first few bits of its SHA256 hash.
3. Add the checksum to the end of the random sequence.
4. Divide the sequence into sections of 11 bits, using those to index a dictionary of 2048 predefined words.
5. Produce 12 to 24 words representing the mnemonic code.

Mnemonic Code Converter(JavaScript)を参考に、128ビットの場合の処理を見てみます。

1. Create a random sequence (entropy) of 128 to 256 bits.

8ビット符号なし整数値の配列を初期化して、crypto.getRandomValuesでランダムな値を取得します。

var buffer = new Uint8Array(strength / 8); // strength=128
var data = crypto.getRandomValues(buffer);
//  [51, 153, 228, 163, 247, 204, 76, 139, 190, 94, 103, 223, 113, 167, 207, 50]

2. Create a checksum of the random sequence by taking the first few bits of its SHA256 hash.

// ??  よく分からない..
var data = byteArrayToWordArray(byteArray);
var hash = sjcl.hash.sha256.hash(data);        
var h = sjcl.codec.hex.fromBits(hash);
var a = byteArrayToBinaryString(byteArray);

// Zero fill
var c = zfill(hexStringToBinaryString(h), 256);

// Checksum
var d = c.substring(0, byteArray.length * 8 / 32);

3. Add the checksum to the end of the random sequence.

var b = a + d;

//a=00110011100110011110010010100011111101111100110001001100100010111011111001011110011001111101111101110001101001111100111100110010

//b=0011

4. Divide the sequence into sections of 11 bits, using those to index a dictionary of 2048 predefined words.

var result = [];
var blen = b.length / 11;
for (var i=0; i<blen; i++) {
    var idx = parseInt(b.substring(i * 11, (i + 1) * 11), 2);
    result.push(wordlist[idx]);
}

5. Produce 12 to 24 words representing the mnemonic code.

["crime", "song", "cigar", "usage", "shadow", "easy", "west", "smooth", "term", "minor", "video", "good"]

まとめ

ランダムシーケンスをハッシュするところがよく分かってないです。難しくなってきました..

参考

BIP39

Mnemonic Code Converter

Hash関数まとめ(md5, sha1, sha2, crc32, PBKDF2)