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.22-py3-none-win_arm64.whl (403.4 kB view details)

Uploaded Python 3Windows ARM64

devolutions_crypto-2026.6.22-py3-none-win_amd64.whl (456.9 kB view details)

Uploaded Python 3Windows x86-64

devolutions_crypto-2026.6.22-py3-none-win32.whl (430.8 kB view details)

Uploaded Python 3Windows x86

devolutions_crypto-2026.6.22-py3-none-manylinux_2_34_x86_64.whl (528.3 kB view details)

Uploaded Python 3manylinux: glibc 2.34+ x86-64

devolutions_crypto-2026.6.22-py3-none-manylinux_2_34_i686.whl (593.0 kB view details)

Uploaded Python 3manylinux: glibc 2.34+ i686

devolutions_crypto-2026.6.22-py3-none-manylinux_2_34_aarch64.whl (507.8 kB view details)

Uploaded Python 3manylinux: glibc 2.34+ ARM64

devolutions_crypto-2026.6.22-py3-none-macosx_11_0_arm64.whl (443.3 kB view details)

Uploaded Python 3macOS 11.0+ ARM64

devolutions_crypto-2026.6.22-py3-none-macosx_10_12_x86_64.whl (502.9 kB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

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

File metadata

File hashes

Hashes for devolutions_crypto-2026.6.22-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 652b1714a0a39d601f6171d257879247d87305d5ad99a2699fb0abade70889ad
MD5 4a6babc86f35cd34a8f2792c287f3675
BLAKE2b-256 866ea8394ad9a897dc28ae7bcbd9c74726f7784db467627aae50c5dc337500af

See more details on using hashes here.

Provenance

The following attestation bundles were made for devolutions_crypto-2026.6.22-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.22-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for devolutions_crypto-2026.6.22-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 c0a600438ad933cb385571bb8f20084629d3b2b3471854dd0bacdf58382a1f23
MD5 060dcf7e816a488eebb526764013ff66
BLAKE2b-256 fc976a1222565931765a97844aadaf0f9f1e7ec53fc4a9a0319cf035e7d1e69b

See more details on using hashes here.

Provenance

The following attestation bundles were made for devolutions_crypto-2026.6.22-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.22-py3-none-win32.whl.

File metadata

File hashes

Hashes for devolutions_crypto-2026.6.22-py3-none-win32.whl
Algorithm Hash digest
SHA256 b5e8d0b49c2ed43a3dddc6cc9fbd19d0d3ddf977ebd285dd04f093ac0abf9548
MD5 516196edf09e612fa14f2f752a3388b4
BLAKE2b-256 40ce22f253808de5d8551fa474c9dd8939d25fd4f4ecf225fcd2aa2410ae62c8

See more details on using hashes here.

Provenance

The following attestation bundles were made for devolutions_crypto-2026.6.22-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.22-py3-none-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for devolutions_crypto-2026.6.22-py3-none-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 4f1d428a41c72b4afde8b16a65b6bf25c32508feb5a42cf9e82ee50c058647a7
MD5 ea60c63d2491b170096a370879b4d85f
BLAKE2b-256 349decfb174afdcf5dfa507ebaa18c2004fb73a4ed2b8e7db21253cbe9790263

See more details on using hashes here.

Provenance

The following attestation bundles were made for devolutions_crypto-2026.6.22-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.22-py3-none-manylinux_2_34_i686.whl.

File metadata

File hashes

Hashes for devolutions_crypto-2026.6.22-py3-none-manylinux_2_34_i686.whl
Algorithm Hash digest
SHA256 ef35d8834f2692cfc9c9975109cbe8a4d00f9a91f5310f9c926a0753c183b002
MD5 54db4e5e276445cd7dec2431db751a30
BLAKE2b-256 f2882b714695d5dbdc8f1c6e7f975441fe89aca906e203d785b5587c1b02533e

See more details on using hashes here.

Provenance

The following attestation bundles were made for devolutions_crypto-2026.6.22-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.22-py3-none-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for devolutions_crypto-2026.6.22-py3-none-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 6981f2147fd009a3f6f6159fed8b96902ddab3640d76cf60adc58c5952176e8e
MD5 b20f0d6835c7743fe092065cbf543e92
BLAKE2b-256 6fc959776fa3a7d267b20c390776f51a8a565a51a8fbdc61c7acdd23cd4fad94

See more details on using hashes here.

Provenance

The following attestation bundles were made for devolutions_crypto-2026.6.22-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.22-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for devolutions_crypto-2026.6.22-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b58ed403376441050ea4a527f282bb5ec3ca2fc3682509f66c6440c68cabd6ad
MD5 fb002498ab8807636505f44936192d6a
BLAKE2b-256 becfe90408e0b039c5ecf246e69e8e8d253b551253033a24b8750e725111150f

See more details on using hashes here.

Provenance

The following attestation bundles were made for devolutions_crypto-2026.6.22-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.22-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for devolutions_crypto-2026.6.22-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 9b0692a0a55299a9384894919cb5c50392b4cf01167b9c6f7a0e68d25c3cfdba
MD5 eeb6dea796873500821c2e60fd83d56d
BLAKE2b-256 3ff8997d5ffa5a749c27e1468674901a94b4f500f4d82e5d44153a8a0b6efca4

See more details on using hashes here.

Provenance

The following attestation bundles were made for devolutions_crypto-2026.6.22-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