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.0.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.0-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.0.tar.gz.

File metadata

  • Download URL: soliton_py-0.1.0.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.0.tar.gz
Algorithm Hash digest
SHA256 17c60219e0fab1d1e24280c2266d2dd2c241e39e31d70549ccbb5963117e54b0
MD5 c1c7da7b6637bb12cafb3908ab5687f1
BLAKE2b-256 07fd4132d1560d243f850b7281175fecbfa98fc8ffda9fa895525343ca97d13d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for soliton_py-0.1.0-cp313-cp313-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 d133a01d1023141ddf30c13ff9a3ef63599345245621bba104e43095d3032a3e
MD5 b17285027ebfdc33e425f7befca28024
BLAKE2b-256 1133bcd430f6b6889a48aab2fa31d9077d2e4ebf46e9be77f3e741bf80fb8b60

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