Class: Ciri::DevP2P::RLPX::EncryptionHandshake

Inherits:
Object
  • Object
show all
Defined in:
lib/ciri/devp2p/rlpx/encryption_handshake.rb

Overview

handle key exchange handshake

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(private_key:, remote_id:) ⇒ EncryptionHandshake

Returns a new instance of EncryptionHandshake.


49
50
51
52
# File 'lib/ciri/devp2p/rlpx/encryption_handshake.rb', line 49

def initialize(private_key:, remote_id:)
  @private_key = private_key
  @remote_id = remote_id
end

Instance Attribute Details

#initiator_nonceObject (readonly)

Returns the value of attribute initiator_nonce


47
48
49
# File 'lib/ciri/devp2p/rlpx/encryption_handshake.rb', line 47

def initiator_nonce
  @initiator_nonce
end

#private_keyObject (readonly)

Returns the value of attribute private_key


47
48
49
# File 'lib/ciri/devp2p/rlpx/encryption_handshake.rb', line 47

def private_key
  @private_key
end

#receiver_nonceObject (readonly)

Returns the value of attribute receiver_nonce


47
48
49
# File 'lib/ciri/devp2p/rlpx/encryption_handshake.rb', line 47

def receiver_nonce
  @receiver_nonce
end

#remote_idObject (readonly)

Returns the value of attribute remote_id


47
48
49
# File 'lib/ciri/devp2p/rlpx/encryption_handshake.rb', line 47

def remote_id
  @remote_id
end

#remote_keyObject (readonly)

Returns the value of attribute remote_key


47
48
49
# File 'lib/ciri/devp2p/rlpx/encryption_handshake.rb', line 47

def remote_key
  @remote_key
end

#remote_random_keyObject (readonly)

Returns the value of attribute remote_random_key


47
48
49
# File 'lib/ciri/devp2p/rlpx/encryption_handshake.rb', line 47

def remote_random_key
  @remote_random_key
end

Instance Method Details

#auth_ack_msgObject


86
87
88
89
90
91
92
# File 'lib/ciri/devp2p/rlpx/encryption_handshake.rb', line 86

def auth_ack_msg  # make nonce bytes

  nonce = random_nonce(SHA_LENGTH)
  @receiver_nonce = nonce
  random_pubkey = random_key.raw_public_key[1..-1]
  AuthRespV4.new(random_pubkey: random_pubkey, nonce: nonce, version: 4)
end

#auth_msgObject

Raises:

  • (StandardError)

62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/ciri/devp2p/rlpx/encryption_handshake.rb', line 62

def auth_msg  # make nonce bytes

  nonce = random_nonce(SHA_LENGTH)
  @initiator_nonce = nonce  # remote first byte tag

  token = dh_compute_key(private_key, remote_key)
  raise StandardError.new("token size #{token.size} not correct") if token.size != nonce.size  # xor

  signed = xor(token, nonce)

  signature = random_key.ecdsa_signature(signed)
  initiator_pubkey = private_key.raw_public_key[1..-1]
  AuthMsgV4.new(signature: signature, initiator_pubkey: initiator_pubkey, nonce: nonce, version: 4)
end

#extract_secrets(auth_packet, auth_ack_packet, initiator:) ⇒ Object


100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/ciri/devp2p/rlpx/encryption_handshake.rb', line 100

def extract_secrets(auth_packet, auth_ack_packet, initiator:)
  secret = dh_compute_key(random_key, remote_random_key)
  shared_secret = Ciri::Utils.sha3(secret, Ciri::Utils.sha3(receiver_nonce, initiator_nonce))
  aes_secret = Ciri::Utils.sha3(secret, shared_secret)
  mac = Ciri::Utils.sha3(secret, aes_secret)
  secrets = Secrets.new(remote_id: remote_id, aes: aes_secret, mac: mac)

  # initial secrets macs
  mac1 = Digest::SHA3.new(256)
  mac1.update xor(mac, receiver_nonce)
  mac1.update auth_packet

  mac2 = Digest::SHA3.new(256)
  mac2.update xor(mac, initiator_nonce)
  mac2.update auth_ack_packet

  if initiator
    secrets.egress_mac = mac1
    secrets.ingress_mac = mac2
  else
    secrets.egress_mac = mac2
    secrets.ingress_mac = mac1
  end
  secrets
end

#handle_auth_ack_msg(msg) ⇒ Object


94
95
96
97
98
# File 'lib/ciri/devp2p/rlpx/encryption_handshake.rb', line 94

def handle_auth_ack_msg(msg)
  # make nonce bytes
  @receiver_nonce = msg.nonce
  @remote_random_key = Ciri::Key.new(raw_public_key: "\x04" + msg.random_pubkey)
end

#handle_auth_msg(msg) ⇒ Object


77
78
79
80
81
82
83
84
# File 'lib/ciri/devp2p/rlpx/encryption_handshake.rb', line 77

def handle_auth_msg(msg)
  @remote_key = Ciri::Key.new(raw_public_key: "\x04" + msg.initiator_pubkey)
  @initiator_nonce = msg.nonce

  token = dh_compute_key(private_key, @remote_key)
  signed = xor(token, msg.nonce)
  @remote_random_key = Ciri::Key.ecdsa_recover(signed, msg.signature)
end

#random_keyObject


58
59
60
# File 'lib/ciri/devp2p/rlpx/encryption_handshake.rb', line 58

def random_key
  @random_key ||= Ciri::Key.random
end