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

Uploaded CPython 3.13manylinux: glibc 2.34+ x86-64

File details

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

File metadata

  • Download URL: soliton_py-0.1.3.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.3.tar.gz
Algorithm Hash digest
SHA256 e4c23d00f65e21a2d4fa5c97532c2c387499a33b0d8d4ff31fdc4c7c92598951
MD5 96ed08d04ed821620dd072a03f043025
BLAKE2b-256 f30fc8dc65544140789d4a043c57b41b4a7e290d058190d7fc8345abc21d66cc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for soliton_py-0.1.3-cp313-cp313-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 0761d02dda355e22acb46ec2325eeee6c44c32b832ebb10d1f7a9a7bfd574e71
MD5 ad4932772fcb553ab635a23eaa02ba24
BLAKE2b-256 14f8813740ffb9f33d38beb28a552b37a0ac100c2fc7f6beee65c8be1f1dc544

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