Summary: I can run cryptsetup benchmark
and sort the results, but seek guidance in their interpretation. E.g., should I give more weight to encryption speed or decryption speed? Should key-derivation speed override either? And how should my usecase affect how I weight/interpret results?
Pointers to doc are appreciated: I have websearched, but haven't seen anything definitive-looking. Particularly, this does not seem to be
- a
cryptsetup
FAQ - discussed in relevant sections of the ArchWiki[1]
Details:
I'm preparing to reinstall OS on a 2007-ish laptop (so presumably no processor support for AES), this time with LUKS+LVM2. (It's my one remaining box with Plain Old Partitions
.) I don't have time to run several loops of the sequence [install LUKS+LVM2+OS, run a real disk benchmark, measure results], though that would obviously give much more empirical guidance. Instead, I'm trying to choose a rational (even optimal 🙂 LUKS cipher specification string "up front" using cryptsetup benchmark
, though I know that one "cannot directly predict real storage encryption speed from it"[2].
When this box runs sudo cryptsetup benchmark
it outputs (after tweaking to label and separate the issues and to sort by speed decreasing):
# key derivation:
PBKDF2-sha1 557753 iterations per second
PBKDF2-sha256 356173 iterations per second
PBKDF2-ripemd160 336082 iterations per second
PBKDF2-sha512 256000 iterations per second
PBKDF2-whirlpool 112219 iterations per second
# encryption:
# Algorithm | Key | Encryption
serpent-xts 512b 144.7 MiB/s
serpent-xts 256b 144.0 MiB/s
twofish-xts 256b 132.1 MiB/s
twofish-xts 512b 132.0 MiB/s
aes-xts 256b 128.4 MiB/s
aes-cbc 128b 109.7 MiB/s
twofish-cbc 256b 108.2 MiB/s
twofish-cbc 128b 107.9 MiB/s
aes-xts 512b 96.7 MiB/s
aes-cbc 256b 86.5 MiB/s
serpent-cbc 256b 42.1 MiB/s
serpent-cbc 128b 42.1 MiB/s
# decryption:
# Algorithm | Key | Decryption
serpent-cbc 256b 160.0 MiB/s
serpent-cbc 128b 159.5 MiB/s
serpent-xts 512b 149.0 MiB/s
serpent-xts 256b 148.4 MiB/s
twofish-cbc 256b 142.1 MiB/s
twofish-cbc 128b 141.6 MiB/s
twofish-xts 256b 133.5 MiB/s
twofish-xts 512b 133.4 MiB/s
aes-cbc 128b 127.5 MiB/s
aes-xts 256b 126.0 MiB/s
aes-cbc 256b 96.0 MiB/s
aes-xts 512b 95.2 MiB/s
The above results show
- encryption:
serpent-xts/512
is fastest,serpent-cbc/*
is slowest - decryption:
serpent-cbc/256
is fastest,serpent-xts/512
is 3rd fastest - key derivation:
sha1
is significantly faster thansha256
is significantly faster thansha512
Less certainly, I believe
sha1
is being retired, so for compatibility going forward, I should deweight (to zero) the significant KDF speed advantage ofsha1
oversha256
.- "For the normal use-case of an authorized user [on a workstation, the key derivation function] will only need to be calculated once per session,"[3] so I should deweight the significant KDF advantage of
sha256
oversha512
.
So a specific question is:
- Should I give more weight to the significant speed advantage of
sha256
in key derivation (|356173 - 256000| / ((356173 + 256000)/2)
~= 0.327), or to the modest speed advantage ofsha512
(which I'm assuming is also more secure) in both decryption and encryption?
A more general question is:
- How should one's usecase affect one's weighting of the importance of speed in key derivation, decryption, and encryption? E.g., will a headless server spend more or less time decrypting (or whatever) than a headful workstation? I'm assuming that decryption is done on read and encryption on write, but I don't know about how one's usecase affects the relative incidence/weight of read and write.
FWIW, the box I'm setting up will be my second-string headful production box for now, so it basically needs to
- run an editor and a browser
- make SSH connections
- play video and music
- be a loaner for folks who want to try Linux
- be ready to go if I hose my first-string production laptop
(It will be running Debian, if that makes a difference.) Of course, I generally prefer faster performance to slower (and more reliability to less) but I'm obviously willing to pay some price for security.
Even more general questions are:
-
Can one generally rank importance of speed of key derivation, decryption, and encryption? I'm guessing KDF speed is much less important[3], but that decryption and encryption speeds are of equal weight for most usecases. (But ICBW.)
-
I know that default, no-argument runs of
cryptsetup benchmark
"[measure only a] few common configurations"[2] and that to "benchmark other ciphers or modes, you need to specify--cipher
and--key-size
options or--hash
for KDF test."[2]. This section of the ArchWiki gives a bit more detail on how one can do this, but I'm not aware of one or more lists of either
4.1. the valid option parameters for specifying non-default cryptographics (ciphers, hashes, keysizes, modes) to cryptsetup benchmark
. Can anyone point to definitive doc for this?
4.2. other, non-default cryptographics one should specify and benchmark, given current technologies and kernel support. Your suggestions appreciated (provided you also provide the appropriate option parameters 🙂
- Are there "better" tools to use for LUKS performance pre-tuning than
cryptsetup benchmark
? If so, what and how?
[1]: e.g., https://wiki.archlinux.org/index.php/Dm-crypt/Device_Encryption#Encryption_options_for_LUKS_mode , https://wiki.archlinux.org/index.php/Disk_encryption#Cryptographic_metadata
[2]: run info cryptsetup
or man cryptsetup
[3]: see https://wiki.archlinux.org/index.php/Disk_encryption#Cryptographic_metadata
Best Answer
KDF speed is important, but contrary to your belief, it should be SLOW.
With LUKS, your encrypted drive contains a header with an encrypted master key that is used to encrypt your device. This master key gets decrypted with one of the keys in your key slots when you boot/open the device (try
cryptsetup luksDump /dev/sdx
to see information contained in the LUKS header).When you first format the LUKS device, it will ask you for a passphrase (or keyfile). This passphrase is then used to create and encrypt a key that will be added in keyslot 0. Your passphrase is also hashed and stored, so that LUKS can verify if you entered the right passphrase when you open the device. This is important to understand, because if you use a fast hashing algorithm, it is easier to crack the passphrase since an attacker can test a lot more combinations in shorter time.
Therefore, you should go for the slowest and most secure hashing algorithm (sha512 or whirlpool) and use a high --iter-time. The --iter-time option allows you to set the time it takes to do 1 hashing iteration. The only downside to a high iteration time is that it takes just that long to actually open the encrypted device. Say you use an --iter-time of 10000 (10 seconds) on your root device, then it will take 10 seconds for your system to get the actual encryption key and thus you will have to wait that long after your password before booting continues. This only happens once when you open the device, so further performance is not affected.
For your actual encryption cipher, it depends on how fast your underlying physical device can read/write and how much workload is on the machine. The encryption/decryption is performed by your CPU, so if you go with the slowest one there is a good chance that it will affect other programs running at the same time. As of right now, aes-xts-plain64 is considered the most secure LUKS cipher, so if you have very confidential information you should probably go with aes-xts-plain64 and a keysize of 512 (since with xts the key is split in 2 so you actually get aes with 256-bit keys).
If I were to make a recommendation on your setup, it would be sha512 as hashing algorithm with an iter-time between 2s-10s and using aes-xts-plain64 with a keysize of 256, since AES-128 is still considered secure.