dm-crypt/Device encryption

From ArchWiki
< Dm-crypt
Revision as of 14:08, 18 November 2013 by Kynikos (talk | contribs) (fix headings + link back)
Jump to navigation Jump to search

Back to Dm-crypt with LUKS/draft.

This section covers how to manually utilize LUKS from the command line to encrypt a system.

Mapping Physical Partitions to LUKS

After writing the partition table to the MBR (optionally set up LVM thereafter) the next step is to create the LUKS and dm-crypt magic and make device mapper mount it to the filesystem of the installation system.

When creating LUKS partitions they must be associated with a key. The key is used to unlock the header of the LUKS-encrypted partitions.

A key is either a:

  • Passphrase
  • Keyfile

It is possible to define up to 8 different keys per LUKS partition. This enables the user to create access keys for save backup storage. Also a different key-slot could be used to grant access to a partition to a user by issuing a second key and later revoking it again without the need to re-encrypt the partition. Having in mind that further passphrases or keyfiles can be added later easily at any time might make the choice for the initial key easier.

Using LUKS to Format Partitions with a Passphrase

Note: Using a passphrase to decrypt LUKS partitions automatically from /etc/crypttab is deprecated.

Cryptsetup is used to interface with LUKS for formatting, mounting and unmounting encrypted partitions.


# cryptsetup [OPTION...] <action> <action-specific>


# cryptsetup --cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 5000 --use-random --verify-passphrase luksFormat <device> 

Common options used with luksFormat:

Available options Cryptsetup (<1.6.0) defaults Comment Example Comment
--cipher, -c/ aes-cbc-essiv:sha256 Use the AES-cipher with CBC/ESSIV. aes-xts-plain64 XTS. For volumes >2TiB use aes-xts-plain64 (requires kernel >= 2.6.33).
--key-size, -s 256 The cipher is used with 256 bit key-size. 512 XTS splits the supplied key into fraternal twins. For an effective AES-256 the XTS key-size must be 512.
--hash, -h sha1 Hash algorithm used for PBKDF2. sha512
--iter-time, -i 1000 Number of milliseconds to spend with PBKDF2 passphrase processing. 5000 Using a hash stronger than sha1 results in less iterations if iter-time is not increased.
--use-random --use-urandom /dev/urandom is used as randomness source for the (long-term) volume master key. --use-random Avoid generating an insecure master key if low on entropy. Will block if the entropy pool is used up.
--verify-passphrase, -y Yes Default only for luksFormat and luksAddKey. - No need to type for archlinux at the moment.

Please note that the above compares historic cryptsetup defaults in the left column. With release 1.6.0 the defaults have changed to an AES cipher in XTS mode, but with other options than the right column example (e.g. an effective key-size of 128-bit). The defaults can be checked with the tail output of

# cryptsetup --help

When deciding on the encryption cipher to use during blockdevice creation, it has to be taken into account that a number of the options stated affect system performance just for creating the initial crypt-blockdevice or opening it, but not the crypto and disk-io operations when the system is running. The throughput and security of the crypted data itself depends on the cipher and key-size. The used hash, iteration-time and random source options affect the cryptographic security of the master-key creation and processing time needed to unlock it in the future.

A full list of options cryptsetup accepts can be found in the manpage. Furthermore, cryptsetup now has a feature to benchmark the crypto performance of the processor:

# cryptsetup benchmark 

can give guidance on deciding for a cipher to use prior to installation. If certain AES ciphers appear in the output to have a considerably (e.g. tenfold) higher throughput, these are probably the ones with hardware support in the CPU.

In the following examples for creating LUKS partitions, we will use the AES cipher in XTS mode; at present this is not only the default, but also a most generally used preferred cipher. More information on this and other ciphers used with cryptsetup can be found here: Wikipedia:Block_cipher

Formatting LUKS Partitions

First of all make sure the device mapper kernel module is loaded by executing the following: # modprobe dm_mod

In order to format a desired partition as an encrypted LUKS partition execute:

# cryptsetup -c <cipher> -y -s <key size> luksFormat /dev/<partition name>
Enter passphrase: <password>
Verify passphrase: <password>

Check results:

# cryptsetup luksDump /dev/<drive>

This should be repeated for all partitions except for /boot and possibly swap. You will note that the dump not only shows the cipher header information, but also the key-slots in use for the LUKS partition.

The example below will create an encrypted root partition using the AES cipher in XTS mode (generally referred to as XTS-AES).

# cryptsetup -c aes-xts-plain -y -s 512 luksFormat /dev/sda2
Note: If hibernation usage is planned, swap must be encrypted in this fashion; otherwise, if hibernation is not a planned feature for the system, encrypting the swap file will be performed in a alternative manner.
Warning: Irrespective of the chosen partitioning method, the /boot partition must remain separate and unencrypted in order to load the kernel and boot the system.

Unlocking/Mapping LUKS Partitions with the Device Mapper

Once the LUKS partitions have been created it is time to unlock them.

The unlocking process will map the partitions to a new device name using the device mapper. This alerts the kernel that /dev/<partition name> is actually an encrypted device and should be addressed through LUKS using the /dev/mapper/<name> so as not to overwrite the encrypted data. To guard against accidental overwriting, read about the possibilities to backup the cryptheader after finishing setup.

In order to open an encrypted LUKS partition execute:

# cryptsetup open --type luks /dev/<partition name> <device-mapper name>
Enter any LUKS passphrase: <password>
key slot 0 unlocked.
Command successful.

Usually the device mapped name is descriptive of the function of the partition that is mapped, example:

cryptsetup open --type luks /dev/sda2 swap
Once opened, the swap partition device address would be /dev/mapper/swap instead of /dev/sda2.
cryptsetup open --type luks /dev/sda3 root
Once opened, the root partition device address would be /dev/mapper/root instead of /dev/sda3.
cryptsetup open --type luks /dev/sda3 lvmpool (alternate)
For setting up LVM ontop the encryption layer the device file for the decrypted volume group would be anything like /dev/mapper/lvmpool instead of /dev/sda3. LVM will then give additional names to all logical volumes created, e.g. /dev/mapper/lvmpool-root and /dev/mapper/lvmpool-swap.

In order to write encrypted data into the partition it must be accessed through the device mapped name.

Note: Since /boot is not encrypted, it does not need a device mapped name and will be addressed as /dev/sda1.

Using LUKS to Format Partitions with a Keyfile

When creating a new LUKS encrypted partition, a keyfile may be associated with the partition on its creation using:

# cryptsetup -c <desired cipher> -s <key size> luksFormat /dev/<volume to encrypt> /path/to/mykeyfile

This is accomplished by appending the bold area to the standard cryptsetup command which defines where the keyfile is located.

Adding Additional Passphrases or Keyfiles to a LUKS Encrypted Partition

LUKS supports the association of up to 8 keyslots with any single encrypted volume. Keyslots can be either keyfiles or passphrases.

Once an encrypted partition has been created, the initial keyslot 0 is created. Additional keyslots are numbered from 1 to 7.

Adding new keyslots is accomplished using cryptsetup with the luksAddKey action.

Don't forget wiping unused keyslots with luksKillSlot as described in #Wipe LUKS keyslots.)

# cryptsetup luksAddKey /dev/<volume> (/path/to/<additionalkeyfile>)
Enter any passphrase:
Enter new passphrase for key slot:
Verify passphrase:

Where <device> is the volume containing the LUKS header to which the new keyslot is added. This works on header backup files as well.

If /path/to/<additionalkeyfile> is given, cryptsetup will add a new keyslot for <additionalkeyfile>. Otherwise a new passphrase will be prompted for twice.

For adding keyslots cryptsetup has to decrypt the master key from an existing keyslot so it first asks for "any passphrase" (of an existing keyslot).

For getting the master key from an existing keyfile keyslot the --key-file or -d option followed by the "old" <keyfile> will try to unlock all available keyfile keyslots.

# cryptsetup luksAddKey /dev/mapper/<device> (/path/to/<additionalkeyfile>) -d /path/to/<keyfile>

Using Cryptsetup with a Keyfile

Note: This section describes using a plaintext keyfile. If you want to encrypt your keyfile giving you two factor authentication see Using GPG or OpenSSL Encrypted Keyfiles for details, but please still read this section.

What is a Keyfile?

A keyfile is any file in which the data contained within it is used as the passphrase to unlock an encrypted volume. Therefore if these files are lost or changed, decrypting the volume will no longer be possible.

Tip: Define a passphrase in addition to the keyfile for backup access to encrypted volumes in the event the defined keyfile is lost or changed.

Why use a Keyfile?

There are many kinds of keyfile. Each type of keyfile used has benefits and disadvantages summarized below:

this is my passphrase I would have typed during boot but I have placed it in a file instead

This is a keyfile containing a simple passphrase. The benefit of this type of keyfile is that if the file is lost the data it contained is known and hopefully easily remembered by the owner of the encrypted volume. However the disadvantage is that this does not add any security over entering a passphrase during the initial system start.

fjqweifj830149-57 819y4my1- 38t1934yt8-91m 34co3;t8y;9p3y-

This is a keyfile containing a block of random characters. The benefit of this type of keyfile is that it is much more resistant to dictionary attacks than a simple passphrase. An additional strength of keyfiles can be utilized in this situation which is the length of data used. Since this is not a string meant to be memorized by a person for entry, it is trivial to create files containing thousands of random characters as the key. The disadvantage is that if this file is lost or changed, it will most likely not be possible to access the encrypted volume without a backup passphrase.

where any binary file, images, text, video could be chosen as the keyfile

This is a binary file that has been defined as a keyfile. When identifying files as candidates for a keyfile, it is recommended to choose files that are relatively static such as photos, music, video clips. The benefit of these files is that they serve a dual function which can make them harder to identify as keyfiles. Instead of having a text file with a large amount of random text, the keyfile would look like a regular image file or music clip to the casual observer. The disadvantage is that if this file is lost or changed, it will most likely not be possible to access the encrypted volume without a backup passphrase. Additionally, there is a theoretical loss of randomness when compared to a randomly generated text file. This is due to the fact that images, videos and music have some intrinsic relationship between neighboring bits of data that does not exist for a text file. However this is controversial and has never been exploited publicly.

Creating a Keyfile with Random Characters

Here dd is used to generate a keyfile of 2048 random bytes.

# dd if=/dev/urandom of=mykeyfile bs=512 count=4

The usage of dd is similar to initially wiping the volume with random data prior to encryption.

Storing the Key File

Tango-view-fullscreen.pngThis article or section needs expansion.Tango-view-fullscreen.png

Reason: The default method to store a keyfile and reference it via crypttab should be added. (Discuss in Talk:Dm-crypt/Device encryption#)

External Storage on a USB Drive

Preparation for Persistent block device naming

For reading the file from an external storage device it is very convenient to access it through udev's Persistent block device naming features and not by ordinary device nodes like /dev/sdb1 whose naming depends on the order in which devices are plugged in. So in order to assure that the encrypt HOOK in the initcpio finds your keyfile, you must use a permanent device name.

Persistent symlinks

Merge-arrows-2.pngThis article or section is a candidate for merging with Persistent block device naming.Merge-arrows-2.png

Notes: Anything not specific to storing LUKS keyfiles should get merged there. (Discuss in Talk:Dm-crypt/Device encryption#)

A quick method (as opposed to setting up a udev rule) for doing so involves referencing the right partition by its UUID, id (based on hardware info and serial number) or filesystem label.

Plug the device in and print every file name under /dev/disk:

#ls -lR /dev/disk/
total 0
drwxr-xr-x 2 root root 180 Feb 12 10:11 by-id
drwxr-xr-x 2 root root  60 Feb 12 10:11 by-label
drwxr-xr-x 2 root root 100 Feb 12 10:11 by-path
drwxr-xr-x 2 root root 180 Feb 12 10:11 by-uuid

total 0
lrwxrwxrwx 1 root root  9 Feb 12 10:11 usb-Generic_STORAGE_DEVICE_000000014583-0:0 -> ../../sdb
lrwxrwxrwx 1 root root 10 Feb 12 10:11 usb-Generic_STORAGE_DEVICE_000000014583-0:0-part1 -> ../../sdb1

total 0
lrwxrwxrwx 1 root root 10 Feb 12 10:11 Keys -> ../../sdb1

total 0
lrwxrwxrwx 1 root root  9 Feb 12 10:11 pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0 -> ../../sdb
lrwxrwxrwx 1 root root 10 Feb 12 10:11 pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0-part1 -> ../../sdb1

total 0
lrwxrwxrwx 1 root root 10 Feb 12 10:11 baa07781-2a10-43a7-b876-c1715aba9d54 -> ../../sdb1


Using the filesystem UUID for persistent block device naming is considered very reliable. Filesystem UUIDs are stored in the filesystem itself, meaning that the UUID will be the same if you plug it into any other computer, and that a dd backup of it will always have the same UUID since dd does a bitwise copy.

The right device node for what is now /dev/sdb1 will always get symlinked by /dev/disk/by-uuid/baa07781-2a10-43a7-b876-c1715aba9d54. Symlinks can be used in a bootloader "cryptkey" kernel option or anywhere else.

For legacy filesystems like FAT the UUID will be much shorter but collision is still unlikely to happen if not mounting many different FAT filesystems at once.


In the following example a FAT partition is labeled as "Keys" and will always get symlinked by /dev/disk/by-label/Keys:

#mkdosfs -n >volume-name< /dev/sdb1
#blkid -o list
device     fs_type label    mount point    UUID
/dev/sdb1  vfat    Keys     (not mounted)  221E-09C0
Persistent udev rule

Optionally you may choose to set up your flash drive with a udev rule. There is some documentation in the Arch wiki about that already; if you want more in-depth, structural info, read this guide. Here is quickly how it goes.

Get the serial number from your USB flash drive:

lsusb -v | grep -A 5 Vendor

Create a udev rule for it by adding the following to a file in /etc/udev/rules.d/, such as 8-usbstick.rules:

KERNEL=="sd*", ATTRS{serial}=="$SERIAL", SYMLINK+="$SYMLINK%n"

Replace $SYMLINK and $SERIAL with their respective values. %n will expand to the partition (just like sda is subdivided into sda1, sda2, ...). You do not need to go with the 'serial' attribute. If you have a custom rule of your own, you can put it in as well (e.g. using the vendor name).

Rescan your sysfs:

udevadm trigger

Now check the contents of /dev:

ls /dev

It should show your device with your desired name.

Generating the keyfile

Optionally you can mount a tmpfs for storing the temporary keyfile.

# mkdir ./mytmpfs
# mount tmpfs ./mytmpfs -t tmpfs -o size=32m
# cd ./mytmpfs

The advantage is that it resides in RAM and not on a physical disk, so after unmounting your keyfile is securly gone. So copy your keyfile to some place you consider as secure before unmounting. If you are planning to store the keyfile as a plain file on your USB device, you can also simply execute the following command in the corresponding directory, e.g. /media/sdb1

The keyfile can be of arbitrary content and size. We will generate a random temporary keyfile of 2048 bytes:

# dd if=/dev/urandom of=secretkey bs=512 count=4

If you stored your temporary keyfile on a physical storage device, remember to not just (re)move the keyfile later on, but use something like

cp secretkey /destination/path
shred --remove --zero secretkey

to securely overwrite it. For overaged filesystems like FAT or ext2 this will suffice while in the case of journaling filesystems, flash memory hardware and other cases it is highly recommended to wipe the entire device or at least the keyfiles partition.

Add a keyslot for the temporary keyfile to the LUKS header:

# cryptsetup luksAddKey /dev/sda2 secretkey
Enter any LUKS passphrase:
key slot 0 unlocked.
Command successful.

Storing the keyfile

The following uses an USB-stick to store the key file and modifies the initramfs to load and use it on boot to unlock the root partition.

Configuration of initcpio

You have to add two extra modules in your /etc/mkinitcpio.conf, one for the drive's file system and one for the codepage. Further if you created a udev rule, you should tell mkinitcpio about it:

MODULES="ata_generic ata_piix nls_cp437 vfat"

In this example it is assumed that you use a FAT formatted USB drive. Replace those module names if you use another file system on your USB stick (e.g. ext2) or another codepage. Users running the stock Arch kernel should stick to the codepage mentioned here.

If you have a non-US keyboard, it might prove useful to load your keyboard layout before you are prompted to enter the password to unlock the root partition at boot. For this, you will need the keymap hook before encrypt.

Generate a new image (maybe you should backup a copy of your old /boot/initramfs-linux.img first):

# mkinitcpio -p linux

Storing the key as a plain (visible) file

Be sure to choose a plain name for your key – a bit of 'security through obscurity' is always nice ;-). Avoid using dotfiles (hidden files) – the encrypt hook will fail to find the keyfile during the boot process.

You have to add cryptdevice=/dev/sda3:root cryptkey=/dev/usbstick:vfat:/secretkey to your kernel parameters. This assumes /dev/usbstick is the FAT partition of your choice. Replace it with /dev/disk/by-... or whatever your device is.

That is all, reboot and have fun!

Backup the cryptheader

If the header of your encrypted partition gets destroyed, you will not be able to decrypt your data. It is just as much as a dilemma as forgetting the passphrase or damaging a key-file used to unlock the partition. A damage may occur by your own fault while re-partitioning the disk later or by third-party programs misinterpreting the partition table.

Therefore, having a backup of the headers and storing them on another disk might be a good idea.

Attention: Many people recommend NOT backing up the cryptheader, but even so it's a single point of failure! In short, the problem is that LUKS is not aware of the duplicated cryptheader, which contains the master key which is used to encrypt all files on your partition. Of course this master key is encrypted with your passphrases or keyfiles. But if one of those gets compromised and you want to revoke it you have to do this on all copies of the cryptheader! I.e. if someone has got your cryptheader and one of your keys he can decrypt the master key and access all your data. Of course the same is true for all backups you create of your partions. So you decide if you are one of those paranoids brave enough to go without a backup for the sake of security or not. See also the LUKS FAQ for further details on this.


Using cryptsetup

Cryptsetup's luksHeaderBackup action stores a binary backup of the LUKS header and keyslot area:

# cryptsetup luksHeaderBackup /dev/<device> --header-backup-file /mnt/<backup>/<file>.img

where <device> is the partition containing the LUKS volume.

Note: Using - as header backup file writes to a file named -.
Tip: You can also back up the plaintext header into ramfs and encrypt it in example with gpg before writing to persistent backup storage by executing the following commands.
# mkdir /root/<tmp>/
# mount ramfs /root/<tmp>/ -t ramfs
# cryptsetup luksHeaderBackup /dev/<device> --header-backup-file /root/<tmp>/<file>.img
# gpg2 --recipient <User ID> --encrypt /root/<tmp>/<file>.img 
# cp /root/<tmp>/<file>.img.gpg /mnt/<backup>/
# umount /root/<tmp>
Warning: Tmpfs can swap to harddisk if low on memory so it is not recommended here.


First you have to find out the payload offset of the crypted partition:

# cryptsetup luksDump /dev/<device> | grep "Payload offset"
 Payload offset:	4040

Second check the sector size of the drive

# fdisk -l /dev/<device> |grep "Sector size"
Sector size (logical/physical): 512 bytes / 512 bytes

Now that you know the values, you can backup the header with a simple dd command:

# dd if=/dev/<device> of=/path/to/<file>.img bs=512 count=4040

and store it safely.


Be careful before restore: make sure that you chose the right partition (again replace sdaX with the corresponding partition). Restoring the wrong header or restoring to an unencrypted partition will cause data loss.

Using cryptsetup

Or you can use the luksHeaderRestore command:

cryptsetup luksHeaderRestore /dev/sdaX --header-backup-file ./backup.img

Note: All the keyslot areas are overwritten; only active keyslots from the backup file are available after issuing this command.


Again, you will need to the same values as when backing up:

dd if=./backup.img of=/dev/sdX bs=512 count=4040