class Bitcoin::Mnemonic

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

Constants

WORD_DIR

Attributes

language[R]

Public Class Methods

new(language) click to toggle source
# 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
word_lists() click to toggle source

get support language list

# 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

Public Instance Methods

checksum(entropy) click to toggle source

calculate entropy checksum @param [String] entropy an entropy with bit string format @return [String] an entropy checksum with bit string format

# 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) click to toggle source

generate entropy from mnemonic word @param [Array] words the array of mnemonic word. @return [String] an entropy with hex format.

# 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) click to toggle source

generate mnemonic words from entropy. @param [String] entropy an entropy with hex format. @return [Array] the array of mnemonic word.

# 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: '') click to toggle source

generate seed from mnemonic if mnemonic protected with passphrase, specify that passphrase. @param [Array] mnemonic a array of mnemonic word. @param [String] passphrase a passphrase which protects mnemonic. the default value is an empty string. @return [String] seed

# 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

Private Instance Methods

load_words() click to toggle source

load word list contents

# File lib/bitcoin/mnemonic.rb, line 71
def load_words
  File.readlines("#{WORD_DIR}/#{language}.txt").map(&:strip)
end