Unlocking a LUKS volume with a keyfile on an USB stick

As I wrote here, I’m trying to get LUKS running on a tablet. It works fine with a keyboard. But there is currently no option for an on-screen keyboard on fedora.
I’m trying to implement LUKS unlocking using an external USB stick with a keyfile. There are lots of (poorly documented) tutorials on the web. But for my use case, most of them are useless for my purposes.
What I want to do:

  • Store a keyfile on an USB stick identifiable by its name (file system label) for easy replacement if a stick dies.
  • Use an image as keyfile - not a suspicious looking text file with a random string.

What I did so far:

  • Build a systemd mount action which mounts any USB key with a certain name using a udev rule + systemd unit. > Tested: ok - the USB stick is automatically mounted.
  • Added a PNG image as keyfile. > Tested: luks dump slot ok, crypsetup --test-passphrase ok
  • Changed my crypttab:
    luks-… UUID=… /media/keystick/my-image.png discard,keyfile-timeout=10s

On boot it keeps asking for my passphrase.
What could go wrong?

I have 46 --key-file I use for Cold Store drives and have not had to do any of this.

All you need to do is add the keyfile to the Luks partition, add the usb drive to the /etc/fstab and /etc/crypttab and you are done.

Add the --key-file to luks:

  • cryptsetup luksAddKey /path/to/luks/device /path/to/key/file
  • enter password
  • done
  • edit /etc/fstab with UUID of the USB device
  • edit /etc/crypttab

I’m on CoffeeShop wifi, so if you give me about an hour, Once I get to the library I can give you some more details.


I would like to add that since you are using an image :

  • Get the SHA256/SHA512 of the image you want to use
  • Make a copy of it to keep in your KeepassXC vault
  • A picture while simple can be replaced, edited or manipulated to seem as an original.

Not sure if you are using other mechanisms like --pbkdf argon2id --pbkdf-force-iterations --hash sha512 so I won’t add more to that for now.

1 Like

I think my setup is mostly the same.

That differs from my use case. During my test, my first USB stick suddenly died. This prompted me to look for a simple replacement solution. So I would like to avoid any UID based mount points for this specific use case. My udev rule only looks at the label of the stick and mounts it automatically if it has a certain name. So I can quickly replace a dying stick. I don’t use any fstab entry so far. It’s all done by systemd.
Maybe my stick is mounted after the LUKS prompt. I was digging through journalctl to find more information, but I wasn’t successful.

That’s unfortunate, but it does happen and can happen with any device.

That is a more difficult approach IMO. udev > systemd.service > bash script ? I can’t test this for a system unlock, and I have had my own problems unlocking devices and running udev rules and systemd.services for a project I am doing with mixed results in the process. . .


On the way here : I just thought another method that might work for you…

I have a small collection of USB drives that I bought from Amazon. They are very cheap 32GB drives. I have key files in most of them. So in the //etc/fstab you can use by-name instead of by-uuid.

This is an alternative to using the UUID and should work in most cases. :+1:

The drawback is that the UUID is almost impossible to duplicate while the fs label is easy to duplicate and can result in having issues with duplicate volumes that may be mounted.
The advantage is as you already noted, a quick and easy change.

Thanks! I was not aware of this option. I will give it a try.

Yes, I agree. I usually prefer UUID for mounting or identifying an item. It’s just this special use case.

I’ll dig up the info I have, but there are several things you can do here. This is the crypttab entry I have for a machine that has about 32 keys.

/run/media/$USER/PNSTAW/ PNSTAW is the device name of these cheap USB’s I mentioned earlier. I’ll update this post with the relevant info in a few minutes.


Here is an older RHEL manual on this topic of identifiers:

If you type mount /dev/disk/by- and Tab you get:

# mount /dev/disk/by-

by-diskseq/   
by-id/        
by-partlabel/ 
by-partuuid/  
by-path/      
by-uuid/

Unfortunately, I haven’t made any progress. I have deactivated my systemd automount entries and changed fstab:

LABEL=mystick   /media/keystick/        vfat    defaults,user   0 0

Unfortunately, that didn’t work. I even tried it with a new keyfile. I wanted to rule out the possibility that it was just a problem with the file.
When I log into the desktop, the stick is mounted with root privileges. So mount seems to work. Bit it seems the mount point is not available at the LUKS unlock screen. Skimming through the journalctl output, I didn’t find any direct reference to the LUKS unlock . I attached some excerpts below. I suppose unlocking is done in the first part of this log snippet. I seems to be part of the dracut stage. My USB stick is mounted several seconds later, at the end of the log.
So I wonder: why is it working for you and not for me? Do I have to edit initram or Grub parameters?

01	Jul 06 11:44:59 urobe systemd-cryptsetup[563]: Set cipher aes, mode xts-plain64, key size 512 bits for device /dev/disk/by-uuid/53c47796-98e1-4fec-93bd-f85053508903.
02	Jul 06 11:45:01 urobe systemd[1]: Found device dev-disk-by\x2duuid-8fcdc430\x2d79bd\x2d4668\x2d944b\x2df6d9cbd59e5b.device - /dev/disk/by-uuid/8fcdc430-79bd-4668-944b-f6d9cbd59e5b.
03	Jul 06 11:45:01 urobe systemd[1]: Reached target initrd-root-device.target - Initrd Root Device.
04	Jul 06 11:45:01 urobe systemd[1]: Finished systemd-cryptsetup@luks\x2d53c47796\x2d98e1\x2d4fec\x2d93bd\x2df85053508903.service - Cryptography Setup for luks-53c47796-98e1-4fec-93bd-f85053>
05	Jul 06 11:45:01 urobe systemd[1]: Reached target cryptsetup.target - Local Encrypted Volumes.
06	Jul 06 11:45:01 urobe systemd[1]: Reached target sysinit.target - System Initialization.
07	Jul 06 11:45:01 urobe systemd[1]: Reached target basic.target - Basic System.
08	Jul 06 11:45:01 urobe systemd[1]: Finished dracut-initqueue.service - dracut initqueue hook.
09	Jul 06 11:45:01 urobe systemd[1]: Reached target remote-fs-pre.target - Preparation for Remote File Systems.
10	Jul 06 11:45:01 urobe systemd[1]: Reached target remote-cryptsetup.target - Remote Encrypted Volumes.
11	Jul 06 11:45:01 urobe systemd[1]: Reached target remote-fs.target - Remote File Systems.
12	Jul 06 11:45:01 urobe systemd[1]: dracut-pre-mount.service - dracut pre-mount hook was skipped because no trigger condition checks were met.
13	Jul 06 11:45:01 urobe systemd[1]: Starting systemd-fsck-root.service - File System Check on /dev/disk/by-uuid/8fcdc430-79bd-4668-944b-f6d9cbd59e5b...
14	Jul 06 11:45:01 urobe systemd[1]: Finished systemd-fsck-root.service - File System Check on /dev/disk/by-uuid/8fcdc430-79bd-4668-944b-f6d9cbd59e5b.
15	Jul 06 11:45:01 urobe systemd[1]: Mounting sysroot.mount - /sysroot...
16	Jul 06 11:45:01 urobe kernel: BTRFS: device label fedora_urobe devid 1 transid 2251 /dev/mapper/luks-53c47796-98e1-4fec-93bd-f85053508903 (253:0) scanned by mount (1185)
17	Jul 06 11:45:01 urobe kernel: BTRFS info (device dm-0): first mount of filesystem 8fcdc430-79bd-4668-944b-f6d9cbd59e5b
18	Jul 06 11:45:01 urobe kernel: BTRFS info (device dm-0): using crc32c (crc32c-intel) checksum algorithm
19	Jul 06 11:45:01 urobe kernel: BTRFS info (device dm-0): using free-space-tree
20	Jul 06 11:45:01 urobe systemd[1]: Mounted sysroot.mount - /sysroot.
21	Jul 06 11:45:01 urobe systemd[1]: Reached target initrd-root-fs.target - Initrd Root File System.
22	Jul 06 11:45:01 urobe systemd[1]: Starting initrd-parse-etc.service - Mountpoints Configured in the Real Root...
23	Jul 06 11:45:01 urobe systemd[1]: initrd-parse-etc.service: Deactivated successfully.
24	Jul 06 11:45:01 urobe systemd[1]: Finished initrd-parse-etc.service - Mountpoints Configured in the Real Root.
25	Jul 06 11:45:01 urobe systemd[1]: Reached target initrd-fs.target - Initrd File Systems.
26	Jul 06 11:45:01 urobe systemd[1]: Reached target initrd.target - Initrd Default Target.
27	Jul 06 11:45:01 urobe systemd[1]: dracut-mount.service - dracut mount hook was skipped because no trigger condition checks were met.
28	Jul 06 11:45:01 urobe systemd[1]: Starting dracut-pre-pivot.service - dracut pre-pivot and cleanup hook...
29	Jul 06 11:45:01 urobe systemd[1]: Finished dracut-pre-pivot.service - dracut pre-pivot and cleanup hook.
30	Jul 06 11:45:01 urobe systemd[1]: Starting initrd-cleanup.service - Cleaning Up and Shutting Down Daemons...
31	Jul 06 11:45:01 urobe systemd[1]: Stopped target remote-cryptsetup.target - Remote Encrypted Volumes.
32	Jul 06 11:45:01 urobe systemd[1]: Stopped target timers.target - Timer Units.
33	Jul 06 11:45:01 urobe systemd[1]: dracut-pre-pivot.service: Deactivated successfully.
34	Jul 06 11:45:01 urobe systemd[1]: Stopped dracut-pre-pivot.service - dracut pre-pivot and cleanup hook.
35	Jul 06 11:45:01 urobe systemd[1]: Stopped target initrd.target - Initrd Default Target.
36	Jul 06 11:45:01 urobe systemd[1]: Stopped target basic.target - Basic System.
37	Jul 06 11:45:01 urobe systemd[1]: Stopped target initrd-root-device.target - Initrd Root Device.
38	Jul 06 11:45:01 urobe systemd[1]: Stopped target initrd-usr-fs.target - Initrd /usr File System.
39	Jul 06 11:45:01 urobe systemd[1]: Stopped target paths.target - Path Units.
40	Jul 06 11:45:01 urobe systemd[1]: Stopped target remote-fs.target - Remote File Systems.
41	Jul 06 11:45:01 urobe systemd[1]: Stopped target remote-fs-pre.target - Preparation for Remote File Systems.
42	Jul 06 11:45:01 urobe systemd[1]: Stopped target slices.target - Slice Units.
43	Jul 06 11:45:01 urobe systemd[1]: Stopped target sockets.target - Socket Units.
44	Jul 06 11:45:01 urobe systemd[1]: Stopped target sysinit.target - System Initialization.
45	Jul 06 11:45:01 urobe systemd[1]: Stopped target cryptsetup.target - Local Encrypted Volumes.
46	Jul 06 11:45:01 urobe systemd[1]: Stopped target swap.target - Swaps.
47	Jul 06 11:45:01 urobe systemd[1]: dracut-initqueue.service: Deactivated successfully.
48	Jul 06 11:45:01 urobe systemd[1]: Stopped dracut-initqueue.service - dracut initqueue hook.
49	------------
50	Jul 06 11:45:01 urobe systemd[1]: Reached target initrd-switch-root.target - Switch Root.
51	Jul 06 11:45:01 urobe systemd[1]: Finished plymouth-switch-root.service - Plymouth switch root service.
52	Jul 06 11:45:01 urobe systemd[1]: Starting initrd-switch-root.service - Switch Root...
53	Jul 06 11:45:01 urobe systemd[1]: Switching root.
54	-------------
55	Jul 06 09:45:03 urobe systemd[1]: systemd-ask-password-plymouth.service: Deactivated successfully.
56	Jul 06 09:45:03 urobe systemd[1]: initrd-switch-root.service: Deactivated successfully.
57	Jul 06 09:45:03 urobe systemd[1]: Stopped initrd-switch-root.service - Switch Root.
58	-------------
60	Jul 06 09:45:03 urobe systemd[1]: Set up automount proc-sys-fs-binfmt_misc.automount - Arbitrary Executable File Formats File System Automount Point.
61	Jul 06 09:45:03 urobe systemd[1]: Expecting device dev-disk-by\x2dlabel-mystick.device - /dev/disk/by-label/mystick...
62	Jul 06 09:45:03 urobe systemd[1]: Expecting device dev-disk-by\x2duuid-060696ff\x2d234b\x2d42af\x2d9829\x2d0a14438c17c5.device - /dev/disk/by-uuid/060696ff-234b-42af-9829-0a14438c17c5...
63	Jul 06 09:45:03 urobe systemd[1]: Expecting device dev-disk-by\x2duuid-110B\x2dE340.device - /dev/disk/by-uuid/110B-E340...
64	Jul 06 09:45:03 urobe systemd[1]: Expecting device dev-zram0.device - /dev/zram0...
65	Jul 06 09:45:03 urobe systemd[1]: Reached target blockdev@dev-mapper-luks\x2d53c47796\x2d98e1\x2d4fec\x2d93bd\x2df85053508903.target - Block Device Preparation for /dev/mapper/luks-53c477>
66	Jul 06 09:45:03 urobe systemd[1]: Reached target cryptsetup.target - Local Encrypted Volumes.
67	Jul 06 09:45:03 urobe systemd[1]: Reached target getty.target - Login Prompts.
68	Jul 06 09:45:03 urobe systemd[1]: Stopped target initrd-switch-root.target - Switch Root.
69	Jul 06 09:45:03 urobe systemd[1]: Stopped target initrd-fs.target - Initrd File Systems.
70	Jul 06 09:45:03 urobe systemd[1]: Stopped target initrd-root-fs.target - Initrd Root File System.
71	Jul 06 09:45:03 urobe systemd[1]: Reached target integritysetup.target - Local Integrity Protected Volumes.
72	Jul 06 09:45:03 urobe systemd[1]: Reached target slices.target - Slice Units.
73	Jul 06 09:45:03 urobe systemd[1]: Reached target veritysetup.target - Local Verity Protected Volumes.
74	---------------
75	ul 06 09:45:04 urobe systemd[1]: Mounted boot.mount - /boot.
76	Jul 06 09:45:04 urobe systemd[1]: modprobe@dm_mod.service: Deactivated successfully.
77	Jul 06 09:45:04 urobe systemd[1]: Finished modprobe@dm_mod.service - Load Kernel Module dm_mod.
78	---------------
79	Jul 06 09:45:04 urobe systemd[1]: Mounting boot-efi.mount - /boot/efi...
80	----------------
86	Jul 06 09:45:04 urobe systemd[1]: Mounted boot-efi.mount - /boot/efi.
87	Jul 06 09:45:04 urobe systemd[1]: Found device dev-disk-by\x2dlabel-mystick.device - Transcend_8GB mystick.
88	Jul 06 09:45:04 urobe systemd[1]: Mounting media-keystick.mount - /media/keystick...
89	Jul 06 09:45:04 urobe systemd[1]: Mounted media-keystick.mount - /media/keystick.
90	Jul 06 09:45:04 urobe systemd[1]: Reached target local-fs.target - Local File Systems.

Added fido2, luks2, security, usb-key

There is no word for these things, “security usb dongles”, so I invented usb-key

it’s --key-file because in essence you are adding a key-file to luks. it can be used on a USB device so usb-key is good too.


Glad you brough me back here, because I needed to show how I did my setup for the OP @smirgl

1 Like

No I meant these secure USB flashdrives.

1 Like