{"id":34587029,"url":"https://github.com/vbhattaccmu/rlpx-handshake","last_synced_at":"2026-05-28T10:32:39.978Z","repository":{"id":206733628,"uuid":"712280961","full_name":"vbhattaccmu/rlpx-handshake","owner":"vbhattaccmu","description":"A minimal implementation to showcase a cryptographic handshake on the transport layer between a node and an external client","archived":false,"fork":false,"pushed_at":"2023-11-22T06:07:47.000Z","size":31,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2023-11-22T07:26:19.992Z","etag":null,"topics":["aes","devp2p","networking","tcp"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vbhattaccmu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-10-31T06:41:10.000Z","updated_at":"2023-10-31T07:04:05.000Z","dependencies_parsed_at":"2023-11-22T07:26:13.742Z","dependency_job_id":null,"html_url":"https://github.com/vbhattaccmu/rlpx-handshake","commit_stats":null,"previous_names":["vbhattaccmu/rlpx-handshake"],"tags_count":0,"template":null,"template_full_name":null,"purl":"pkg:github/vbhattaccmu/rlpx-handshake","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbhattaccmu%2Frlpx-handshake","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbhattaccmu%2Frlpx-handshake/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbhattaccmu%2Frlpx-handshake/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbhattaccmu%2Frlpx-handshake/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vbhattaccmu","download_url":"https://codeload.github.com/vbhattaccmu/rlpx-handshake/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbhattaccmu%2Frlpx-handshake/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33605378,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-28T02:00:06.440Z","response_time":99,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aes","devp2p","networking","tcp"],"created_at":"2025-12-24T10:33:55.724Z","updated_at":"2026-05-28T10:32:39.966Z","avatar_url":"https://github.com/vbhattaccmu.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Problem statement\n\nReimplement RLPx protocol in Rust.\n\n## Technical Goals\n\nThe implementation focusses on following:-\n\n1. Simplifying MAC egress/ingress validation.\n2. Simplifying transport layer and codec definitions.\n3. Updating secp256k1 crates to its latest version and its function signatures.\n4. Adding handshake tests to make sure it communicates with latest geth client.\n\n## Hard Requirements\n\n- The solution has to perform a full **protocol-level** (post-TCP/etc.) handshake with the target node.\n\n## Solution\n\nThe repository consists of a geth client which can spin up a local network in your machine. The other crate is a lightweight client performing\nthe handshake with the geth client.\n\nThe handhake occurs in two phases:-\n\nPhase I - Send auth and receive ack to/from recipient\n\nPhase II - Send/Recv outbound message to/from recipient\n\nThe formulation for Phase I and II are adapted from source [RLPx protocol](https://hackmd.io/@Nhlanhla/SJv3wnhMK)\n\n### Phase I\n\nPhase I is implemented by using a state machine to decode incoming data via codec and transition between different states of the handshake between peers.The implementation can be found in `server/networking/codec.rs`\n\nThe initial auth-ack handshake from [source](https://hackmd.io/@Nhlanhla/SJv3wnhMK) is defined as follows:-\n\n```\nauth = auth-size || enc-auth-body\nauth-size = size of enc-auth-body, encoded as a big-endian 16-bit integer\nauth-body = [sig, initiator-pubk, initiator-nonce...]\nenc-auth-body = codec.encrypt(recipient-pubk, auth-body || auth-padding, auth-size)\n\nack = ack-size || enc-ack-body\nack-size = size of enc-ack-body, encoded as a big-endian 16-bit integer\nack-body = [recipient-ephemeral-pubk, recipient-nonce,...]\nenc-ack-body = codec.encrypt(initiator-pubk, ack-body || ack-padding, ack-size)\n```\n\n### Other cryptographic exhanges taking place in Phase I\n\n1. Secrets generated following the exchange of auth-ack handshake messages.\n   ```\n   ephemeral-key = ecdh.agree(ephemeral-privkey, remote-ephemeral-pubk)\n   shared-secret = keccak256(ephemeral-key || keccak256(nonce || initiator-nonce))\n   aes-secret = keccak256(ephemeral-key || shared-secret)\n   mac-secret = keccak256(ephemeral-key || aes-secret)\n   ```\n2. MAC: Message Authentication Code from initiator\n   ```\n   ingress-mac = keccak256.init((mac-secret ^ initiator-nonce) || ack)\n   ```\n   ingress mac is checked against mac bytes received from the header and body.\n\n### Phase II\n\nAfter the auth-ack phase is complete an outbound message is sent to the recipient and it sends\nback a response which is deserialized back.\n\n## Prerequisites\n\nThe following service utilizes docker\n\n- cargo: compiler for Rust.\n  To install Rust you will need the following command.This will install rustup as well.\n  ```\n  curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y\n  ```\n- gcc: required for libc bindings\n  See [here](https://phoenixnap.com/kb/install-gcc-ubuntu) for installation options.\n\n- docker and its utilities\n  User requires to install Docker and Docker Compose(v2) on their machine. See [Install Docker Engine on Ubuntu](https://docs.docker.com/engine/install/ubuntu/)\n\n  The following are the versions of the toolchain\n\n  | Toolchain      | Version                       |\n  | :------------- | :---------------------------- |\n  | Ubuntu         | 22.04.3 LTS                   |\n  | cargo          | 1.72.0 (103a7ff2e 2023-08-15) |\n  | rustup         | 1.26.0                        |\n  | gcc            | 11.4.0                        |\n  | docker         | 24.0.5 build ced0996          |\n  | docker compose | v2.20.0                       |\n\n## How to execute\n\n1. Enable permissions on the run.sh file by performing\n   ```\n   chmod +x run.sh\n   ```\n2. Run run.sh file. You will be prompted to enter your password because docker compose needs to be run with\n   admin privileges. You will get the following output.\n\n   ```\n   ./run.sh\n   ```\n\n   Output:-\n\n   ```\n    [+] Running 4/4\n    ✔ Network geth_priv-eth-net           Crea...                             0.2s\n    ✔ Container geth-geth-bootnode-1      Started                             1.0s\n    ✔ Container geth-geth-rpc-endpoint-1  Started                             1.8s\n    ✔ Container geth-geth-miner-1         St...                               1.6s\n        Finished test [unoptimized + debuginfo] target(s) in 0.08s\n        Running unittests src/lib.rs (target/debug/deps/rlpx_handshake-31be7cfd58185a34)\n\n    running 2 tests\n    test tests::test_handshake_failure_with_incorrect_id ... ok\n    test tests::test_handshake_success ... ok\n\n    test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s\n   ```\n\n3. Please run the `cleanup.sh` command in order to clean up artifacts to save resources.\n   ```\n   ./cleanup.sh\n   ```\n\n## How to know if handshake is successful\n\nThe only way to know if the handshake is successful is\n\n1. To check if the geth recipient node sends back its client version and its current protocol version at the end of the\n   handshake in Phase II after the initiator sends a `Hello` frame with its own client and protocol version.\n\n   In this case the recipient client version: `Geth/v1.10.1-stable-c2d2f4ed/linux-amd64/go1.16`\n   and the protocol version is `5`.\n\n2. To check if the the handshake fails when we use a different public key other than the actual node public key.\n\n   In this case the node public key defined in docker compose setupfor geth node:\n   `af22c29c316ad069cf48a09a4ad5cf04a251b411e45098888d114c6dd7f489a13786620d5953738762afa13711d4ffb3b19aa5de772d8af72f851f7e9c5b164a`\n\nTwo `tests test tests::test_handshake_failure_with_incorrect_id` and `test tests::test_handshake_success` are defined two test (1) and (2).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvbhattaccmu%2Frlpx-handshake","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvbhattaccmu%2Frlpx-handshake","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvbhattaccmu%2Frlpx-handshake/lists"}