ex_wire v0.1.1 ExWire.Handshake
Implements the RLPx ECIES handshake protocol.
This handshake is the first thing that happens after establishing a connection. Afterwards, we will do a HELLO and protocol handshake.
Note: this protocol is not extremely well defined, but you can read up on it here:
- https://github.com/ethereum/devp2p/blob/master/rlpx.md
- https://github.com/ethereum/EIPs/blob/master/EIPS/eip-8.md
- https://github.com/ethereum/go-ethereum/wiki/RLPx-Encryption
- https://github.com/ethereum/wiki/wiki/%C3%90%CE%9EVp2p-Wire-Protocol
- https://github.com/ethereum/wiki/wiki/Ethereum-Wire-Protocol
Link to this section Summary
Functions
Builds a response for an incoming authentication message
Builds an AuthMsgV4 which can be serialized and sent over the wire. This will also build an ephemeral key pair to use during the signing process
Reads a given ack message, transported during the key initialization phase of the RLPx protocol. This will generally be handled by the dialer of the connection
Reads a given auth message, transported during the key initialization phase of the RLPx protocol. This will generally be handled by the listener of the connection
Given an incoming message, let’s try to accept it as an ack resp. If that works, we’ll derive our secrets from it
Give an incoming msg, let’s try to accept it as an auth msg. If that works, we’ll prepare an ack response to send back and derive our secrets
Link to this section Types
Link to this section Functions
build_ack_resp(ExthCrypto.Key.public_key, binary | nil) :: ExWire.Handshake.Struct.AckRespV4.t
Builds a response for an incoming authentication message.
Examples
iex> ExWire.Handshake.build_ack_resp(ExthCrypto.Test.public_key(:key_c), ExthCrypto.Test.init_vector())
%ExWire.Handshake.Struct.AckRespV4{
remote_ephemeral_public_key: <<4, 146, 201, 161, 205, 19, 177, 147, 33, 107, 190, 144, 81, 145, 173, 83, 20, 105, 150, 114, 196, 249, 143, 167, 152, 63, 225, 96, 184, 86, 203, 38, 134, 241, 40, 152, 74, 34, 68, 233, 204, 91, 240, 208, 254, 62, 169, 53, 201, 248, 156, 236, 34, 203, 156, 75, 18, 121, 162, 104, 3, 164, 156, 46, 186>>,
remote_nonce: <<1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16>>,
remote_version: 63
}
build_auth_msg(ExthCrypto.Key.public_key, ExthCrypto.Key.private_key, ExthCrypto.Key.public_key, binary | nil, ExthCrypto.Key.key_pair | nil) :: {ExWire.Handshake.Struct.AuthMsgV4.t, ExthCrypto.Key.key_pair, binary}
Builds an AuthMsgV4 which can be serialized and sent over the wire. This will also build an ephemeral key pair to use during the signing process.
Examples
iex> {auth_msg_v4, ephemeral_keypair, nonce} = ExWire.Handshake.build_auth_msg(ExthCrypto.Test.public_key(:key_a), ExthCrypto.Test.private_key(:key_a), ExthCrypto.Test.public_key(:key_b), ExthCrypto.Test.init_vector(1, 32), ExthCrypto.Test.key_pair(:key_c))
iex> %{auth_msg_v4 | signature: nil} # signature will be unique each time
%ExWire.Handshake.Struct.AuthMsgV4{
remote_ephemeral_public_key: nil,
remote_nonce: <<1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32>>,
remote_public_key: <<4, 54, 241, 224, 126, 85, 135, 69, 213, 129, 115, 3, 41, 161, 217, 87, 215, 159, 64, 17, 167, 128, 113, 172, 232, 46, 34, 145, 136, 72, 160, 207, 161, 171, 255, 26, 163, 160, 158, 227, 196, 92, 62, 119, 84, 156, 99, 224, 155, 120, 250, 153, 134, 180, 218, 177, 186, 200, 199, 106, 97, 103, 50, 215, 114>>,
remote_version: 63,
signature: nil
}
iex> ephemeral_keypair
{
<<4, 146, 201, 161, 205, 19, 177, 147, 33, 107, 190, 144, 81, 145, 173, 83,
20, 105, 150, 114, 196, 249, 143, 167, 152, 63, 225, 96, 184, 86, 203, 38,
134, 241, 40, 152, 74, 34, 68, 233, 204, 91, 240, 208, 254, 62, 169, 53,
201, 248, 156, 236, 34, 203, 156, 75, 18, 121, 162, 104, 3, 164, 156, 46, 186>>,
<<178, 68, 134, 194, 0, 187, 118, 35, 33, 220, 4, 3, 50, 96, 97, 91, 96, 14,
71, 239, 7, 102, 33, 187, 194, 221, 152, 36, 95, 22, 121, 48>>
}
iex> nonce
<<1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32>>
read_ack_resp(binary, ExthCrypto.Key.private_key, String.t) :: {:ok, ExWire.Handshake.Struct.AckRespV4.t, binary, binary} | {:error, String.t}
Reads a given ack message, transported during the key initialization phase of the RLPx protocol. This will generally be handled by the dialer of the connection.
Note: this will handle pre- or post-EIP 8 messages. We take a different approach to other
implementations and try EIP-8 first, and if that fails, plain.
read_auth_msg(binary, ExthCrypto.Key.private_key, String.t) :: {:ok, ExWire.Handshake.Struct.AuthMsgV4.t, binary} | {:error, String.t}
Reads a given auth message, transported during the key initialization phase of the RLPx protocol. This will generally be handled by the listener of the connection.
Note: this will handle pre or post-EIP 8 messages. We take a different approach to other
implementations and try EIP-8 first, and if that fails, plain.
try_handle_ack(binary, binary, ExthCrypto.Key.private_key, binary, String.t) :: {:ok, ExWire.Framing.Secrets.t, binary} | {:invalid, String.t}
Given an incoming message, let’s try to accept it as an ack resp. If that works, we’ll derive our secrets from it.
TODO: Add examples
try_handle_auth(binary, ExthCrypto.Key.key_pair, binary, binary, String.t) :: {:ok, binary, ExWire.Framing.Secrets.t} | {:invalid, String.t}
Give an incoming msg, let’s try to accept it as an auth msg. If that works, we’ll prepare an ack response to send back and derive our secrets.
TODO: Add examples