First of all, your runtime encrypt-decrypt speed will be dependent on how fast your CPU/ core can handle AES, and whether it's implemented in software or on the hardware - the method by which the volume key is unlocked has almost no bearing on runtime operations.
I'll propose LUKS2 in mode aes-xts-plain64
(or aes-xts-plain
depending on your kernel) which is AES-256, and a secondary 256-bit key for the 'tweak' that XTS mode uses to determine the IV from the on-disc block. (TODO REF.)
To unlock the volume key I propose Argon2id, ie. cryptsetup --pbkdf=argon2id
, tuned as hard as your patience can tolerate.
Your 5GB volume doesn't introduce any problems - it's large enough for the standard key-slot area^ and small enough that you don't need to use aes-xts-plain64
, however, you can use plain64
if your kernel supports it, but is limited to more recent kernels, from the manpage: XTS mode requires kernel 2.6.24 or later and plain64 requires kernel 2.6.33 or later.
You should leave the source of random bits as the default /dev/urandom
unless you have a good reason to change it. I don't believe cryptsetup
allows you to provide other files to source random bits, however, you can provide the master key file - this is the "volume key" that you ask about. Left alone, the new volume master key is created from random sources. If you do specify the volume key via cryptsetup --master-key-file
then be sure it is high-entropy. A circumstance where this might be useful is when you wish to be able to (re)produce the volume key from another technique.
I propose the use of at least SHA2-256 as the digest hash. I use SHA2-384 as this is a truncated SHA2-512 hash, which is slightly more efficient on 64-bit architecture, among other reasons.
cryptsetup --type=luks2 --pbkdf=argon2id --type=luks2 --pbkdf=argon2id --pbkdf-memory=1048576 --pbkdf-parallel=4 --pbkdf-force-iterations=8 --hash=sha384 luksFormat /dev/new_luks_partition1
Memory is in KiB, so 1 GiB, and the number of iterations are forced to be 8, rather than allowing the software to auto-tune. (If you want auto-tuning don't set --pbkdf-force-iterations
.)
Also, be sure to add at least a second key-slot for recovery purposes (you can use the same password if you wish, as a new salt is created for each key slot, but keep the hardness tuning the same) - you can add up to eight of these by default. Each key slot basically holds an encrypted copy of the volume key. This is in addition to taking a header backup, described later.
cryptsetup --batch-mode --type=luks2 --pbkdf=argon2id --pbkdf-memory=1048576 --pbkdf-parallel=4 --pbkdf-force-iterations=8 --hash=sha384 --priority=ignore luksAddKey /dev/new_luks_partition1
Now that the volume is created and one or more additional key-slots are populated, take a back up of the volume header. Note this backup file is still encrypted.
cryptsetup luksHeaderBackup --header-backup-file=~/luks-202102 /dev/new_luks_partition1
diff -sq <(cryptsetup luksDump ~/luks-202102) <(cryptsetup luksDump /dev/new_luks_partition1)
To produce a plain-text copy of the volume key, use the following (you'll need to re-type your password):
cryptsetup luksDump --dump-master-key ~/luks-202102
Good discussion on the LUKS header (2019):
What does LUKS header contain?
More on aes-xts-plain
vs aes-xts-plain64
, viz. cryptsetup
FAQ s5.15
First, "plain" and "plain64" are both not secure to use with CBC, see
previous FAQ item.
However there are modes, like XTS, that are secure with "plain" IV. The
next limit is that "plain" is 64 bit, with the upper 32 bit set to zero.
This means that on volumes larger than 2TiB, the IV repeats, creating a
vulnerability that potentially leaks some data. To avoid this, use
"plain64", which uses the full sector number up to 64 bit. Note that
"plain64" requires a kernel 2.6.33 or more recent. Also note that
"plain64" is backwards compatible for volume sizes of maximum size 2TiB,
but not for those > 2TiB. Finally, "plain64" does not cause any
performance penalty compared to "plain".
More on GRUB:
There is support for LUKS2 in GRUB, however, I found I still had to use LUKS1 in the past when I was following this: "Ubuntu 20.04 with btrfs-luks full disk encryption including /boot and auto-APT snapshots with Timeshift" Mutschler 2020.
Something to note is that when using LUKS1 and GRUB, the time it takes PBKDF2 to run is much slower, for eg. I find that I can stomach a cryptsetup --type luks1 --pbkdf pbkdf2 --pbkdf-force-iterations 2000000
without GRUB, but only say --pbkdf-force-iterations 400000
if using GRUB.