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

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

我正在编写一个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

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

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

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

答案1

将密码传递到输入中的单独文件描述符上(两次,一次用于加密,一次用于解密)。请勿出口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

如果您的系统没有/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

答案2

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

欲了解更多信息,请参阅:命令行参数的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

)

答案3

抱歉,我之前的回答来自 openssl man,而不是 openssl enc 文档。

这个解决方案不是管道,但我相信这个解决方案可以防止密码对 ps 可见。

使用此处文档,只有 openssl 可以看到密码文本。
只要您确定删除了中间文件,就不会留下任何痕迹。也许有人可以帮助在管道中完成此操作并消除中间文件?

# cp file{,.old}  don't need this anymore since intermediate becomes same
read -sp 'Enter password. ' PASS; echo
#no need to export, env's are readable, as mentioned

# decode into intermediate file
openssl <<HERE 2>&1 >/dev/null
enc -d -aes-256-cbc -k "$PASS" -in file -out intermediate
HERE

# edit intermediate

# encode intermediate back into file
openssl <<HERE 2>&1 >/dev/null
enc -e -aes-256-cbc -k "$PASS" -in intermediate -out file 
HERE
unset PASS
rm -f intermediate

答案4

我创建了这个小 bash 脚本来进行完整的重置并保留配置文件。强制推送有效地重新创建了您的 GitHub 存储库。

#!/bin/bash
tfile=$(mktemp /tmp/config.XXXXXXXXX)
GITCONF=".git/config"
commitmsg=${1:-git repository initialised}
if [ -f $GITCONF ]; then
   mv .git/config tfile
   rm -rf .git
   git init .
   mv tfile .git/config
   git add .
   git commit -a -m "${commitmsg}"
   git push -f
else
   echo "Warning: No git config file found. Aborting.";exit;
fi

相关内容