Files
quicproquo/sdks/python
Christian Nennemann 49e8e066d7 feat(sdk): add Python SDK with QUIC and FFI transport backends
Implements quicproquo-py with two transport backends:
- Async QUIC transport via aioquic with v2 protobuf wire format
- Synchronous Rust FFI transport via CFFI wrapping libquicproquo_ffi

Includes manual protobuf encode/decode (no codegen), full RPC coverage
(auth, delivery, channels, users, keys, health), PyPI-ready packaging,
async echo bot and FFI demo examples, and 15 passing unit tests.
2026-03-04 20:52:02 +01:00
..

quicproquo Python SDK

Python client library for the quicproquo E2E encrypted messenger.

Prerequisites

  • Python 3.10+
  • A running quicproquo server

Installation

pip install quicproquo

For development:

pip install -e ".[dev]"

Transport Backends

1. Async QUIC (pure Python)

Uses aioquic for native QUIC transport with the v2 protobuf wire format. No Rust dependency required.

import asyncio
from quicproquo import QpqClient, ConnectOptions

async def main():
    client = await QpqClient.connect(ConnectOptions(
        addr="127.0.0.1:5001",
        ca_cert_path="ca.pem",
    ))

    health = await client.health()
    print(f"Server: {health.status}")

    # OPAQUE auth (requires external OPAQUE library for crypto)
    server_resp = await client.login_start("alice", opaque_request_bytes)
    # ... process server_resp with OPAQUE library ...
    token = await client.login_finish("alice", finalization, identity_key)

    # Resolve a user
    key, proof = await client.resolve_user("bob")

    # Send a message
    seq, proof = await client.send(recipient_key, b"hello")

    # Receive messages (long-poll)
    messages = await client.receive_wait(my_key, timeout_ms=5000)
    for msg in messages:
        print(f"[{msg.seq}] {msg.data}")

    await client.close()

asyncio.run(main())

2. Rust FFI (synchronous)

Wraps libquicproquo_ffi via CFFI for full Rust crypto stack (MLS, hybrid KEM, OPAQUE) at native speed.

# Build the FFI library first
cargo build --release -p quicproquo-ffi
from quicproquo import QpqClient, ConnectOptions

client = QpqClient.connect_ffi(ConnectOptions(
    addr="127.0.0.1:5001",
    ca_cert_path="ca.pem",
))

client.ffi_login("alice", "password123")
client.ffi_send("bob", b"hello from Python!")

messages = client.ffi_receive(timeout_ms=5000)
for msg in messages:
    print(msg)

client.close_sync()

API Reference

Connection

Method Transport Description
QpqClient.connect(opts) QUIC Async connect to server
QpqClient.connect_ffi(opts) FFI Sync connect via Rust FFI
client.close() QUIC Async disconnect
client.close_sync() Both Sync disconnect

Authentication (QUIC)

Method Description
client.register_start(username, request) Start OPAQUE registration
client.register_finish(username, upload, identity_key) Complete registration
client.login_start(username, request) Start OPAQUE login
client.login_finish(username, finalization, identity_key) Complete login
client.set_session_token(token) Set pre-existing session token

Authentication (FFI)

Method Description
client.ffi_login(username, password) Full OPAQUE login (Rust handles crypto)

Messaging (QUIC)

Method Description
client.health() Server health check
client.resolve_user(username) Look up identity key
client.resolve_identity(key) Reverse look up username
client.create_channel(peer_key) Create 1:1 DM channel
client.send(recipient_key, payload) Send a message
client.receive(recipient_key) Fetch queued messages
client.receive_wait(recipient_key, timeout_ms=5000) Long-poll for messages
client.ack(recipient_key, seq_up_to) Acknowledge messages
client.upload_key_package(key, package) Upload MLS key package
client.fetch_key_package(key) Fetch MLS key package
client.delete_account() Permanently delete account

Messaging (FFI)

Method Description
client.ffi_send(recipient, message) Send message by username
client.ffi_receive(timeout_ms=5000) Receive pending messages

Wire Format

The SDK implements the qpq v2 wire format:

[method_id:u16][req_id:u32][len:u32][protobuf payload]

Each RPC is sent over its own QUIC bidirectional stream.

Structure

  • quicproquo/client.py -- High-level client API
  • quicproquo/transport.py -- QUIC transport (aioquic)
  • quicproquo/ffi.py -- Rust FFI transport (CFFI)
  • quicproquo/proto.py -- Protobuf encode/decode (no codegen)
  • quicproquo/wire.py -- v2 wire format framing
  • quicproquo/types.py -- Data types and exceptions
  • examples/bot.py -- Async echo bot example
  • examples/ffi_demo.py -- Synchronous FFI example

Running Tests

pip install -e ".[dev]"
pytest