Class: Tapyrus::Mnemonic

Inherits:
Object
  • Object
show all
Defined in:
lib/tapyrus/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(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_listObject (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_listsObject

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



69
70
71
72
# File 'lib/tapyrus/mnemonic.rb', line 69

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
35
36
# 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)


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

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:



55
56
57
58
59
60
61
62
63
64
# File 'lib/tapyrus/mnemonic.rb', line 55

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