March 16, 2007

How to create a command-line password vault

Author: Duane Odom

Like many people, I have too many passwords to remember. To keep them straight, I wrote a simple password security script using dialog and GnuPG (GNU Privacy Guard). The script prompts the user for a master password using a dialog box, unencrypts a file that holds a list of passwords, and opens the file in a text editor. When the editor is closed, the script re-encrypts the password file.

Dialog is an ncurses-based utility for providing text-based message and input boxes. GnuPG is a free implementation of the OpenPGP standard. Both applications are available as binary packages on Debian-based systems.

First, I had to create an encryption key using the command gpg --gen-key. I was prompted for the type of key I wanted to generate. Some keys were labeled "sign only," but I needed to use my key to encrypt data, so I selected "DSA and Elgamal" (which wasn't marked sign only). The only other important thing about the questions that followed was that I needed to remember what I typed when prompted for the "Real Name," because it is used when you encrypt.

Once I successfully generated my key, I needed to create a password file and encrypt it. I created a text file called passwords, typed in some URLs and passwords, and saved the file. Next, I ran the command gpg -e -r "Duane Odom" passwords, which encrypted the text file to another file named passwords.gpg using the recipient "Duane Odom" (the "Real Name" that I typed in while generating my key). Finally, I needed to delete the unencrypted version of the passwords file.

Now that I had my GnuPG key generated and an encrypted version of my passwords file, I could create my password script. The first line creates a suitable temporary file name using the command tempfile. The next line ensures that no matter how the script exits, the temporary file gets deleted. The last line uses dialog to prompt the user for the GnuPG password and redirects dialog's standard error, which provides the actual text that the user typed, to the tempfile that the script created. The dialog command uses the return value to inform you whether the user selected the "Ok" button, the "Cancel" button or the program had an error. The return value is 0 if the "Ok" button was pressed, 1 if the "Cancel" button was pressed, and -1 if an error occurred or the "Esc" key was pressed (as the dialog man page specifies, most shell scripts can't distinguish between -1 and 255, so the script uses the more standard 255).

TEMPFILE=`tempfile 2>/dev/null` || TEMPFILE=/tmp/`basename $0`.tmp
trap "rm -f $TEMPFILE" 0 1 2 5 15
dialog --backtitle "Password Database" --title "Master Password" --clear --insecure --passwordbox "Enter the Password Database master password." 10 51 2> $TEMPFILE

The next important line in the script is where the password file is decrypted. I use the cat command to send password from the file to gpg, and use the --passphrase-fd 0 parameter to tell gpg that the password is being given via standard in:

cat $TEMPFILE | gpg -d -r "$KEY_RECIPIENT_NAME" -o $PASSWD_LIST_UNENCRYPTED --passphrase-fd 0 $PASSWD_LIST &> /dev/null

The next line opens the unencrypted password file in the user's default editor. The script then waits for the editor to terminate (you close the editor when you are finished) and the next line encrypts the password again. The final line removes the unencrypted version of the file:


The handy thing about this script is that (with slight modifications) you can use it to store other documents, images, slide shows, etc., in an encrypted format and still have easy access to editing them. If you have a set of files that you'd like to keep encrypted, you might consider using TrueCrypt instead to create a virtual encrypted disk within a file and mount it as a real disk.

You should never blindly trust anyone's scripts, especially when it comes to your security. As always, read the man page for gpg and dialog for more information on those applications.