Hacks

A Simple Password Manager in a Dozen Lines of Bash

A while ago I wanted to create my own password manager, something very simple that would enable me to generate random passwords instead of using the same one all over the internet. I ended up using the code below for a few years now.

The idea that I went with was to make two bash scripts:

  • savepass.sh used to generate a random password, save it in an encrypted file and keep that file in a git repo, with a private remote GitHub repo (Bitbucket actually, before GitHub allowed unlimited private repos)
  • getpass.sh used to retrieve the password from the encrypted file and pipe it to pbcopy. (I use Mac OS, but there are Linux alternatives to pbcopy)

It’s not a particularly original idea and you can probably find more robust implementations somewhere on GitHub.

The first step is to generate a gpg key. Here’s a nice tutorial on gpg that should be enough to understand what’s going on here.

Once we’ve generated our key, we can access it from the gpg keychain, and it’s not a bad idea to export the private key and create a backup somewhere, since you can’t recover your passwords without it.

To list the available keys use gpg --list-secret-keys, that gives you something like this:

------------------------
sec   2048R/ABCD10BF 2019-07-09
uid                  sh_pass_manager (key for sh_pass_manager) <sh_pass_manager@sh_pass_manager>
ssb   2048R/BAC4160B 2019-07-09

Now we can create the savepass.sh that will take the service name (eg. “gmail.com”) as a parameter and save the encrypted random password in a file

#!/bin/sh

SERVICE_NAME=$1
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &amp;&amp; pwd )"

mkdir -p "$SCRIPT_DIR/pass"

GPG_RECEPIENT="sh_pass_manager (key for sh_pass_manager) <sh_pass_manager@sh_pass_manager>"

openssl rand -base64 32 | gpg --encrypt --recipient "$GPG_RECEPIENT" > "$SCRIPT_DIR/pass/$SERVICE_NAME"


Run this with ./savepass.sh gmail.com and you should get a file pass/gmail.com. Open it with less to check that it’s a garbled binary file.

Note that we used openssl rand -base64 32 to generate a random password which is nothing but 32 random bytes encoded in base64 (see the docs).

We can now write the getpass.sh to retrieve our encrypted passwords.

#!/bin/sh

set -e
set -o pipefail

PASS_FILE=$1

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &amp;&amp; pwd )"

gpg --decrypt $PASS_FILE | pbcopy
echo "Password copied to clipboard

It’s as simple as calling gpg --decrypt on an encrypted file.

Now, if all this is done inside a git repo, you can backup your encrypted passwords by pushing them to a git remote. (You can also do it automatically upon password creation, at the end of savepass.sh)

You can clone the two files from https://github.com/drazenz/sh-pass-manager.

Disclaimer: I am by no means a computer security expert, and the simple hack above likely has some security flaws. It’s aimed more as an illustration of a simple unix command line workflow, rather than a properly secured password manager.