Encrypted USB stick using LUKS

A quick blog on how to create an encrypted USB stick for some secure storage. For example to store/backup your private keys, GPG keys, scans of your important documents and any other files you don’t want falling in the wrong hands. I intend to backup my (private) keys and some client information to the stick. I use a small old stick (just 256MB) for this. If you’re using a larger stick you can partition it, for example a large first partition formatted as FAT32 for general use, and a smaller second partition to encrypt.


First off, you need a (recent) Linux machine with dm_crypt support and the cryptsetup utility. The first is often included in the default kernel config, and the cryptsetup utility can likely be installed using your package manager. On Debian this is done as follows:

# apt-get install cryptsetup

Clear the drive

To make your encrypted files less distinguishable from any free space on the drive it is a good idea to perform a secure erase by filling the drive with random data before you set up the encryption. There are multiple ways to do this. In this case I like to keep it simple and use ‘dd’ to write pseudo-random data to the entire drive. Beware: ‘dd’ will do as it’s told, so make absolutely sure you got the output device set right or it will destroy your precious data.

# dd if=/dev/urandom of=/dev/sdb bs=1M

This step is optional, but I recommend doing it. Not only will it make your encrypted data blend in, it will also overwrite any remnants of old data on the drive. So any old file(-system) structures will be gone as well, preventing old files being read or confusing any utilities looking at the drive.

Create the encrypted volume


After you have wiped the drive, you will need to recreate the partition table. For my USB stick I can use fdisk for this job, and it will probably be sufficient in most other cases. In case you need/want (e.g. disks larger than 2TB) the more modern GPT way of partitioning you can look a gdisk for this purpose.

# fdisk /dev/sdb
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0x8127bc8c.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

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): 
Using default value 1
First sector (2048-506111, default 2048): 
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-506111, default 506111): 
Using default value 506111

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

The new partition is now available at /dev/sdb1 in my case.

Configuring LUKS

Now it’s time to add the encryption layer, which is handled by the device mapper (dm_mod) and dm_crypt. In most cases the required modules are loaded automatically when you need them. In case your system does not, you can load them by hand:

# modprobe dm_mod 
# modprobe dm_crypt

Encrypt the fresh partition is done with cryptsetup. It has plenty of options, so feel free to read the manual or look up some additional information if you feel you want to deviate from the default, for example to use a stronger cipher, longer key-size, different hashing algorithm, etc.

This is also the moment to think of a passphrase required to access the volume, as you will be asked to provide one now.

A simple sane variant you can use:

# cryptsetup -c aes-xts-plain64 -s 512 -y luksFormat /dev/sdb1

Or, a little stronger one that I used:

# cryptsetup -c aes-xts-plain64 -s 512 -h sha512 -i=5000 --use-random -y luksFormat /dev/sdb1

This will overwrite data on /dev/sdb1 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter LUKS passphrase: 
Verify passphrase:

This uses /dev/random instead of /dev/urandom to generate the master key. Note that this will block if there is not enough random data, so try to have your entropy pool filled up a bit. You can check how many bits are in there by checking /proc/sys/kernel/random/entropy_avail.

Adding a file-system

To be able to store data on your encrypted drive, you need a mountable file-system on there. First, you need to mount the encrypted partition in unencrypted form, so it can be accessed like any other drive. Next, you format the decrypted partition, for example with the ext4 file-system or something multi-platform like FAT32. And lastly, unmount it again.

# cryptsetup luksOpen /dev/sdb1 USBVault
Enter passphrase for /dev/sdb1: 
# mkfs.ext4 -m 0.1 -L USBVault /dev/mapper/USBVault
mke2fs 1.42.5 (29-Jul-2012)
Filesystem label=USBVault
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
62496 inodes, 249984 blocks
249 blocks (0.10%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
31 block groups
8192 blocks per group, 8192 fragments per group
2016 inodes per group
Superblock backups stored on blocks: 
        8193, 24577, 40961, 57345, 73729, 204801, 221185

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

# cryptsetup luksClose USBVault

Done! You can now unplug the drive from your machine.

Using the encrypted stick

It works just like a regular stick, with the exception that you need to enter the passphrase before it mounts. Insert the stick, a notification pops up and as soon as I try to mount the stick I get asked for the passphrase. From that point forwards it’s just like any other stick. Copy files to it, and don’t forget to unmount it cleanly when you’re done. Works fine KDE 4.8 over here, had a similar result on a machine running XFCE.