Block device encryption with cryptsetup and LUKS

In this post I'll demonstrate how to encrypt a block device on Debian using the cryptsetup [1] toolset.

cryptsetup is a utility that can encrypt/decrypt block devices based on dm-crypt kernel module [2] in real time.

I'll be using the LUKS specification [3] which is the standard for Linux hard disk encryption.

First lets install the package:
root@server:~# apt-get install cryptsetup=2:1.6.4-4~bpo70+1
view raw gistfile1.sh hosted with ❤ by GitHub

Then create your symmetric key file:
root@server:~# head -c 256 /dev/urandom > private.key
view raw gistfile1.sh hosted with ❤ by GitHub

Next format the block device with LUKS, specifying the key size and the cipher (from /proc/crypto):
root@server:~# cryptsetup luksFormat /dev/sdi --key-file=private.key --use-urandom --batch-mode -v --key-size=256 --cipher=aes
view raw gistfile1.sh hosted with ❤ by GitHub

Check if the device is a LUKS encrypted device:
root@server:~# cryptsetup -v isLuks /dev/sdi
Command successful.
root@server:~# blkid -p /dev/sdi
/dev/sdi: UUID="2132ba0a-f27d-4ca3-aae9-53d51ff5314c" VERSION="1" TYPE="crypto_LUKS" USAGE="crypto"
view raw gistfile1.sh hosted with ❤ by GitHub

Dump information about the LUKS device (metadata is stored in the LUKS header):
root@server:~# cryptsetup luksDump /dev/sdi
LUKS header information for /dev/sdi
Version: 1
Cipher name: aes
Cipher mode: cbc-plain
Hash spec: sha1
Payload offset: 4096
MK bits: 256
MK digest: 21 98 1f 17 b0 ce a1 c6 fd 51 c0 b1 ff f3 b5 46 97 90 e2 ec
MK salt: eb d2 9c b7 83 47 c1 5f ff 86 2c 63 cb d1 38 d0
ff ec 05 3f f6 c7 ff 7a ef 92 b2 22 17 39 fd 37
MK iterations: 55250
UUID: 2132ba0a-f27d-4ca3-aae9-53d51ff5314c
Key Slot 0: ENABLED
Iterations: 221085
Salt: 8b 95 4b 0a 34 22 2f 1d 4b 27 45 79 08 fb 05 4c
74 76 1e 43 39 a2 44 66 5e 7d ac 7c fa 1b cf c0
Key material offset: 8
AF stripes: 4000
Key Slot 1: DISABLED
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED
view raw gistfile1.sh hosted with ❤ by GitHub

Now that the device has been prepared we can "open" it by creating a device mapper file named "encrypt-volume":
root@server:~# cryptsetup luksOpen /dev/sdi encrypt-volume --key-file=private.key -v
Key slot 0 unlocked.
Command successful.
view raw gistfile1.sh hosted with ❤ by GitHub

This will create a device mapping file in /dev/mapper that can be formatted and mounted:
root@server:~# ls -la /dev/mapper/encrypt-volume
lrwxrwxrwx 1 root root 7 Mar 3 16:20 encrypt-volume -> ../dm-1
view raw gistfile1.sh hosted with ❤ by GitHub

Create a file system and mount the block device:
root@server:~# mkfs.ext3 /dev/mapper/encrypt-volume
root@server:~# mount -t ext3 /dev/mapper/encrypt-volume /mnt/
view raw gistfile1.sh hosted with ❤ by GitHub

If this is an iSCSI block device, it can easily be moved to a different host, but first we need to unmount it and "close" it:
root@server:~# umount /mnt
root@server:~# cryptsetup luksClose encrypt-volume --key-file=private.key -v --batch-mode
view raw gistfile1.sh hosted with ❤ by GitHub

On the new server:
root@server5:~# cryptsetup luksOpen /dev/sdi encrypt-volume --key-file=private.key -v
root@server5:~# mount /dev/mapper/encrypt-volume /mnt/
view raw gistfile1.sh hosted with ❤ by GitHub

LUKS uses a special header to store some metadata like the master password, salt values etc. If the header gets corrupted, i.e you reformat the encrypted block device instead of the mapped one, you'll not be able to decrypt it and will loose the data. To prevent this make sure you have a backup of the header, stored at a secure location. To backup and restore the LUKS header run:
root@server:~# cryptsetup luksHeaderBackup --header-backup-file headerBackup /dev/sdi
root@server:~# cryptsetup luksHeaderRestore --header-backup-file headerBackup /dev/sdi
view raw gistfile1.sh hosted with ❤ by GitHub

With this you have an encrypted block device in few quick steps. One thing worth mentioning is that the private key should be kept at a secure location, if lost you'll not be able to decrypt your device.

Here's a list of the most popular available options for disk encruption:

- Loop-AES - longest-existing one; possibly the fastest; works on legacy systems, must manually compile custom kernel, not ideal for containers;
- dm-crypt +/- LUKS - the de-facto standard for block device encryption on Linux; very flexible, kernel modules already shipped with default kernel;
- Truecrypt - very portable, well-polished, self-contained solution, but the project died mid 2014;
- eCryptfs - stacked filesystem encryption instead of block level, slower, individual encrypted files portable between systems;
- EncFs - stacked filesystem encryption instead of block level, the slowest, easiest one to use; supports non-root administration;

Resources:

[1]. https://code.google.com/p/cryptsetup/
[2]. https://code.google.com/p/cryptsetup/wiki/DMCrypt
[3]. http://en.wikipedia.org/wiki/Linux_Unified_Key_Setup