Class: TonSdkRuby::TonMnemonic

Inherits:
Object
  • Object
show all
Extended by:
TonSdkRuby
Includes:
TonSdkRuby
Defined in:
lib/ton-sdk-ruby/johnny_mnemonic/ton_mnemonic.rb

Constant Summary collapse

TON_PBKDF_ITERATIONS =
100_000
TON_KEYS_SALT =
'TON default seed'
TON_SEED_SALT =
'TON seed version'
TON_PASSWORD_SALT =
'TON fast seed version'

Constants included from TonSdkRuby

DEPTH_BITS, FLAG_BOUNCEABLE, FLAG_NON_BOUNCEABLE, FLAG_TEST_ONLY, HASH_BITS, INT32_MAX, INT32_MIN, LEAN_BOC_MAGIC_PREFIX, LEAN_BOC_MAGIC_PREFIX_CRC, REACH_BOC_MAGIC_PREFIX, VERSION

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from TonSdkRuby

augment, base64_to_bytes, bits_to_big_int, bits_to_big_uint, bits_to_bytes, bits_to_hex, bits_to_int_uint, breadth_first_sort, bytes_compare, bytes_needed_for_words_bip39, bytes_to_base64, bytes_to_bits, bytes_to_data_string, bytes_to_hex, bytes_to_string, bytes_to_uint, crc16, crc16_bytes_be, crc32c, crc32c_bytes_le, depth_first_sort, deserialize, deserialize_cell, deserialize_fift, deserialize_header, generate_words_bip39, get_mapper, hex_to_bits, hex_to_bytes, hex_to_data_string, read_json_from_link, read_post_json_from_link, require_type, rollback, serialize, serialize_cell, sha256, sha512, sign_cell, slice_into_chunks, string_to_bytes, uint_to_hex, validate_library_reference, validate_merkle_proof, validate_merkle_update, validate_ordinary, validate_pruned_branch

Constructor Details

#initialize(password = nil, words_count = 24) ⇒ TonMnemonic

Returns a new instance of TonMnemonic.



19
20
21
22
23
24
25
# File 'lib/ton-sdk-ruby/johnny_mnemonic/ton_mnemonic.rb', line 19

def initialize(password = nil, words_count = 24)
  @words_count = words_count
  @password = password
  @mnemonic_array = generate_seed(words_count, password)
  @seed = mnemonic_array.join(' ')
  @keys = mnemonic_to_private_key(mnemonic_array, password)
end

Instance Attribute Details

#keysObject

Returns the value of attribute keys.



17
18
19
# File 'lib/ton-sdk-ruby/johnny_mnemonic/ton_mnemonic.rb', line 17

def keys
  @keys
end

#mnemonic_arrayObject

Returns the value of attribute mnemonic_array.



17
18
19
# File 'lib/ton-sdk-ruby/johnny_mnemonic/ton_mnemonic.rb', line 17

def mnemonic_array
  @mnemonic_array
end

#passwordObject

Returns the value of attribute password.



17
18
19
# File 'lib/ton-sdk-ruby/johnny_mnemonic/ton_mnemonic.rb', line 17

def password
  @password
end

#seedObject

Returns the value of attribute seed.



17
18
19
# File 'lib/ton-sdk-ruby/johnny_mnemonic/ton_mnemonic.rb', line 17

def seed
  @seed
end

#words_countObject

Returns the value of attribute words_count.



17
18
19
# File 'lib/ton-sdk-ruby/johnny_mnemonic/ton_mnemonic.rb', line 17

def words_count
  @words_count
end

Class Method Details

.parse(mnemonic_string, password = nil) ⇒ Object



27
28
29
30
31
32
33
34
35
36
# File 'lib/ton-sdk-ruby/johnny_mnemonic/ton_mnemonic.rb', line 27

def self.parse(mnemonic_string, password = nil)
  mnemonic = new
  mnemonic_string.gsub!(/\s+/, ' ')
  mnemonic.mnemonic_array = mnemonic_string.split(' ')
  mnemonic.words_count = mnemonic.mnemonic_array.size
  mnemonic.password = password
  mnemonic.seed = mnemonic.mnemonic_array.join(' ')
  mnemonic.keys = mnemonic.mnemonic_to_private_key(mnemonic.mnemonic_array, password)
  mnemonic
end

Instance Method Details

#generate_seed(words_count = 24, password = nil) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/ton-sdk-ruby/johnny_mnemonic/ton_mnemonic.rb', line 59

def generate_seed(words_count = 24, password = nil)
  mnemonic_array = []
  while true
    # Regenerate new mnemonics
    mnemonic_array = generate_words_ton(words_count)
    # # Check password conformance
    if password && password.length > 0
      next unless password_needed?(mnemonic_array)
    end
    # Check if basic seed correct
    unless basic_seed?(mnemonic_to_entropy(mnemonic_array, password))
      next
    end
    break
  end
  mnemonic_array
end

#generate_words_ton(length) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
# File 'lib/ton-sdk-ruby/johnny_mnemonic/ton_mnemonic.rb', line 87

def generate_words_ton(length)
  mnemonic_array = []
  current_file_path = File.expand_path(File.dirname(__FILE__))
  bip0039en = JSON.parse(File.read("#{current_file_path}/words/english.json"))
  length.times do
    index = get_secure_random_number(0, bip0039en.size)
    mnemonic_array.push(bip0039en[index])
  end

  mnemonic_array
end

#get_secure_random_number(min, max) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/ton-sdk-ruby/johnny_mnemonic/ton_mnemonic.rb', line 38

def get_secure_random_number(min, max)
  range = max - min
  bits_needed = Math.log2(range).ceil
  bytes_needed = (bits_needed / 8.0).ceil
  mask = (2 ** bits_needed) - 1

  loop do
    res = SecureRandom.random_bytes(bytes_needed)
    number_value = 0

    power = (bytes_needed - 1) * 8
    res.each_byte do |byte|
      number_value += byte.ord * (2 ** power)
      power -= 8
    end

    number_value = number_value & mask # Truncate
    return min + number_value if number_value < range
  end
end

#mnemonic_to_entropy(mnemonic_array, password = nil) ⇒ Object



77
78
79
80
81
82
83
84
85
# File 'lib/ton-sdk-ruby/johnny_mnemonic/ton_mnemonic.rb', line 77

def mnemonic_to_entropy(mnemonic_array, password = nil)
  mnemonic_string = mnemonic_array.join(' ')
  password_string = password || ''
  # OpenSSL::HMAC.digest(digest, key, data)
  hmac = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha512'), mnemonic_string, password_string)
  entropy = bytes_to_hex(hmac.unpack('C*'))

  entropy
end

#mnemonic_to_private_key(mnemonic_array, password = nil) ⇒ Object



99
100
101
102
103
104
105
106
107
# File 'lib/ton-sdk-ruby/johnny_mnemonic/ton_mnemonic.rb', line 99

def mnemonic_to_private_key(mnemonic_array, password = nil)
  mnemonic_array = normalize_mnemonic(mnemonic_array)
  seed = mnemonic_to_seed(mnemonic_array, TON_KEYS_SALT, password)
  key_pair = Ed25519::SigningKey.new(seed[0, 32])
  {
    public: key_pair.verify_key.to_bytes.unpack1('H*'),
    secret: key_pair.to_bytes.unpack1('H*')
  }
end

#mnemonic_to_seed(mnemonic_array, salt, password) ⇒ Object



109
110
111
112
113
114
# File 'lib/ton-sdk-ruby/johnny_mnemonic/ton_mnemonic.rb', line 109

def mnemonic_to_seed(mnemonic_array, salt, password)
  entropy_hex = mnemonic_to_entropy(mnemonic_array, password)
  entropy = bytes_to_data_string(hex_to_bytes(entropy_hex))
  hash = OpenSSL::Digest::SHA512.new
  OpenSSL::KDF.pbkdf2_hmac(entropy, salt: salt, iterations: TON_PBKDF_ITERATIONS, length: 64, hash: hash)
end