
Security News
Astral Launches pyx: A Python-Native Package Registry
Astral unveils pyx, a Python-native package registry in beta, designed to speed installs, enhance security, and integrate deeply with uv.
Cryptography Suite is an advanced cryptographic toolkit for Python, meticulously engineered for applications demanding robust security and seamless integration. It offers a comprehensive set of cryptographic primitives and protocols, empowering developers and organizations to implement state-of-the-art encryption, hashing, key management, digital signatures, and more.
pip install "cryptography-suite[pqc]"
β demo-only, not production-grade). These are available under cryptography_suite.experimental
.cryptography_suite.experimental.signal
(experimental, not production-ready).cryptography_suite.experimental
(experimental, demo-only).cryptography_suite.experimental
(experimental).Feature | Module | Pipeline? | CLI? | Keystore? | Status | Extra |
---|---|---|---|---|---|---|
AESGCMDecrypt | cryptography_suite.pipeline | Yes | No | No | stable | |
AESGCMEncrypt | cryptography_suite.pipeline | Yes | No | No | stable | |
BULLETPROOF_AVAILABLE | No | Yes | No | experimental | ||
ECIESX25519Decrypt | cryptography_suite.pipeline | Yes | No | No | stable | |
ECIESX25519Encrypt | cryptography_suite.pipeline | Yes | No | No | stable | |
FHE_AVAILABLE | No | No | No | experimental | ||
HandshakeFlowWidget | cryptography_suite.viz.widgets | No | No | No | experimental | |
HybridDecrypt | cryptography_suite.pipeline | Yes | No | No | stable | |
HybridEncrypt | cryptography_suite.pipeline | Yes | No | No | stable | |
KeyGraphWidget | cryptography_suite.viz.widgets | No | No | No | experimental | |
KyberDecrypt | cryptography_suite.pipeline | Yes | No | No | experimental | |
KyberEncrypt | cryptography_suite.pipeline | Yes | No | No | experimental | |
PQCRYPTO_AVAILABLE | No | Yes | No | experimental | ||
RSADecrypt | cryptography_suite.pipeline | Yes | No | No | stable | |
RSAEncrypt | cryptography_suite.pipeline | Yes | No | No | stable | |
SIGNAL_AVAILABLE | No | No | No | experimental | ||
SPHINCS_AVAILABLE | No | Yes | No | experimental | ||
SessionTimelineWidget | cryptography_suite.viz.widgets | No | No | No | experimental | |
SignalReceiver | cryptography_suite.experimental.signal | No | No | No | experimental | |
SignalSender | cryptography_suite.experimental.signal | No | No | No | experimental | |
ZKSNARK_AVAILABLE | No | Yes | No | experimental | ||
blake3_hash_v2 | cryptography_suite.hashing | No | No | No | deprecated | |
bls_aggregate | cryptography_suite.asymmetric.bls | No | No | No | deprecated | |
bls_aggregate_verify | cryptography_suite.asymmetric.bls | No | No | No | deprecated | |
bls_sign | cryptography_suite.asymmetric.bls | No | No | No | deprecated | |
bls_verify | cryptography_suite.asymmetric.bls | No | No | No | deprecated | |
bulletproof | No | Yes | No | experimental | ||
dilithium_sign | No | No | No | experimental | ||
dilithium_verify | No | No | No | experimental | ||
fhe_add | cryptography_suite.homomorphic | No | No | No | experimental | |
fhe_decrypt | cryptography_suite.homomorphic | No | No | No | experimental | |
fhe_encrypt | cryptography_suite.homomorphic | No | No | No | experimental | |
fhe_keygen | cryptography_suite.homomorphic | No | No | No | experimental | |
fhe_load_context | cryptography_suite.homomorphic | No | No | No | experimental | |
fhe_multiply | cryptography_suite.homomorphic | No | No | No | experimental | |
fhe_serialize_context | cryptography_suite.homomorphic | No | No | No | experimental | |
generate_bls_keypair | cryptography_suite.asymmetric.bls | No | No | No | deprecated | |
generate_dilithium_keypair | No | Yes | No | experimental | ||
generate_ed448_keypair | cryptography_suite.asymmetric.signatures | No | No | No | deprecated | |
generate_kyber_keypair | No | Yes | No | experimental | ||
generate_sphincs_keypair | No | Yes | No | experimental | ||
initialize_signal_session | cryptography_suite.experimental.signal | No | No | No | experimental | |
kyber_decrypt | No | No | No | experimental | ||
kyber_encrypt | No | No | No | experimental | ||
sign_message_ed448 | cryptography_suite.asymmetric.signatures | No | No | No | deprecated | |
sphincs_sign | No | No | No | experimental | ||
sphincs_verify | No | No | No | experimental | ||
verify_signature_ed448 | cryptography_suite.asymmetric.signatures | No | No | No | deprecated | |
x3dh_initiator | cryptography_suite.experimental.signal | No | No | No | experimental | |
x3dh_responder | cryptography_suite.experimental.signal | No | No | No | experimental | |
zksnark | No | Yes | No | experimental |
Version 3.0.0 ushers in a modular design centered on formal verification and pipeline-driven workflows. Major enhancements include:
KeyVault
and
secure_zero
enable best-effort memory wiping, but plain bytes
may
persist until garbage collection.Example pipeline configuration:
from cryptography_suite import use_backend
from cryptography_suite.pipeline import (
Pipeline,
AESGCMEncrypt,
AESGCMDecrypt,
list_modules,
)
with use_backend("pyca"):
p = (
Pipeline()
>> AESGCMEncrypt(password="pass")
>> AESGCMDecrypt(password="pass")
)
assert p.run("data") == "data"
print(list_modules()) # ['AESGCMDecrypt', 'AESGCMEncrypt']
Backend selection is context-local: each thread or async task maintains its
own active backend when using :func:use_backend
as a context manager.
Contributors: new pipeline modules can be exposed with the
@register_module
decorator in cryptography_suite.pipeline
.
Visualize and export the pipeline:
from cryptography_suite.pipeline import PipelineVisualizer
viz = PipelineVisualizer(p)
print(viz.render_ascii()) # AESGCMEncrypt -> AESGCMDecrypt
print(p.to_proverif()) # formal model output
KeyVault
context manager and KeyManager
utilities.Install the latest stable release from PyPI:
pip install cryptography-suite
For optional functionality install extras:
pip install "cryptography-suite[pqc,fhe,zk]"
To include deprecated stream ciphers:
pip install cryptography-suite[legacy]
The SPHINCS+ signature helpers are included in the pqc
extra and are experimental/demo-only.
Note: Requires Python 3.10 or higher. Homomorphic encryption features need
Pyfhel
installed separately if thefhe
extra is not used.
Clone the repository and install manually:
git clone https://github.com/Psychevus/cryptography-suite.git
cd cryptography-suite
pip install .
# Optional extras for development (pytest, mypy, etc.) and PQC
pip install -e ".[dev,pqc]"
pip install cryptography-suite
# Encrypt a file
cryptography-suite file encrypt --in input.txt --out encrypted.bin --password mypass
# Decrypt it back
cryptography-suite file decrypt --in encrypted.bin --out output.txt --password mypass
# Export a pipeline for formal verification
cryptography-suite export examples/formal/pipeline.yaml --format proverif
cryptography-suite keystore migrate --from local --to mock_hsm --dry-run
Omit --key
to stream all keys. Only local
β aws-kms
and local
β mock_hsm
are supported. Migrating between different algorithms is not supported.
Execute the fuzz harness locally:
cryptosuite-fuzz --runs 1000
cryptography
exposes XChaCha20Poly1305
.chacha20_encrypt
/xchacha_encrypt
or AESGCMEncrypt
instead.β οΈ Secrets used for OTP (TOTP/HOTP) will now be auto-padded to prevent base32 decoding issues. No manual padding is required.
Primitive | Backend | Notes |
---|---|---|
AES-GCM | pyca/cryptography | Authoritative |
ChaCha20-Poly1305 / XChaCha20-Poly1305 | pyca/cryptography | Authoritative |
Salsa20 | PyCryptodome (optional) | Deprecated; provided for reference only |
Ascon-128a | Pure Python | Experimental |
RSA, ECDSA, Ed25519, Ed448 | pyca/cryptography | Authoritative |
BLS12-381 | py_ecc | Optional |
SHA-2, SHA-3, BLAKE2b | pyca/cryptography | Authoritative |
BLAKE3 | blake3 | Authoritative |
Argon2id, Scrypt, PBKDF2, HKDF | pyca/cryptography | Authoritative |
Kyber, Dilithium (PQC) | pqcrypto (optional) | Optional |
See docs/backend_consistency.md
for
policies on backend usage.
salsa20_encrypt
or ascon_encrypt
are for research/education only and will be removed in v4.0.0. They are NOT supported for production use. If you depend on them, migrate now.VERBOSE_MODE
leaks sensitive information to stdout; never
enable it in production.serialize_private_key
or
KeyManager.save_private_key
, always provide a password.CRYPTOSUITE_STRICT_KEYS=error
to refuse loading or saving unencrypted private
keys (raising an error). To disable these checks entirely β which is unsafe β set
CRYPTOSUITE_STRICT_KEYS=0
or CRYPTOSUITE_STRICT_KEYS=false
.This module is not a full Signal implementation. It lacks critical security properties and should never be used for production or high-assurance messaging.
Legacy one-shot helpers such as aes_encrypt
and rsa_encrypt
are now
deprecated. New code should build pipelines using modules like
AESGCMEncrypt
and RSAEncrypt
. See docs/migration_pipeline_api.md
for
full details.
from cryptography_suite.pipeline import Pipeline, AESGCMEncrypt, AESGCMDecrypt
p = Pipeline() >> AESGCMEncrypt(password="pw") >> AESGCMDecrypt(password="pw")
assert p.run("secret") == "secret"
For a catalog of built-in modules see docs/pipeline_catalog.md.
Encrypt and decrypt messages using AES-GCM with password-derived keys.
from cryptography_suite.pipeline import AESGCMEncrypt, AESGCMDecrypt
message: str = "Highly Confidential Information"
password: str = "ultra_secure_password"
encrypted_message: str = AESGCMEncrypt(password=password).run(message)
print(f"Encrypted: {encrypted_message}")
decrypted_message: str = AESGCMDecrypt(password=password).run(encrypted_message)
print(f"Decrypted: {decrypted_message}")
scrypt_encrypted: str = AESGCMEncrypt(password=password, kdf="scrypt").run(message)
print(AESGCMDecrypt(password=password, kdf="scrypt").run(scrypt_encrypted))
Argon2id support is provided by the cryptography
package and requires no
additional dependencies.
Stream files of any size with AES-GCM. The functions read and write in chunks, so even large files can be processed efficiently.
from cryptography_suite.symmetric import encrypt_file, decrypt_file
password: str = "file_password"
encrypt_file("secret.txt", "secret.enc", password)
decrypt_file("secret.enc", "secret.out", password)
For asynchronous applications install aiofiles
and use the async variants:
from cryptography_suite.symmetric import encrypt_file_async, decrypt_file_async
import asyncio
password = "file_password"
async def main():
await encrypt_file_async("secret.txt", "secret.enc", password)
await decrypt_file_async("secret.enc", "secret.out", password)
asyncio.run(main())
Generate RSA key pairs and perform encryption/decryption.
Ciphertext and related binary outputs are returned as Base64 strings by
default. Pass raw_output=True
to obtain raw bytes instead.
from cryptography_suite.asymmetric import (
ec_encrypt,
generate_rsa_keypair,
ec_decrypt,
generate_x25519_keypair,
)
from cryptography_suite.pipeline import RSAEncrypt, RSADecrypt
private_key, public_key = generate_rsa_keypair()
message: bytes = b"Secure Data Transfer"
encrypted_message: str = RSAEncrypt(public_key=public_key).run(message)
print(f"Encrypted: {encrypted_message}")
decrypted_message: bytes = RSADecrypt(private_key=private_key).run(encrypted_message)
print(f"Decrypted: {decrypted_message}")
# Non-blocking key generation using a ThreadPoolExecutor. The call returns a
# ``Future`` which resolves to ``(private_key, public_key)``.
from cryptography_suite.asymmetric import generate_rsa_keypair_async
future = generate_rsa_keypair_async(key_size=2048)
private_async, public_async = future.result()
# Serializing keys
from cryptography_suite.utils import to_pem, from_pem, pem_to_json
pem_priv: str = to_pem(private_key)
loaded_priv = from_pem(pem_priv)
json_pub: str = pem_to_json(public_key)
from cryptography_suite.asymmetric import (
generate_x25519_keypair,
derive_x25519_shared_key,
generate_x448_keypair,
derive_x448_shared_key,
)
# X25519 exchange
alice_priv, alice_pub = generate_x25519_keypair()
bob_priv, bob_pub = generate_x25519_keypair()
shared_a: bytes = derive_x25519_shared_key(alice_priv, bob_pub)
shared_b: bytes = derive_x25519_shared_key(bob_priv, alice_pub)
print(shared_a == shared_b)
# X448 exchange
a_priv, a_pub = generate_x448_keypair()
b_priv, b_pub = generate_x448_keypair()
print(
derive_x448_shared_key(a_priv, b_pub)
== derive_x448_shared_key(b_priv, a_pub)
)
Sign and verify messages using Ed25519, Ed448 or BLS.
from cryptography_suite.asymmetric.signatures import (
generate_ed25519_keypair,
generate_ed448_keypair,
sign_message,
sign_message_ed448,
verify_signature,
verify_signature_ed448,
)
# Generate Ed25519 key pair
ed_priv, ed_pub = generate_ed25519_keypair()
signature: str = sign_message(b"Authenticate this message", ed_priv)
print(verify_signature(b"Authenticate this message", signature, ed_pub))
# Ed448 usage
ed448_priv, ed448_pub = generate_ed448_keypair()
sig448: str = sign_message_ed448(b"Authenticate this message", ed448_priv)
print(verify_signature_ed448(b"Authenticate this message", sig448, ed448_pub))
from cryptography_suite.bls import generate_bls_keypair, bls_sign, bls_verify
# Generate BLS key pair
bls_sk, bls_pk = generate_bls_keypair()
bls_sig: bytes = bls_sign(b"Authenticate this message", bls_sk)
print(bls_verify(b"Authenticate this message", bls_sig, bls_pk))
Split and reconstruct secrets using Shamir's Secret Sharing.
from cryptography_suite.protocols import create_shares, reconstruct_secret
secret: int = 1234567890
threshold: int = 3
num_shares: int = 5
# Create shares
shares = create_shares(secret, threshold, num_shares)
# Reconstruct the secret
selected_shares = shares[:threshold]
recovered_secret: int = reconstruct_secret(selected_shares)
print(f"Recovered secret: {recovered_secret}")
Perform arithmetic over encrypted values using Pyfhel. These helpers are experimental.
from cryptography_suite.experimental import (
fhe_keygen,
fhe_encrypt,
fhe_decrypt,
fhe_add,
fhe_multiply,
)
he = fhe_keygen("CKKS")
ct1: bytes = fhe_encrypt(he, 10.5)
ct2: bytes = fhe_encrypt(he, 5.25)
sum_ct: bytes = fhe_add(he, ct1, ct2)
prod_ct: bytes = fhe_multiply(he, ct1, ct2)
print(f"Sum: {fhe_decrypt(he, sum_ct)}")
print(f"Product: {fhe_decrypt(he, prod_ct)}")
Prove knowledge of a SHA-256 preimage without revealing it. These
functions require the optional PySNARK
dependency.
from cryptography_suite.experimental import zksnark
# Zero-knowledge helpers are experimental and require PySNARK.
zksnark.setup()
hash_hex: str
proof_file: str
hash_hex, proof_file = zksnark.prove(b"secret")
print(zksnark.verify(hash_hex, proof_file))
Leverage Kyber and Dilithium for quantum-resistant operations. See
tests/test_pqc.py
for thorough unit tests.
from cryptography_suite.pqc import (
generate_kyber_keypair,
kyber_encrypt,
kyber_decrypt,
generate_dilithium_keypair,
dilithium_sign,
dilithium_verify,
)
ky_pub, ky_priv = generate_kyber_keypair()
ct, ss = kyber_encrypt(ky_pub, b"hello pqc")
assert kyber_decrypt(ky_priv, ct, ss) == b"hello pqc"
dl_pub, dl_priv = generate_dilithium_keypair()
sig = dilithium_sign(dl_priv, b"package")
assert dilithium_verify(dl_pub, b"package", sig)
Combine asymmetric keys with AES-GCM for efficient encryption. See
tests/test_hybrid.py
.
from cryptography_suite.hybrid import HybridEncryptor
from cryptography_suite.asymmetric import generate_rsa_keypair
encryptor = HybridEncryptor()
priv, pub = generate_rsa_keypair()
payload = b"hybrid message"
encrypted = encryptor.encrypt(payload, pub)
decrypted = encryptor.decrypt(priv, encrypted)
from cryptography_suite.utils import encode_encrypted_message, decode_encrypted_message
blob: str = encode_encrypted_message(encrypted)
parsed = decode_encrypted_message(blob)
Additional stream cipher available when cryptography
exposes
XChaCha20Poly1305
. Tested in
tests/test_xchacha.py
.
from cryptography_suite.symmetric import xchacha_encrypt, xchacha_decrypt
key: bytes = os.urandom(32)
nonce: bytes = os.urandom(24)
data = xchacha_encrypt(b"secret", key, nonce)
plain = xchacha_decrypt(data["ciphertext"], key, data["nonce"])
Use KeyVault
to erase keys from memory after use. Unit tests are
located in tests/test_utils.py
.
from cryptography_suite.utils import KeyVault
key_material = b"supersecretkey"
with KeyVault(key_material) as buf:
use_key(buf)
This library provides tools (KeyVault
, secure_zero
) for explicit
zeroization of secrets. However, due to Python's memory model, secrets
stored as plain bytes
may remain in memory until garbage collected.
For highest assurance, always use KeyVault
or the sensitive=True
option on key-generation functions when handling private keys or session
secrets.
from cryptography_suite.protocols import generate_aes_key
with generate_aes_key() as key_bytes:
use_key(key_bytes)
Persist key pairs to disk with the high-level KeyManager
helper.
from cryptography_suite.protocols import KeyManager, generate_random_password
km = KeyManager()
password = generate_random_password()
km.generate_rsa_keypair_and_save("rsa_priv.pem", "rsa_pub.pem", password)
km.generate_ec_keypair_and_save("ec_priv.pem", "ec_pub.pem", password)
from cryptography_suite.protocols import SPAKE2Client, SPAKE2Server
c = SPAKE2Client("pw")
s = SPAKE2Server("pw")
ck: bytes = c.compute_shared_key(s.generate_message())
sk: bytes = s.compute_shared_key(c.generate_message())
print(ck == sk)
Requires the optional spake2
package.
from cryptography_suite.asymmetric import ec_encrypt, ec_decrypt, generate_x25519_keypair
priv, pub = generate_x25519_keypair()
# ``cipher`` is Base64 encoded by default. Use ``raw_output=True`` for bytes.
cipher: str = ec_encrypt(b"secret", pub)
print(ec_decrypt(cipher, priv))
Note: The Signal Protocol helpers are experimental and intended for demonstrations only.
from cryptography_suite.experimental.signal import initialize_signal_session
sender, receiver = initialize_signal_session()
demo_msg: bytes = sender.encrypt(b"demo") # demo-only data
print(receiver.decrypt(demo_msg))
Generate message digests with standard algorithms.
from cryptography_suite.hashing import (
sha256_hash,
sha3_256_hash,
sha3_512_hash,
blake2b_hash,
blake3_hash,
)
data = "The quick brown fox jumps over the lazy dog"
data: str = "The quick brown fox jumps over the lazy dog"
print(sha256_hash(data))
print(sha3_256_hash(data))
print(sha3_512_hash(data))
print(blake2b_hash(data))
print(blake3_hash(data))
Ensure the integrity of the suite by running comprehensive tests:
coverage run -m unittest discover
coverage report -m
Some tests rely on optional dependencies such as petlib
for zero-knowledge proofs.
Install extras before running them:
pip install .[zkp]
Our test suite achieves 99% code coverage, guaranteeing reliability and robustness.
Two console scripts are provided for zero-knowledge proofs:
cryptosuite-bulletproof 42
cryptosuite-zksnark secret
Run each command with -h
for detailed help.
File encryption and decryption are available via the main CLI:
cryptography-suite file encrypt --in secret.txt --out secret.enc --password mypass
cryptography-suite file decrypt --in secret.enc --out decrypted.txt --password mypass
You can inject keys managed by hardware security modules (HSMs) or cloud key
management services (KMS) by providing wrapper classes that mimic the standard
private key interface. These wrappers allow the suite to call decrypt
on the
external key just like a locally generated one.
from cryptography_suite.asymmetric import rsa_decrypt
from my_hsm_wrapper import load_rsa_private_key
private_key = load_rsa_private_key("enterprise-key-id")
plaintext = rsa_decrypt(ciphertext, private_key)
This project provides deterministic builds and signed release artifacts.
Every GitHub release ships with a CycloneDX SBOM, a SLSA provenance
attestation and cosign
signatures.
Verify the wheel's signature:
cosign verify --certificate-identity "https://github.com/Psychevus/cryptography-suite/.github/workflows/release.yml@refs/tags/v3.0.0" <wheel>.sig <wheel>
Validate the checksums:
sha256sum -c checksums.txt
Inspect the SLSA provenance:
jq '.subject | .name' provenance.intoto.jsonl
The SBOM (sbom.json
) can be inspected via cyclonedx-bom
or pip sbom
.
Reproducibility is tested in CI via reproducibility.yml
. See
release process documentation for details on
verifying artifacts and SBOM contents.
cryptography-suite/
βββ cryptography_suite/
β βββ __init__.py
β βββ asymmetric/
β βββ audit.py
β βββ cli.py
β βββ debug.py
β βββ errors.py
β βββ hashing/
β βββ homomorphic.py
β βββ hybrid.py
β βββ pqc/
β βββ protocols/
β β βββ __init__.py
β β βββ key_management.py
β β βββ otp.py
β β βββ pake.py
β β βββ secret_sharing.py
β β βββ signal/
β βββ symmetric/
β βββ utils.py
β βββ x509.py
β βββ zk/
βββ tests/
β βββ test_audit.py
β βββ test_hybrid.py
β βββ test_pqc.py
β βββ test_xchacha.py
β βββ ...
βββ README.md
βββ example_usage.py
βββ demo_homomorphic.py
βββ setup.py
βββ .github/
βββ workflows/
βββ python-app.yml
cryptography_suite.pqc
and cryptography_suite.protocols
.MissingDependencyError
and ProtocolError
extend
CryptographySuiteError
.bytes
when
raw_output=True
.audit_log
and KeyVault
for logging and
secure key handling.kyber_encrypt
and kyber_decrypt
accept a
level
parameter (512/768/1024). kyber_decrypt
now computes the shared
secret automatically when omitted.KeyManager
now provides generate_rsa_keypair_and_save
.
The standalone generate_rsa_keypair_and_save
helper is deprecated and will
be removed in v4.0.0.derive_pbkdf2
is deprecated and will be removed in v4.0.0.
Use kdf_pbkdf2
instead.Version 3.0.0 introduces several breaking changes. To upgrade from 2.x:
use_backend
; the library emits a
runtime warning if no backend is explicitly selected.This project is licensed under the MIT License - see the LICENSE file for details.
We welcome contributions from the community. To contribute:
feature/new-algorithm
).main
branch of the original repository.Please ensure that your contributions adhere to the project's coding standards and include relevant tests.
For support or inquiries:
Special thanks to all contributors and users who have helped improve this project through feedback and collaboration.
Empower your applications with secure and reliable cryptographic functions using Cryptography Suite.
FAQs
A comprehensive and secure cryptographic toolkit.
We found that cryptography-suite demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Β It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Astral unveils pyx, a Python-native package registry in beta, designed to speed installs, enhance security, and integrate deeply with uv.
Security News
The Latio podcast explores how static and runtime reachability help teams prioritize exploitable vulnerabilities and streamline AppSec workflows.
Security News
The latest Opengrep releases add Apex scanning, precision rule tuning, and performance gains for open source static code analysis.