OpenSSL Cheatsheet
Symmetric Encryption
Use this OpenSSL reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Encrypt and decrypt a file
enc is a password-to-file encryptor. -e encrypts (the default) and -d
decrypts.
# encrypt, always with a KDF openssl enc -aes-256-cbc -pbkdf2 -iter 600000 -salt \ -in secret.txt -out secret.enc # decrypt, with the exact same options openssl enc -d -aes-256-cbc -pbkdf2 -iter 600000 \ -in secret.enc -out secret.txt
Decryption must repeat every option used to encrypt. The cipher, -pbkdf2,
-iter, and -md are not stored in the file. Get any of them wrong and you get
bad decrypt with no hint which one.
Always pass -pbkdf2
Without it, enc derives the key with a single-round OpenSSL-specific KDF that
a GPU brute-forces trivially.
$ openssl enc -aes-256-cbc -in f.txt -out f.enc -pass pass:x *** WARNING : deprecated key derivation used. Using -iter or -pbkdf2 would be better.
| Option | Effect |
|---|---|
-pbkdf2 | Use PBKDF2, default 10000 iterations |
-iter N | Set the iteration count, implies -pbkdf2 |
-md sha512 | Digest inside the KDF, default SHA-256 |
-salt | Random salt, the default since 1.1.0 |
-nosalt | No salt, identical plaintext gives identical ciphertext |
-saltlen N | Salt length in bytes, default 8 |
Use 600000 or more iterations for a human-chosen password. The 10000 default is below current guidance.
openssl enc -aes-256-cbc -pbkdf2 -iter 600000 -md sha512 -saltlen 16 \ -in f.txt -out f.enc
encis a convenience tool, not a modern format. For real secret storage useage,gpg, or an application library with an AEAD.enchas no authentication tag, so a tampered file decrypts to garbage rather than failing cleanly.
Ciphers
openssl enc -ciphers lists everything available.
| Cipher | Notes |
|---|---|
-aes-256-cbc | The practical default for enc |
-aes-128-cbc | Fine, and faster on hardware without AES-NI |
-aes-256-ctr | Stream mode, no padding, still unauthenticated |
-chacha20 | Fast in software, no AES instructions needed |
-aes-256-gcm | enc refuses this, see below |
-des-ede3-cbc | 3DES, 64-bit block, legacy interop only |
-rc4, -des-cbc | Broken, do not use |
$ openssl enc -aes-256-gcm -in f.txt -out f.enc enc: AEAD ciphers not supported
enc cannot do GCM or any AEAD mode. It has nowhere to put the
authentication tag. If you need authenticated encryption from a shell, use
age or gpg, not OpenSSL's enc.
Base64 and pipes
-a (or -base64) armours the output so it survives email, JSON, and YAML.
openssl enc -aes-256-cbc -pbkdf2 -iter 600000 -a -in f.txt -out f.b64 openssl enc -d -aes-256-cbc -pbkdf2 -iter 600000 -a -in f.b64 -out f.txt # -A keeps it on one line, needed for a shell variable or a header openssl enc -aes-256-cbc -pbkdf2 -iter 600000 -a -A -in f.txt
Base64 alone, no encryption, is the same subcommand:
printf 'hello' | openssl base64 -A # aGVsbG8= echo 'aGVsbG8=' | openssl base64 -d openssl base64 -in file.bin -out file.b64 openssl base64 -d -A -in file.b64 -out file.bin
Passphrase sources and scripting
-pass and -k take the same source syntax used everywhere in OpenSSL.
| Source | Meaning |
|---|---|
pass:secret | Literal, visible in history and ps |
env:VARNAME | From an environment variable |
file:/path | First line of a file |
fd:3 | From an open file descriptor |
stdin | Read from standard input |
export ENCPW='correct horse battery staple' openssl enc -aes-256-cbc -pbkdf2 -iter 600000 \ -pass env:ENCPW -in f.txt -out f.enc openssl enc -d -aes-256-cbc -pbkdf2 -iter 600000 \ -pass file:/run/secrets/pw -in f.enc -out f.txt
Encrypt a tarball on the fly, no plaintext ever hitting disk:
tar czf - ./data | openssl enc -aes-256-cbc -pbkdf2 -iter 600000 -pass env:ENCPW \ -out data.tar.gz.enc openssl enc -d -aes-256-cbc -pbkdf2 -iter 600000 -pass env:ENCPW \ -in data.tar.gz.enc | tar xzf -
Inspect the derived key and IV instead of encrypting, useful when matching another implementation:
$ openssl enc -aes-256-cbc -pbkdf2 -iter 10000 -pass pass:x -P -in f.txt salt=00CD98B213F930A2 key=E4C151DE9A2F1DD80B6F25D35F0548B00156A808A5541F1AC7AF4C0D16DD0ABC iv =D9C895BF4E294F89D856A36C1E771055
-P prints and exits, -p prints and continues with the encryption.
Gotchas
- bad decrypt means an option mismatch, not a corrupt file nine times out
of ten. Check the cipher, -pbkdf2, -iter, -md, and -a first.
- enc output starts with the ASCII bytes Salted__ followed by the 8-byte
salt. That is how another implementation finds the salt.
- The OpenSSL 1.x default digest was MD5, and 1.1.0 changed it to SHA-256.
A file encrypted on an old box may need -md md5 to open.
- No integrity protection at all. An attacker can flip bits in the
ciphertext and CBC turns that into controlled plaintext changes. Sign the file
separately or use a real AEAD tool.
- -k secret is the deprecated spelling of -pass pass:secret, and -kfile of
-pass file:. Both still work and both are worse.
- With -nosalt, two encryptions of the same file under the same password are
byte identical, which leaks that the contents did not change.