Class: Bitcoin::Wallet::MasterKey

Inherits:
Object
  • Object
show all
Extended by:
Util
Includes:
HexConverter, KeyPath, Util
Defined in:
lib/bitcoin/wallet/master_key.rb

Overview

HD Wallet master seed

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Util

byte_to_bit, calc_checksum, decode_base58_address, double_sha256, encode_base58_address, hash160, hkdf_sha256, hmac_sha256, pack_boolean, pack_var_int, pack_var_string, padding_zero, sha256, tagged_hash, unpack_boolean, unpack_var_int, unpack_var_int_from_io, unpack_var_string, valid_address?

Methods included from KeyPath

#parse_key_path, #to_key_path

Methods included from HexConverter

#to_hex

Constructor Details

#initialize(seed, salt: '', encrypted: false, mnemonic: nil) ⇒ MasterKey

Returns a new instance of MasterKey.



16
17
18
19
20
21
# File 'lib/bitcoin/wallet/master_key.rb', line 16

def initialize(seed, salt: '', encrypted: false, mnemonic: nil)
  @mnemonic = mnemonic
  @seed = seed
  @encrypted = encrypted
  @salt = salt
end

Instance Attribute Details

#encryptedObject

Returns the value of attribute encrypted.



13
14
15
# File 'lib/bitcoin/wallet/master_key.rb', line 13

def encrypted
  @encrypted
end

#mnemonicObject

ephemeral data existing only at initialization



14
15
16
# File 'lib/bitcoin/wallet/master_key.rb', line 14

def mnemonic
  @mnemonic
end

#saltObject

Returns the value of attribute salt.



12
13
14
# File 'lib/bitcoin/wallet/master_key.rb', line 12

def salt
  @salt
end

#seedObject (readonly)

Returns the value of attribute seed.



11
12
13
# File 'lib/bitcoin/wallet/master_key.rb', line 11

def seed
  @seed
end

Class Method Details

.generateObject

generate new master key.

Returns:

  • Bitcoin::Wallet::MasterKey



25
26
27
28
29
# File 'lib/bitcoin/wallet/master_key.rb', line 25

def self.generate
  entropy = SecureRandom.hex(32)
  mnemonic = Bitcoin::Mnemonic.new('english')
  self.recover_from_words(mnemonic.to_mnemonic(entropy))
end

.parse_from_payload(payload) ⇒ Bitcoin::Wallet::MasterKey

parse master key raw data

Parameters:

  • payload (String)

    raw data

Returns:



43
44
45
46
47
48
49
50
# File 'lib/bitcoin/wallet/master_key.rb', line 43

def self.parse_from_payload(payload)
  flag, payload = unpack_var_int(payload)
  raise 'encrypted flag is invalid.' unless [0, 1].include?(flag)
  salt, payload = unpack_var_string(payload)
  salt = '' unless salt
  seed, payload = unpack_var_string(payload)
  self.new(seed.bth, salt: salt.bth, encrypted: flag == 1)
end

.recover_from_words(words) ⇒ Object

recover master key from mnemonic word list.

Parameters:

  • words (Array)

    the mnemonic word list.

Returns:

  • Bitcoin::Wallet::MasterKey



34
35
36
37
38
# File 'lib/bitcoin/wallet/master_key.rb', line 34

def self.recover_from_words(words)
  mnemonic = Bitcoin::Mnemonic.new('english')
  seed = mnemonic.to_seed(words)
  self.new(seed, mnemonic: words)
end

Instance Method Details

#decrypt(passphrase) ⇒ Object

decrypt seed



89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/bitcoin/wallet/master_key.rb', line 89

def decrypt(passphrase)
  raise 'The wallet is not encrypted.' unless encrypted
  dec = OpenSSL::Cipher.new('AES-256-CBC')
  dec.decrypt
  dec.key, dec.iv = key_iv(dec, passphrase)
  decrypted_data = ''
  decrypted_data << dec.update(seed)
  decrypted_data << dec.final
  @seed = decrypted_data
  @encrypted = false
  @salt = ''
end

#derive(path) ⇒ Bitcoin::ExtKey

derive child key using derivation path.

Returns:



68
69
70
71
72
# File 'lib/bitcoin/wallet/master_key.rb', line 68

def derive(path)
  derived_key = key
  parse_key_path(path).each{|num| derived_key = derived_key.derive(num)}
  derived_key
end

#encrypt(passphrase) ⇒ Object

encrypt seed



75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/bitcoin/wallet/master_key.rb', line 75

def encrypt(passphrase)
  raise 'The wallet is already encrypted.' if encrypted
  @salt = SecureRandom.hex(16)
  enc = OpenSSL::Cipher.new('AES-256-CBC')
  enc.encrypt
  enc.key, enc.iv = key_iv(enc, passphrase)
  encrypted_data = ''
  encrypted_data << enc.update(seed)
  encrypted_data << enc.final
  @seed = encrypted_data
  @encrypted = true
end

#keyBitcoin::ExtKey

get master key

Returns:



61
62
63
64
# File 'lib/bitcoin/wallet/master_key.rb', line 61

def key
  raise 'seed is encrypted. please decrypt the seed.' if encrypted
  Bitcoin::ExtKey.generate_master(seed)
end

#to_payloadObject

generate payload with following format

encrypted(false:0, true:1)][salt(var str)][seed(var str)


54
55
56
57
# File 'lib/bitcoin/wallet/master_key.rb', line 54

def to_payload
  flg = encrypted ? 1 : 0
  pack_var_int(flg) << [salt, seed].map{|v|pack_var_string(v.htb)}.join
end