在bash中为> 1个程序传递密码的安全方法

22 command-line bash password openssl

我正在编写一个bash脚本,需要向用户询问他的密码并将其传递给openssl. 虽然openssl可以读取密码本身,但我需要两次运行该程序并且不想询问用户两次。这是脚本:

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
Run Code Online (Sandbox Code Playgroud)

这并不安全,因为通过查看命令行很容易获得密码;ps例如,有人可以使用 阅读它。

openssl可以从环境变量读取密码,这样我就可以代替-k "$PASS"-pass env:PASS,但它仍然不是安全的; 任何进程的环境变量都可以自由读取(再次,ps可以做到)。

那么,如何安全地将密码传递给两个openssl实例呢?

Gil*_*il' 17

在与输入不同的文件描述符上传递密码(两次,一次用于加密,一次用于解密)。不要出口PASS到环境中。

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
Run Code Online (Sandbox Code Playgroud)

如果您的系统没有/dev/fd,您可以使用-pass参数来告诉openssl从打开的文件描述符中读取密码。

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
Run Code Online (Sandbox Code Playgroud)

  • @ user14284 不,也不。`env:PASS` 是不安全的,因为密码会出现在 `openssl` 进程的环境中(它不会出现在 `bash` 进程的环境中,但这还不够)。使用 `printf` 是安全的,因为它是内置的 bash。 (6认同)

小智 9

使用 Bash 可以通过printf '%s\n' "$PASS"使用 Bash 内置exec命令将所谓的 here 字符串与文件描述符相关联来完成,而无需使用。

有关详细信息,请参阅:命令行参数的 Shell 脚本密码安全性

(

# sample code to edit password-protected file with openssl
# user should have to enter password only once
# password should not become visible using the ps command

echo hello > tmp.file

#env -i bash --norc   # clean up environment
set +o history
unset PASS || exit 1

read -sp 'Enter password. ' PASS; echo

# encrypt file and protect it by given password
exec 3<<<"$PASS"
openssl enc -e -aes-256-cbc -pass fd:3  -in tmp.file -out file

cp file{,.old}

# decode | edit | encode
exec 3<<<"$PASS" 4<<<"$PASS"
openssl enc -d -aes-256-cbc -pass fd:3 -in file.old | 
   sed 's/l/L/g' | 
   openssl enc -e -aes-256-cbc -pass fd:4 -out file

exec 3<<<"$PASS"
openssl enc -d -aes-256-cbc -pass fd:3 -in file

rm -P tmp.file file.old
unset PASS

)
Run Code Online (Sandbox Code Playgroud)