[TriLUG] encrypted filesystems
Alan Porter
porter at trilug.org
Thu Apr 27 16:03:12 EDT 2006
Ever since I played with Knoppix 3.3, I have been fascinated with
encrypted filesystems (Knoppix allows you to keep your persistent
data on a USB pen drive, either in the clear or encrypted).
If you have not played with encrypted filesystems, the magic is
done by the 'loop' device, /dev/loop#. I won't go into it here,
but you can Google for 'cryptoloop'.
Recently, I read an article that showed how to do some neat tricks
with encrypted filesystems. Most of the time you simply encrypt a
filesystem using a passphrase. However, if you want to change your
passphrase, you have to create a second encrypted filesystem with
the new passphrase and then copy over all of your data. Ugh. This
article explained how to use a key file, and then encrypt that key
file with your passphrase.
This led me to experiment a little, and it eventually led to a
little shell script to automate the process. I have included it
here, because I think the TriLUG community might find it useful.
You can play with it in your own home directory (it does not have
to be used on a USB pen drive, but that's a good situation where
an encrypted filesystem is handy).
Simply run the script to create an encrypted filesystem image:
sudo ./crypto.sh create test1
It'll ask you a few questions and then create a big file that looks
like gibberish. Then mount the filesystem:
sudo ./crypto.sh mount test1
It'll create a mount point directory called "test1.mnt" and it will
mount the encrypted filesystem there. When you're done, just unmount
it the same way.
sudo ./crypto.sh umount test1
You can change the passphrase with the script as well.
sudo ./crypto.sh password test1
None of this stuff is really new, and it's not really rocket science.
But I liked how the article used that key file, and I have found the
script to the useful. Maybe you will, too.
If you have questions about the script or about encrypted filesystems
in general, email me (either on-list of off-list).
Alan
[1] One common gotcha is storing a journaled filesystem image on top
of another journaled filesystem -- this can lead to data corruption.
In my script, I use a non-journaled ext2 filesystem. In practice, I
store this image on a FAT-based USB pen drive.
[2] This script was written for use on a Ubuntu system. I have seen
problems under Fedora, since their version of losetup took different
command-line parameters. I might not have had loop-aes-utils installed
properly.
--
#!/bin/sh
#-------------------------------------------------------------------------------
usage() {
echo "$program_name [ mount | unmount | create | password ] <basename>"
echo " example: $program_name mount crypto"
echo " mounts the 'crypto.img' filesystem on 'crypto.mnt'"
exit 0
}
#-------------------------------------------------------------------------------
find_available_loop_device () {
for loop_device in `( cd /dev ; ls -1 loop[0-9]* )` ; do
sudo losetup /dev/$loop_device 2> /dev/null
if [ $? -gt 0 ] ; then
return
fi
done
loop_device=""
}
#-------------------------------------------------------------------------------
find_loop_device_in_use () {
loop_device=`losetup -a | grep "\($image_file\)" | sed -e
"s/^\/dev\///g" | sed -e "s/:.*$//g"`
}
#-------------------------------------------------------------------------------
crypto_mount () {
# set up a loop device
find_available_loop_device
echo "Openssl will now ask for the password to the encrypted drive..."
openssl aes-256-ecb -d -in $key_file | losetup -p 0 -e AES256
/dev/$loop_device $image_file
if [ $? -ne 0 ] ; then
echo "Could not set up the loop device '$loop_device'."
losetup -d /dev/$loop_device
return
fi
echo "The loop device '$loop_device' has been set up."
losetup /dev/$loop_device
# create a mount point
mkdir $mount_point
# mount the filesystem
mount -t ext2 /dev/$loop_device $mount_point
if [ $? -ne 0 ] ; then
echo "The encrypted drive was not mounted properly."
losetup -d /dev/$loop_device
return
fi
echo "The encrypted drive has been mounted OK."
}
#-------------------------------------------------------------------------------
crypto_unmount () {
# unmount the filesystem
umount $mount_point
if [ $? -ne 0 ] ; then
echo "Could not unmount the encrypted drive."
else
echo "The encrypted drive is unmounted."
fi
# remove the mount point
rmdir $mount_point
# de-configure the loop device
find_loop_device_in_use
for ld in $loop_device ; do
losetup -d /dev/$ld
if [ $? -ne 0 ] ; then
echo "Could not deactivate the loop device '$ld'."
else
echo "The loop device '$ld' has been deactivated."
fi
done
# change the timestamp so we know that the image file may have been
modified
touch $image_file
}
#-------------------------------------------------------------------------------
crypto_password () {
echo "You are about to change the password for the encrypted drive."
echo "Enter the old password..."
plain=`openssl aes-256-ecb -d -in $key_file`
echo "Your old key file will be saved as '$key_file.old'."
mv $key_file $key_file.old
echo "Enter the new password (twice)..."
echo $plain | openssl aes-256-ecb -e -out $key_file
echo "The password has been changed."
}
#-------------------------------------------------------------------------------
crypto_create () {
# create the image file
if [ -f $image_file ] ; then
echo "File '$image_file' already exists... operation aborted."
return
fi
echo -n "Enter the filesystem size in megabytes: "
read size
dd if=/dev/zero of=$image_file bs=1M count=$size
# create the key file
plain=`head -c 2880 /dev/urandom | uuencode -m - | head -n 65 | tail
-n 64 | tr -d '\r\n'`
echo "Enter the encryption password (twice)..."
echo $plain | openssl aes-256-ecb -e -out $key_file
# find an available loop device
find_available_loop_device
# configure the loop device
echo $plain | losetup -p 0 -e AES256 /dev/$loop_device $image_file
# create the filesystem
mkfs.ext2 /dev/$loop_device
# de-configure the loop device
losetup -d /dev/$loop_device
}
#-------------------------------------------------------------------------------
crypto_test () {
find_available_loop_device
echo "available=[$loop_device]"
find_loop_device_in_use
echo "in_use=[$loop_device]"
}
#-------------------------------------------------------------------------------
# PERMISSIONS
if [ $EUID -ne 0 ] ; then
echo "You must be root to run this script."
exit
fi
# COMMAND-LINE OPTIONS
program_name=`basename $0`
if [ $# -ne 2 ] ; then
usage
fi
action=$1
basename=$2
# CONFIGURATION
image_file="$basename.img"
key_file="$basename.key"
mount_point="$basename.mnt"
# load mondules
modprobe aes
modprobe cryptoloop
# COMMAND-LINE PARAMETERS
case "$action" in
mount)
crypto_mount
;;
unmount|umount)
crypto_unmount
;;
password|passwd)
crypto_password
;;
create)
crypto_create
;;
test)
crypto_test
;;
*)
usage
;;
esac
More information about the TriLUG
mailing list