I want to:
- Encrypt my whole HDD with a keyfile and a password (meaning that both are required to decrypt it),
- Be able to back up pieces of the keyfile in several distant locations using Secret Sharing,
- Be able to change the password often and easily.
- The keyfile is made of 4096 random bits and is done using
dd if=/dev/urandom /keys/keyfile bs=1024 count=4,
- The password is approximately 20 characters long,
To make things clear, I'll state the intended meaning of a few words:
- keyfile – the randomly generated file
- password – the text asked to the user and never stored in a file
- key – the data used to decrypt the masterkey
- masterkey – the data used to encrypt / decrypt the drive
To allow “3.”, I use
cryptsetupsince it uses a masterkey that's encrypted with your key so I can change my key without having to rencrypt everything. I could use
dm-cryptdirectly but it'd be much harder and would only save the space occupied by the luks headers. And I already have enough space so I don't think it's worth the trouble.
To allow “1.”, I could encrypt the keyfile with the password and use the keyfile as key but then,
- If I backed the encrypted version of the keyfile, I'd have to update all backups every time I changed the password,
- If I backed the non-encrypted version of the keyfile, I'd allow to bypass the password by recovering the backup.
- So instead, I chose to combine the keyfile and the password.
Combination of keyfile and password into key:
I use a bitwise XOR to compute the key from the keyfile and the password. I start at the left and when one of then is empty, I just output the rest of the other one. See my C source file at GitHub.
The other option I thought of was concatenating them. But I didn't like the idea of my key having a recognizable pattern: Random data followed by text.
I therefore used the XOR because it preserves the randomness: for a given password, the distribution of a uniform distribution XORed with that password is still the uniform distribution.
I have something that should work and if there are bugs, I probably will be able to fix them.
/dev/urandomfine for my use-case or should I use
- Some people told me that I should use a key derivation function because otherwise, the effect of the password isn't spread. But do I need the effect of the password to be spread? The way I see it,
cryptsetupwill already use a key derivation function on my key to increase computation time and try to spread the effect of each bit.
Feel free to criticize (constructively) any decision or assumptions I've made (for that project).