Encrypting a USB flash drive on Ubuntu

Using an encrypted USB flash drive is more or less transparent on Ubuntu. In the Nautilus file manager the drive mounts automatically and looks and works the same as any other drive. The only noticeable difference is that you will be prompted for a passphrase when the drive mounts.

Install cryptsetup

This is the only extra package we need:

sudo apt-get install cryptsetup

Find the USB device node

Applications usually work with disks through the Virtual File System that abstracts away the actual filesystem (of which Linux has plenty ext3, ext4, xfs etc.) and the physical media. However to encrypt and format a USB flash drive we need to work directly with the raw device. We do so through the device node. Disk devices have device nodes such as /dev/sda and /dev/sdb. It's important we find the correct one as the changes we will be doing are destructive to the content of the drive.

Insert the USB flash drive and run the command lsblk:

bob@home:~$ sudo lsblk
sda 8:0 0 238.5G 0 disk
--sda1 8:1 0 350M 0 part
--sda2 8:2 0 3G 0 part
--sda3 8:3 0 220.1G 0 part /
--sda4 8:4 0 1K 0 part
--sda5 8:5 0 15.1G 0 part [SWAP]
sdb 8:16 1 500M 0 disk /media/1173-7DA0

USB flash drives usually come formatted with a FAT filesystem from the factory and Ubuntu will mount it somewhere under the /media folder. From the output above we find the USB flash drive device node to be sdb. The full device node name is therefore /dev/sdb.

Fill the drive with noise

This is your last chance to backup any existing files on the USB flash drive. You can copy the files from the /media folder to your harddisk. The next step wipes all data on the USB flash drive.

Now we are going to put random data on the entire USB disk to increase encryption strength. An attacker will have less information to work with when he can't distinguish the part of the disk that is empty from the part that has actual files.

First unmount the USB from the file hierarchy. The argument to umount is the USB folder name under /media as listed in the output of the lsblk command.

umount /media/3173-7DA0

Ideally we would put random data on the USB flash drive using this command:

sudo dd if=/dev/urandom of=/dev/sdb bs=4K

But /dev/urandom is rather slow in generating random data (by design) and there is no progress indicator. To get an idea how long it would take to fill the whole disk we can measure the performance of urandom on a small block of data and compare that with the size of the USB flash drive. Here we measure the performance over 100 MB of random data.

bob@home:~$ dd if=/dev/urandom of=/dev/null bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 15.1391 s, 6.9 MB/s

6.9 MB/s is OK for a small 500 MB drive but if the capacity of your drive is in the gigabytes then you probably want this alternative method which is fast, and even has a progress indicator, but is not as random:

sudo badblocks -c 10240 -s -w -t random -v /dev/sdb

Partition the drive

Create a new primary partition:

bob@home:~$ sudo fdisk /dev/sdb
Command (m for help): n
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-1023999, default 2048):
Command (m for help): w

If we run lsblk again we can now see the new partition is on the device node /dev/sdb1. This is the node we want to encrypt.

bob@home:~$ sudo lsblk
sda 8:0 0 238.5G 0 disk
--sda1 8:1 0 350M 0 part
--sda2 8:2 0 3G 0 part
--sda3 8:3 0 220.1G 0 part /
--sda4 8:4 0 1K 0 part
--sda5 8:5 0 15.1G 0 part [SWAP]
sdb 8:16 1 500M 0 disk
--sdb1 8:17 1 499M 0 part

Setup LUKS

Using the cryptsetup command we will format the drive with Linux Unified Key Setup (LUKS). LUKS stores some metadata at the beginning of the partition regarding the type of encryption used and the encryption key. The key is randomly generated but is itself encrypted using a passphrase that you provide. The passphrase should be at least 3 random words.

bob@home:~$ sudo cryptsetup luksFormat /dev/sdb1

Now create a virtual device using cryptsetup that encrypts and decrypts all data going to and from the physical device.

bob@home:~$ sudo cryptsetup luksOpen /dev/sdb1 myusb

The virtual device is created using a feature built into the Linux Kernel called the Device Mapper. The virtual device is made available under the device node /dev/mapper/myusb. This is the device that eventually will be mounted into the file hierarchy, but before we can mount it we need a filesystem on the device.

Putting a filesystem on the device

So let's put a EXT4 filesystem on the device. Using the -L option we can freely choose a label although it cannot be longer than 16 characters. The label is how the USB flash drive will later appear in the Nautilus file manager.

Because we do this work through the virtual device node /dev/mapper/myusb the whole EXT4 filesystem will be encrypted!

bob@home:~$ sudo mkfs.ext4 /dev/mapper/myusb -L myusb

Now close the virtual device.

sudo cryptsetup luksClose myusb

And remove the drive from the USB port.

Don't worry, as we shall see next, you don't have to create a virtual device yourself in your daily work with encrypted drives.

Mounting and using the encrypted drive

Insert the USB flash drive again. The Nautilus file manager detects the LUKS partition and prompts you for the passphrase. Enter the passphrase and the drive is now mounted and ready to use.

Should you find yourself without a graphical user interface then you can create the virtual device and mount it from commandline.

sudo cryptsetup luksOpen /dev/sdb1 myusb
sudo mkdir -p /media/myusb
sudo mount /dev/mapper/myusb /media/myusb

And to unmount the USB flash drive:

sudo umount /media/myusb
sudo cryptsetup luksClose myusb