module HDetEc::ECManipulation
Public Instance Methods
@abstract Generic derivation method for non-hardened keys
Alogrithm to derive public and private key if it not hardened key. That means no {#index} above 2^31 - 1 are allowed.
# File lib/hdet-ec-key/ec_manipulation.rb, line 57 def child_key_derivation(extended_key, index) k, c = extended_key key = c data = serp(k) + ser32(index) OpenSSL::HMAC.digest('SHA512', key, data) end
@abstract Generic derivation method for hardened keys
Alogrithm to derive only hardened private key. That means no {#index} below 2^31 are allowed.
# File lib/hdet-ec-key/ec_manipulation.rb, line 44 def child_key_derivation_hardened(extended_key, index) k, c = extended_key key = c data = "\x00" + k + ser32(index) OpenSSL::HMAC.digest('SHA512', key, data) end
@abstract Derive a public key according to BIP32 specifications
Public parent key → public child key.
@param extended_key [Array] extended_key @param index [Integer]
@note
https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#private-parent-key--private-child-key
# File lib/hdet-ec-key/ec_manipulation.rb, line 75 def child_key_derivation_private(extended_key, index) k, c = extended_key if index >= 2**31 inter = child_key_derivation_hardened(extended_key, index) else inter = child_key_derivation([point(k), c], index) end iL, iR = split_hash(inter) bn = parse256(iL) + parse256(k) k_child = OpenSSL::BN.new(bn) % group.order [k_child.to_s(2), iR] end
@abstract Derive a public key according to BIP32 specifications
Public parent key → public child key.
@param extended_key [Array] extended_key @param index [Integer]
@note
https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#public-parent-key--public-child-key
# File lib/hdet-ec-key/ec_manipulation.rb, line 104 def child_key_derivation_public(extended_key, index) k, c = extended_key if index >= 2**31 raise "No hardened public key derivation possible" end inter = child_key_derivation(extended_key, index) iL, iR = split_hash(inter) bn = OpenSSL::BN.new(iL, 2) pub_key = OpenSSL::PKey::EC::Point.new(group, k).mul(1, bn) [pub_key.to_octet_string(:compressed), iR] end
@abstract Generate public key from the private one
The input parameter {#private_key} a binary string representation of the private key
@return [String] The output is a binary representation of the public key
in the compressed form.
# File lib/hdet-ec-key/ec_manipulation.rb, line 31 def generate_public_key_from_private(private_key) bn_private_key = OpenSSL::BN.new private_key, 2 public_key = group.generator.mul(bn_private_key) public_key.to_bn.to_s(2) end
# File lib/hdet-ec-key/ec_manipulation.rb, line 18 def group @@group ||= OpenSSL::PKey::EC.new("secp256k1").group @@group.point_conversion_form = :compressed @@group end
The default group is the same as used by Bitcoin network, “secp256k1”. But it can be change, just provide the a OpenSSL group string.
example:
HDetEc::Key.group = "secp256r1"
# File lib/hdet-ec-key/ec_manipulation.rb, line 12 def group=(openssl_group) @@group = OpenSSL::PKey::EC.new(openssl_group).group @@group.point_conversion_form = :compressed @@group end
Serializes the coordinate pair P = (x,y) as a byte sequence using SEC1's compressed form: (0x02 or 0x03) || ser256(x), where the header byte depends on the parity of the omitted y coordinate. input kp: public key
# File lib/hdet-ec-key/ec_manipulation.rb, line 125 def serp(kp) # ensure kp is in compressed form point = OpenSSL::PKey::EC::Point.new(group, kp) point.to_octet_string(:compressed) end