Encrypting and Decrypting Backups

by Thomas Urban

On backing up sensitive information of any size you might wish to encrypt it safely to keep it secret even when its stolen or leaked otherwise. Since backups are frequently created by scripts without user interaction you probably require encryption keys working without a passphrase. Here comes a solution to this problem.

Below there is a script using OpenSSL to symmetrically encrypt some arbitrary file using a one-time key. Due to using one-time key this must be backed up in combination with the encrypted data and thus needs to be protected itself. This is achieved by asymmetrically encrypting it using some public key which is available to the encrypting service. Since that key is public it isn't protected by any passphrase and thus the whole script can be used to encrypt on regular basis.

#!/bin/bash

DATAFILE="${1}"
PUBKEYFILE="${2}"
KEYOUTFILE="${3}"


UMASK="$(umask)"
umask 0077

# create random one-time passphrase
PASSPHRASEFILE="$(mktemp)"

dd if=/dev/urandom count=1 bs=128 2>/dev/null | base64 -w0 >>"$PASSPHRASEFILE"

# encrypt file symmetrically using one-time passphrase
/usr/bin/openssl enc -aes-256-cbc \
        -pass file:"$PASSPHRASEFILE" \
        -out "${DATAFILE}.encrypted" \
        -in "${DATAFILE}"
status="$?"

umask "$UMASK"

if [ "$status" -eq 0 ]
then
        # asymmetrically enrypt one-time passphrase using public key
        /usr/bin/openssl rsautl -encrypt -pubin \
                -inkey "$PUBKEYFILE" \
                -in "$PASSPHRASEFILE" \
                -out "$KEYOUTFILE"
        status="$?"
fi

rm "$PASSPHRASEFILE" || echo "ALERT: failed removing cleartext passphrase" >&2

exit $status

The second script is required to decrypt any data encrypted using the script above. It takes the encrypted data and the additionally encrypted one-time key, but requires private key matching the public one used on encrypting. This private key doesn't have to be available to the encryption service and thus should be stored in a safe place like an encrypted USB stick put in a locker at your office or similar.

You should protect it with a passphrase, too. This way you can't restore from backups automatically, though, as you need to enter that passphrase when running the script which is okay for us.

#!/bin/bash

DATAFILE="${1}"
PRIVKEYFILE="${2}"
KEYINFILE="${3}"

CLEARDATAFILE="${DATAFILE%.encrypted}"
if [ "$CLEARDATAFILE" = "$DATAFILE" ]
then
        CLEARDATAFILE="${DATAFILE}.decrypted"
fi


UMASK="$(umask)"
umask 0077

# create temporary file to hold cleartext passphrase
PASSPHRASEFILE="$(mktemp)"

# asymmetrically decrypt passphrase
/usr/bin/openssl rsautl -decrypt \
        -inkey "$PRIVKEYFILE" \
        -out "$PASSPHRASEFILE" \
        -in "$KEYINFILE"
status="$?"


umask "$UMASK"

if [ "$status" -eq 0 ]
then
        # decrypt file symmetrically using decrypted passphrase
        /usr/bin/openssl enc -d -aes-256-cbc \
                -pass file:"$PASSPHRASEFILE" \
                -in "${DATAFILE}" \
                -out "${CLEARDATAFILE}"
        status="$?"
fi

rm "$PASSPHRASEFILE" || echo "ALERT: failed removing cleartext passphrase" >&2

exit $status

Usage

Both scripts take three arguments:

  1. name of file to be encrypted/decrypted
  2. name of file containing public key (on encrypting) or private key (on decrypting)
  3. name of encrypted one-time key combined with encrypted data file

On encrypting the data is read from given file and written to file with additional extension .encrypted. On decrypting the given file name might end with .encrypted. In this case, the resulting file is named without that additional extension. If encrypted file's name does not end with .encrypted the decrypted file's name is extended by .decrypted, instead.

./encrypt.sh some-backup.tgz public-key.pem backup.key

This example will encrypt some compressed tar archive using provided public key. The encrypted archive will be available in file some-backup.tgz.encrypted. Your backup must include file backup.key which is also created by the script.

./decrypt.sh some-backup.tgz.encrypted private-key.pem backup.key

This example decrypts content of file some-backup.tgz.encrypted and writes resulting data to file some-backup.tgz. The required key is found in provided file backup.key which needs to be decrypted itself using provided private key file.

How safe is it?

This approach helps with creating encrypted backups prior to putting them into probably insecure storage such as  cloud storage. This storage may be considered safe as long as your private key is kept in a safe offline place. You still need to protect your service using any sensitive information prior to be backed up. But attacking it won't leak backups you've made before (except for any unchanged sensitive information that is still available via that service).

Go back