Bash – Safe Way to Pass Password for Multiple Programs

bashcommand lineopensslpassword

I'm writing a bash script, and need to ask user for his password and pass it to openssl. Whilst openssl can read the password itself, I need for two runs of the program and don't want to ask the user twice. Here is the script:

cp file{,.old}
read -sp 'Enter password. ' PASS; echo
export PASS

# decode | edit | encode
openssl enc -d -aes-256-cbc -k "$PASS" -in file.old | \
  sed ... | openssl enc -e -aes-256-cbc -k "$PASS" -out file

unset PASS

This is not safe as the password is easily available by looking at the command line; somebody can read it using ps, for example.

openssl can read a password from an environment variable, so I can replace -k "$PASS" with -pass env:PASS, but it's still not safe; the environment variables of any process can be read freely (again, ps can do it).

So, how can I safely pass the password to the two openssl instances?

Best Answer

Pass the password on a separate file descriptor from the input (twice, once for encryption and once for decryption). Do not export PASS to the environment.

read -sp 'Enter password. ' PASS
printf '%s\n' "$PASS" |
openssl enc -d -aes-256-cbc -kfile /dev/stdin -in file.old |
sed ... | {
  printf '%s\n' "$PASS" |
  openssl enc -e -aes-256-cbc -kfile /dev/stdin -in /dev/fd/3 -out file;
} 3<&0

If your system doesn't have /dev/fd, you can use the -pass argument to tell openssl to read the passphrase from an open file descriptor.

printf '%s\n' "$PASS" | {
  printf '%s\n' "$PASS" |
  openssl enc -d -aes-256-cbc -pass fd:0 -in file.old |
  tr a-z A-Z | tee /dev/tty | {
  openssl enc -e -aes-256-cbc -pass fd:3 -out file; }
} 3<&0
Related Question