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.
OptionEffect
-pbkdf2Use PBKDF2, default 10000 iterations
-iter NSet the iteration count, implies -pbkdf2
-md sha512Digest inside the KDF, default SHA-256
-saltRandom salt, the default since 1.1.0
-nosaltNo salt, identical plaintext gives identical ciphertext
-saltlen NSalt 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

enc is a convenience tool, not a modern format. For real secret storage use age, gpg, or an application library with an AEAD. enc has no authentication tag, so a tampered file decrypts to garbage rather than failing cleanly.

Ciphers

openssl enc -ciphers lists everything available.

CipherNotes
-aes-256-cbcThe practical default for enc
-aes-128-cbcFine, and faster on hardware without AES-NI
-aes-256-ctrStream mode, no padding, still unauthenticated
-chacha20Fast in software, no AES instructions needed
-aes-256-gcmenc refuses this, see below
-des-ede3-cbc3DES, 64-bit block, legacy interop only
-rc4, -des-cbcBroken, 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.

SourceMeaning
pass:secretLiteral, visible in history and ps
env:VARNAMEFrom an environment variable
file:/pathFirst line of a file
fd:3From an open file descriptor
stdinRead 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.