dt.iki.fi

Encrypt a USB stick

This is still work in progress.

A USB stick set up in this way is recognised by common filemanagers (e.g. Thunar, PCManFM) - it shows up as an encrypted device in the side bar, a password dialog pops up, and the twofold decrypt/mount process happens on one click.

We will be using LUKS. The "plain dm-crypt" method might be faster, but it does not offer that convenience.

I have done this before on a consumer 32GB USB (3.0) stick but had noticed occasional lag (freezes) when reading files, so this time I am trying to get faster decryption (trading off some security no doubt).
Whether this will succeed remains to be seen. This article suggests that the bottleneck might be elsewhere, but faster encryption might still help...

We are root.
Find out which device you want to encrypt with fdisk -l. Let's say it's dev/sdX.
By the way, we will be encrypting the whole device, and not create a partition for it first. So there will be only one filesystem on it later, and one - well, partition.
I'm not sure if it's required, but better to a) unmount it and b) nuke it with e.g.: dd if=/dev/urandom of=/dev/sdX bs=16M count=10.

The cryptsetup command offers a benchmark function:

$> cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1      1661768 iterations per second for 256-bit key
PBKDF2-sha256    2088796 iterations per second for 256-bit key
PBKDF2-sha512    1468593 iterations per second for 256-bit key
PBKDF2-ripemd160  851116 iterations per second for 256-bit key
PBKDF2-whirlpool  640156 iterations per second for 256-bit key
argon2i       5 iterations, 1048576 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
argon2id      5 iterations, 1048576 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
#     Algorithm |       Key |      Encryption |      Decryption
        aes-cbc        128b      1086.6 MiB/s      3287.4 MiB/s
    serpent-cbc        128b        89.1 MiB/s       707.8 MiB/s
    twofish-cbc        128b       199.9 MiB/s       373.4 MiB/s
        aes-cbc        256b       834.2 MiB/s      2658.0 MiB/s
    serpent-cbc        256b        92.7 MiB/s       707.9 MiB/s
    twofish-cbc        256b       205.8 MiB/s       373.0 MiB/s
        aes-xts        256b      2054.1 MiB/s      2063.4 MiB/s
    serpent-xts        256b       673.1 MiB/s       672.7 MiB/s
    twofish-xts        256b       370.5 MiB/s       372.0 MiB/s
        aes-xts        512b      1839.7 MiB/s      1891.6 MiB/s
    serpent-xts        512b       674.3 MiB/s       674.3 MiB/s
    twofish-xts        512b       367.2 MiB/s       370.9 MiB/s

The sentence "Tests are approximate using memory only (no storage IO)" is discouraging for my specific use case.
Nevertheless, I let the numbers dictate my choices:

#> cryptsetup luksFormat --hash sha256  --pbkdf pbkdf2 --iter-time 200 --cipher aes-cbc-essiv:sha256 --key-size 128  --verbose /dev/sdX

For reading, this should be the fastest option.

Create a filesystem (FAT32 is sufficient for my use case, and probably faster than a journaling filesystem):

#> cryptsetup luksOpen /dev/sde usbcrypt # "usbcrypt" or whatever label you like
#> mkfs.vfat /dev/mapper/usbcrypt

Further reading

https://wiki.archlinux.org/index.php/Dm-crypt/Device_encryption
https://wiki.gentoo.org/wiki/Dm-crypt_full_disk_encryption