Skip to main content

A client library for accessing reeeductio Spaces API

Project description

reeeductio Python SDK

A clean, modern Python SDK for the reeeductio Spaces API - an end-to-end encrypted messaging system with capability-based authorization.

Features

  • End-to-end encryption: Zero-knowledge server design
  • Blockchain-like message chains: Cryptographic integrity verification
  • Capability-based authorization: Granular, signed permissions
  • Multiple storage types:
    • Messages: Append-only topic streams
    • State: Event-sourced key-value store
    • Data: Simple signed key-value store
    • Blobs: Content-addressed binary storage
  • Real-time streaming: WebSocket support (coming soon)
  • Async support: Built on httpx for both sync and async usage
  • Type-safe: Full type hints and dataclass models

Installation

pip install reeeductio-client

Or install from source:

cd new-python-sdk
pip install -e .

Quick Start

from reeeductio import Space, generate_keypair
import os

# Generate a key pair
keypair = generate_keypair()
user_id = keypair.to_user_id()

# Generate or retrieve the space's symmetric root key (32 bytes)
symmetric_root = os.urandom(32)  # In practice, derive from space key or shared secret

# Connect to a space
# The Space client automatically derives encryption keys on init:
#   - message_key (for encrypting messages)
#   - blob_key (for encrypting blobs)
#   - state_key (for encrypting state)
#   - data_key (for encrypting KV data)
with Space(
    space_id="Cabc123...",  # 44-char space ID
    keypair=keypair,
    symmetric_root=symmetric_root,  # 256-bit root key for encryption
    base_url="http://localhost:8000"
) as space:
    # Keys are available as space.message_key, space.blob_key, etc.
    # Post a message
    result = space.post_message(
        topic_id="general",
        msg_type="chat",
        data=b"Hello, world!"  # Should be encrypted
    )
    print(f"Posted message: {result.message_hash}")

    # Get messages
    messages = space.get_messages("general", limit=10)
    for msg in messages:
        print(f"{msg.sender}: {msg.data}")

    # Upload a blob
    blob = space.upload_blob(b"file contents")
    print(f"Uploaded blob: {blob.blob_id}")

    # Set state
    space.set_state("profiles/alice", b'{"name": "Alice"}')

    # Get state
    state_msg = space.get_state("profiles/alice")
    print(f"State: {state_msg.data}")

Architecture

Components

  • Space: High-level client for interacting with a space
  • Messages: Blockchain-style append-only message streams
  • State: Event-sourced key-value store (stored as messages in "state" topic)
  • Data: Simple signed key-value store
  • Blobs: Content-addressed encrypted file storage
  • Auth: Challenge-response authentication with Ed25519 signatures

Cryptography

All identifiers use typed base64 encoding with a header byte:

  • User IDs start with U (e.g., Uabc123...)
  • Space IDs start with C (e.g., Cabc123...)
  • Message IDs start with M (e.g., Mabc123...)
  • Blob IDs start with B (e.g., Babc123...)
  • Tool IDs start with T (e.g., Tabc123...)

Message Chains

Messages form blockchain-like chains with hash pointers:

Message 1 → Message 2 → Message 3
  (M_abc)    (M_def)     (M_ghi)
              ↑            ↑
         prev_hash    prev_hash

Each message hash is computed over: topic_id|type|prev_hash|data|sender

Key Derivation

The Space client uses HKDF-SHA256 to derive encryption keys from the symmetric_root:

space = Space(space_id, keypair, symmetric_root)

# Automatically derived on initialization (scoped to space_id):
space.message_key  # HKDF(symmetric_root, info="message key | {space_id}") → 32 bytes
space.blob_key     # HKDF(symmetric_root, info="blob key | {space_id}") → 32 bytes
space.data_key     # HKDF(symmetric_root, info="data key | {space_id}") → 32 bytes
space.state_key    # HKDF(message_key, info="topic key | state") → 32 bytes

Security Benefits:

  • Single shared secret (symmetric_root) per space
  • Cryptographically independent keys for each data type
  • Domain separation: Keys are scoped to space_id to prevent cross-space key reuse
  • Deterministic: same root + same space always produces same keys
  • Forward-compatible for key rotation

Usage:

from reeeductio import derive_key

# Manual key derivation if needed
custom_key = derive_key(symmetric_root, "custom context", length=32)

API Reference

Space Client

class Space:
    def __init__(
        self,
        space_id: str,
        keypair: Ed25519KeyPair,
        symmetric_root: bytes,  # 256-bit (32-byte) root key for HKDF
        base_url: str = "http://localhost:8000",
        auto_authenticate: bool = True,
    )

    # Authentication
    def authenticate(self) -> str

    # Messages
    def post_message(self, topic_id: str, msg_type: str, data: bytes, prev_hash: str | None = None) -> MessageCreated
    def get_messages(self, topic_id: str, from_timestamp: int | None = None, to_timestamp: int | None = None, limit: int = 100) -> list[Message]
    def get_message(self, topic_id: str, message_hash: str) -> Message

    # State
    def get_state(self, path: str) -> Message
    def set_state(self, path: str, data: bytes, prev_hash: str | None = None) -> MessageCreated
    def get_state_history(self, from_timestamp: int | None = None, to_timestamp: int | None = None, limit: int = 100) -> list[Message]

    # Data (KV)
    def get_data(self, path: str) -> DataEntry
    def set_data(self, path: str, data: bytes) -> int

    # Blobs
    def upload_blob(self, data: bytes) -> BlobCreated
    def download_blob(self, blob_id: str) -> bytes
    def delete_blob(self, blob_id: str) -> None

Crypto Utilities

from reeeductio import generate_keypair, sign_data, compute_hash

# Generate keys
keypair = generate_keypair()
user_id = keypair.to_user_id()
space_id = keypair.to_space_id()

# Sign data
signature = sign_data(b"data to sign", keypair.private_key)

# Hash data
hash_bytes = compute_hash(b"data to hash")

Development Status

This is a clean-slate rewrite of the reeeductio Python SDK, built without auto-generated code for better maintainability and developer experience.

Implemented

  • ✅ Core models (Message, Capability, etc.)
  • ✅ Cryptography (Ed25519 signing, HKDF key derivation)
  • ✅ Authentication (challenge-response)
  • ✅ Message posting and retrieval
  • ✅ State management
  • ✅ Data (KV) storage
  • ✅ Blob upload/download
  • ✅ Sync API using httpx
  • ✅ Comprehensive test suite (pytest)

Coming Soon

  • ⏳ Async client support
  • ⏳ WebSocket streaming
  • ⏳ Message encryption helpers (AES-GCM)
  • ⏳ Blob encryption helpers
  • ⏳ Additional examples

Testing

Run the test suite:

# Install dev dependencies
uv pip install -e ".[dev]"

# Run all tests (19 tests total)
uv run pytest

# Run with verbose output
uv run pytest -v

# Run specific test file
uv run pytest tests/test_key_derivation.py  # 18 key derivation tests
uv run pytest tests/test_smoke.py           # 1 comprehensive API smoke test

The test suite includes:

  • test_smoke.py: Comprehensive smoke test validating the entire public API surface
  • test_key_derivation.py: 18 tests covering HKDF key derivation, domain separation, and security properties

See tests/README.md for more details.

License

[Your License Here]

Contributing

Contributions welcome! Please open an issue or PR.

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

reeeductio-0.1.0.tar.gz (74.8 kB view details)

Uploaded Source

Built Distribution

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

reeeductio-0.1.0-py3-none-any.whl (67.1 kB view details)

Uploaded Python 3

File details

Details for the file reeeductio-0.1.0.tar.gz.

File metadata

  • Download URL: reeeductio-0.1.0.tar.gz
  • Upload date:
  • Size: 74.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for reeeductio-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b36325b0168c2f98b25bba0374dfdc2e0a0032b6b2919d414e56cfdcd3b9944f
MD5 1bf05e8908b4e301ac92b5aba0ee2aca
BLAKE2b-256 9c9c11196f5bab0ebbc1debda9a375364ba2e068e6031f853e77b2bdd1f78229

See more details on using hashes here.

File details

Details for the file reeeductio-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: reeeductio-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 67.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for reeeductio-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 101a8c2bc2b811f3b9f8b110734c0a2186eec28dea44c68328fb382dc07ad47c
MD5 2aeabb4adfee46353ab7f622fadf4207
BLAKE2b-256 8f367f5f858ddc51e35c2d29a4f0549c663f971727606020227f231179471d46

See more details on using hashes here.

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