在 bash 文件中隐藏/加密密码以防止意外看到它
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3318853/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hide/encrypt password in bash file to stop accidentally seeing it
提问by Rich
Sorry if this has been asked before, I did check but couldn't find anything...
对不起,如果之前有人问过这个问题,我确实检查过但找不到任何东西......
Is there a function in Unix to encrypt anddecrypt a password in a batch file so that I can pipe it into some other commands in a bash file?
Unix 中是否有一个函数可以加密和解密批处理文件中的密码,以便我可以将其通过管道传输到 bash 文件中的其他一些命令中?
I realise that doing this provides no real security, it is more to stop someone accidentally seeing the password if they are looking at the script over my shoulder :)
我意识到这样做并不能提供真正的安全性,如果有人在我肩上查看脚本,则更重要的是阻止他们意外看到密码:)
I'm running on Red Hat 5.3.
我在 Red Hat 5.3 上运行。
I have a script which does something similar to this:
我有一个脚本,它执行类似的操作:
serverControl.sh -u admin -p myPassword -c shutdown
and I would like to do something like this:
我想做这样的事情:
password = decrypt("fgsfkageaivgea", "aDecryptionKey")
serverControl.sh -u admin -p $password -c shutdown
This doesn't protect the password in any way, but does stop someone from accidentally seeing it over my shoulder.
这不会以任何方式保护密码,但确实可以防止有人不小心从我的肩膀上看到它。
采纳答案by Kaleb Pederson
OpenSSL provides a passwdcommand that can encrypt but doesn't decrypt as it only does hashes. You could also download something like aesutilso you can use a capable and well-known symmetric encryption routine.
OpenSSL 提供了一个passwd命令,它可以加密但不能解密,因为它只进行散列。您还可以下载类似aesutil 的东西,这样您就可以使用功能强大且众所周知的对称加密例程。
For example:
例如:
#!/bin/sh
# using aesutil
SALT=$(mkrand 15) # mkrand generates a 15-character random passwd
MYENCPASS="i/b9pkcpQAPy7BzH2JlqHVoJc2mNTBM=" # echo "passwd" | aes -e -b -B -p $SALT
MYPASS=$(echo "$MYENCPASS" | aes -d -b -p $SALT)
# and usage
serverControl.sh -u admin -p $MYPASS -c shutdown
回答by White_Nazgul
I used base64 for the overcoming the same problem, i.e. people can see my password over my shoulder.
我使用 base64 来克服同样的问题,即人们可以在我的肩膀上看到我的密码。
Here is what I did - I created a new "db_auth.cfg" file and created parameters with one being my db password. I set the permission as 750 for the file.
这就是我所做的 - 我创建了一个新的“db_auth.cfg”文件并创建了参数,其中一个是我的数据库密码。我将文件的权限设置为 750。
DB_PASSWORD=Z29vZ2xl
In my shell script I used the "source" command to get the file and then decode it back to use in my script.
在我的 shell 脚本中,我使用“source”命令来获取文件,然后将其解码回我的脚本中使用。
source path_to_the_file/db_auth.cfg
DB_PASSWORD=$(eval echo ${DB_PASSWORD} | base64 --decode)
I hope this helps.
我希望这有帮助。
回答by Alexander Nick
Although this is not a built in Unix solution, I've implemented a solution for this using a shell script that can be included in whatever shell script you are using. This is usable on POSIX compliant setups. (sh, bash, ksh, zsh) The full description is available in the github repo -> https://github.com/plyint/encpass.sh. This solution will auto-generate a key for your script and store the key and your password (or other secrets) in a hidden directory under your user (i.e. ~/.encpass).
虽然这不是内置的 Unix 解决方案,但我已经使用 shell 脚本为此实现了一个解决方案,该脚本可以包含在您使用的任何 shell 脚本中。这可用于符合 POSIX 的设置。(sh, bash, ksh, zsh) 完整的描述可以在 github repo -> https://github.com/plyint/encpass.sh 中找到。此解决方案将为您的脚本自动生成一个密钥,并将密钥和您的密码(或其他机密)存储在您用户下的隐藏目录中(即 ~/.encpass)。
In your script you just need to source encpass.sh and then call the get_secret method. For example:
在您的脚本中,您只需要获取 encpass.sh,然后调用 get_secret 方法。例如:
#!/bin/sh
. encpass.sh
password=$(get_secret)
Pasted below is lite version of the code for encpass.sh(you can get the full version over on github) for easier visibility:
下面粘贴的是 encpass.sh 代码的精简版(您可以在 github 上获得完整版本),以便于查看:
#!/bin/sh
################################################################################
# Copyright (c) 2020 Plyint, LLC <[email protected]>. All Rights Reserved.
# This file is licensed under the MIT License (MIT).
# Please see LICENSE.txt for more information.
#
# DESCRIPTION:
# This script allows a user to encrypt a password (or any other secret) at
# runtime and then use it, decrypted, within a script. This prevents shoulder
# surfing passwords and avoids storing the password in plain text, which could
# inadvertently be sent to or discovered by an individual at a later date.
#
# This script generates an AES 256 bit symmetric key for each script (or user-
# defined bucket) that stores secrets. This key will then be used to encrypt
# all secrets for that script or bucket. encpass.sh sets up a directory
# (.encpass) under the user's home directory where keys and secrets will be
# stored.
#
# For further details, see README.md or run "./encpass ?" from the command line.
#
################################################################################
encpass_checks() {
[ -n "$ENCPASS_CHECKS" ] && return
if [ -z "$ENCPASS_HOME_DIR" ]; then
ENCPASS_HOME_DIR="$HOME/.encpass"
fi
[ ! -d "$ENCPASS_HOME_DIR" ] && mkdir -m 700 "$ENCPASS_HOME_DIR"
if [ -f "$ENCPASS_HOME_DIR/.extension" ]; then
# Extension enabled, load it...
ENCPASS_EXTENSION="$(cat "$ENCPASS_HOME_DIR/.extension")"
ENCPASS_EXT_FILE="encpass-$ENCPASS_EXTENSION.sh"
if [ -f "./extensions/$ENCPASS_EXTENSION/$ENCPASS_EXT_FILE" ]; then
# shellcheck source=/dev/null
. "./extensions/$ENCPASS_EXTENSION/$ENCPASS_EXT_FILE"
elif [ ! -z "$(command -v encpass-"$ENCPASS_EXTENSION".sh)" ]; then
# shellcheck source=/dev/null
. "$(command -v encpass-$ENCPASS_EXTENSION.sh)"
else
encpass_die "Error: Extension $ENCPASS_EXTENSION could not be found."
fi
# Extension specific checks, mandatory function for extensions
encpass_"${ENCPASS_EXTENSION}"_checks
else
# Use default OpenSSL implementation
if [ ! -x "$(command -v openssl)" ]; then
echo "Error: OpenSSL is not installed or not accessible in the current path." \
"Please install it and try again." >&2
exit 1
fi
[ ! -d "$ENCPASS_HOME_DIR/keys" ] && mkdir -m 700 "$ENCPASS_HOME_DIR/keys"
[ ! -d "$ENCPASS_HOME_DIR/secrets" ] && mkdir -m 700 "$ENCPASS_HOME_DIR/secrets"
[ ! -d "$ENCPASS_HOME_DIR/exports" ] && mkdir -m 700 "$ENCPASS_HOME_DIR/exports"
fi
ENCPASS_CHECKS=1
}
# Checks if the enabled extension has implented the passed function and if so calls it
encpass_ext_func() {
[ ! -z "$ENCPASS_EXTENSION" ] && ENCPASS_EXT_FUNC="$(command -v "encpass_${ENCPASS_EXTENSION}_")" || return
[ ! -z "$ENCPASS_EXT_FUNC" ] && shift && $ENCPASS_EXT_FUNC "$@"
}
# Initializations performed when the script is included by another script
encpass_include_init() {
encpass_ext_func "include_init" "$@"
[ ! -z "$ENCPASS_EXT_FUNC" ] && return
if [ -n "" ] && [ -n "" ]; then
ENCPASS_BUCKET=
ENCPASS_SECRET_NAME=
elif [ -n "" ]; then
if [ -z "$ENCPASS_BUCKET" ]; then
ENCPASS_BUCKET=$(basename "echo -n "pAssw0rd" | gpg --armor --no-default-keyring --keyring /media/usb/key.pub --recipient [email protected] --encrypt
")
fi
ENCPASS_SECRET_NAME=
else
ENCPASS_BUCKET=$(basename "password=$(gpg --batch --quiet --no-default-keyring --secret-keyring /media/usb/key.priv --decrypt <<EOF
-----BEGIN PGP MESSAGE-----
hQEMA0CjbyauRLJ8AQgAkZT5gK8TrdH6cZEy+Ufl0PObGZJ1YEbshacZb88RlRB9
h2z+s/Bso5HQxNd5tzkwulvhmoGu6K6hpMXM3mbYl07jHF4qr+oWijDkdjHBVcn5
0mkpYO1riUf0HXIYnvCZq/4k/ajGZRm8EdDy2JIWuwiidQ18irp07UUNO+AB9mq8
5VXUjUN3tLTexg4sLZDKFYGRi4fyVrYKGsi0i5AEHKwn5SmTb3f1pa5yXbv68eYE
lCVfy51rBbG87UTycZ3gFQjf1UkNVbp0WV+RPEM9JR7dgR+9I8bKCuKLFLnGaqvc
beA3A6eMpzXQqsAg6GGo3PW6fMHqe1ZCvidi6e4a/dJDAbHq0XWp93qcwygnWeQW
Ozr1hr5mCa+QkUSymxiUrRncRhyqSP0ok5j4rjwSJu9vmHTEUapiyQMQaEIF2e2S
/NIWGg==
=uriR
-----END PGP MESSAGE-----
EOF)
")
ENCPASS_SECRET_NAME="password"
fi
}
encpass_generate_private_key() {
ENCPASS_KEY_DIR="$ENCPASS_HOME_DIR/keys/$ENCPASS_BUCKET"
[ ! -d "$ENCPASS_KEY_DIR" ] && mkdir -m 700 "$ENCPASS_KEY_DIR"
if [ ! -f "$ENCPASS_KEY_DIR/private.key" ]; then
(umask 0377 && printf "%s" "$(openssl rand -hex 32)" >"$ENCPASS_KEY_DIR/private.key")
fi
}
encpass_set_private_key_abs_name() {
ENCPASS_PRIVATE_KEY_ABS_NAME="$ENCPASS_HOME_DIR/keys/$ENCPASS_BUCKET/private.key"
[ ! -n "" ] && [ ! -f "$ENCPASS_PRIVATE_KEY_ABS_NAME" ] && encpass_generate_private_key
}
encpass_set_secret_abs_name() {
ENCPASS_SECRET_ABS_NAME="$ENCPASS_HOME_DIR/secrets/$ENCPASS_BUCKET/$ENCPASS_SECRET_NAME.enc"
[ ! -n "" ] && [ ! -f "$ENCPASS_SECRET_ABS_NAME" ] && set_secret
}
encpass_rmfifo() {
trap - EXIT
kill "" 2>/dev/null
rm -f ""
}
encpass_mkfifo() {
fifo="$ENCPASS_HOME_DIR/.$$"
mkfifo -m 600 "$fifo" || encpass_die "Error: unable to create named pipe"
printf '%s\n' "$fifo"
}
get_secret() {
encpass_checks
encpass_ext_func "get_secret" "$@"; [ ! -z "$ENCPASS_EXT_FUNC" ] && return
[ "$(basename "DB_PASSWORD=$(eval echo ${DB_PASSWORD} | base64 --decode)
")" != "encpass.sh" ] && encpass_include_init "" ""
encpass_set_private_key_abs_name
encpass_set_secret_abs_name
encpass_decrypt_secret "$@"
}
set_secret() {
encpass_checks
encpass_ext_func "set_secret" "$@"; [ ! -z "$ENCPASS_EXT_FUNC" ] && return
if [ "" != "reuse" ] || { [ -z "$ENCPASS_SECRET_INPUT" ] && [ -z "$ENCPASS_CSECRET_INPUT" ]; }; then
echo "Enter $ENCPASS_SECRET_NAME:" >&2
stty -echo
read -r ENCPASS_SECRET_INPUT
stty echo
echo "Confirm $ENCPASS_SECRET_NAME:" >&2
stty -echo
read -r ENCPASS_CSECRET_INPUT
stty echo
# Use named pipe to securely pass secret to openssl
fifo="$(encpass_mkfifo set_secret_fifo)"
fi
if [ "$ENCPASS_SECRET_INPUT" = "$ENCPASS_CSECRET_INPUT" ]; then
encpass_set_private_key_abs_name
ENCPASS_SECRET_DIR="$ENCPASS_HOME_DIR/secrets/$ENCPASS_BUCKET"
[ ! -d "$ENCPASS_SECRET_DIR" ] && mkdir -m 700 "$ENCPASS_SECRET_DIR"
# Generate IV and create secret file
printf "%s" "$(openssl rand -hex 16)" > "$ENCPASS_SECRET_DIR/$ENCPASS_SECRET_NAME.enc"
ENCPASS_OPENSSL_IV="$(cat "$ENCPASS_SECRET_DIR/$ENCPASS_SECRET_NAME.enc")"
echo "$ENCPASS_SECRET_INPUT" > "$fifo" &
# Allow expansion now so PID is set
# shellcheck disable=SC2064
trap "encpass_rmfifo $! $fifo" EXIT HUP TERM INT TSTP
# Append encrypted secret to IV in the secret file
openssl enc -aes-256-cbc -e -a -iv "$ENCPASS_OPENSSL_IV" \
-K "$(cat "$ENCPASS_HOME_DIR/keys/$ENCPASS_BUCKET/private.key")" \
-in "$fifo" 1>> "$ENCPASS_SECRET_DIR/$ENCPASS_SECRET_NAME.enc"
else
encpass_die "Error: secrets do not match. Please try again."
fi
}
encpass_decrypt_secret() {
encpass_ext_func "decrypt_secret" "$@"; [ ! -z "$ENCPASS_EXT_FUNC" ] && return
if [ -f "$ENCPASS_PRIVATE_KEY_ABS_NAME" ]; then
ENCPASS_DECRYPT_RESULT="$(dd if="$ENCPASS_SECRET_ABS_NAME" ibs=1 skip=32 2> /dev/null | openssl enc -aes-256-cbc \
-d -a -iv "$(head -c 32 "$ENCPASS_SECRET_ABS_NAME")" -K "$(cat "$ENCPASS_PRIVATE_KEY_ABS_NAME")" 2> /dev/null)"
if [ ! -z "$ENCPASS_DECRYPT_RESULT" ]; then
echo "$ENCPASS_DECRYPT_RESULT"
else
# If a failed unlock command occurred and the user tries to show the secret
# Present either a locked or failed decrypt error.
if [ -f "$ENCPASS_HOME_DIR/keys/$ENCPASS_BUCKET/private.lock" ]; then
echo "**Locked**"
else
# The locked file wasn't present as expected. Let's display a failure
echo "Error: Failed to decrypt"
fi
fi
elif [ -f "$ENCPASS_HOME_DIR/keys/$ENCPASS_BUCKET/private.lock" ]; then
echo "**Locked**"
else
echo "Error: Unable to decrypt. The key file \"$ENCPASS_PRIVATE_KEY_ABS_NAME\" is not present."
fi
}
encpass_die() {
echo "$@" >&2
exit 1
}
#LITE
回答by Lèse majesté
You should be able to use crypt
, mcrypt
, or gpg
to meet your needs. They all support a number of algorithms. crypt
is a bit outdated though.
您应该能够使用crypt
,mcrypt
或gpg
满足您的需求。它们都支持多种算法。crypt
虽然有点过时。
More info:
更多信息:
回答by Juanu
Another solution, without regard to security (I also think it is better to keep the credentials in another file or in a database) is to encrypt the password with gpg and insert it in the script.
另一个不考虑安全性的解决方案(我也认为将凭据保存在另一个文件或数据库中更好)是使用 gpg 加密密码并将其插入脚本中。
I use a password-less gpg key pair that I keep in a usb. (Note: When you export this key pair don't use --armor, export them in binary format).
我使用保存在 USB 中的无密码 gpg 密钥对。(注意:导出此密钥对时不要使用--armor,以二进制格式导出)。
First encrypt your password:
首先加密您的密码:
EDIT: Put a space before this command, so it is not recorded by the bash history.
编辑:在此命令之前放置一个空格,因此它不会被 bash 历史记录。
DB_PASSWORD=`echo $PASSWORD|base64 -d`
That will be print out the gpg encrypted password in the standart output. Copy the whole message and add this to the script:
这将在标准输出中打印出 gpg 加密密码。复制整个消息并将其添加到脚本中:
1. wget link-to-the-zip-file
2. unzip the-newly-downloaded-zip-file
3. cd /tmp/KingLazySHIELD
4. ./install.sh /var/tmp/KINGLAZY/SHIELDX-(your-script-name) /home/(your-username) -force
In this way only if the usb is mounted in the system the password can be decrypted. Of course you can also import the keys into the system (less secure, or no security at all) or you can protect the private key with password (so it can not be automated).
这样只有系统挂载了usb才能解密密码。当然,您也可以将密钥导入系统(安全性较低,或根本没有安全性),或者您可以使用密码保护私钥(因此无法自动化)。
回答by Ashton
- indent it off the edge of your screen (assuming you don't use line wrapping and you have a consistant editor width)
- 将它从屏幕边缘缩进(假设您不使用换行并且您有一致的编辑器宽度)
or
或者
- store it in a separate file and read it in.
- 将它存储在一个单独的文件中并读取它。
回答by user133617
Following line in above code is not working
上面代码中的以下行不起作用
##代码##Correct line is:
正确的行是:
##代码##And save the password in other file as PASSWORD.
并将密码保存在其他文件中作为 PASSWORD。
回答by EasyLife
There's a more convenient way to store passwords in a script but you will have to encrypt and obfuscate the script so that it cannot be read. In order to successfully encrypt and obfuscate a shell script and actually have that script be executable, try copying and pasting it here:
有一种更方便的方法可以将密码存储在脚本中,但您必须对脚本进行加密和混淆,使其无法被读取。为了成功加密和混淆 shell 脚本并使该脚本真正可执行,请尝试将其复制并粘贴到此处:
http://www.kinglazy.com/shell-script-encryption-kinglazy-shieldx.htm
http://www.kinglazy.com/shell-script-encryption-kinglazy-shieldx.htm
On the above page, all you have to do is submit your script and give the script a proper name, then hit the download button. A zip file will be generated for you. Right click on the download link and copy the URL you're provided. Then, go to your UNIX box and perform the following steps.
在上面的页面上,您所要做的就是提交您的脚本并给脚本一个正确的名称,然后点击下载按钮。将为您生成一个 zip 文件。右键单击下载链接并复制您提供的 URL。然后,转到您的 UNIX 框并执行以下步骤。
Installation:
安装:
##代码##What the above install command will do for you is:
上面的安装命令将为您做的是:
- Install the encrypted version of your script in the directory /var/tmp/KINGLAZY/SHIELDX-(your-script-name).
- It'll place a link to this encrypted script in whichever directory you specify in replacement of /home/(your-username) - that way, it allows you to easily access the script without having to type the absolute path.
- Ensures NO ONE can modify the script - Any attempts to modify the encrypted script will render it inoperable...until those attempts are stopped or removed. It can even be configured to notify youwhenever someone tries to do anything with the script other than run it...i.e. hacking or modification attempts.
- Ensures absolutely NO ONE can make copies of it. No one can copy your script to a secluded location and try to screw around with it to see how it works. All copies of the script must be links to the original location which you specified during install (step 4).
- 在目录 /var/tmp/KINGLAZY/SHIELDX-(your-script-name) 中安装脚本的加密版本。
- 它将在您指定的任何目录中放置一个指向此加密脚本的链接以替换 /home/(your-username) - 这样,您就可以轻松访问该脚本,而无需键入绝对路径。
- 确保没有人可以修改脚本 - 任何修改加密脚本的尝试都将使其无法操作......直到这些尝试被停止或删除。它甚至可以配置为在有人尝试对脚本执行任何操作而不是运行脚本时通知您……即黑客攻击或修改尝试。
- 确保绝对没有人可以复制它。没有人可以将您的脚本复制到一个僻静的位置并尝试使用它来查看它是如何工作的。脚本的所有副本都必须链接到您在安装(第 4 步)期间指定的原始位置。
NOTE:
笔记:
This does not work for interactive scripts that prompts and waits on the user for a response. The values that are expected from the user should be hard-coded into the script. The encryption ensures no one can actually see those values so you need not worry about that.
这不适用于提示和等待用户响应的交互式脚本。用户期望的值应该硬编码到脚本中。加密确保没有人可以真正看到这些值,因此您无需担心。
RELATION:
关系:
The solution provided in this post answers your problem in the sense that it encrypts the actual script containing the password that you wanted to have encrypted. You get to leave the password as is (unencrypted) but the script that the password is in is so deeply obfuscated and encrypted that you can rest assured no one will be able to see it. And if attempts are made to try to pry into the script, you will receive email notifications about them.
这篇文章中提供的解决方案可以解决您的问题,因为它加密了包含您想要加密的密码的实际脚本。您可以将密码保持原样(未加密),但密码所在的脚本已被深度混淆和加密,您可以放心,没有人能够看到它。如果有人试图窥探脚本,您将收到有关它们的电子邮件通知。