Skip to main content

An abstraction layer for the cryptography used by Devolutions

Project description

devolutions-crypto

PyPI version Python versions

Cryptographic library used in Devolutions products. It is made to be fast, easy to use and misuse-resistant.

This is the official Python wrapper for the devolutions-crypto Rust library, providing high-performance cryptographic operations with a simple, Pythonic API.

Installation

pip install devolutions-crypto

Features

  • Symmetric Encryption: Fast AES-256-GCM encryption for shared-key scenarios
  • Asymmetric Encryption: X25519-based public-key encryption
  • Password Hashing: Secure password hashing with Argon2 and PBKDF2
  • Digital Signatures: Ed25519 signatures for data authentication
  • Key Derivation: Argon2 and PBKDF2 key derivation functions
  • Type Safety: Full type hints and IDE support

Quick Start

import devolutions_crypto
import os

# Generate a random encryption key
key = os.urandom(32)

# Encrypt some data
plaintext = b"Hello, World!"
ciphertext = devolutions_crypto.encrypt(plaintext, key)

# Decrypt it back
decrypted = devolutions_crypto.decrypt(ciphertext, key)
assert decrypted == plaintext

Usage Examples

Table of Contents

Symmetric Encryption

Use symmetric encryption when both parties share the same secret key.

import devolutions_crypto
import os

# Generate a 32-byte encryption key
key = os.urandom(32)

# Encrypt data
plaintext = b"This is secret data"
ciphertext = devolutions_crypto.encrypt(plaintext, key)

# Decrypt data
decrypted = devolutions_crypto.decrypt(ciphertext, key)
assert decrypted == plaintext

With Additional Authenticated Data (AAD)

AAD allows you to bind additional context to the ciphertext without encrypting it:

import devolutions_crypto
import os

key = os.urandom(32)
plaintext = b"Secret message"
aad = b"user_id:12345"  # Context data (not encrypted, but authenticated)

# Encrypt with AAD
ciphertext = devolutions_crypto.encrypt_with_aad(plaintext, key, aad)

# Decrypt with AAD (must match encryption AAD)
decrypted = devolutions_crypto.decrypt_with_aad(ciphertext, key, aad)
assert decrypted == plaintext

# Decryption fails with wrong or missing AAD
try:
    devolutions_crypto.decrypt_with_aad(ciphertext, key, b"wrong_context")
except devolutions_crypto.DevolutionsCryptoError:
    print("Authentication failed - AAD mismatch")

Asymmetric Encryption

Use asymmetric encryption when you want to encrypt data for a recipient using their public key.

import devolutions_crypto

# Generate a keypair
keypair = devolutions_crypto.generate_keypair()

# Encrypt data with the public key
plaintext = b"Secret message for Bob"
ciphertext = devolutions_crypto.encrypt_asymmetric(plaintext, keypair.public_key)

# Decrypt with the private key
decrypted = devolutions_crypto.decrypt_asymmetric(ciphertext, keypair.private_key)
assert decrypted == plaintext

Key Exchange Example

Alice and Bob can establish a shared secret without transmitting it:

import devolutions_crypto

# Alice generates her keypair
alice_keypair = devolutions_crypto.generate_keypair()

# Bob generates his keypair
bob_keypair = devolutions_crypto.generate_keypair()

# They exchange public keys (public keys can be transmitted over insecure channels)

# Alice encrypts a message for Bob using his public key
message = b"Hello Bob!"
ciphertext = devolutions_crypto.encrypt_asymmetric(message, bob_keypair.public_key)

# Bob decrypts the message using his private key
decrypted = devolutions_crypto.decrypt_asymmetric(ciphertext, bob_keypair.private_key)
assert decrypted == message

Password Hashing

Securely hash and verify passwords. The default uses Argon2id:

import devolutions_crypto

# Hash a password (this is slow by design)
password = b"my_secure_password123!"
password_hash = devolutions_crypto.hash_password(password)

# Verify the password
is_valid = devolutions_crypto.verify_password(password, password_hash)
assert is_valid is True

# Wrong password fails verification
is_valid = devolutions_crypto.verify_password(b"wrong_password", password_hash)
assert is_valid is False

Digital Signatures

Sign data to prove authenticity and verify signatures:

Generating a Signing Keypair

import devolutions_crypto

# Generate a signing keypair
signing_keypair = devolutions_crypto.generate_signing_keypair()

# Extract the public key
public_key = signing_keypair.get_public_key()

Signing Data

import devolutions_crypto

# Sign some data
data = b"This is an important message"
signature = devolutions_crypto.sign(data, signing_keypair.get_private_key())

Verifying Signatures

import devolutions_crypto

# Verify the signature with the public key
is_valid = devolutions_crypto.verify_signature(data, public_key, signature)
assert is_valid is True

# Verification fails for modified data
modified_data = b"This is a tampered message"
is_valid = devolutions_crypto.verify_signature(modified_data, public_key, signature)
assert is_valid is False

Key Derivation

Derive cryptographic keys from passwords or other key material.

PBKDF2

import devolutions_crypto
import os

# Derive a key from a password
password = b"user_password"
salt = os.urandom(16)  # Use a unique random salt per user

derived_key = devolutions_crypto.derive_key_pbkdf2(
    password,
    salt=salt,
    iterations=600000,
    length=32
)

# Use the derived key for encryption
plaintext = b"User data"
ciphertext = devolutions_crypto.encrypt(plaintext, derived_key)

Argon2

import devolutions_crypto

# Derive a key using Argon2id
password = b"user_password"
parameters = devolutions_crypto.Argon2ParametersBuilder().build()  # default Argon2id parameters
derived_key = devolutions_crypto.derive_key_argon2(password, parameters)

Password-Based Encryption

Encrypt data directly with a password. The key is derived with Argon2id and the derivation parameters (including the random salt) are stored in the returned blob, so decryption only needs the password.

import devolutions_crypto

password = b"my_secure_password"
plaintext = b"secret data"

# Encrypt with a password
blob = devolutions_crypto.derive_encrypt_with_password(plaintext, password)

# Decrypt with the same password
decrypted = devolutions_crypto.derive_decrypt_with_password(blob, password)
assert decrypted == plaintext

With Additional Authenticated Data (AAD)

import devolutions_crypto

password = b"my_secure_password"
plaintext = b"secret data"
aad = b"context"

blob = devolutions_crypto.derive_encrypt_with_password_and_aad(plaintext, password, aad)
decrypted = devolutions_crypto.derive_decrypt_with_password_and_aad(blob, password, aad)
assert decrypted == plaintext

# Decryption fails with wrong or missing AAD
try:
    devolutions_crypto.derive_decrypt_with_password(blob, password)
except devolutions_crypto.DevolutionsCryptoError:
    print("Authentication failed - AAD required")

Supported Python Versions

  • Python 3.10+
  • Python 3.11
  • Python 3.12
  • Python 3.13
  • Python 3.14

Supported Platforms

Pre-built wheels are available for:

  • Linux: x86_64, i686, aarch64
  • macOS: x86_64 (Intel), aarch64 (Apple Silicon)
  • Windows: x86, x64, ARM64

Security Notes

  1. Key Management: Always use cryptographically secure random number generators (like os.urandom()) for key generation
  2. Salt Uniqueness: Use unique salts for each password/user when deriving keys
  3. Iterations: Use high iteration counts (100,000+) for password hashing and key derivation
  4. Key Size: Use 32-byte (256-bit) keys for symmetric encryption
  5. AAD: Additional Authenticated Data must match exactly between encryption and decryption

Exception Handling

All functions may raise DevolutionsCryptoError on errors:

import devolutions_crypto

try:
    # Invalid key size
    result = devolutions_crypto.encrypt(b"data", b"short_key")
except devolutions_crypto.DevolutionsCryptoError as e:
    print(f"Encryption error: {e}")

Underlying Algorithms

As of the current version:

  • Symmetric encryption: AES-256-GCM
  • Asymmetric encryption: X25519 (ECDH) + AES-256-GCM (ECIES)
  • Password hashing: PBKDF2-HMAC-SHA256
  • Digital signatures: Ed25519
  • Key derivation: PBKDF2-HMAC-SHA256, Argon2

Performance

This library is built on Rust and compiled to native code, providing excellent performance:

  • Symmetric encryption/decryption: Millions of operations per second
  • Asymmetric operations: Thousands of operations per second
  • Password hashing: Intentionally slow (configurable via iterations)

Contributing

This project is open source. Visit the GitHub repository to report issues or contribute.

License

This project is licensed under MIT OR Apache-2.0.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

devolutions_crypto-2026.6.16-py3-none-win_arm64.whl (403.2 kB view details)

Uploaded Python 3Windows ARM64

devolutions_crypto-2026.6.16-py3-none-win_amd64.whl (457.7 kB view details)

Uploaded Python 3Windows x86-64

devolutions_crypto-2026.6.16-py3-none-win32.whl (431.5 kB view details)

Uploaded Python 3Windows x86

devolutions_crypto-2026.6.16-py3-none-manylinux_2_34_x86_64.whl (529.4 kB view details)

Uploaded Python 3manylinux: glibc 2.34+ x86-64

devolutions_crypto-2026.6.16-py3-none-manylinux_2_34_i686.whl (591.9 kB view details)

Uploaded Python 3manylinux: glibc 2.34+ i686

devolutions_crypto-2026.6.16-py3-none-manylinux_2_34_aarch64.whl (508.0 kB view details)

Uploaded Python 3manylinux: glibc 2.34+ ARM64

devolutions_crypto-2026.6.16-py3-none-macosx_11_0_arm64.whl (442.8 kB view details)

Uploaded Python 3macOS 11.0+ ARM64

devolutions_crypto-2026.6.16-py3-none-macosx_10_12_x86_64.whl (502.2 kB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file devolutions_crypto-2026.6.16-py3-none-win_arm64.whl.

File metadata

File hashes

Hashes for devolutions_crypto-2026.6.16-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 914f5a21b15ab39b0ab14f307c34e0bd0613c431f96e98694fc366e22c50cc19
MD5 4bbdbfd346c4fbcee78bddf3f21e7e58
BLAKE2b-256 033632249142a64ac12caf71e25a2ef7d60ad09688d91a5abf0ad6ef51119394

See more details on using hashes here.

Provenance

The following attestation bundles were made for devolutions_crypto-2026.6.16-py3-none-win_arm64.whl:

Publisher: release-others.yml on Devolutions/devolutions-crypto

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file devolutions_crypto-2026.6.16-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for devolutions_crypto-2026.6.16-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 ab21ba08c4bfd4b6b6622accbb867cbb2b9ed380d8a1b5edb40076aec13ab0e6
MD5 306b4aca293ee774d2088e5ba9ea4aa6
BLAKE2b-256 dadb8f8141ec4c72410c0282e8e128ea24772ddb6ffb755b0c05199c54aba903

See more details on using hashes here.

Provenance

The following attestation bundles were made for devolutions_crypto-2026.6.16-py3-none-win_amd64.whl:

Publisher: release-others.yml on Devolutions/devolutions-crypto

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file devolutions_crypto-2026.6.16-py3-none-win32.whl.

File metadata

File hashes

Hashes for devolutions_crypto-2026.6.16-py3-none-win32.whl
Algorithm Hash digest
SHA256 8232bc2f2ea6a245c553ef181da41a269df0996298ea7391da1c3bb71327629e
MD5 3d695f0e2082a436b921d3329924b2a3
BLAKE2b-256 704bd541f676726759ccf6251430cb35276dc2fc2c1bae528e3d41961f3b7d7c

See more details on using hashes here.

Provenance

The following attestation bundles were made for devolutions_crypto-2026.6.16-py3-none-win32.whl:

Publisher: release-others.yml on Devolutions/devolutions-crypto

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file devolutions_crypto-2026.6.16-py3-none-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for devolutions_crypto-2026.6.16-py3-none-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 4494840956b44519fe01b16a144a0638e62a0e64272af79082699687ce2e19aa
MD5 d04ce251dc6a5fa49bd5b7aff19c75b9
BLAKE2b-256 bb1c717d72daeb757658d1f3187f07a15c68abb38c6d3e19d4b77a93ec317edc

See more details on using hashes here.

Provenance

The following attestation bundles were made for devolutions_crypto-2026.6.16-py3-none-manylinux_2_34_x86_64.whl:

Publisher: release-others.yml on Devolutions/devolutions-crypto

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file devolutions_crypto-2026.6.16-py3-none-manylinux_2_34_i686.whl.

File metadata

File hashes

Hashes for devolutions_crypto-2026.6.16-py3-none-manylinux_2_34_i686.whl
Algorithm Hash digest
SHA256 c9510b0cc129a488144b61ffc7fcf7f9bd7ad3ca150f987f0fcbd4a609e13307
MD5 3769524a1d03e4ee67969c4c7981e281
BLAKE2b-256 0b044f61b5575d76c9bc2a38e40ab23a159a26f82250f1af2eec92fce248d6fe

See more details on using hashes here.

Provenance

The following attestation bundles were made for devolutions_crypto-2026.6.16-py3-none-manylinux_2_34_i686.whl:

Publisher: release-others.yml on Devolutions/devolutions-crypto

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file devolutions_crypto-2026.6.16-py3-none-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for devolutions_crypto-2026.6.16-py3-none-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 c8b3a72831e6fc63cacd50511c99457c36a9cfeb90c21e625009c328a34068ee
MD5 cfd01c40a108864b62f59da8907d04d1
BLAKE2b-256 25b29451c3f662c5de79b408740ba93f7218f033872b5e0a39137c0757fb10d2

See more details on using hashes here.

Provenance

The following attestation bundles were made for devolutions_crypto-2026.6.16-py3-none-manylinux_2_34_aarch64.whl:

Publisher: release-others.yml on Devolutions/devolutions-crypto

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file devolutions_crypto-2026.6.16-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for devolutions_crypto-2026.6.16-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 071369c1f86c1bfd178292915e969bdbdd5bf6d72d794d763a206a44233b8427
MD5 0f254e52df758d75f29788d7d5c4dd95
BLAKE2b-256 3fd2be1a292fef756e3ebf62fc5856348b750c03c8d56ea35331af7520671446

See more details on using hashes here.

Provenance

The following attestation bundles were made for devolutions_crypto-2026.6.16-py3-none-macosx_11_0_arm64.whl:

Publisher: release-others.yml on Devolutions/devolutions-crypto

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file devolutions_crypto-2026.6.16-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for devolutions_crypto-2026.6.16-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 2f4b6c1ff24ba8718b7e099f04bb4df27534acaa0a82c0824dec0b62bb354ac9
MD5 c86f88c6c5cd72a3869743fdd0540584
BLAKE2b-256 b4d98aa75470caf3fff07cda653119057bbaf03acea697ae005d363309031a57

See more details on using hashes here.

Provenance

The following attestation bundles were made for devolutions_crypto-2026.6.16-py3-none-macosx_10_12_x86_64.whl:

Publisher: release-others.yml on Devolutions/devolutions-crypto

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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