Skip to main content

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

  1. Fork the repository on GitHub.
  2. Create a branch for your change.
  3. Install development dependencies with .venv/bin/python -m pip install -e ".[dev]".
  4. Add or update tests in tests/.
  5. Run .venv/bin/python -m pytest.
  6. 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 bytes
  • transcript_hash — 32 bytes
  • protection_level = "opportunistic"
  • peer_identity = null

Notes

  • transcript_hash is unique per handshake.
  • Possible values for protection_level are "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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wirekx-0.1.0.tar.gz (13.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wirekx-0.1.0-py3-none-any.whl (12.8 kB view details)

Uploaded Python 3

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

Hashes for wirekx-0.1.0.tar.gz
Algorithm Hash digest
SHA256 7b7a4b11360fe927654c1e63451fa5327ec2be1e860bdfdbcd6b724a69ecb1e4
MD5 ece2d9c3315c8d75d72135ad1b640d37
BLAKE2b-256 012edce9fe477b663c14782bc04412f043e1d93f4dc5a00e8eea1b158f89812f

See more details on using hashes here.

Provenance

The following attestation bundles were made for wirekx-0.1.0.tar.gz:

Publisher: publish.yml on wirekx/wirekx

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for wirekx-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fab5a221148d84ab0ebe45669ee4500bc5ca67ce4d563468c601be06062c5514
MD5 bf2bbbbed0a9086f2906088a7e582f64
BLAKE2b-256 f40d73fe3a9a20a96259759fc020265d35d28b304a7398430690d6fc652f736e

See more details on using hashes here.

Provenance

The following attestation bundles were made for wirekx-0.1.0-py3-none-any.whl:

Publisher: publish.yml on wirekx/wirekx

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page