Module: HDetEc::ECManipulation

Included in:
Key
Defined in:
lib/hdet-ec-key/ec_manipulation.rb

Instance Method Summary collapse

Instance Method Details

#child_key_derivation(extended_key, index) ⇒ Object Also known as: CKD

This method is 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.



57
58
59
60
61
62
# 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

#child_key_derivation_hardened(extended_key, index) ⇒ Object Also known as: CKDh

This method is abstract.

Generic derivation method for hardened keys

Alogrithm to derive only hardened private key. That means no #index below 2^31 are allowed.



44
45
46
47
48
49
# 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

#child_key_derivation_private(extended_key, index) ⇒ Object Also known as: CKDpriv

This method is abstract.

Derive a public key according to BIP32 specifications

Public parent key → public child key.

Parameters:

  • extended_key (Array)

    extended_key

  • index (Integer)


75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# 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

#child_key_derivation_public(extended_key, index) ⇒ Object Also known as: CKDpub

This method is abstract.

Derive a public key according to BIP32 specifications

Public parent key → public child key.

Parameters:

  • extended_key (Array)

    extended_key

  • index (Integer)


104
105
106
107
108
109
110
111
112
113
114
115
116
117
# 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

#generate_public_key_from_private(private_key) ⇒ String Also known as: point

This method is abstract.

Generate public key from the private one

The input parameter #private_key a binary string representation of the private key

Returns:

  • (String)

    The output is a binary representation of the public key in the compressed form.



31
32
33
34
35
36
# 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

#groupObject



18
19
20
21
22
# 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

#group=(openssl_group) ⇒ Object

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"


12
13
14
15
16
# 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

#serp(kp) ⇒ Object

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



125
126
127
128
129
# 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