USB or password boot decrypt
Here is a small guide to create a USB key that store the decryption key for your LUKS encrypted disk, this is useful for when your device is in a safe place and you want it to boot without the need to type a password, and then going back to normal password workflow simply unplugging the USB key.
Generate the decryption key
We will generate a random decryption key and will store it in a file enc_file
in the USB key,
to do that just get in the root folder of the USB key and run:
dd if=/dev/urandom bs=1 count=256 > enc_file
Let's make sure that the file has the right permissions:
sudo chown root:root enc_file
# 400 is user read only
sudo chmod 400 enc_file
Add the key to the encrypted drive
Done this let's figure out the device that is a LUKS encrypted device with:
sudo blkid --match-token TYPE=crypto_LUKS -o device
Now that we know the device (in my case /dev/nvme0n1p1
) we can add the generated key as decryption key:
sudo cryptsetup luksAddKey /dev/nvme0n1p1 enc_file
To check if the key is added successfully you can use the command:
sudo cryptsetup --verbose open /dev/nvme0n1p1 --test-passphrase --key-file enc_file
Change the boot configuration
The next step is to change the boot decryption process to try to fetch the decryption key from
the USB key, for do this we need a script, in my case I used the following script that I put in /bin/luksunlockusb
set -e if [ ! -e /mnt ]; then mkdir -p /mnt sleep 3 fi for usbpartition in /dev/disk/by-id/usb-*-part1; do usbdevice=$(readlink -f $usbpartition) if mount -t ext4 $usbdevice /mnt 2>/dev/null; then if [ -e /mnt/enc_file ]; then cat /mnt/enc_file umount $usbdevice exit fi umount $usbdevice fi done /lib/cryptsetup/askpass "Insert USB key or password and press ENTER: " END
This script at boot list the plugged USB keys, mount them and try to read the enc_file
, it will
iterate all of them until it find one, otherwise it exit and ask for a password or to plug the USB key.
Now we need to make sure that this script is used, so let's edit the /etc/cryptab
from:
nvme0n1p1_crypt UUID=033ad4d9-78d5-4b69-8eab-30c89000fc76 none luks,discard
to:
nvme0n1p1_crypt UUID=033ad4d9-78d5-4b69-8eab-30c89000fc76 none luks,keyscript=/bin/luksunlockusb,initramfs
Done this we just need to run the following command to make sure that all the configuration and scripts are copied in the initramfs
so can be used in the boot process:
update-initramfs -u
Things to be careful
When I wrote this not all went smooth, it has been quite hard to test and debug, because you cannot really get debug output from decryption scripts. So do not give up at the first problem, just try again double checking things and tweaking things after some internet search.
Things that I got wrong when trying this:
- Missing the option
-t ext4
in the mount command, often mount works fine without it in your normal shell but is not the case when run in the boot - Make sure that your initramfs has all the kernel modules loaded for reading the USB key and the file system in the key.
- Make sure the mount command has the correct file system of the USB key.
- This seems to work fine also if you have multiple devices you just need to repeat the commands and settings for all the devices, one thing
I noticed was for work with multiple devices I need to have the additional option
initramfs
in the cryptab file (like I did), it may work without if you have only one device, have your own try.
References
I did not do this by scratch I learned and copied from a number of guides online here the few main one:
https://tqdev.com/2022-luks-with-usb-unlock
https://linuxconfig.org/usb-stick-encryption-using-linux
https://wejn.org/how-to-make-passwordless-cryptsetup.html