Home / Alt manpages / openssl-passphrase-options(1ssl)

  • openssl-passphrase-options(1ssl)
  • OpenSSL command
  • linux

OpenSSL Passphrase Sources: Safe Files, Pipes and Prompts

You will finish with a small set of OpenSSL commands that take passphrases from a prompt, environment variable, file, file descriptor or standard input. You will also know which choices expose the secret and how to prove that the same passphrase decrypts the result.

Allow about fifteen minutes. You need OpenSSL and a POSIX shell. The examples use openssl enc with AES-256-CBC and PBKDF2 only as a reproducible demonstration of the passphrase interface. They are not a recommendation to design a new file format around enc. No command needs elevated privileges, and none changes system configuration.

1. Check the installed OpenSSL

Start by checking the binary that your shell will actually run. Package metadata and the executable selected by PATH can describe different installations:

$ command -v openssl
/home/linuxbrew/.linuxbrew/bin/openssl
$ openssl version
OpenSSL 3.6.1 27 Jan 2026

Your version and path may differ. The installed manpage on this machine is from the Ubuntu openssl package, version 3.0.13-0ubuntu3.15, while the selected executable is OpenSSL 3.6.1. The passphrase-source syntax described here is the same in both references, but always use the help and manpages belonging to the binary you will run.

Checkpoint: confirm that the command accepts a passphrase source through -pass:

$ openssl enc -help 2>&1 | grep -- ' -pass '
 -pass val              Passphrase source

2. Know what the source names mean

OpenSSL passphrase arguments have a prefix followed by a value. The common forms are:

SourceMeaningPractical warning
pass:VALUEUse the literal value.Visible to process-listing tools. Use only for disposable tests.
env:NAMERead an environment variable.Other processes may be able to inspect environments on some systems.
file:PATHRead the first line of a file or stream.Protect the path and remember that only one line is consumed.
fd:NUMBERRead from an open file descriptor.Useful for a pipe, but not supported on Windows.
stdinRead from standard input.Do not confuse the password stream with the command's data input.

If an OpenSSL command needs a password and you omit its passphrase argument, it normally prompts on the current terminal with echo disabled. That is often the least surprising interactive choice. Character encoding can matter for non-ASCII passphrases, so use a deliberately agreed encoding when different systems will exchange the data.

3. Use a prompt for an interactive operation

Make a short plaintext file, then let OpenSSL prompt for the encryption passphrase. The redirection writes only to /tmp and can be removed after the test:

$ printf '%s\n' 'passphrase source test' > /tmp/openssl-passphrase-plain
$ openssl enc -aes-256-cbc -pbkdf2 -salt \
    -in /tmp/openssl-passphrase-plain \
    -out /tmp/openssl-passphrase-cipher
enter AES-256-CBC encryption password:
Verifying - enter AES-256-CBC encryption password:

Type the same test passphrase twice. Nothing should be echoed. This is an ordinary command. Do not use sudo to make a private file readable: fix its ownership or permissions instead.

Checkpoint: decrypt it into a different file and compare the content:

$ openssl enc -d -aes-256-cbc -pbkdf2 \
    -in /tmp/openssl-passphrase-cipher \
    -out /tmp/openssl-passphrase-plain.dec
enter AES-256-CBC decryption password:
$ cmp /tmp/openssl-passphrase-plain /tmp/openssl-passphrase-plain.dec
$ cat /tmp/openssl-passphrase-plain.dec
passphrase source test

A zero exit status from cmp means the recovered bytes match. A wrong password normally produces a non-zero OpenSSL status and an error such as a bad decrypt message; do not treat a partial output file as valid.

4. Use a protected file or environment variable in automation

For a job that cannot answer a prompt, file: keeps the secret out of the command line. Create a temporary password file with a restrictive mode, use it, and remove it when the job finishes:

$ umask 077
$ printf '%s\n' 'TEST-ONLY-passphrase' > /tmp/openssl-passphrase.secret
$ chmod 600 /tmp/openssl-passphrase.secret
$ openssl enc -d -aes-256-cbc -pbkdf2 \
    -pass file:/tmp/openssl-passphrase.secret \
    -in /tmp/openssl-passphrase-cipher \
    -out /tmp/openssl-passphrase-file.dec
$ cmp /tmp/openssl-passphrase-plain /tmp/openssl-passphrase-file.dec
$ rm /tmp/openssl-passphrase.secret

The file source reads its first line. A newline terminates that password; extra lines are not a way to supply a longer passphrase to this invocation. A file, device or named pipe can be used as the pathname, but every reader of a pipe must be considered part of the security boundary.

An environment variable avoids a password file but is not automatically private:

$ export OPENSSL_TEST_PASS='TEST-ONLY-passphrase'
$ openssl enc -d -aes-256-cbc -pbkdf2 \
    -pass env:OPENSSL_TEST_PASS \
    -in /tmp/openssl-passphrase-cipher \
    -out /tmp/openssl-passphrase-env.dec
$ cmp /tmp/openssl-passphrase-plain /tmp/openssl-passphrase-env.dec
$ unset OPENSSL_TEST_PASS

Unset the variable after use, but do not claim that this erases every copy from process memory or shell history. For a high-value secret, prefer an interactive prompt or a dedicated secret-delivery mechanism supplied by your service platform.

5. Pass a password through a descriptor or standard input

fd: is useful when a parent process already has a pipe. In Bash, descriptor 3 can be attached for one command without putting the secret in the argument list:

$ openssl enc -d -aes-256-cbc -pbkdf2 \
    -pass fd:3 \
    -in /tmp/openssl-passphrase-cipher \
    -out /tmp/openssl-passphrase-fd.dec \
    3<<'PASSWORD'
TEST-ONLY-passphrase
PASSWORD
$ cmp /tmp/openssl-passphrase-plain /tmp/openssl-passphrase-fd.dec

The here-document is convenient for a disposable test, not for a real secret. A production wrapper can connect descriptor 3 to a protected pipe instead. On Unix-like systems, descriptor numbers are per-process handles. On Windows, the OpenSSL manpage says fd: is not supported.

stdin reads the password from standard input. Keep the encrypted data on -in or another descriptor so the two streams do not collide:

$ printf '%s\n' 'TEST-ONLY-passphrase' | \
  openssl enc -d -aes-256-cbc -pbkdf2 -pass stdin \
    -in /tmp/openssl-passphrase-cipher \
    -out /tmp/openssl-passphrase-stdin.dec
$ cmp /tmp/openssl-passphrase-plain /tmp/openssl-passphrase-stdin.dec

6. Avoid the common traps

pass:... is easy to type and easy to leak. Unix process listings can expose command arguments, so never use a real secret there. Environment variables can also be visible to other processes, depending on the operating system and permissions. A protected file can remain on disk after the command exits, so remove it or use your platform's secret store. A named pipe avoids a persistent file but can block or deliver the password to the wrong reader.

Do not confuse -passin and -passout when using commands that read and write separate passphrases, such as key-management commands. If the same file: pathname is supplied to both, OpenSSL consumes the first line for input and the next line for output. That is an intentional two-line protocol, not a default password-file format you should guess at.

When an operation fails, check the source first: the variable may be unset, the file may be unreadable, the descriptor may not be open, or the password may contain an unexpected newline. Inspect paths and permissions without printing the secret. If a failed decryption wrote output, treat that output as untrusted and remove it after preserving any evidence you actually need.

Done means

  • You checked the OpenSSL binary and version used by your shell.
  • You can explain the difference between pass:, env:, file:, fd: and stdin.
  • You kept real passphrases out of command arguments and disposable examples out of permanent storage.
  • You verified a decryption with cmp, rather than trusting a successful-looking command alone.
  • You understand that file and stream sources consume the first line, and that the same file can provide successive lines for input and output passwords.
  • You removed the temporary test files when finished: rm -f /tmp/openssl-passphrase-plain /tmp/openssl-passphrase-cipher /tmp/openssl-passphrase-plain.dec /tmp/openssl-passphrase-file.dec /tmp/openssl-passphrase-env.dec /tmp/openssl-passphrase-fd.dec /tmp/openssl-passphrase-stdin.dec.