Class: Bitcoin::Mnemonic

Inherits:
Object
  • Object
show all
Defined in:
lib/bitcoin/mnemonic.rb

Overview

Mnemonic code for generating deterministic keys github.com/bitcoin/bips/blob/master/bip-0039.mediawiki

Constant Summary collapse

WORD_DIR =
"#{__dir__}/mnemonic/wordlist"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(language) ⇒ Mnemonic

Returns a new instance of Mnemonic.

Raises:

  • (ArgumentError)


11
12
13
14
# File 'lib/bitcoin/mnemonic.rb', line 11

def initialize(language)
  raise ArgumentError, 'specified language is not supported.' unless Mnemonic.word_lists.include?(language)
  @language = language
end

Instance Attribute Details

#languageObject (readonly)

Returns the value of attribute language.



9
10
11
# File 'lib/bitcoin/mnemonic.rb', line 9

def language
  @language
end

Class Method Details

.word_listsObject

get support language list



17
18
19
# File 'lib/bitcoin/mnemonic.rb', line 17

def self.word_lists
  Dir.glob("#{WORD_DIR}/**.txt").map{|f| f.gsub("#{WORD_DIR}/", '').gsub('.txt', '') }
end

Instance Method Details

#checksum(entropy) ⇒ String

calculate entropy checksum

Parameters:

  • entropy (String)

    an entropy with bit string format

Returns:

  • (String)

    an entropy checksum with bit string format



63
64
65
66
# File 'lib/bitcoin/mnemonic.rb', line 63

def checksum(entropy)
  b = Bitcoin.sha256([entropy].pack('B*')).unpack1('B*')
  b.slice(0, (entropy.length/32))
end

#to_entropy(words) ⇒ String

generate entropy from mnemonic word

Parameters:

  • words (Array[String])

    the array of mnemonic word.

Returns:

  • (String)

    an entropy with hex format.

Raises:

  • (SecurityError)


24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/bitcoin/mnemonic.rb', line 24

def to_entropy(words)
  word_master = load_words
  mnemonic = words.map do |w|
    index = word_master.index(w.downcase)
    raise IndexError, 'word not found in words list.' unless index
    index.to_s(2).rjust(11, '0')
  end.join
  entropy = mnemonic.slice(0, (mnemonic.length * 32) / 33)
  checksum = mnemonic.gsub(entropy, '')
  raise SecurityError, 'checksum mismatch.' unless checksum == checksum(entropy)
  [entropy].pack('B*').bth
end

#to_mnemonic(entropy) ⇒ Array

generate mnemonic words from entropy.

Parameters:

  • entropy (String)

    an entropy with hex format.

Returns:

  • (Array)

    the array of mnemonic word.

Raises:

  • (ArgumentError)


40
41
42
43
44
45
46
47
# File 'lib/bitcoin/mnemonic.rb', line 40

def to_mnemonic(entropy)
  raise ArgumentError, 'entropy is empty.' if entropy.nil? || entropy.empty?
  e = entropy.htb.unpack1('B*')
  seed = e + checksum(e)
  mnemonic_index = seed.chars.each_slice(11).map{|i|i.join.to_i(2)}
  word_master = load_words
  mnemonic_index.map{|i|word_master[i]}
end

#to_seed(mnemonic, passphrase: '') ⇒ String

generate seed from mnemonic if mnemonic protected with passphrase, specify that passphrase.

Parameters:

  • mnemonic (Array)

    a array of mnemonic word.

  • passphrase (String) (defaults to: '')

    a passphrase which protects mnemonic. the default value is an empty string.

Returns:



54
55
56
57
58
# File 'lib/bitcoin/mnemonic.rb', line 54

def to_seed(mnemonic, passphrase: '')
  to_entropy(mnemonic)
  OpenSSL::PKCS5.pbkdf2_hmac(mnemonic.join(' ').downcase,
                             'mnemonic' + passphrase, 2048, 64, OpenSSL::Digest::SHA512.new).bth
end