OpenSSL¶
OpenSSL is ubiquitous for general-purpose symmetric encryption. cryptkey can supply the key or passphrase for its CLI operations over stdin (preferred) or via an environment variable (a weaker transport — see Secret delivery: stdin vs --env for the full reasoning).
Preferred: pipe to -pass stdin¶
OpenSSL's -pass stdin reads a single line from stdin as the passphrase. cryptkey's default hex output fits that exactly: 64 hex characters + newline, which OpenSSL consumes as a 256-bit-entropy passphrase:
# Encrypt a file
cryptkey derive -- openssl enc -aes-256-cbc -salt -pbkdf2 \
-in secret.txt -out secret.enc -pass stdin
# Decrypt
cryptkey derive -- openssl enc -aes-256-cbc -d -pbkdf2 \
-in secret.enc -out secret.txt -pass stdin
cryptkey derive -- <cmd> runs OpenSSL as a child process with the derived key streamed to its stdin as a caller-owned []byte buffer; cryptkey wipes the buffer from memory as soon as OpenSSL exits. Nothing touches disk, and nothing lingers in the parent process's heap.
Encrypting a directory¶
# Encrypt
tar czf - ~/private/ | cryptkey derive -- \
openssl enc -aes-256-cbc -salt -pbkdf2 \
-out private.tar.gz.enc -pass stdin
# Decrypt
cryptkey derive -- \
openssl enc -aes-256-cbc -d -pbkdf2 \
-in private.tar.gz.enc -pass stdin | tar xzf -
Both the plaintext stream (from tar) and the key (from cryptkey) flow through pipes — no intermediate files.
When you need -K (raw key, no KDF)¶
-pass stdin still runs PBKDF2 inside OpenSSL over whatever you hand it. If you want OpenSSL to use the cryptkey-derived 256-bit output directly as the AES key — no additional stretching — use -K <hex> with cryptkey's default hex output:
# Encrypt with the cryptkey-derived key as the AES key directly.
# The IV is random per-ciphertext and stored with the ciphertext.
IV_HEX=$(openssl rand -hex 16)
cryptkey derive -- sh -c '
read -r KEY
openssl enc -aes-256-cbc -K "$KEY" -iv "'"$IV_HEX"'" \
-in secret.txt -out secret.enc
'
echo "$IV_HEX" > secret.iv # IV is not secret
# Decrypt
IV_HEX=$(cat secret.iv)
cryptkey derive -- sh -c '
read -r KEY
openssl enc -aes-256-cbc -d -K "$KEY" -iv "'"$IV_HEX"'" \
-in secret.enc -out secret.txt
'
The sh -c 'read -r KEY; openssl … -K "$KEY" …' trick pulls the key off stdin into a shell variable local to the subshell. The variable dies with the subshell when OpenSSL exits — no env inheritance across processes.
HMAC / digest signing¶
cryptkey derive -- sh -c 'read -r KEY; openssl dgst -sha256 -hmac "$KEY" -in document.pdf'
Same pattern — key pulled off stdin into a scoped shell variable, used inline, scope exits.
Why not -pass env: / --env KEY?¶
OpenSSL also supports -pass env:VARNAME, which cryptkey can drive with cryptkey derive --env KEY -- openssl … -pass env:KEY. It works. We don't recommend it over stdin:
- Environment variables are readable by any same-UID process (and by root) via
/proc/<pid>/environfor the entire lifetime of the OpenSSL process. stdin is a pipe — once the child has drained it, the key isn't accessible again. - Go's
exec.Cmd.Envis[]string-typed. The cryptkey-side copy of the key is unavoidably stored as a Go string, which is immutable and can't be zeroed viacrypto.WipeBytes; it's left to the garbage collector. The stdin delivery path uses[]byteend-to-end and wipes the buffer deterministically when the child exits.
See Secret delivery: stdin vs --env for the fuller explanation. Short version: use stdin unless the tool literally has no stdin path for the key.
Notes¶
- Always pass
-pbkdf2when using-pass stdin/-pass env:— without it, OpenSSL uses its legacy, weak KDF. The-K <hex>form bypasses the KDF entirely and uses the key you give it directly. cryptkey deriveproduces a 64-character hex string (256 bits of entropy), which OpenSSL happily consumes as either a-pass stdinpassphrase or a-K <hex>raw key.- The examples use the default profile. Pass a name (
cryptkey derive work -- …) when you want more than one profile. - Use
--useto derive domain-separated keys from the same profile:cryptkey derive --use photos -- openssl …,cryptkey derive --use backups -- openssl …. Different OpenSSL-encrypted blobs, one cryptkey profile, independent keys.