Docker images ship your source in the clear: anyone can docker save and read it. cryptship ships the app encrypted, with a thin loader that decrypts and runs it only when a valid license is present. One tool, one license format, three deployment modes.
Build time on your side, run time on the customer’s.
There is no “is the license valid?” check to patch out. The decryption key is derived from the license itself.
# the key is derived from the license, so a valid license and a successful decrypt are the same event content_key = unwrap(license.wrapped_key, KEK = derive(machine_fingerprint, license_id)) plaintext = aead_open(payload.enc, content_key) # wrong key => AEAD tag fails
Air-gapped, on-prem and cloud differ only in how the content key is obtained.
| Mode | Provider | Binding | Revocation |
|---|---|---|---|
| Air-gapped | offline | Machine fingerprint, or none | Expiry only |
| On-prem / cloud | online | Per-license secret held by your server | Real: the server declines |
| Confidential | attested | SEV-SNP / TDX attestation gates the key | Real, plus anti-tamper |
pack --transform-cmd runs your toolchain first, so a memory dump yields bytecode, not sourceattested) path, or keeping critical logic server-side, prevents extraction.
Needs only Docker. The demo packs a small Python app, proves no layer contains the source, runs it, then tampers with the license to show the loader refuse.
$ git clone https://github.com/AI2TH/cryptship && cd cryptship $ bash scripts/demo.sh