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:

  1. https://github.com/ethereum/devp2p/blob/master/rlpx.md
  2. https://github.com/ethereum/EIPs/blob/master/EIPS/eip-8.md
  3. https://github.com/ethereum/go-ethereum/wiki/RLPx-Encryption
  4. https://github.com/ethereum/wiki/wiki/%C3%90%CE%9EVp2p-Wire-Protocol
  5. 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 type token()
token() :: binary

Link to this section Functions

Link to this function build_ack_resp(remote_ephemeral_public_key, nonce \\ nil)

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
}
Link to this function build_auth_msg(my_static_public_key, my_static_private_key, her_static_public_key, nonce \\ nil, my_ephemeral_keypair \\ nil)

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>>
Link to this function read_ack_resp(encoded_ack, my_static_private_key, remote_addr)
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.
Link to this function read_auth_msg(encoded_auth, my_static_private_key, remote_addr)
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.
Link to this function try_handle_ack(ack_data, auth_data, my_ephemeral_private_key, my_nonce, host)
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

Link to this function try_handle_auth(auth_data, my_ephemeral_key_pair, my_nonce, remote_id, host)
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