Quick Links

If you're forced to use a Linux script to connect to a password-protected resource, you probably feel uneasy about putting that password in the script. OpenSSL solves that problem for you.

Passwords and Scripts

It isn't a great idea to put passwords in shell scripts. In fact, it's a really bad idea. If the script falls into the wrong hands, everyone who reads it can see what the password is. But if you're forced to use a script, what else can you do?

You can enter the password manually when the process reaches that point, but if the script is going to run unattended, that won't work. Thankfully, there's an alternative to hard-coding the passwords into the script. Counterintuitively, it uses a different password to achieve this, along with some strong encryption.

In our example scenario, we need to make a remote connection to a Fedora Linux computer from our Ubuntu computer. We'll be using a Bash shell script to make an SSH connection to the Fedora computer. The script must run unattended, and we don't want to put the password for the remote account in the script. We can't use SSH keys in this case, because we're pretending that we don't have any control or admin rights over the Fedora computer.

We're going to make use of the well-known OpenSSL toolkit to handle the encryption and a utility called sshpass to feed the password into the SSH command.

Related: How to Create and Install SSH Keys From the Linux Shell

Installing OpenSSL and sshpass

Because a lot of other encryption and security tools use OpenSSL, it might already be installed on your computer. However, if it isn't, it only takes a moment to install.

On Ubuntu, type this command:

sudo apt get openssl

sudo apt get openssh in a terminal window

To install sshpass, use this command:

sudo apt install sshpass

sudo apt install sshpass in a terminal window

On Fedora, you need to type:

sudo dnf install openssl

sudo dnf install openssh in a terminal window

The command to install sshpass is:

sudo dnf install sshpass

sudo dnf install sshpass in a terminal window

On Manjaro Linux, we can install OpenSSL with:

sudo pacman -Sy openssl

sudo pacman -Sy openssl in a terminal window

Finally, to install sshpass, use this command:

sudo pacman -Sy sshpass

sudo pacman -sy sshpass in a terminal window

Encrypting on the Command Line

Before we get into using the openssl command with scripts, let's become familiar with it by using it on the command line. Let's say that the password for the account on the remote computer is rusty!herring.pitshaft. We're going to encrypt that password using openssl.

We need to provide an encryption password when we do. The encryption password is used in the encryption and decryption processes. There are a lot of parameters and options in the openssl command. We'll take a look at each of them in a moment.

echo 'rusty!herring.pitshaft' | openssl enc -aes-256-cbc -md sha512 -a -pbkdf2 -iter 100000 -salt -pass pass:'pick.your.password'

echo 'rusty!herring.pitshaft' | openssl enc -aes-256-cbc -md sha512 -a -pbkdf2 -iter 100000 -salt -pass pass:'pick.your.password' in a terminal window

We're using echo to send the remote account password through a pipe and into the openssl command.

The openssl parameters are:

  • enc -aes-256-cbc: The encoding type. We're using the Advanced Encryption Standard 256-bit key cipher with cipher-block chaining.
  • -md sha512: The message digest (hash) type. We're using the SHA512 cryptographic algorithm.
  • -a: This tells openssl to apply base-64 encoding after the encryption phase and before the decryption phase.
  • -pbkdf2: Using Password-Based Key Derivation Function 2 (PBKDF2) makes it much more difficult for a brute force attack to succeed in guessing your password. PBKDF2 requires many computations to perform the encryption. An attacker would need to replicate all of those computations.
  • -iter 100000: Sets the number of computations that PBKDF2 will use.
  • -salt: Using a randomly applied salt value makes the encrypted output different every time, even if the plain text is the same.
  • -pass pass:'pick.your.password': The password we'll need to use to decrypt the encrypted remote password. Substitute pick.your.password with a robust password of your choosing.

The encrypted version of our rusty!herring.pitshaft password is written to the terminal window.

Encrypted password written to the terminal window

To decrypt this, we need to pass that encrypted string into openssl with the same parameters that we used to encrypt, but adding in the -d (decrypt) option.

echo U2FsdGVkX19iiiRNhEsG+wm/uKjtZJwnYOpjzPhyrDKYZH5lVZrpIgo1S0goZU46 | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 -iter 100000 -salt -pass pass:'pick.your.password'

echo U2FsdGVkX19iiiRNhEsG+wm/uKjtZJwnYOpjzPhyrDKYZH5lVZrpIgo1S0goZU46 | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 -iter 100000 -salt -pass pass:'pick.your.password' in a terminal window

The string is decrypted, and our original text---the password for the remote user account---is written to the terminal window.

Decrypted password written to the terminal window

That proves that we can securely encrypt our remote user account password. We can also decrypt it when we need it using the password that we provided in the encryption phase.

But does this actually improve our situation? If we need the encryption password to decrypt the remote account password, surely the decryption password will need to be in the script? Well, yes, it does. But the encrypted remote user account password will be stored in a different, hidden file. The permissions on the file will prevent anyone but you---and the system's root user, obviously---from accessing it.

To send the output from the encryption command to a file, we can use redirection. The file is called ".secret_vault.txt." We've changed the encryption password to something more robust.

echo 'rusty!herring.pitshaft' | openssl enc -aes-256-cbc -md sha512 -a -pbkdf2 -iter 100000 -salt -pass pass:'secret#vault!password' > .secret_vault.txt

echo 'rusty!herring.pitshaft' | openssl enc -aes-256-cbc -md sha512 -a -pbkdf2 -iter 100000 -salt -pass pass:'secret#vault!password' > .secret_vault.txt in a terminal window

Nothing visible happens, but the password is encrypted and sent to the ".secret_vault.txt" file.

We can test that it worked by decrypting the password in the hidden file. Note that we're using cat here, not echo.

cat .secret_vault.txt | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 -iter 100000 -salt -pass pass:'secret#vault!password'

cat .secret_vault.txt | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 -iter 100000 -salt -pass pass:'secret#vault!password' in a terminal window in a terminal window in a terminal window in a terminal window in a terminal window in a terminal window in a terminal window in a terminal window in a terminal window

The password is successfully decrypted from the data in the file. We'll use chmod to change the permissions on this file so that no one else can access it.

chmod 600 .secret_vault.txt

ls -l .secret_vault.txt

chmod 600 .secret_vault.txt in a terminal window

Using a permissions mask of 600 removes all access for anyone other than the file owner. We can now move on to writing our script.

Related: How to Use the chmod Command on Linux

Using OpenSSL in a Script

Our script is pretty straightforward:

#!/bin/bash
    

# name of the remote account

REMOTE_USER=geek

# password for the remote account

REMOTE_PASSWD=$(cat .secret_vault.txt | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 -iter 100000 -salt -pass pass:'secret#vault!password')

# remote computer

REMOTE_LINUX=fedora-34.local

# connect to the remote computer and put a timestamp in a file called script.log

sshpass -p $REMOTE_PASSWD ssh -T $REMOTE_USER@$REMOTE_LINUX << _remote_commands

echo $USER "-" $(date) >> /home/$REMOTE_USER/script.log

_remote_commands

  • We set a variable called REMOTE_USER to "geek."
  • We then set a variable called REMOTE_PASSWD to the value of the decrypted password pulled from the ".secret_vault.txt" file, using the same command that we used a moment ago.
  • The location of the remote computer is stored in a variable called REMOTE_LINUX.

With that information, we can use the ssh command to connect to the remote computer.

  • The sshpass command is the first command on the connection line. We use it with the -p (password) option. This lets us specify the password that should be sent to the ssh command.
  • We use the -T (disable pseudo-terminal allocation) option with ssh because we don't need to have a pseudo-TTY allocated to us on the remote computer.

Related: How to Use "Here Documents" in Bash on Linux

We're using a short here document to pass a command to the remote computer. Everything between the two _remote_commands strings is sent as instructions to the user session on the remote computer---in this case, it's a single line of Bash script.

The command sent to the remote computer simply logs the user account name and a timestamp to a file called "script.log."

Copy and paste the script into an editor and save it to a file called "go-remote.sh." Remember to change the details to reflect the address of your own remote computer, remote user account, and remote account password.

Use chmod to make the script executable.

chmod +x go-remote.sh

chmod +x go-remote.sh in a terminal window

All that's left is to try it out. Let's fire up our script.

./go-remote.sh

./go-remote.sh in a terminal window

Because our script is a minimalist template for an unattended script, there's no output to the terminal. But if we check the "script.log" file on the Fedora computer, we can see that remote connections have been successfully made and that the "script.log" file has been updated with timestamps.

cat script.log

cat script.log in a terminal window

Your Password Is Private

Your remote account password isn't recorded in the script.

And although the decryption password is, in the script, no one else can access your ".secret_vault.txt" file in order to decrypt it and retrieve the remote account password.