Class: Tapyrus::Mnemonic

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

Overview

Mnemonic code for generating deterministic keys https://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(word_list) ⇒ Mnemonic

Returns a new instance of Mnemonic.

Raises:

  • (ArgumentError)


9
10
11
12
# 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

Instance Attribute Details

#word_list ⇒ Object (readonly)

Returns the value of attribute word_list.



7
8
9
# File 'lib/tapyrus/mnemonic.rb', line 7

def word_list
  @word_list
end

Class Method Details

.word_lists ⇒ Object

get support language list



15
16
17
# 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

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



67
68
69
70
# 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) ⇒ String

generate entropy from mnemonic word

Parameters:

  • words (Array[String]) —

    the array of mnemonic word.

Returns:

  • (String) —

    an entropy with hex format.

Raises:

  • (SecurityError)


22
23
24
25
26
27
28
29
30
31
32
33
34
# 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) ⇒ Array

generate mnemonic words from entropy.

Parameters:

  • entropy (String) —

    an entropy with hex format.

Returns:

  • (Array) —

    the array of mnemonic word.

Raises:

  • (ArgumentError)


39
40
41
42
43
44
45
46
# 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: '') ⇒ 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:



53
54
55
56
57
58
59
60
61
62
# 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