class Bitcoin::ExtKey

BIP32 Extended private key

Attributes

chain_code[RW]
depth[RW]
number[RW]
parent_fingerprint[RW]
priv_key[RW]

Public Class Methods

from_base58(address) click to toggle source

import private key from Base58 private key address

# File lib/hdkey/ext_key.rb, line 110
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) click to toggle source

generate master key from seed.

# File lib/hdkey/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

Public Instance Methods

addr() click to toggle source

get address

# File lib/hdkey/ext_key.rb, line 69
def addr
  priv_key.addr
end
derive(number) click to toggle source

derive new key

# File lib/hdkey/ext_key.rb, line 89
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_pubkey() click to toggle source

get ExtPubkey from priv_key

# File lib/hdkey/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
fingerprint() click to toggle source

get fingerprint

# File lib/hdkey/ext_key.rb, line 84
def fingerprint
  identifier.slice(0..7)
end
identifier() click to toggle source

get key identifier

# File lib/hdkey/ext_key.rb, line 79
def identifier
  Bitcoin.hash160(priv_key.pub)
end
priv() click to toggle source

get private key(hex)

# File lib/hdkey/ext_key.rb, line 59
def priv
  priv_key.priv
end
pub() click to toggle source

get public key(hex)

# File lib/hdkey/ext_key.rb, line 64
def pub
  priv_key.pub
end
segwit_addr() click to toggle source

get segwit p2wpkh address

# File lib/hdkey/ext_key.rb, line 74
def segwit_addr
  ext_pubkey.segwit_addr
end
to_base58() click to toggle source

Base58 encoded extended private key

# File lib/hdkey/ext_key.rb, line 52
def to_base58
  h = to_payload.bth
  hex = h + Bitcoin.checksum(h)
  Bitcoin.encode_base58(hex)
end
to_payload() click to toggle source

serialize extended private key

# File lib/hdkey/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