class Tapyrus::Mnemonic

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

Constants

WORD_DIR

Attributes

word_list[R]

Public Class Methods

new(word_list) click to toggle source
# File lib/tapyrus/mnemonic.rb, line 9
def initialize(word_list)
  raise ArgumentError, 'specified language is not supported.' unless Mnemonic.word_lists.include?(word_list)
  @word_list = word_list
end
word_lists() click to toggle source

get support language list

# File lib/tapyrus/mnemonic.rb, line 15
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/tapyrus/mnemonic.rb, line 67
def checksum(entropy)
  b = Tapyrus.sha256([entropy].pack('B*')).unpack('B*').first
  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/tapyrus/mnemonic.rb, line 22
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/tapyrus/mnemonic.rb, line 39
def to_mnemonic(entropy)
  raise ArgumentError, 'entropy is empty.' if entropy.nil? || entropy.empty?
  e = entropy.htb.unpack('B*').first
  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/tapyrus/mnemonic.rb, line 53
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/tapyrus/mnemonic.rb, line 75
def load_words
  File.readlines("#{WORD_DIR}/#{word_list}.txt").map(&:strip)
end