Skip to main content

Python bindings for Asherah envelope encryption

Project description

asherah

Python bindings for the Asherah envelope encryption and automatic key rotation library.

Prebuilt wheels for Python 3.8+ (stable ABI): Linux x64/ARM64 (manylinux + musl), macOS universal2, Windows x64/ARM64.

Installation

pip install asherah

Quick Start (Static API)

The static API manages a global session factory internally. Call setup() once, then encrypt/decrypt with partition-scoped functions.

import os
os.environ["STATIC_MASTER_KEY_HEX"] = "22" * 32  # testing only

import asherah

asherah.setup({
    "ServiceName": "my-service",
    "ProductID": "my-product",
    "Metastore": "memory",    # testing only — use "rdbms" or "dynamodb" in production
    "KMS": "static",          # testing only — use "aws" in production
    "EnableSessionCaching": True,
})

ciphertext = asherah.encrypt_string("partition-1", "sensitive data")
plaintext = asherah.decrypt_string("partition-1", ciphertext)
print(plaintext)  # "sensitive data"

asherah.shutdown()

Session-Based API

The SessionFactory class reads configuration from environment variables (set them before construction). Each Session is scoped to a partition. Both support context managers.

import os
os.environ["SERVICE_NAME"] = "my-service"
os.environ["PRODUCT_ID"] = "my-product"
os.environ["Metastore"] = "memory"  # testing only
os.environ["KMS"] = "static"       # testing only
os.environ["STATIC_MASTER_KEY_HEX"] = "22" * 32
os.environ["SESSION_CACHE"] = "1"

import asherah

with asherah.SessionFactory() as factory:
    with factory.get_session("partition-1") as session:
        ciphertext = session.encrypt_bytes(b"secret")
        plaintext = session.decrypt_bytes(ciphertext)
        print(plaintext)  # b"secret"

        # Text variants
        ct = session.encrypt_text("hello")
        pt = session.decrypt_text(ct)
        print(pt)  # "hello"

Async API

Async wrappers dispatch to the default thread pool executor via asyncio.run_in_executor. The GIL is released during the native call.

import asyncio
import os
os.environ["STATIC_MASTER_KEY_HEX"] = "22" * 32

import asherah

async def main():
    await asherah.setup_async({
        "ServiceName": "my-service",
        "ProductID": "my-product",
        "Metastore": "memory",
        "KMS": "static",
    })

    ciphertext = await asherah.encrypt_string_async("partition-1", "data")
    plaintext = await asherah.decrypt_string_async("partition-1", ciphertext)
    print(plaintext)  # "data"

    await asherah.shutdown_async()

asyncio.run(main())

Async Behavior

  • The event loop is not blocked -- work runs on a thread pool thread.
  • The GIL is released during the native Rust call.
  • Overhead: ~37 us vs ~1 us sync (hot cache, 64B payload).
  • Best for: I/O-bound asyncio applications that need non-blocking encryption.

For CPU-bound batch encryption, use the sync API directly.

Configuration

The setup() function accepts a dict (or any JSON-serializable object) with PascalCase keys matching the Go canonical API:

Key Type Required Description
ServiceName str Yes Service identifier for key hierarchy
ProductID str Yes Product identifier for key hierarchy
Metastore str Yes "rdbms", "dynamodb", "memory" (testing)
KMS str No "static" (default) or "aws"
ConnectionString str Conditional Required for sqlite and rdbms metastores
RegionMap dict Conditional Required for aws KMS. Maps preferred region to ARN.
PreferredRegion str No Preferred AWS region for KMS
EnableRegionSuffix bool No Append region suffix to system key IDs
EnableSessionCaching bool No Enable session caching (default: true)
SessionCacheMaxSize int No Max cached sessions
SessionCacheDuration int No Cache TTL in seconds
ExpireAfter int No Key expiration in seconds
CheckInterval int No Revocation check interval in seconds
DynamoDBEndpoint str No Custom DynamoDB endpoint URL
DynamoDBRegion str No DynamoDB region
DynamoDBSigningRegion str No Signing region (overrides DynamoDBRegion)
DynamoDBTableName str No DynamoDB table name
ReplicaReadConsistency str No DynamoDB read consistency
SQLMetastoreDBType str No "mysql" or "postgres" hint for rdbms
Verbose bool No Enable verbose logging
EnableCanaries bool No Enable canary buffer overflow detection
NullDataCheck bool No Enable null data validation
DisableZeroCopy bool No Disable zero-copy optimization

AWS KMS Example

asherah.setup({
    "ServiceName": "my-service",
    "ProductID": "my-product",
    "Metastore": "dynamodb",
    "KMS": "aws",
    "RegionMap": {
        "us-west-2": "arn:aws:kms:us-west-2:123456789012:key/mrk-abc123"
    },
    "PreferredRegion": "us-west-2",
    "DynamoDBTableName": "EncryptionKey",
    "EnableSessionCaching": True,
})

Performance

Approximate latency on Apple M4 Max (hot cache, 64-byte payload):

Operation Latency
Encrypt ~1,049 ns
Decrypt ~791 ns

This Rust-backed implementation replaces the Go Cobhan-based canonical asherah PyPI package. Run scripts/benchmark.sh for head-to-head comparisons.

API Reference

Static Functions

Function Description
setup(config) Initialize the global session factory from a config dict
shutdown() Shut down the global session factory and release resources
get_setup_status() Returns True if setup() has been called
encrypt_bytes(partition_id, data) Encrypt bytes, returns JSON str (DataRowRecord)
encrypt_string(partition_id, text) Encrypt str, returns JSON str (DataRowRecord)
decrypt_bytes(partition_id, drr) Decrypt JSON DataRowRecord, returns bytes
decrypt_string(partition_id, drr) Decrypt JSON DataRowRecord, returns str
setenv(env_dict) Set environment variables from a dict (both os.environ and Rust)
set_metrics_hook(callback) Register a callback for metrics events, or None to clear
set_log_hook(callback) Register a callback for log events, or None to clear
version() Returns the native library version string

Async Functions

Function Description
setup_async(config) Async version of setup()
shutdown_async() Async version of shutdown()
encrypt_bytes_async(partition_id, data) Async version of encrypt_bytes()
encrypt_string_async(partition_id, text) Async version of encrypt_string()
decrypt_bytes_async(partition_id, drr) Async version of decrypt_bytes()
decrypt_string_async(partition_id, drr) Async version of decrypt_string()

Classes

SessionFactory

Constructed from environment variables (not a config dict). Supports context manager protocol.

Method Description
SessionFactory() Create from env vars
SessionFactory.from_env() Same as constructor
get_session(partition_id) Create a Session for the given partition
close() Release resources

Session

Scoped to a single partition. Supports context manager protocol.

Method Description
encrypt_bytes(data) Encrypt bytes, returns JSON str
encrypt_text(text) Encrypt str, returns JSON str
decrypt_bytes(drr) Decrypt JSON DataRowRecord, returns bytes
decrypt_text(drr) Decrypt JSON DataRowRecord, returns str
close() Release resources

Hooks

Metrics Hook

def on_metric(event):
    # event is a dict with "type" and additional fields
    # type: "encrypt", "decrypt", "store", "load" -> has "duration_ns"
    # type: "cache_hit", "cache_miss" -> has "name"
    print(event)

asherah.set_metrics_hook(on_metric)
asherah.set_metrics_hook(None)  # clear

Log Hook

def on_log(record):
    # record is a dict with "level", "message", "target"
    print(f"[{record['level']}] {record['target']}: {record['message']}")

asherah.set_log_hook(on_log)
asherah.set_log_hook(None)  # clear

Cross-Language Compatibility

Ciphertext produced by any Asherah implementation (Go, Node.js, Java, .NET, Ruby) can be decrypted by any other, as long as they share the same metastore and KMS configuration. The DataRowRecord JSON format is the interchange format.

License

Licensed under the Apache License, Version 2.0.

Project details


Release history Release notifications | RSS feed

Download files

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

Source Distribution

asherah-0.5.27.tar.gz (185.4 kB view details)

Uploaded Source

Built Distributions

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

asherah-0.5.27-cp38-abi3-win_arm64.whl (7.9 MB view details)

Uploaded CPython 3.8+Windows ARM64

asherah-0.5.27-cp38-abi3-win_amd64.whl (8.2 MB view details)

Uploaded CPython 3.8+Windows x86-64

asherah-0.5.27-cp38-abi3-musllinux_1_2_x86_64.whl (13.1 MB view details)

Uploaded CPython 3.8+musllinux: musl 1.2+ x86-64

asherah-0.5.27-cp38-abi3-musllinux_1_2_aarch64.whl (13.3 MB view details)

Uploaded CPython 3.8+musllinux: musl 1.2+ ARM64

asherah-0.5.27-cp38-abi3-manylinux_2_28_x86_64.whl (12.2 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.28+ x86-64

asherah-0.5.27-cp38-abi3-manylinux_2_28_aarch64.whl (12.8 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.28+ ARM64

asherah-0.5.27-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (19.0 MB view details)

Uploaded CPython 3.8+macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

File details

Details for the file asherah-0.5.27.tar.gz.

File metadata

  • Download URL: asherah-0.5.27.tar.gz
  • Upload date:
  • Size: 185.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for asherah-0.5.27.tar.gz
Algorithm Hash digest
SHA256 03e8847d0faca2ce3d2f45aadf448e031558b130f6b9bca2b195429eced0d2ca
MD5 3d68220922164f168bfaa2d5358730dc
BLAKE2b-256 52c5f21fbebd7759d09451c3e290b6120399ec1c32bd13e9af71fcc464fda87f

See more details on using hashes here.

File details

Details for the file asherah-0.5.27-cp38-abi3-win_arm64.whl.

File metadata

  • Download URL: asherah-0.5.27-cp38-abi3-win_arm64.whl
  • Upload date:
  • Size: 7.9 MB
  • Tags: CPython 3.8+, Windows ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for asherah-0.5.27-cp38-abi3-win_arm64.whl
Algorithm Hash digest
SHA256 10bd478d25fdc34944b46ea63c00a66badde3cee667dac3cba2b1ad1a0c6b6c8
MD5 0652f2be9200fb0e6e31f30f8c66ff4a
BLAKE2b-256 fcf05cd03bda29e4293231c302087e584430ce6412bce7dd288e9275a8156645

See more details on using hashes here.

File details

Details for the file asherah-0.5.27-cp38-abi3-win_amd64.whl.

File metadata

  • Download URL: asherah-0.5.27-cp38-abi3-win_amd64.whl
  • Upload date:
  • Size: 8.2 MB
  • Tags: CPython 3.8+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for asherah-0.5.27-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 566fe45fb0ca3e71145553e06d7f4365c6a1bfc1243cb7411bb79f004096bd0a
MD5 6bea5f125129ba9af68e1ad9fef17c33
BLAKE2b-256 7095f54a11978e7253302818432602cda4e2cde9eee9fa8d2a376f57cf5e55ef

See more details on using hashes here.

File details

Details for the file asherah-0.5.27-cp38-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for asherah-0.5.27-cp38-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 e32548c80d9fbdb53729851d3c2eb4adb548831cdbdc16bff9a53ab72875b57d
MD5 bc92424a7c44dac3c37b5ff2a1cdd3cc
BLAKE2b-256 a2e2c6a51720e7334c8d1f76659f1cc960bc63e91b0f228cf1e5a593be087045

See more details on using hashes here.

File details

Details for the file asherah-0.5.27-cp38-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for asherah-0.5.27-cp38-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 04ff9174678a7bca73ad2da0329493dc73600ab62a8fd3f65b6524c57e8c1d0f
MD5 82d4e98c0b5a7f4dafb6ef8c9eb3e428
BLAKE2b-256 8127808acbc6af040dc506e3c8c9f91e4e4321716b03a6f7ea1cd5348b1ecc5f

See more details on using hashes here.

File details

Details for the file asherah-0.5.27-cp38-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for asherah-0.5.27-cp38-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 0055283cf0eabe509492e8f2ff64a515c33dd019de70c4e74e6211a79ec23a4d
MD5 b05e414c84b1dff1427bc84361c91c20
BLAKE2b-256 fa64baf64431d577baf1e8927783a91872fb6dc869b5c06e4df79c04bdab03f2

See more details on using hashes here.

File details

Details for the file asherah-0.5.27-cp38-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for asherah-0.5.27-cp38-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 890c3ecd925d59cce908354067129fd76aa5968063a390bfa55b38439c886557
MD5 dd2b73a33c1fa07c783d2d0f2f520520
BLAKE2b-256 effdfd8b118562c8d79f7cdcb2ff393f661a6b28b37ffa6aaac2bfa5ce57cbe2

See more details on using hashes here.

File details

Details for the file asherah-0.5.27-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for asherah-0.5.27-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 7c9d486bb18c519f9b30dc457868fad9cee54f83123e61b0b074c1169280c7d0
MD5 ca1f5feeecc727202f3262270e58a529
BLAKE2b-256 adce8b16956c08188da17f9caaf0c441c262de7e29c53d043f84043bdaf9abfc

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