TIP Encrypted GNUCash
From Gentoo Linux Wiki
| Terminals / Shells • Network • X Window System • Portage • System • Filesystems • Kernel • Other |
[edit] Encrypted GNUCash
[edit] Introduction
I've been using GnuCash since a few months ago, and I was worried about having all the information about my accounts, expenses and incomes stored in clear text files. So I thought it would be a good idea to store the data in a more secure way.
This tip uses GnuPG to encrypt files. The shell script basically does the following:
- if the encrypted bookfile is not found, but the data file is then
- run the program
- encrypt afterwards
- else (the encrypted bookfile is found)
- ask user for password
- decrypt
- run the program
- encrypt afterwards
You can make a link from your menu, or on the desktop to start it. You can choose how you want to be asked for the password: zenity (gnome, xfce dialog), kdialog (for kde) or, if you prefer to call the script from the shell, a simple text question.
[edit] Software you will need
- "app-arch/tar"
- "app-arch/gzip"
- "app-crypt/gnupg"
- optionally, but useful: "gnome-extra/zenity" or "kde-base/kdialog"
- Your pair of secret/public GnuPG keys have to be set up.
| Code: gpgarmor.sh |
#!/bin/bash
# gpgarmor - based on code by Jose Antonio Martin
# rewritten by Johannes Buchner
#
# This shell script will wrap around any program and protect the data files
# by encrypting it using tar and gpg.
# You can put a link to this script on your desktop or in the menu.
#
# Adjust the following options:
# program to call
PROG="gnucash"
# executing directory (where your data file lives)
DIR="/home/user/test"
# File which is parameter for the program (PROG).
# The encrypted file will be called the $BOOK.tar.gz.asc
BOOK="mybook"
# All files that should be protected (archived and encrypted).
FILES="${BOOK} ${BOOK}.*.xac ${BOOK}.*.log"
# Your gpg key ID. Read man gpg section HOW TO SPECIFY A USER ID
KEY="<buchner.johannes@myhost.com>"
# KEY="0xFA9572BD" # another possible format
# less important:
# which interface you want to use: zenity (gnome/xfce), kdialog (kde) or simple text
INTERFACE_ERR='zenity --error --text'
INTERFACE_PASS='zenity --entry --hide-text --text '
#INTERFACE_ERR='kdialog --error'
#INTERFACE_PASS='kdialog --password '
#INTERFACE_ERR='echo' # INTERFACE_PASS will be read from shell if this is set
function do_error {
$INTERFACE_ERR "$@"
cd - &> /dev/null
exit 1
}
function run_and_encrypt {
"$PROG" $BOOK
tar -czf "$BOOK.tar.gz" $FILES ||
do_error "tar failed on $BOOK"
gpg --recipient "$KEY" --armor --encrypt "$BOOK.tar.gz" ||
do_error "gpg encryption failed on $BOOK"
rm -f $FILES $BOOK.tar.gz
cd - &> /dev/null
exit 0
}
cd "$DIR"
test -f "$BOOK.tar.gz.asc" || \
if test -f "$BOOK"; then
# Found not-encrypted file (first-run)
run_and_encrypt ||
do_error "book \"$BOOK\" not found"
fi
rm -f "$BOOK.tar.gz"
# Found encrypted file
if [[ "$INTERFACE_ERR" == 'echo' ]]; then
gpg --quiet --decrypt --output "$BOOK".tar.gz "$BOOK".tar.gz.asc ||
do_error "gpg decryption failed"
else
$INTERFACE_PASS 'GnuPG passphrase for '"$KEY"':' |
gpg --quiet --decrypt --batch --passphrase-fd 0 \
--output "$BOOK".tar.gz "$BOOK".tar.gz.asc ||
do_error "gpg decryption failed"
fi
# untar
tar -zxkf "$BOOK.tar.gz" &> /dev/null
rm -f $BOOK.tar.gz "$BOOK.tar.gz.asc"
run_and_encrypt
|
A few notes of caution when using the above script:
(1) rm does not destroy the original file from the disc, it simply removes it from the directory. An intruder with suitable hard-disc analysis software can usually retrieve it. A very well-equipped intruder may even recover it after it has been overwritten, if he is willing to make a substantial investment. Safer to precede this with the shred command which overwrites the file several times (e.g., 25) with pseudo-random data.
(2) It is a little dangerous to use pgp public keys for this process. They may have an expiry date set, or a user unaware of the inner workings of this script may discard a PGP public key, thereby rendering the locked files inaccessible. Some might prefer a symmetric key which is sufficient for this purpose. In this case the password should be confirmed (user prompted twice).
(3) It might be safer to pack the entire gnucash directory into the tar ball since not all files correspond to the $FILES mask. However, executing rm -f * is a bit frightening...
This works for me:
| Code: gpgarmor.sh |
#!/bin/bash
# gpgarmor - based on code by Jose Antonio Martin
# rewritten by Johannes Buchner
#
# This shell script will wrap around any program and protect the data files
# by encrypting it using tar and gpg.
# You can put a link to this script on your desktop or in the menu.
#
# Adjust the following options:
# program to call
PROG="gnucash"
# executing directory (where your data file lives)
DIR="/home/pdb/test"
# File which is parameter for the program (PROG).
# The encrypted file will be called the $BOOK.tar.gz.asc
BOOK="gnucash"
# All files that should be protected (archived and encrypted).
FILES="${BOOK} ${BOOK}.*.xac ${BOOK}.*.log"
#INTERFACE_ERR='zenity --error --text'
#INTERFACE_PASS='zenity --entry --hide-text --text '
INTERFACE_ERR='kdialog --error'
INTERFACE_PASS='kdialog --password '
#INTERFACE_ERR='echo' # INTERFACE_PASS will be read from shell if this is set
function do_error {
$INTERFACE_ERR "$@"
cd - &> /dev/null
exit 1
}
function run_and_encrypt {
"$PROG" $BOOK
tar -czf "$BOOK.tar.gz" $FILES ||
do_error "tar failed on $BOOK"
if [[ "$INTERFACE_ERR" == 'echo' ]]; then
gpg --quiet -ca --output "$BOOK".tar.gz.asc "$BOOK".tar.gz ||
do_error "gpg encryption failed"
else
PASS1=`$INTERFACE_PASS "Enter passphrase"`
PASS2=`$INTERFACE_PASS "Repeat passphrase"`
while [ $PASS1 != $PASS2 ]
do
$INTERFACE_ERR 'Error. Passphrases do not match'
PASS1=`$INTERFACE_PASS "Enter passphrase"`
PASS2=`$INTERFACE_PASS "Repeat passphrase"`
done
gpg --quiet -ca --batch --passphrase $PASS1 \
--output "$BOOK".tar.gz.asc "$BOOK".tar.gz ||
do_error "gpg encryption failed"
fi
shred $FILES $BOOK.tar.gz > /dev/null
rm -f $FILES $BOOK.tar.gz
cd - &> /dev/null
exit 0
}
cd "$DIR"
test -f "$BOOK.tar.gz.asc" || \
if test -f "$BOOK"; then
# Found not-encrypted file (first-run)
run_and_encrypt ||
do_error "file \"$BOOK\" not found"
fi
# Found encrypted file
if [[ "$INTERFACE_ERR" == 'echo' ]]; then
gpg --quiet --decrypt --output "$BOOK".tar.gz "$BOOK".tar.gz.asc ||
do_error "gpg decryption failed"
else
$INTERFACE_PASS 'Enter passphrase:' |
gpg --quiet --decrypt --batch --passphrase-fd 0 \
--output "$BOOK".tar.gz "$BOOK".tar.gz.asc ||
do_error "gpg decryption failed"
fi
# untar
tar -zxkf "$BOOK.tar.gz" &> /dev/null
shred $BOOK.tar.gz "$BOOK.tar.gz.asc"
rm -f $BOOK.tar.gz "$BOOK.tar.gz.asc"
run_and_encrypt
|
