Skip to content
Evan edited this page Feb 8, 2015 · 31 revisions

Bash script to keep an encrypted text file of passwords

On a secret cloud server, with ssh key access only, I like to keep a encrypted text file with passwords that I can never remember e.g. because I seldom use some of them, and/or have too many of them.

The following bash script prompts for a password for encryption using openssl, decrypts the file, lets me edit the plain text contents, and then encrypts it again.

github.com/evanx/vellum/blob/master/src/scripts/edit-secret.sh

You can fetch as follows.

cd
mkdir -p ~/scripts
cd ~/scripts && 
  [ ! -f edit-secret.sh ] &&
  curl -s -O https://raw.githubusercontent.com/evanx/vellum/master/src/scripts/edit-secret.sh &&
  chmod +x edit-secret.sh &&
  cat edit-secret.sh &&
  ls -l edit-secret.sh 

Below is the script itself.

#!/bin/bash

# Source https://github.com/evanxvellum by @evanxsummers

if ! echo $BASH | grep -q '/bin/bash' 
then
  echo "Please invoke this using bash"
  exit 1
fi

if ! which openssl 
then
  echo "Please install openssl"
  exit 1
fi

set -u 

cd

dir=.secret
enc=info.enc
txt=info.txt

if [ ! -d $dir ]
then
  echo "Creating $dir in $HOME"
  mkdir $dir
fi

cd $dir 

c0rm() {
  if [ -f $txt ]
  then
    if [ `stat -c %s $txt` -gt 0 ]
    then
      echo "Removing $txt"
    fi
    rm -f $txt
  fi
  pwd
  ls -l 
  cat $enc
}

trap c0rm EXIT

c0passwd() {
  echo -n "Password: "
  read -s passwd
  echo
}

c0enc() {
  openssl enc -aes-256-cbc -a -salt -in $txt -out $enc -k "$passwd"
}

c0dec() {
  openssl enc -d -aes-256-cbc -a -in $enc -out $txt -k "$passwd"
}

c0cat() {
  c0dec
  cat $txt
}

c0edit() {
  if [ -f $enc ] 
  then
    if ! c0dec 
    then
      echo "Decryption failed: incorrect password?"
      exit 1
    fi
  fi
  echo "Invoking $EDITOR $txt"
  "${EDITOR:-vi}" $txt
  c0enc
}

c0delete() {
  if [ -f $enc ]
  then
    cat $enc
    echo "Deleting $enc"
    rm -f $enc
  fi
}

if [ $# -gt 0 ]
then
  command=$1
  shift
  if [ $command != 'delete' ] 
  then
    c0passwd
  fi
  c$#$command $@
else
  c0passwd
  c0edit
fi

Note the EXIT signal trap to ensure that we remove the temporary plain text copy.

The script must be run with bash rather than sh for the read -s to work.

evan@boromir:~$ bash scripts/edit.sh 
/usr/bin/openssl
Password: 
Invoking vim info.txt
Removing info.txt
/home/evan/.secret
total 4
-rw-rw-r-- 1 evan  evan  65 Feb  8 16:10 info.enc
U2FsdGVkX18oarmZ89xPJqE37ho7ZW6hpNOqKEAXB3FSmuP4ZNwAV2Rw9vEL/E6q

We use AES symmetric encryption courtesy of openssl, and also elect for the file to Base64 encoded via the -a option.

  openssl enc -aes-256-cbc -a -salt -in $txt -out $enc -k "$passwd"

The next exercise is to rewrite this in Node.js, whose crypto uses openssl under the hood, to edit encrypted text stored in Redis ;)