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.2.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.2-cp313-cp313-manylinux_2_34_x86_64.whl (643.4 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.34+ x86-64

File details

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

File metadata

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

File hashes

Hashes for soliton_py-0.1.2.tar.gz
Algorithm Hash digest
SHA256 a42e47149a3333b517ed6516005eab608dab0fee8653ed1b5cca772a3fe96d74
MD5 69bb929a04469f55d803cb19f1f8e46c
BLAKE2b-256 3a882e344761d5acdfc0c639641b90e49465e44f38654937353542999846dd73

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for soliton_py-0.1.2-cp313-cp313-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 64781ff0c85e5581631642bd072cc98cbab5408bb4ecf11a82e401ae86ddb660
MD5 f521e70ccdac97218b436267970c9b3f
BLAKE2b-256 578ec61745762baf99d4cd8729d5be4f2b0bfd82589e1a1ad322de9b9ecfef22

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