Class: DEVp2p::Crypto::ECCx

Inherits:
Object
  • Object
show all
Defined in:
lib/devp2p/crypto/ecc_x.rb

Constant Summary collapse

CURVE =
'secp256k1'.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(raw_privkey = nil, raw_pubkey = nil) ⇒ ECCx

Returns a new instance of ECCx.



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/devp2p/crypto/ecc_x.rb', line 66

def initialize(raw_privkey=nil, raw_pubkey=nil)
  if raw_privkey && raw_pubkey
    raise ArgumentError, 'must not provide pubkey with privkey'
  elsif raw_privkey
    raw_pubkey = Crypto.privtopub raw_privkey
  elsif raw_pubkey
    raise ArgumentError, 'invalid pubkey length' unless raw_pubkey.size == 64
  else
    raw_privkey, raw_pubkey = self.class.generate_key
  end

  if self.class.valid_key?(raw_pubkey, raw_privkey)
    @raw_pubkey, @raw_privkey = raw_pubkey, raw_privkey
    @pubkey_x, @pubkey_y = decode_pubkey raw_pubkey
    set_curve
  else
    @raw_pubkey, @raw_privkey = nil, nil
    @pubkey_x, @pubkey_y = nil, nil
    raise InvalidKeyError, "bad ECC keys"
  end
end

Instance Attribute Details

#raw_pubkeyObject (readonly)

Returns the value of attribute raw_pubkey.



64
65
66
# File 'lib/devp2p/crypto/ecc_x.rb', line 64

def raw_pubkey
  @raw_pubkey
end

Class Method Details

.generate_keyObject

Raises:



29
30
31
32
33
34
35
36
37
38
# File 'lib/devp2p/crypto/ecc_x.rb', line 29

def generate_key
  curve = OpenSSL::PKey::EC.new(CURVE)
  curve.generate_key

  raw_privkey = Utils.zpad Utils.int_to_big_endian(curve.private_key.to_i), 32
  raw_pubkey = Utils.int_to_big_endian(curve.public_key.to_bn.to_i)
  raise InvalidKeyError, 'invalid pubkey' unless raw_pubkey.size == 65 && raw_pubkey[0] == "\x04"

  [raw_privkey, raw_pubkey[1,64]]
end

.get_ecdh_key(curve, raw_pubkey) ⇒ Object

Compute public key with the local private key and returns a 256bits shared key



44
45
46
47
# File 'lib/devp2p/crypto/ecc_x.rb', line 44

def get_ecdh_key(curve, raw_pubkey)
  pubkey = raw_pubkey_to_openssl_pubkey raw_pubkey
  curve.dh_compute_key pubkey
end

.raw_privkey_to_openssl_privkey(raw_privkey) ⇒ Object



57
58
59
60
61
# File 'lib/devp2p/crypto/ecc_x.rb', line 57

def raw_privkey_to_openssl_privkey(raw_privkey)
  return unless raw_privkey

  OpenSSL::BN.new Utils.big_endian_to_int(raw_privkey)
end

.raw_pubkey_to_openssl_pubkey(raw_pubkey) ⇒ Object



49
50
51
52
53
54
55
# File 'lib/devp2p/crypto/ecc_x.rb', line 49

def raw_pubkey_to_openssl_pubkey(raw_pubkey)
  return unless raw_pubkey

  bn = OpenSSL::BN.new Utils.encode_hex("\x04#{raw_pubkey}"), 16
  group = OpenSSL::PKey::EC::Group.new CURVE
  OpenSSL::PKey::EC::Point.new group, bn
end

.valid_key?(raw_pubkey, raw_privkey = nil) ⇒ Boolean

Returns:

  • (Boolean)


12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/devp2p/crypto/ecc_x.rb', line 12

def valid_key?(raw_pubkey, raw_privkey=nil)
  return false unless raw_pubkey.size == 64

  group = OpenSSL::PKey::EC::Group.new CURVE
  bn = OpenSSL::BN.new Utils.encode_hex("\x04#{raw_pubkey}"), 16
  point = OpenSSL::PKey::EC::Point.new group, bn

  key = OpenSSL::PKey::EC.new(CURVE)
  key.public_key = point
  key.private_key = OpenSSL::BN.new Utils.big_endian_to_int(raw_privkey) if raw_privkey
  key.check_key

  true
rescue
  false
end

Instance Method Details

#curveObject



113
114
115
# File 'lib/devp2p/crypto/ecc_x.rb', line 113

def curve
  @curve ||= OpenSSL::PKey::EC.new(CURVE)
end

#ecies_decrypt(*args) ⇒ Object Also known as: decrypt



108
109
110
# File 'lib/devp2p/crypto/ecc_x.rb', line 108

def ecies_decrypt(*args)
  ECIES.decrypt curve, *args
end

#ecies_encrypt(*args) ⇒ Object Also known as: encrypt



103
104
105
# File 'lib/devp2p/crypto/ecc_x.rb', line 103

def ecies_encrypt(*args)
  ECIES.encrypt *args
end

#get_ecdh_key(raw_pubkey) ⇒ Object



99
100
101
# File 'lib/devp2p/crypto/ecc_x.rb', line 99

def get_ecdh_key(raw_pubkey)
  self.class.get_ecdh_key curve, raw_pubkey
end

#sign(data) ⇒ Object



88
89
90
91
92
# File 'lib/devp2p/crypto/ecc_x.rb', line 88

def sign(data)
  sig = Crypto.ecdsa_sign data, @raw_privkey
  raise InvalidSignatureError unless sig.size == 65
  sig
end

#verify(sig, msg) ⇒ Object

Raises:

  • (ArgumentError)


94
95
96
97
# File 'lib/devp2p/crypto/ecc_x.rb', line 94

def verify(sig, msg)
  raise ArgumentError, 'invalid signature length' unless sig.size == 65
  Crypto.ecdsa_verify @raw_pubkey, sig, msg
end