Ubuntu hard drive encryption with external key
We present the following improved method for installing Ubuntu desktop on an encrypted hard drive and storing the encryption key on a password-protected USB stick or memory card. It works on Ubuntu 7.10 (Gutsy Gibbon) and 8.04 (Hardy Heron).
Our method is heavily based on a clever solution called GutsyLUKSTwoFormFactor from the community documentation for Ubuntu. We wish to simplify and update the procedure by taking advantage of the Ubuntu Live CD to perform the actual desktop installation, as was done in the article Encrypted root using LUKS and Ubuntu 7.04 installer. For a similar method in pure Debian, you might want to check out Wejn’s solution.
Note that there are many simpler HOWTOs and tutorials for using encryption on Ubuntu, which are based on using the Ubuntu Alternate Install CD. The major limitation of such methods is that they depend solely on a single passphrase. Our method stores a 256-bit key on a portable device, which is, in turn encrypted by a passphrase.
(1) Equipment check
The instructions on this page will clearly destroy your data, so make backups before proceeding. Also, there is no such thing as digital data security so don’t depend on it. By proceeding, you agree to audit this procedure yourself and take responsibilty for any risks of any kind that you might incur. Please help us to spot flaws and make improvements by leaving comments.
All of the following steps occur within the Ubuntu Live CD desktop environment. So, download it, burn it, boot it. We are using Ubuntu 8.04 LTS (Hardy Heron) PC (Intel x86) desktop CD.
When we refer to a USB drive, note that this can be a standalone flash drive or any kind of memory card or other similar device.
(2) Prepare an encrypted USB drive to store the key
After you boot into the Ubuntu Live CD environment, plug in your USB drive. If it’s already formatted, Ubuntu may try to auto-mount it, in which case it will appear as an icon on the desktop. The USB drive needs to be unmounted, so just right-click on it and unmount it.
Open a terminal window and figure out your device names. Your USB drive will be something like /dev/sda, /dev/sdb, etc.
dmesg | grep sd
In this example (see screenshot), the dmesg output shows a 107 MB device on /dev/sdb and a much larger 8590 MB device on /dev/sda. The /dev/sda device is the hard drive and /dev/sdb is the USB drive. The instructions will always have /dev/sd@ as the USB device name and /dev/sdx as the hard drive device name. You’ll have to substitute as appropriate for your circumstances. So, we would substitue /dev/sdb for /dev/sd@ (the USB drive) and /dev/sda for /dev/sdx (the hard drive).
If your hard drive has an IDE connection rather than SATA, its device name will be /dev/hda or something similar. Figure it out like this.
dmesg | grep hd
Proceed once you know the device names for your USB drive and your hard drive.
Now, be the root user.
sudo -i
Fill the USB drive with random bits.
dd if=/dev/urandom of=/dev/sd@
Install needed packages into the Live CD environment and add load dm-crypt.
aptitude -y install cryptsetup
modprobe dm-crypt
Format the USB drive with a 256-bit AES encryption (see cryptsetup man page for more info). You will be prompted for a passphrase, which should be a good one! This passphrase protects your stick, on which your computer’s encryption key will be stored.
cryptsetup luksFormat --hash=sha512 --cipher=aes-cbc-essiv:sha256 --key-size=256 /dev/sd@
cryptsetup luksOpen /dev/sd@ cryptkeys
So, now the encrypted USB device is mapped to /dev/mapper/cryptkeys, which we will format as ext2 and mount.
mkfs.ext2 /dev/mapper/cryptkeys
mount /dev/mapper/cryptkeys /mnt
Make a random keyfile that’s 256 bits big using the device /dev/random. According to the random man page, it’s “suitable for uses that need very high quality randomness such as one-time pad or key generation.” Also, “when the entropy pool is empty, reads from /dev/random will block until additional environmental noise is gathered.” So, move your mouse around and execute:
dd if=/dev/random of=/mnt/mykey bs=1 count=256
Now we have a key at /mnt/mykey.
(3) Encrypt and partition your hard drive
It’s not a bad idea to fill the drive with random bits, but this takes a long time. It’s up to you if you want to skip it. Remember to substitute /dev/sdx for the hard drive device we figured out in (1). And, as previously mentioned, this will destroy your data (!!) so be sure about what you’re doing.
dd if=/dev/urandom of=/dev/sdx
Now, we will create the following partitions with fdisk, but the same effect can be achieved with a GUI tool like gparted.
- 100 MB for /boot
- 1 GB for swap
- and the rest on /
We will use these one-letter commands in fdisk:
- o create a new empty DOS partition table
- n add a new partition
- a toggle a bootable flag
- p print the partition table
- w write table to disk and exit
Run fdisk and issue these commands (see below for a lazy method).
fdisk /dev/sdx
- Enter o to clear the partition table.
- Enter n, then 1, then p for primary, then hit enter for the default, then +100M for a 100 megabyte chunk.
- Enter n, then 2, then p for primary, then hit enter for the default, then +1G for a 1 gigabyte chunk.
- Enter n, then 3, then p for primary, then hit enter twice for the defaults, to use the remainder of the disk.
- Enter a, then 1, to set bootable flag on the first partition.
- Enter p to show you the partitions.
- Enter w to write the partition data and quit.
The express/lazy method of doing everything at once is:
echo -e "o\nn\np\n1\n\n+100M\nn\np\n2\n\n+1G\nn\np\n3\n\n\na\n1\np\nw\n" | fdisk /dev/sdx
You should see some output like this.
Encrypt the root partition (/dev/sdx3) with the key generated in step 2.
cryptsetup --hash=sha512 --cipher=aes-cbc-essiv:sha256 --key-size=256 luksFormat /dev/sdx3 /mnt/mykey
Open the drive as root, which will create the device /dev/mapper/root.
cryptsetup --key-file /mnt/mykey luksOpen /dev/sdx3 root
Now we’re ready to install Ubuntu on root.
(4) Install Ubuntu
Double-click the install icon on the desktop and do the following.
- choose language and time zone, etc.
- then choose manual partitioning
- click on /dev/mapper/root, click new partition table, then click on the free space, click new paritition, select ext3, mount point /, and check the format box if necessary
- click /dev/sdx1, click edit parition, select ext3, mount point /boot, check the format box
- click /dev/sdx2, click edit parition, select swap area

- leave the rest
- do NOT restart (!!) at the end of the installation
(5) Configure the crypttab
Find out the UUIDs of the USB stick and all the sdx partitions. Just leave the output on the screen, we’ll use it in a second.
ls -l /dev/disk/by-uuid
Unmount and close USB drive (you can unplug it too).
umount /mnt
cryptsetup luksClose cryptkeys
Mount the new system (n.b. we’re reusing the same mount point that was last used by the USB drive):
mount /dev/mapper/root /mnt
Edit the crypttab, which is easy with gedit:
gedit /mnt/etc/crypttab &
Make it look something like this, substituting in UUIDs that correspond to the swap (/dev/sdx2), root (/dev/sdx3) and USB drive (/dev/sd@) device names. The screenshot might help.
# <target name> <source device> <key file> <options>
swap /dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /dev/random swap
root /dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/mykey luks,keyscript=/usr/local/sbin/keyscript
Ubuntu doesn’t come with a script that will look for a key on an external USB drive, so you have to provide one. You can use the one that we use or roll your own. A key script is a personal thing, so we recommend customizing it a little or at least familiarizing yourself with it. The following steps use our script.
cd /mnt/usr/local/sbin
wget http://mazeoflies.com/files/keyscript
chmod 755 keyscript
Basically, the crypttab is an administrator-maintained file that describes your encrypted filesystems. Here it’s saying, give the arbitrary name swap to a certain disk (by UUID) and use /dev/random as the key, which will result in a random key for each boot. The option swap at the end of the line tells the system to use mkswap to create the filesystem. The next line says, give the name root to a certain disk (by UUID), with the options luks (which uses LUKS encryption extensions) and keyscript. The script that we just installed to /usr/local/sbin will receive as a parmeter:
/dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/mykey
The keyscript will then use this parameter to get the key mykey from the USB drive (examine the keyscript to see how this happens).
(6) Configure the boot menu and the fstab
Mount the boot drive:
mount /dev/sdx1 /mnt/boot
Edit the boot menu.
gedit /mnt/boot/grub/menu.lst &
Take out splash from the defoptions line. The splash screen needs to be removed because the keyscript we’re using doesn’t support it.
Now, fstab needs to be modified to use the encrypted partitions.
gedit /mnt/etc/fstab &
For the root entry, take out UUID=xxxx… and replace with /dev/mapper/root and similarly, for the swap entry take out UUID=xxxx… and replace with /dev/mapper/swap. The result might look something like this:
(7) Get into the system
Mount another few things in preparation to “change root” into the new system.
for dir in proc dev sys; do mount --bind /$dir /mnt/$dir; done
Change root and say hello to your new system.
chroot /mnt
Update Ubuntu and install cryptsetup (all this takes a bit of time, but hey, it’s your new system, so it’s worth it).
aptitude -y update && aptitude -y safe-upgrade
aptitude -y install cryptsetup
Yes, that was the second time you had to install cryptsetup, but the first time was only for the Live CD environment. This time it’s for your system.
(8) Update and verify initramfs
update-initramfs -u ALL
update-grub
This process will examine the fstab and crypttab modifications we’ve made and build an appropriate image for the initial root filesystem. The initramfs, which is a gzipped cpio archive living in /boot/, can be examined by unzipping it.
mkdir /tmp/initramfs
cd /tmp/initramfs
gunzip -c -9 /boot/initrd.img-`uname -r` | cpio -i -d -H newc --no-absolute-filenames
The first thing to check is for the presence of a file called cryptroot.
cat conf/conf.d/cryptroot
It should be similar to the crypttab, e.g.
target=root,source=/dev/mapper/root,key=/dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/keyfile.key,keyscript=/keyscripts/keyscript
Note that the path of the keyscript is now /keyscripts/keyscript, which you should also be able to find in the unpacked initramfs.
cat keyscripts/keyscript
This outputs the keyscript. Note that the update-initramfs command worked some magic to find the keyscript that we put in /usr/local/sbin and stuff it into the initramfs image.
(9) Reboot
exit
for dir in proc dev sys boot; do umount /mnt/$dir; done
cd
umount /mnt
cryptsetup remove root
Cross your fingers. Reboot and plug in your USB stick. If everything worked, your new system prompt you for a password to unlock the stick and then boot you into your new system.
(10) Post-installation
It worked? Nice. Open a terminal window.
cat /proc/swaps
The output should mention /dev/mapper/swap as the swap partition. Then try out these commands. They show the status of the two encrypted partitions.
sudo cryptsetup status swap
sudo cryptsetup status root
Summary
Now the hard drive is partitioned into three parts. The swap partition is encrypted with a random key. The root partition is encrypted with a 256-bit key that is stored on a USB stick, which itself is encrypted with a password. Note that the third, boot, partition is not encrypted, and is therefore susceptible to being modified by anyone having access to the machine. Also, if someone gains access to your machine while it’s on or in sleep mode, the key can be found in the RAM and the whole encryption scheme falls apart. There is a more detailed, but not exhaustive, discussion of vulnerabilities in the GutsyLUKSTwoFormFactor article and elsewhere on the internet. As stated in the introduction, spend time and energy auditing this procedure in proportion to your security needs.






This is a great article. The reason I haven’t encrypted my filesystems up to now is that I see a high risk of losing my data by either forgetting the password, losing the encryption key (if it’s stored somewhere) or somehow otherwise corrupting a key part of a file index or something. So many times I’ve accidentally screwed up an important part of my OS (especially on Windows computers) and had to rip out the hard drive and recover the data on a second computer. In this case, the whole system is only as good as not losing the USB key or not having it corrupted accidentally, like being stepped on or chewed up by a cat.
In the end, the door to my apartment is (hopefully) enough security for my PC.
Hi antipode, thanks for the pointer - as you can see I found my way here :) I’ll need time to look at this in more detail, but it looks like a great way of doing things… and it’s a big way to kick off a new blog, too!
Really great article, thank you very much !
I successfully setup the encryption on my eeePC with eeebuntu netbook.