在 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 19:30:04  来源:igfitidea点击:

Hide/encrypt password in bash file to stop accidentally seeing it

securitybashunixpasswords

提问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 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:

上面的安装命令将为您做的是:

  1. Install the encrypted version of your script in the directory /var/tmp/KINGLAZY/SHIELDX-(your-script-name).
  2. 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.
  3. 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.
  4. 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).
  1. 在目录 /var/tmp/KINGLAZY/SHIELDX-(your-script-name) 中安装脚本的加密版本。
  2. 它将在您指定的任何目录中放置一个指向此加密脚本的链接以替换 /home/(your-username) - 这样,您就可以轻松访问该脚本,而无需键入绝对路径。
  3. 确保没有人可以修改脚本 - 任何修改加密脚本的尝试都将使其无法操作......直到这些尝试被停止或删除。它甚至可以配置为在有人尝试对脚本执行任何操作而不是运行脚本时通知您……即黑客攻击或修改尝试。
  4. 确保绝对没有人可以复制它。没有人可以将您的脚本复制到一个僻静的位置并尝试使用它来查看它是如何工作的。脚本的所有副本都必须链接到您在安装(第 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.

这篇文章中提供的解决方案可以解决您的问题,因为它加密了包含您想要加密的密码的实际脚本。您可以将密码保持原样(未加密),但密码所在的脚本已被深度混淆和加密,您可以放心,没有人能够看到它。如果有人试图窥探脚本,您将收到有关它们的电子邮件通知。