Loading repository data…
Loading repository data…
godaddy / repository
Application-layer envelope encryption with automatic key rotation. Rust core with bindings for Node.js, Python, .NET, Java, Ruby, and Go.
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
Application-layer encryption with automatic key rotation. Rust implementation with bindings for Node.js, Python, .NET, Java, Ruby, and Go.
Asherah implements envelope encryption: data is encrypted with a random data key, which is itself encrypted with an intermediate key, which is encrypted by a master key held in a KMS. Keys rotate automatically based on configurable intervals, and old keys remain accessible for decryption while new data is always encrypted with fresh keys.
This design means application code never handles raw master keys, key rotation happens transparently, and compromise of a single data key exposes only one record.
KMS backends: AWS KMS (recommended), HashiCorp Vault Transit (on-prem), AWS Secrets Manager (migration only), static (testing only)
Metastores: DynamoDB, MySQL, Postgres, SQLite, in-memory (testing only)
| Language | Package | Docs |
|---|---|---|
| Node.js | asherah on npm | README |
| Python | asherah on PyPI | README |
| .NET | GoDaddy.Asherah.Encryption on NuGet | README |
| Java | com.godaddy.asherah.encryption:appencryption on Maven Central | README |
| Ruby | asherah on GitHub Packages | README |
| Go | github.com/godaddy/asherah-ffi/asherah-go | README |
| PHP | godaddy/asherah on Composer | README |
| Platform | Architecture | Status |
|---|---|---|
| Linux | x86_64 (glibc) | Supported |
| Linux | x86_64 (musl) | Supported |
| Linux | ARM64 (glibc) | Supported |
| Linux | ARM64 (musl) | Supported |
| macOS | x86_64 | Supported |
| macOS | ARM64 (Apple Silicon) | Supported |
| Windows | x64 | Supported |
| Windows | ARM64 | Supported |
const asherah = require('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
});
const ct = asherah.encryptString('partition', 'secret data');
const pt = asherah.decryptString('partition', ct);
asherah.shutdown();
See each binding's README for complete examples including async APIs, session-based usage, and production configuration.
There are two argument categories with different rules:
null, nil,
undefined, and the empty string "" are always programming errors.
Bindings reject them at the API boundary with the language-native
exception type — no row is ever written to the metastore under a
degenerate ID. (Stricter than canonical asherah-csharp / asherah-java,
which silently accept null and persist _IK__service_product rows.)null/nil/undefined is rejected
as a programming error. Empty String and empty byte array are
valid plaintexts that produce a real DataRowRecord envelope and
round-trip back to empty on decrypt. Do not short-circuit empty
plaintext encryption in caller code — empty data is real data,
encrypting it is a real cryptographic operation, and skipping it leaks
the fact that the value was empty as a side channel.null/nil/undefined and empty
string/bytes are all rejected — empty input cannot be a valid
DataRowRecord JSON envelope.See docs/input-contract.md for the full per-binding behavior matrix, exception types, and rationale.
The Rust core delivers sub-microsecond encrypt/decrypt. All language bindings stay under 2μs for sync operations. The table includes both sync and async variants, plus head-to-head comparison with the canonical Go/C#/Java implementations:
Benchmark results — hot cache, Apple M4 Max
See each binding's README for detailed async behavior and per-metastore performance characteristics.
Asherah uses a four-level key hierarchy with envelope encryption:
+------------------------------------------------------+
| KMS Backend |
| (AWS KMS / HashiCorp Vault Transit API) |
| |
| Master Key -- never exposed, encrypt/decrypt via API |
+------------------+-----------------------------------+
| encrypts
+------------------v-----------------------------------+
| System Key (SK) |
| Stored in metastore, cached in memory, auto-rotated |
+------------------+-----------------------------------+
| encrypts
+------------------v-----------------------------------+
| Intermediate Key (IK) |
| Per-partition, stored in metastore, auto-rotated |
+------------------+-----------------------------------+
| encrypts
+------------------v-----------------------------------+
| Data Row Key (DRK) |
| Unique per write -- effectively rotated every time |
+------------------+-----------------------------------+
| encrypts
v
Your Data
Keys are protected at rest by a three-tier cache with hardware-enforced memory protection:
TIER 1: mlock'd Slab (hot cache, ~400ns access)
========================================================
Guard Page [PROT_NONE -- segfaults on access]
+----------------------------------------------------+
| mlock'd Page (4KB, pinned in RAM, never swapped) |
| |
| Slot 0: Coffer Left (XOR'd master key half) |
| Slot 1: Coffer Right (random, key derivation) |
| [neither half alone reveals the key] |
| |
| Slot 2: SK decrypt key <-- hot cache (LRU) |
| Slot 3: IK decrypt key <-- hot cache (LRU) |
| Slot 4: [transient op] <-- acquired/released |
| ... |
| Slot N: [free] |
+----------------------------------------------------+
Guard Page [PROT_NONE -- segfaults on access]
Guard pages fault on page-boundary overflows and underflows.
Standalone secure buffers also use canaries for corruption detection.
TIER 2: Encrypted Enclaves (cold cache, ~1us access)
========================================================
Regular heap memory (not mlock'd, can be swapped)
+----------------------------------------------------+
| Enclave { id, ciphertext, data_len } |
| ciphertext = AES-256-GCM(key, coffer_master) |
| On access: decrypt into Tier 1 slab slot |
| Promoted to hot cache after first use |
+----------------------------------------------------+
Each CryptoKey holds an Enclave. When the hot cache
is full, LRU eviction frees a slab slot. The evicted
key remains safe in its Enclave (encrypted at rest).
TIER 3: Metastore (persistent, ~1ms access)
========================================================
DynamoDB / MySQL / Postgres / SQLite
+----------------------------------------------------+
| EnvelopeKeyRecord { id, created, encrypted_key } |
| encrypted_key = AES-256-GCM(key, parent_key) |
| Loaded on cold start or cache miss |
| Decrypted through the key hierarchy (IK->SK->KMS)|
+----------------------------------------------------+
Tier 1 hit (typical encrypt/decrypt): The decrypted key is already in an mlock'd slab slot — zero crypto overhead, just a pointer read. This is why hot-cache encrypt is ~400ns.
Tier 1 miss, Tier 2 hit: The key's Enclave (AES-256-GCM encrypted ciphertext in heap memory) is decrypted using the Coffer master key from the slab, placed in a free slot, and promoted to the hot cache.
Tier 2 miss (cold start): The key is loaded from the metastore, decrypted through the key hierarchy (KMS decrypts SK, SK decrypts IK), sealed into an Enclave, and promoted into the slab hot cache.
Coffer: The master key for Enclave encryption is split across two mlock'd slots using XOR + hash derivation. Neither slot alone reveals the key. Initialized once at startup with OS entropy.
Above the memory tiers, Asherah maintains logical caches with stale-while-revalidate to prevent thundering herd on cache expiry:
Request --> Session Cache (LRU, per-factory)
| miss
v
IK Cache (stale-while-revalidate)
| miss
v
SK Cache (shared, stale-while-revalidate)
| miss
v
Metastore load --> Tier 2/1 promotion
On cache expiry, the stale key is returned immediately while a background refresh loads the latest version from the metastore.
# Run all tests
scripts/test.sh --all
# Individual test modes
scripts/test.sh --unit
scripts/test.sh --integration # requires Docker (MySQL, Postgres, DynamoDB)
scripts/test.sh --bindings # requires language toolchains
scripts/test.sh --interop
scripts/test.sh --lint
scripts/test.sh --sanitizers # Miri, AddressSanitizer, Valgrind
scripts/test.sh --fuzz # requires nightly
| Directory | Description |
|---|---|
asherah/ | Rust core library |
asherah-node/ | Node.js bindings |
asherah-py/ | Python bindings |
asherah-dotnet/ | .NET bindings |
| `asherah-java/ |