A user asks you to delete their data. You delete the row. Then you remember the replica, last month's backup, the S3 export someone made for analytics, and the log line with their email in it. You can't edit most of those.
Crypto-shredding is the standard way out: encrypt each person's data under their own key, keep the keys in one small keystore, and "delete" a person by destroying their key. The ciphertext can stay wherever it is. Without the key it's noise.
I built a small library for this called aegis-shred: a Rust core, a Python package and a CLI.
from aegis_shred import MasterKey, Vault
vault = Vault.open("keys.db", MasterKey.from_env("AEGIS_MASTER_KEY"), create=True)
blob = vault.seal("user-42", b"alice@example.com", context=b"users.email") # store anywhere
vault.unseal(blob, context=b"users.email") # b'alice@example.com'
vault.shred("user-42") # erase user-42, everywhere, at once
vault.unseal(blob, context=b"users.email") # raises aegis_shred.Shredded
How it works
master key (from your secret manager)
└─ wraps one data key per subject ───── keystore (SQLite file)
└─ HKDF → one key per sealed object
└─ AES-256-GCM, chunked (STREAM)
└─ sealed blob/file ── your database, S3, backups, …
-
sealcreates the subject's key on first use and returns a self-describing blob. The blob names a random key id, never the user. -
unsealchecks every chunk. A modified byte, a reordered or missing chunk, truncation, or a differentcontextall fail. -
shreddeletes the wrapped key in one transaction, writes a tombstone and a hash-chained audit entry, and returns a receipt. From then on, in every process, that user's blobs raiseShredded. - The keystore stores subjects only as
HMAC(index_key, subject_id), so the keystore and audit log don't list your users either.
The context argument binds a blob to where it lives, so a ciphertext copied from one column into another won't decrypt.
Large files are streamed in 64 KiB chunks with constant memory, and the output file only appears if every chunk verifies.
Install
pip install aegis-shred # prebuilt wheels for Linux, macOS, Windows
cargo add aegis-shred # Rust library
cargo install aegis-shred-cli # the aegis command
Honest limits
This is v0.1, alpha. The byte format is specified and versioned, every guarantee has a test, and a second independent implementation in Python runs in CI. But there has been no independent security audit. Read the threat model in the repo before relying on it.
Whether crypto-shredding satisfies GDPR Art. 17, CCPA or India's DPDP Act for your situation is a question for your lawyers. The library gives you the mechanism and an audit trail, not legal cover.
Repo (MIT OR Apache-2.0): https://github.com/Lingikaushikreddy/Aegis
Feedback on the threat model and the file format is the most useful thing you could send me.
Top comments (0)