class Ciri::P2P::RLPX::EncryptionHandshake
handle key exchange handshake
Attributes
initiator_nonce[R]
private_key[R]
receiver_nonce[R]
remote_id[R]
remote_key[R]
remote_random_key[R]
Public Class Methods
new(private_key:, remote_id:)
click to toggle source
# File lib/ciri/p2p/rlpx/encryption_handshake.rb, line 48 def initialize(private_key:, remote_id:) @private_key = private_key @remote_id = remote_id end
Public Instance Methods
auth_ack_msg()
click to toggle source
# File lib/ciri/p2p/rlpx/encryption_handshake.rb, line 85 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_msg()
click to toggle source
# File lib/ciri/p2p/rlpx/encryption_handshake.rb, line 61 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).signature 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:)
click to toggle source
# File lib/ciri/p2p/rlpx/encryption_handshake.rb, line 99 def extract_secrets(auth_packet, auth_ack_packet, initiator:) secret = dh_compute_key(random_key, remote_random_key) shared_secret = Ciri::Utils.keccak(secret, Ciri::Utils.keccak(receiver_nonce, initiator_nonce)) aes_secret = Ciri::Utils.keccak(secret, shared_secret) mac = Ciri::Utils.keccak(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)
click to toggle source
# File lib/ciri/p2p/rlpx/encryption_handshake.rb, line 93 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)
click to toggle source
# File lib/ciri/p2p/rlpx/encryption_handshake.rb, line 76 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_key()
click to toggle source
# File lib/ciri/p2p/rlpx/encryption_handshake.rb, line 57 def random_key @random_key ||= Ciri::Key.random end
Private Instance Methods
dh_compute_key(private_key, public_key)
click to toggle source
# File lib/ciri/p2p/rlpx/encryption_handshake.rb, line 127 def dh_compute_key(private_key, public_key) private_key.ec_key.dh_compute_key(public_key.ec_key.public_key) end
random_nonce(size)
click to toggle source
# File lib/ciri/p2p/rlpx/encryption_handshake.rb, line 135 def random_nonce(size) size.times.map {rand(8)}.pack('c*') end
xor(b1, b2)
click to toggle source
# File lib/ciri/p2p/rlpx/encryption_handshake.rb, line 131 def xor(b1, b2) b1.each_byte.with_index.map {|b, i| b ^ b2[i].ord}.pack('c*') end