How to use a file as a LUKS device key

LUKS is the acronym of Linux Unified Key Setup: it is the most used encryption implementation used on Linux systems and can be configured as an alternative to dm-crypt plain setup. Compared to the latter it provides some additional features like password hashing and salting and the ability to store multiple passwords in the so called LUKS header. In this tutorial I will assume the reader has a certain familiarity with LUKS; if you want to know more about this subject, you can check our basic guide about encrypting linux partitions with luks. The most common way to protect a LUKS device is to use a passphrase, however it is also possible to use a file as a key; in this tutorial we will see how to do this. Let’s go!

In this tutorial you will learn:

  • How to create a file with random data to use as a LUKS device key
  • How to add a key to a LUKS device
  • How to automatically decrypt a LUKS device at boot using a file as a key

How to use a file as a LUKS device key

How to use a file as a LUKS device key

Software requirements and conventions used

Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Any Linux distribution
Software cryptsetup
Other Root permissions to access encrypted block devices
Conventions # – requires given linux-commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – requires given linux-commands to be executed as a regular non-privileged user

Creating a LUKS container

For the sake of this tutorial we will create a LUKS container on a file filled with zeros we will generate using dd. To create the file we can run:

$ sudo dd if=/dev/zero of=/luks-container.img bs=1M count=300

In the example above we used the /dev/zero file as the dd command input source (/dev/zero is a “special” file: everytime we read from it, it returns 0s) and /luks-container.img as destination and argument of the dd of operand. We instructed dd to read and write 300 blocks of 1MiB of size using respectively the bs and count operands. To use the file as a LUKS container, we must prepare it using cryptsetup; we can run:

$ sudo cryptsetup luksFormat --type=luks1 --hash=sha512 --key-size=512 --cipher=aes-xts-plain64 /luks-container.img

The luksFormat sub-command of cryptsetup is used to initialize a LUKS container and set the initial passphrase. Once we run the command above, will be warned that the operation is destructive, since it will overwrite all the existing data. We will be prompted to confirm that we want to perform the operation; we write YES (capital letters) and press enter to confirm:

This will overwrite data on /luks-container.img irrevocably.

Are you sure? (Type 'yes' in capital letters): YES

At this point we will be asked to provide and confirm a passphrase that will be used as the first of the eight possible device keys:

Enter passphrase for /luks-container.img:
Verify passphrase:

Our LUKS container is now ready. We can use the luksDump subcommand of cryptsetup to dump header information:

$ sudo cryptsetup luksDump /luks-container.img
LUKS header information for /luks-container.img

Version:        1
Cipher name:    aes
Cipher mode:    xts-plain64
Hash spec:      sha512
Payload offset: 4096
MK bits:        512
MK digest:      91 da 2e 2e 7f ea ae a1 f7 81 55 cc b7 27 fd b1 ab f4 65 f1
MK salt:        f1 03 65 e2 f1 d7 4e 77 99 48 e8 57 75 65 dd 73
                a3 eb a4 24 be 36 9e 84 f7 84 c5 d3 94 2e d8 52
MK iterations:  79054
UUID:           ea23c244-2dc5-402e-b23e-d9da3219ff8a

Key Slot 0: ENABLED
    Iterations:             1108430
    Salt:                   69 99 95 88 6e 2f e8 b9 d8 9c 91 36 b6 a2 55 c1
                            35 27 c7 da 5d 9a 9e f9 8c ec 70 68 db 41 53 4b
    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

In the output above we can see various information are reported: the Cipher name and Cipher mode used for the device, for example. What really interests us in this case, however, is the Key slots section. As you can see, in this case only the first keyslot is used: it stores the passphrase we provided when we formatted the device. In this case, there are a total of 8 slots; 7 are available to store additional keys. We will use one of them to store the file we will use to unlock the LUKS device.

Creating a random-data file to use as a key

Any existing file can be used as a LUKS device key, however it can be more secure to create a file specifically for the purpose, out of random data. To create the file, once again, we will resort to the venerable dd command, this time using /dev/urandom as data source:

$ sudo dd if=/dev/urandom of=/container-key bs=512 count=8
8+0 records in
8+0 records out
4096 bytes (4.1 kB, 4.0 KiB) copied, 0.000631541 s, 6.5 MB/s

The /dev/urandom file works similarly to /dev/zero but it returns random data every time it is read. This time we read 8 blocks of 512 bytes, creating a file “filled” with 4096 bytes of random data.

Adding the key-file to the LUKS device

Once the file is created, we can add it to the LUKS header, and use it as a key. The cryptsetup sub-command which let us perform this task is luksAddKey.

The first argument it takes is the LUKS device the key should be used for; the second, optional, is the path of a key file to be used as key. If it is omitted the user is prompted to provide a passphrase. Among the options accepted by the command, there is --key-slot: with it, we can specify what key slot should be used to store the key. In this case we will omit the option, so the first available slot will be used (in this case slot number 1).

To add the file as a LUKS key, we run:

$ sudo cryptsetup luksAddKey /luks-container.img /container-key

We will be asked to provide one already existing passphrase for the container; after we do it, the new key will be added. After the command above is successfully executed, if we run luksDump again, we can observe a new slot is now in use:

Key Slot 0: ENABLED
    Iterations:             1108430
    Salt:                   69 99 95 88 6e 2f e8 b9 d8 9c 91 36 b6 a2 55 c1
                            35 27 c7 da 5d 9a 9e f9 8c ec 70 68 db 41 53 4b
    Key material offset:    8
    AF stripes:             4000
Key Slot 1: ENABLED
    Iterations:             921420
    Salt:                   62 54 f1 61 c4 d3 8d 87 a6 45 3e f4 e8 66 b3 95
                            e0 5d 5d 78 18 6a e3 f0 ae 43 6d e2 24 14 bc 97
    Key material offset:    512
    AF stripes:             4000
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED

Opening the LUKS container

To verify that the key is working, we can now attempt to open the LUKS container using it. For this purpose we use the luksOpen sub-command of cryptsetup: it takes two mandatory arguments:

  1. The LUKS device
  2. The name to use to map the device once it is opened.

How can we specify that we want to use a file to open the device? Easy! We use the
--key-file option and pass the path to the key file as its argument. In our
case, to open the device, the complete command to run is:

$ sudo cryptsetup luksOpen /luks-container.img luks-container-crypt --key-file=/container-key

If everything goes as expected, we should find an entry for the opened container under the /dev/mapper directory, in this case: /dev/mapper/luks-container-crypt.

By the way, we can now treat the container just as we would do with any block device: perhaps we can create a filesystem on it and mount it:

sudo mkfs.ext4 /dev/mapper/luks-container-crypt && sudo mount /dev/mapper/luks-container-crypt /media

Open a LUKS container automatically at boot

Once we learned how to use a file as a LUKS container key, we can make so that a LUKS device is automatically opened at boot, without user interaction. It goes by itself that this is a setup that poses security risks, so it should be used very carefully! At least in unsafe places, the file used to unlock the device should be accessible only by the root user, and should be itself stored on an encrypted filesystem, otherwise the encryption becomes useless (is the equivalent of using a big fat lock to protect a door but leaving the key where it can be reached by anyone).

To make so that a LUKS container is automatically unlocked at boot, we must specify the needed information inside the /etc/crypttab file. This file is used to describe encrypted block devices that are setup during the system boot. The syntax to be used in the file is quite easy to understand; in each line we add, we need to specify, in order:

  1. The name to use for the mapping of the device (in the previous example we used luks-container-crypt)
  2. The device hosting the LUKS container that should be opened
  3. The device password (optional)
  4. The options to use (optional)

In this case we would enter this line:

luks-container-crypt /luks-container.img /container-key luks

On the next boot, the device will be automatically unlocked!


In this tutorial we learned how we can use a file as a key to unlock a LUKS container. Although any file can be used for the purpose, we saw how to use dd to create a random-data file, and we saw how to add it to one of the 8 available LUKS header slots using the luksAddKey command. Finally, we saw how it’s possible to automatically unlock the LUKS container at boot by using a keyfile, providing the needed information inside the /etc/crypttab file, and we saw why this can represent a possible security risk.

Comments and Discussions
Linux Forum