Encrypt any block device


A hard drive or 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 in one click.

Device encryption, performance considerations-up-

We will be using dm-crypt with cryptsetup.

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 helps remains to be seen. This article suggests that the bottleneck might be elsewhere.

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, but of course mkfs.ext4 etc. is equally valid here):

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

That's all really.

Fixing permissions for Udisks-up-

Assuming the device shows up in your filemanager's sidebar - it should. If you want to access it through a single click, you have to give polkit permission to do so without additional user authentication (i.e. you only enter the decryption password, not the user or root password).

Are you getting "Not authorized to perform operation" instead, after entering the encryption passphrase, or are you getting an additional password dialog? Both mean the same thing: polkit requires additional authentication for mounting a (internal) device; FAT32 formatted USB drives usually do not require this.

If your filemanager uses udisks2, try this in a terminal first: udisksctl unlock -b /dev/sdX - if it only asks for the passphrase then it should work in your filemanager, too. If it asks for AUTHENTICATING FOR org.freedesktop.udisks2.encrypted-unlock-system etc., you can add this polkit rule:

polkit.addRule(function(action, subject) {
    if (
        action.id == "org.freedesktop.udisks2.encrypted-unlock-system" &&
        subject.local && subject.active && subject.isInGroup("storage")
    return polkit.Result.YES;

Save it in /etc/polkit-1/rules.d/ as e.g. allow-unlock.rules.

This applies to members of the storage group. I actually had to add my normal user (let's call it normuser) to that group with
sudo usermod -a -G storage normuser, but you could use any other group your user already belongs to. Check with id.

Now it should work, command line first:

udisksctl unlock -b /dev/sdX
Unlocked /dev/sdX as /dev/dm-0.
udisksctl mount -b /dev/dm-0
Mounted /dev/dm-0 at /run/media/normuser/XXXXXXXXX

And the same should happen when you click the device in your filemanager.

Changing ownership-up-

The filesystem on the device belongs to root. Let's change that. Assuming your normal user is called normuser:

cd /run/media/normuser/XXXXXXXXX # or wherever udisks mounted your device to
sudo chown -R normuser:normuser . ..
rmdir lost+found # for good measure and a clean slate

Further reading-up-