Experimental anonymous X25519 key exchange wire format.
Project description
* * __ __ ___ ____ _____ _ __ __ __
\ / \ \ / / |_ _|| _ \ | ____|| |/ / \ \/ /
^/ | \^ \ \ /\ / / | | | |_) || _| | ' / \ /
| o:1 | \ V V / | | | _ < | |___ | . \ / \
-| 1:o |- \_/\_/ |___||_| \_\|_____||_|\_\ /_/\_\
/ \_|_/ \
Python library and wire format for anonymous X25519 key exchange.
wirekx v1 performs the following:
- Opportunistic key agreement for anonymous handshake
V1 caveat: Since this is an anonymous handshake, MITM is undetectable.
Use cases:
- Derive symmetric key for payload encryption between trusted services
Future releases:
- publicCA validation for anonymous handshake
- Pre-shared fingerprint validation
- Quantum-safe encryption
Install for development
python3 -m venv .venv
.venv/bin/python -m pip install -e ".[dev]"
Run the manual example:
.venv/bin/python testrun.py
Run tests:
.venv/bin/python -m pytest
Use as a library:
from wirekx import InitiatorHandshake, ResponderHandshake
initiator = InitiatorHandshake()
responder = ResponderHandshake()
hello = initiator.create_hello()
responder.receive_hello(hello)
hello_back = responder.create_hello_back()
initiator.receive_hello_back(hello_back)
initiator_confirm = initiator.create_confirm()
responder.receive_confirm(initiator_confirm)
responder_confirm = responder.create_confirm()
initiator.receive_confirm(responder_confirm)
result = initiator.result()
print(result.symmetric_key.hex())
Open source contribution flow
- Fork the repository on GitHub.
- Create a branch for your change.
- Install development dependencies with
.venv/bin/python -m pip install -e ".[dev]". - Add or update tests in
tests/. - Run
.venv/bin/python -m pytest. - Open a pull request.
License
wirekx is licensed under the Apache License, Version 2.0. See LICENSE.
Redistributions should preserve the attribution notices in NOTICE. If you use
wirekx in a public project, a README or documentation mention is appreciated.
wirekx wire format (v1, anonymous mode)
Two parties run a handshake and end up holding the same 32-byte symmetric key. This document specifies the bytes that go on the wire.
Envelope
Every message starts with a 4-byte header followed by its payload.
┌─────────┬──────────┬─────────────┬──────────────┐
│ version │ msg_type │ payload_len │ payload │
│ 1 byte │ 1 byte │ 2 bytes BE │ payload_len │
└─────────┴──────────┴─────────────┴──────────────┘
version = 0x01. Multi-byte integers are big-endian.
Messages
| Code | Name | From | Payload |
|---|---|---|---|
0x01 |
HELLO |
initiator | eph_pub_a (32) + nonce_a (32) |
0x02 |
HELLO_BACK |
responder | eph_pub_b (32) + nonce_b (32) |
0x03 |
CONFIRM |
both | verify_data (32) |
eph_pub_* is an X25519 public key. nonce_* is 32 random bytes.
Cryptography
shared_secret = X25519(own_eph_priv, peer_eph_pub)
symmetric_key = HKDF-SHA256(
ikm = shared_secret,
salt = nonce_a || nonce_b,
info = "wirekx v1 session key",
length = 32)
transcript = SHA-256(HELLO_bytes || HELLO_BACK_bytes)
verify_data = HMAC-SHA256(
key = symmetric_key,
data = "wirekx v1 <role> confirm" || transcript)
<role> is initiator or responder depending on who sent the CONFIRM.
Compare received verify_data with constant-time equality. Mismatch = abort.
Flow
initiator responder
│ │
│ HELLO (eph_pub_a, nonce_a) │
│ ────────────────────────────────────► │
│ │
│ HELLO_BACK (eph_pub_b, nonce_b) │
│ ◄──────────────────────────────────── │
│ │
│ derive symmetric_key, transcript │
│ CONFIRM (verify_data_initiator) │
│ ────────────────────────────────────► │
│ │
│ │ verify, then:
│ CONFIRM (verify_data_responder) │
│ ◄──────────────────────────────────── │
│ │
│ verify │
│ COMPLETE │ COMPLETE
On any malformed message, unexpected type, or verification mismatch: abort, discard state, do not return the key.
Output
After both CONFIRM messages verify, return to the caller:
symmetric_key— 32 bytestranscript_hash— 32 bytesprotection_level="opportunistic"peer_identity=null
Notes
transcript_hashis unique per handshake.- Possible values for
protection_levelare"opportunistic"and"authenticated". Opportunistic means anonymous players, active MITM is undetectable. Authenticated means you have verified peer's identity by exchanging certificate via an external channel. - Ephemeral keys are fresh per handshake and discarded after use.
- No version negotiation. Different versions cannot interoperate.
- Authenticated modes (
fingerprint,shared,publicCA) will be built in future.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wirekx-0.1.0.tar.gz.
File metadata
- Download URL: wirekx-0.1.0.tar.gz
- Upload date:
- Size: 13.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7b7a4b11360fe927654c1e63451fa5327ec2be1e860bdfdbcd6b724a69ecb1e4
|
|
| MD5 |
ece2d9c3315c8d75d72135ad1b640d37
|
|
| BLAKE2b-256 |
012edce9fe477b663c14782bc04412f043e1d93f4dc5a00e8eea1b158f89812f
|
Provenance
The following attestation bundles were made for wirekx-0.1.0.tar.gz:
Publisher:
publish.yml on wirekx/wirekx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wirekx-0.1.0.tar.gz -
Subject digest:
7b7a4b11360fe927654c1e63451fa5327ec2be1e860bdfdbcd6b724a69ecb1e4 - Sigstore transparency entry: 1819611888
- Sigstore integration time:
-
Permalink:
wirekx/wirekx@8c9ba2d9671f97bb175e1d5b807195014234914d -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/wirekx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8c9ba2d9671f97bb175e1d5b807195014234914d -
Trigger Event:
release
-
Statement type:
File details
Details for the file wirekx-0.1.0-py3-none-any.whl.
File metadata
- Download URL: wirekx-0.1.0-py3-none-any.whl
- Upload date:
- Size: 12.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fab5a221148d84ab0ebe45669ee4500bc5ca67ce4d563468c601be06062c5514
|
|
| MD5 |
bf2bbbbed0a9086f2906088a7e582f64
|
|
| BLAKE2b-256 |
f40d73fe3a9a20a96259759fc020265d35d28b304a7398430690d6fc652f736e
|
Provenance
The following attestation bundles were made for wirekx-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on wirekx/wirekx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wirekx-0.1.0-py3-none-any.whl -
Subject digest:
fab5a221148d84ab0ebe45669ee4500bc5ca67ce4d563468c601be06062c5514 - Sigstore transparency entry: 1819611921
- Sigstore integration time:
-
Permalink:
wirekx/wirekx@8c9ba2d9671f97bb175e1d5b807195014234914d -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/wirekx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8c9ba2d9671f97bb175e1d5b807195014234914d -
Trigger Event:
release
-
Statement type: