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.28.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.28-cp38-abi3-win_arm64.whl (7.9 MB view details)

Uploaded CPython 3.8+Windows ARM64

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

Uploaded CPython 3.8+Windows x86-64

asherah-0.5.28-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.28-cp38-abi3-musllinux_1_2_aarch64.whl (13.3 MB view details)

Uploaded CPython 3.8+musllinux: musl 1.2+ ARM64

asherah-0.5.28-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.28-cp38-abi3-manylinux_2_28_aarch64.whl (12.8 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.28+ ARM64

asherah-0.5.28-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.28.tar.gz.

File metadata

  • Download URL: asherah-0.5.28.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.28.tar.gz
Algorithm Hash digest
SHA256 bb40c52cf26bb0b36333d12a98b19dea06fee49c7cf2ff63623c2f5151d23234
MD5 e23303183799d03a8823d461a93e1268
BLAKE2b-256 0cfea8f534d5d316862d771d19ccc0c7b08db587b7c702ffcf012c53026e3884

See more details on using hashes here.

File details

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

File metadata

  • Download URL: asherah-0.5.28-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.28-cp38-abi3-win_arm64.whl
Algorithm Hash digest
SHA256 f72069b8b7f958a90ec1b3a1c14a88df7992bef1bea946ac68ba3054e8f4e109
MD5 6c4a1e2e7427da2aba8c0df9597b0b68
BLAKE2b-256 64a05d430a2d6e9e9ab8b512233f981ac7a7104583b07ec4c0be75d050a67085

See more details on using hashes here.

File details

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

File metadata

  • Download URL: asherah-0.5.28-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.28-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 7c5df9f5fba9c5028a31ec78eb463a0df1ad18c508a969d0ad77c31f5d45aae5
MD5 f17b8189cbf0ad2ec294a7e8eef78000
BLAKE2b-256 33e9a2784126dcab0d7a5063c943ddd0b0886588c7b866c726fe132f59318920

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for asherah-0.5.28-cp38-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 18eaf60e5e25b34f67f70fb545cae86c409adb9a570af785dbb993f3a3147c84
MD5 c7918ffefd53a14e9cfaa4060544e6b3
BLAKE2b-256 3013f045b55c4bddf6f5db3b6153df6dec409b4eb5489d03864654feebe8e325

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for asherah-0.5.28-cp38-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 5541861e413f2bce2a91716908bcda6e8af1a6795511f28c22f60a073f13b2df
MD5 ad2843766516317ee3d4e2d127d15f6b
BLAKE2b-256 65c2a25351f4377c0317564016342d046dfca02e53a5160992e37e31b52d598e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for asherah-0.5.28-cp38-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 dcb2a0895b9091f81c74b06fbfbcd5d54c004d0a2793f9cca19d5126936563af
MD5 f3cd64cc36f8edc55764ca4ea543b80d
BLAKE2b-256 2196e344601e370528cbb3da801ef0e8c715f46357ef620200703c01b6df071a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for asherah-0.5.28-cp38-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 c579709c0b6227bfa70f6e9310b5c0f2d9a9f833c4318ce119efb879929f2305
MD5 714c5e9c9885ab9321905e62506ec658
BLAKE2b-256 a56c1a819942eac91ee0e91fef1f41629e30eeb754c2fc051c6ed00fb38d0f67

See more details on using hashes here.

File details

Details for the file asherah-0.5.28-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.28-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 2e75387415ebe29bcabadffcf4a6dd811c6b866b82dd9c77cb54c7fd6c940304
MD5 c46a57748ddc69b27ed620653fb86eec
BLAKE2b-256 b5ea89c3e0c4847aac4428869342a40396aa9bf77d2a7e1e8942fe9c0f0b6d33

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