Class: Bitcoin::ExtKey

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

Overview

BIP32 Extended private key

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#chain_codeObject

Returns the value of attribute chain_code.



17
18
19
# File 'lib/bitcoin/ext_key.rb', line 17

def chain_code
  @chain_code
end

#depthObject

Returns the value of attribute depth.



15
16
17
# File 'lib/bitcoin/ext_key.rb', line 15

def depth
  @depth
end

#numberObject

Returns the value of attribute number.



16
17
18
# File 'lib/bitcoin/ext_key.rb', line 16

def number
  @number
end

#parent_fingerprintObject

Returns the value of attribute parent_fingerprint.



19
20
21
# File 'lib/bitcoin/ext_key.rb', line 19

def parent_fingerprint
  @parent_fingerprint
end

#priv_keyObject

Returns the value of attribute priv_key.



18
19
20
# File 'lib/bitcoin/ext_key.rb', line 18

def priv_key
  @priv_key
end

Class Method Details

.from_base58(address) ⇒ Object

import private key from Base58 private key address



105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/bitcoin/ext_key.rb', line 105

def self.from_base58(address)
  data = StringIO.new(Bitcoin.decode_base58(address).htb)
  key = ExtKey.new
  data.read(4).bth # version
  key.depth = data.read(1).unpack('C').first
  key.parent_fingerprint = data.read(4).bth
  key.number = data.read(4).unpack('N').first
  key.chain_code = data.read(32)
  data.read(1) # 0x00
  key.priv_key = Bitcoin::Key.new(data.read(32).bth)
  key
end

.generate_master(seed) ⇒ Object

generate master key from seed.



22
23
24
25
26
27
28
29
30
31
32
# File 'lib/bitcoin/ext_key.rb', line 22

def self.generate_master(seed)
  key = ExtKey.new
  key.depth = key.number = 0
  key.parent_fingerprint = '00000000'
  l = Bitcoin.hmac_sha512('Bitcoin seed', seed)
  left = OpenSSL::BN.from_hex(l[0..31].bth).to_i
  raise 'invalid key' if left >= CURVE_ORDER || left == 0
  key.priv_key = Bitcoin::Key.new(l[0..31].bth)
  key.chain_code = l[32..-1]
  key
end

Instance Method Details

#addrObject

get address



69
70
71
# File 'lib/bitcoin/ext_key.rb', line 69

def addr
  priv_key.addr
end

#derive(number) ⇒ Object

derive new key



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/bitcoin/ext_key.rb', line 84

def derive(number)
  new_key = ExtKey.new
  new_key.depth = depth + 1
  new_key.number = number
  new_key.parent_fingerprint = fingerprint
  if number > (2**31 -1)
    data = [0x00].pack('C') << priv_key.priv.htb << [number].pack('N')
  else
    data = priv_key.pub.htb << [number].pack('N')
  end
  l = Bitcoin.hmac_sha512(chain_code, data)
  left = OpenSSL::BN.from_hex(l[0..31].bth).to_i
  raise 'invalid key' if left >= CURVE_ORDER
  child_priv = OpenSSL::BN.new((left + OpenSSL::BN.from_hex(priv_key.priv).to_i) % CURVE_ORDER)
  raise 'invalid key ' if child_priv.to_i >= CURVE_ORDER
  new_key.priv_key = Bitcoin::Key.new(child_priv.to_hex.rjust(64, '0'))
  new_key.chain_code = l[32..-1]
  new_key
end

#ext_pubkeyObject

get ExtPubkey from priv_key



35
36
37
38
39
40
41
42
43
44
# File 'lib/bitcoin/ext_key.rb', line 35

def ext_pubkey
  k = ExtPubkey.new
  k.depth = depth
  k.number = number
  k.parent_fingerprint = parent_fingerprint
  k.chain_code = chain_code
  key = Bitcoin::Key.new(nil, priv_key.pub, compressed: true)
  k.pub_key = key.key.public_key
  k
end

#fingerprintObject

get fingerprint



79
80
81
# File 'lib/bitcoin/ext_key.rb', line 79

def fingerprint
  identifier.slice(0..7)
end

#identifierObject

get key identifier



74
75
76
# File 'lib/bitcoin/ext_key.rb', line 74

def identifier
  Bitcoin.hash160(priv_key.pub)
end

#privObject

get private key(hex)



59
60
61
# File 'lib/bitcoin/ext_key.rb', line 59

def priv
  priv_key.priv
end

#pubObject

get public key(hex)



64
65
66
# File 'lib/bitcoin/ext_key.rb', line 64

def pub
  priv_key.pub
end

#to_base58Object

Base58 encoded extended private key



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

def to_base58
  h = to_payload.bth
  hex = h + Bitcoin.checksum(h)
  Bitcoin.encode_base58(hex)
end

#to_payloadObject

serialize extended private key



47
48
49
# File 'lib/bitcoin/ext_key.rb', line 47

def to_payload
  Bitcoin.network[:extended_privkey_version].htb << [depth].pack('C') << parent_fingerprint.htb << [number].pack('N') << chain_code << [0x00].pack('C') << priv_key.priv.htb
end