Class: HDetEc::Key
- Inherits:
-
Object
- Object
- HDetEc::Key
- Extended by:
- DataManipulation, ECManipulation
- Includes:
- DataManipulation
- Defined in:
- lib/hdet-ec-key/key.rb
Instance Attribute Summary collapse
-
#chain_code ⇒ Object
readonly
Returns the value of attribute chain_code.
-
#depth ⇒ Object
readonly
Returns the value of attribute depth.
- #fingerprint ⇒ Object readonly abstract
-
#index ⇒ Object
readonly
Returns the value of attribute index.
-
#key ⇒ Object
readonly
Returns the value of attribute key.
-
#parent_fingerprint ⇒ Object
readonly
Returns the value of attribute parent_fingerprint.
-
#public_or_private ⇒ Object
readonly
Returns the value of attribute public_or_private.
Class Method Summary collapse
-
.generate_master_key(seed, key = "Bitcoin seed") ⇒ Key
abstract
According to BIP32 specification, the master key is generated from a HMAC512 and splited in two vector of 256 bits each.
-
.import(serialized_key_string) ⇒ Object
abstract
Conforming to the BIP32 specification, the key should start with ‘xpub’ or ‘xprv’.
Instance Method Summary collapse
-
#derive(path) ⇒ HDetEc
abstract
Derive a private or a public key by applying multiple derivation definined by the derivation path.
-
#initialize(extended_k, public_or_private, depth, index, parent_fingerprint) ⇒ Key
constructor
A new instance of Key.
- #private? ⇒ Boolean
- #public? ⇒ Boolean
- #public_key ⇒ Object (also: #public_key_from_private)
-
#serialize_extended_key ⇒ Object
(also: #serialize)
abstract
The serialization result is a string in Base58 that represents the public or the private extented key.
Methods included from ECManipulation
child_key_derivation, child_key_derivation_hardened, child_key_derivation_private, child_key_derivation_public, generate_public_key_from_private, group, group=, serp
Methods included from DataManipulation
double_sha256, left_hash, right_hash, rmd160_sha256, ser256, ser32, split_hash, to_binary, to_number
Constructor Details
#initialize(extended_k, public_or_private, depth, index, parent_fingerprint) ⇒ Key
Returns a new instance of Key.
73 74 75 76 77 78 79 |
# File 'lib/hdet-ec-key/key.rb', line 73 def initialize(extended_k, public_or_private, depth, index, parent_fingerprint) @depth = depth @index = index @key, @chain_code = extended_k @public_or_private = public_or_private @parent_fingerprint = parent_fingerprint end |
Instance Attribute Details
#chain_code ⇒ Object (readonly)
Returns the value of attribute chain_code.
70 71 72 |
# File 'lib/hdet-ec-key/key.rb', line 70 def chain_code @chain_code end |
#depth ⇒ Object (readonly)
Returns the value of attribute depth.
70 71 72 |
# File 'lib/hdet-ec-key/key.rb', line 70 def depth @depth end |
#fingerprint ⇒ Object (readonly)
Compute the key fingerprint
152 153 154 |
# File 'lib/hdet-ec-key/key.rb', line 152 def fingerprint @fingerprint end |
#index ⇒ Object (readonly)
Returns the value of attribute index.
70 71 72 |
# File 'lib/hdet-ec-key/key.rb', line 70 def index @index end |
#key ⇒ Object (readonly)
Returns the value of attribute key.
70 71 72 |
# File 'lib/hdet-ec-key/key.rb', line 70 def key @key end |
#parent_fingerprint ⇒ Object (readonly)
Returns the value of attribute parent_fingerprint.
71 72 73 |
# File 'lib/hdet-ec-key/key.rb', line 71 def parent_fingerprint @parent_fingerprint end |
#public_or_private ⇒ Object (readonly)
Returns the value of attribute public_or_private.
70 71 72 |
# File 'lib/hdet-ec-key/key.rb', line 70 def public_or_private @public_or_private end |
Class Method Details
.generate_master_key(seed, key = "Bitcoin seed") ⇒ Key
Generate a master extended key from #seed and #key
According to BIP32 specification, the master key is generated from a HMAC512 and splited in two vector of 256 bits each. The first is the master key and the later is the chain code.
You just have to provide the #seed. The standard #key is “Bitcoin seed” but it can be overrided.
The #seed could be any kind of string. No convertion is performed (idem for #key), so if you want a binary seed represented by the hex form you have to convert it like:
@example: Binary seed with hex form
seed = ["000102030405060708090a0b0c0d0e0f"].pack("H*")
30 31 32 33 34 |
# File 'lib/hdet-ec-key/key.rb', line 30 def generate_master_key(seed, key = "Bitcoin seed") inter = OpenSSL::HMAC.digest('SHA512', key, seed) m = split_hash(inter) Key.new(m, :private, 0, 0, "\x00" * 4) end |
.import(serialized_key_string) ⇒ Object
Import a serialized key in as describe in BIP32 specification
Conforming to the BIP32 specification, the key should start with ‘xpub’ or ‘xprv’. Other version of testnet is not supported.
Because a checksum is stored in the key, this function check the integrety of imported data, if check sum could not be verified it raise an ArgumentError “Wrong checksum”.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/hdet-ec-key/key.rb', line 45 def import(serialized_key_string) data = Base58.base58_to_binary(serialized_key_string, :bitcoin) unpacked = data.unpack("L>Ca4L>a32a33a4") version, depth, parent_fingerprint, index, c, k, checksum = unpacked # Remove checksum from data data.slice!(-4..-1) raise ArgumentError, "Wrong checksum" unless hash256(data)[0..3] == checksum case version when 0x0488ADE4 k.slice!(0) Key.new([k, c], :private, depth, index, parent_fingerprint) when 0x0488B21E Key.new([k, c], :public, depth, index, parent_fingerprint) else raise "version not supported #{version.to_s(16)}" end end |
Instance Method Details
#derive(path) ⇒ HDetEc
Derive key by specifying derivation path
Derive a private or a public key by applying multiple derivation definined by the derivation path.
The #path is an Array of multiple indexes. For example to derive a key like m/0H/1/2H/2, use indexes [0.h, 1, 2.h, 2].
137 138 139 140 141 142 143 144 145 146 |
# File 'lib/hdet-ec-key/key.rb', line 137 def derive(path) return self if path.nil? || path.empty? case public_or_private when :public then public_key_derivation(path) when :private then private_key_derivation(path) else raise "Wrong key" end end |
#private? ⇒ Boolean
96 97 98 |
# File 'lib/hdet-ec-key/key.rb', line 96 def private? public_or_private == :private end |
#public? ⇒ Boolean
92 93 94 |
# File 'lib/hdet-ec-key/key.rb', line 92 def public? public_or_private == :public end |
#public_key ⇒ Object Also known as: public_key_from_private
81 82 83 84 85 86 87 88 |
# File 'lib/hdet-ec-key/key.rb', line 81 def public_key case public_or_private when :public self when :private Key.new([Key.point(key), chain_code], :public, depth, index, parent_fingerprint) end end |
#serialize_extended_key ⇒ Object Also known as: serialize
serialize key according to BIP32 specifications
The serialization result is a string in Base58 that represents the public or the private extented key.
108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/hdet-ec-key/key.rb', line 108 def serialize_extended_key k, c = key, chain_code case public_or_private when :private data = ser32(0x0488ADE4) + to_binary(depth) + parent_fingerprint + ser32(index) + c + "\x00" + k when :public then data = ser32(0x0488B21E) + to_binary(depth) + parent_fingerprint + ser32(index) + c + Key.serp(public_key.key) else raise "invalid property #{public_or_private}" end Base58.binary_to_base58(data + hash256(data)[0..3], :bitcoin) end |