Skip to main content

Python bindings for libsoliton — post-quantum cryptographic library

Project description

soliton

Python bindings for libsoliton — a pure-Rust post-quantum cryptographic library providing composite identity keys (X-Wing + ML-DSA-65), hybrid signatures, KEM-based authentication, asynchronous key exchange, double-ratchet message encryption, streaming AEAD, and encrypted storage.

Install

pip install soliton-py

Builds from source via maturin — requires a Rust toolchain.

Quick Start

Identity Keys

import soliton

# Generate a post-quantum identity keypair.
with soliton.Identity.generate() as alice:
    # Sign a message (Ed25519 + ML-DSA-65 hybrid).
    sig = alice.sign(b"hello")
    alice.verify(b"hello", sig)

    # Fingerprint (SHA3-256 of public key).
    print(alice.fingerprint_hex())

    # Persist keys.
    pk = alice.public_key()   # 3200 bytes
    sk = alice.secret_key()   # 2496 bytes
# Secret key is zeroized on context exit.

Key Exchange (KEX)

# Bob generates a signed pre-key.
spk_pub, spk_sk = soliton.xwing_keygen()
spk_sig = soliton.kex_sign_prekey(bob_sk, spk_pub)

# Alice initiates a session.
initiated = soliton.kex_initiate(
    alice_pk, alice_sk, bob_pk,
    spk_pub, spk_id=1, spk_sig=spk_sig,
    crypto_version="lo-crypto-v1",
)

# Bob receives the session.
received = soliton.kex_receive(
    bob_pk, bob_sk, alice_pk,
    initiated.session_init_encoded(),
    initiated.sender_sig(), spk_sk,
)

Ratchet (Ongoing Messaging)

# First message (pre-ratchet).
aad = soliton.kex_build_first_message_aad(
    initiated.sender_fingerprint(),
    initiated.recipient_fingerprint(),
    initiated.session_init_encoded(),
)
ct, rik_a = soliton.Ratchet.encrypt_first_message(
    initiated.take_initial_chain_key(), b"hello bob", aad,
)
pt, rik_b = soliton.Ratchet.decrypt_first_message(
    received.take_initial_chain_key(), ct, aad,
)

# Initialize ratchets.
with soliton.Ratchet.init_alice(
    initiated.take_root_key(), rik_a,
    alice_fp, bob_fp, initiated.ek_pk(), initiated.ek_sk(),
) as alice_r:
    header, ciphertext = alice_r.encrypt(b"message 1")

    # Serialize for persistence.
    blob, epoch = alice_r.to_bytes()  # consumes the ratchet

Encrypted Storage

with soliton.StorageKeyRing(version=1, key=key_bytes) as ring:
    blob = ring.encrypt_blob("channel-1", "segment-0", plaintext)
    data = ring.decrypt_blob("channel-1", "segment-0", blob)

    # Key rotation.
    ring.add_key(version=2, key=new_key, make_active=True)

Streaming AEAD (File Encryption)

with soliton.StreamEncryptor(key) as enc:
    header = enc.header()  # 26 bytes — send first
    ct1 = enc.encrypt_chunk(chunk1)            # non-final: must be 1 MiB
    ct2 = enc.encrypt_chunk(chunk2, is_last=True)  # final: any size

with soliton.StreamDecryptor(key, header) as dec:
    pt1, is_last = dec.decrypt_chunk(ct1)
    pt2, is_last = dec.decrypt_chunk(ct2)

Authentication (Zero-Knowledge)

# Server generates challenge.
ct, token = soliton.auth_challenge(client_pk)

# Client responds.
proof = soliton.auth_respond(client_sk, ct)

# Server verifies (constant-time).
assert soliton.auth_verify(token, proof)

Primitives

digest = soliton.sha3_256(b"data")                      # 32 bytes
tag = soliton.hmac_sha3_256(key, data)                   # 32 bytes
okm = soliton.hkdf_sha3_256(salt, ikm, info, length=64)  # variable
ok = soliton.hmac_sha3_256_verify(tag1, tag2)             # constant-time
phrase = soliton.verification_phrase(pk_a, pk_b)           # 6 EFF words

Error Handling

All errors are subclasses of soliton.SolitonError:

Exception Meaning
AeadError AEAD decryption failed (wrong key, tampered ciphertext)
VerificationError Signature verification failed
BundleVerificationError Pre-key bundle invalid
DuplicateMessageError Replayed message counter
ChainExhaustedError Counter-space exhausted — re-establish session
InvalidLengthError Wrong-size parameter
InvalidDataError Malformed input

Context Managers

All types holding secret material support with statements for automatic zeroization:

with soliton.Identity.generate() as id:
    ...  # secret key zeroized on exit

with soliton.Ratchet.init_alice(...) as r:
    ...  # ratchet state reset on exit

with soliton.StorageKeyRing(1, key) as ring:
    ...  # key material zeroized on exit

Documentation

License

AGPL-3.0-only

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

soliton_py-0.1.1.tar.gz (266.5 kB view details)

Uploaded Source

Built Distribution

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

soliton_py-0.1.1-cp313-cp313-manylinux_2_34_x86_64.whl (643.0 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.34+ x86-64

File details

Details for the file soliton_py-0.1.1.tar.gz.

File metadata

  • Download URL: soliton_py-0.1.1.tar.gz
  • Upload date:
  • Size: 266.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.12.6

File hashes

Hashes for soliton_py-0.1.1.tar.gz
Algorithm Hash digest
SHA256 2e95db23110a5398c044a086ad3990ac09d6e2214e1dd01396d409633bf065b3
MD5 31574ea05d63b62910b248d55cfbfec8
BLAKE2b-256 9a871d0152ecf49dd2924ed3bd7896eeb1b1ff425df53642c6ff18db31d02014

See more details on using hashes here.

File details

Details for the file soliton_py-0.1.1-cp313-cp313-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for soliton_py-0.1.1-cp313-cp313-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 6bc4219beeb69dc1e9aa9e629523148349eb31af74c110fa158bea1f7665c978
MD5 eb3b7d04326b31b10348883219db0074
BLAKE2b-256 418122b2290ab56f2211cb66205f6772f6662b4e9d2de9177d8f4862986e401a

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