Class: BipMnemonic

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

Constant Summary collapse

VERSION =
'0.0.4'.freeze

Class Method Summary collapse

Class Method Details

.checksum(entropy_binary) ⇒ Object



52
53
54
55
56
# File 'lib/bip_mnemonic.rb', line 52

def self.checksum(entropy_binary)
  sha256hash = OpenSSL::Digest::SHA256.hexdigest([entropy_binary].pack('B*'))
  sha256hash_binary = [sha256hash].pack('H*').unpack('B*').first
  sha256hash_binary.slice(0, (entropy_binary.length / 32))
end

.to_entropy(options) ⇒ Object

Raises:

  • (ArgumentError)


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/bip_mnemonic.rb', line 30

def self.to_entropy(options)
  options ||= {}
  language = options[:language] || "english"
  raise ArgumentError, 'Mnemonic not set' if options[:mnemonic].nil?
  raise ArgumentError, 'Mnemonic is empty' if options[:mnemonic].empty?
  words_array = File.readlines(
    File.join(
      File.dirname(File.expand_path(__FILE__)), '../words/', language + '.txt'
    )
  ).map(&:strip)
  mnemonic_array = options[:mnemonic].split(' ').map do |word|
    word_index = words_array.index(word)
    raise IndexError, 'Word not found in words list' if word_index.nil?
    word_index.to_s(2).rjust(11, '0')
  end
  mnemonic_binary_with_checksum = mnemonic_array.join.to_s
  entropy_binary =mnemonic_binary_with_checksum.slice(0, mnemonic_binary_with_checksum.length * 32 / 33)
  checksum_bits = mnemonic_binary_with_checksum.slice(-(entropy_binary.length / 32), (entropy_binary.length / 32))
  raise SecurityError, 'Checksum mismatch, invalid mnemonic' unless checksum(entropy_binary) == checksum_bits
  [entropy_binary].pack('B*').unpack('H*').first
end

.to_mnemonic(options) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/bip_mnemonic.rb', line 5

def self.to_mnemonic(options)
  options ||= {}
  bits = options[:bits] || 128
  language = options[:language] || "english"
  if options[:entropy].nil?
    entropy_bytes = OpenSSL::Random.random_bytes(bits / 8)
  else
    raise ArgumentError, 'Entropy is empty' if options[:entropy].empty?
    entropy_bytes = [options[:entropy]].pack('H*')
  end
  entropy_binary = entropy_bytes.unpack('B*').first
  seed_binary = entropy_binary + checksum(entropy_binary)
  words_array = File.readlines(
    File.join(
      File.dirname(File.expand_path(__FILE__)), '../words/', language + '.txt'
    )
  ).map(&:strip)
  seed_binary.chars
             .each_slice(11)
             .map(&:join)
             .map { |item| item.to_i(2) }
             .map { |i| words_array[i] }
             .join(' ')
end

.to_seed(options) ⇒ Object

Raises:

  • (ArgumentError)


58
59
60
61
62
63
64
65
66
67
# File 'lib/bip_mnemonic.rb', line 58

def self.to_seed(options)
  raise ArgumentError, 'Mnemonic not set' if options[:mnemonic].nil?
  OpenSSL::PKCS5.pbkdf2_hmac(
    options[:mnemonic],
    "mnemonic#{options[:password]}",
    2048,
    64,
    OpenSSL::Digest::SHA512.new
  ).unpack('H*')[0]
end