1. Overview

We can protect the data on a block device using disk encryption. This is important for removable media since it protects the data even if the media is physically removed from a system.

LUKS (Linux Unified Key Setup) is a popular disk encryption method in Linux. LUKS encrypts a block device — typically a disk partition — with a master key, and multiple users can use the encrypted block device with different passphrases by decrypting the master key.

In this tutorial, we’ll discuss how to change a LUKS passphrase. First, we’ll give a brief introduction to LUKS. Then, we’ll prepare the necessary setup. Finally, we’ll see how to change a passphrase.

2. Brief Introduction to LUKS

LUKS encrypts a block device with a randomly generated master key and contains an unencrypted header preceding the encrypted data. This unencrypted header supports multiple passphrases by providing several key slots. Therefore, multiple users can use the same LUKS-encrypted partition using different passphrases.

There are two versions of LUKS. The older version, LUKS1, allows the usage of up to eight key slots. LUKS2, on the other hand, supports up to 32 key slots and is more resilient to header corruption.

LUKS encrypts the master key with user keys generated from the passphrases of users. Therefore, when we want to access an encrypted partition, it first decrypts the master key using our passphrase and decrypts the partition using the master key. This multi-layer approach enhances security.

3. Preparing the Setup

Let’s start by checking the block devices on our host using the lsblk command:

$ lsblk 
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda           8:0    0  512G  0 disk 
├─sda1        8:1    0    1G  0 part /boot
└─sda2        8:2    0  511G  0 part 
  ├─cs-root 253:0    0   70G  0 lvm  /
  ├─cs-swap 253:1    0  2.1G  0 lvm  [SWAP]
  └─cs-home 253:2    0  439G  0 lvm  /home
sdb           8:16   0   20G  0 disk

According to the last line in the output of lsblk, we have a hard disk, namely sdb, which hasn’t been mounted yet.

Let’s also check the file system on /dev/sdb:

$ lsblk -f /dev/sdb
NAME FSTYPE LABEL UUID MOUNTPOINT
sdb

The -l option of lsblk gives information about the file systems. Notably, the disk doesn’t have a file system.

3.1. Creating a LUKS Partition

Since the disk has no file system, let’s format the disk with LUKS:

$ sudo cryptsetup luksFormat /dev/sdb

WARNING!
========
This will overwrite data on /dev/sdb irrevocably.

Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/sdb: 
Verify passphrase:

cryptsetup is a command-line tool we use to create, access, and manage dm-crypt and LUKS-encrypted volumes. The cryptsetup luksFormat command initializes a LUKS partition and sets the initial passphrase for the specified device. We pass /dev/sdb as the device in our case.

We get a warning about overwriting the existing data in the device and cryptsetup wants us to confirm it by typing YES. Then, it prompts for the passphrase. Additionally, it wants us to verify the passphrase.

cryptsetup has several options for specifying arguments like the LUKS version, the hash algorithm, and the key sizes used under the hood. However, using it with the default options is sufficient for our purpose.

We need root privileges for using cryptsetup, so we use it together with the sudo command.

Having created the LUKS partition, let’s check the file system on /dev/sdb using lsblk again:

$ lsblk -f /dev/sdb
NAME FSTYPE      LABEL UUID                                 MOUNTPOINT
sdb  crypto_LUKS       c39f7404-6fa3-4c39-ba81-0a3fe41cb642

Now, /dev/sdb has a LUKS-encrypted file system as is apparent from the output.

3.2. Opening the LUKS Partition

We can open the LUKS partition using the cryptsetup luksOpen command:

$ sudo cryptsetup luksOpen /dev/sdb luks_disk
Enter passphrase for /dev/sdb:

We pass the LUKS formatted device name, which is /dev/sdb in our case, to the cryptsetup luksOpen command. Notably, we must provide the passphrase we created while using cryptsetup luksFormat.

In addition to the device name, we specify the name of the map point, which is luks_disk. The map point can be assigned any name and specifies the name in /dev/mapper. In our case, the LUKS partition is mapped to /dev/mapper/luks_disk:

$ ls /dev/mapper/luks_disk 
/dev/mapper/luks_disk

We can also check the mapping using lsblk:

$ lsblk -f /dev/sdb
NAME        FSTYPE      LABEL UUID                                 MOUNTPOINT
sdb         crypto_LUKS       c39f7404-6fa3-4c39-ba81-0a3fe41cb642 
└─luks_disk

As we can see from the output, luks_disk doesn’t have a file system on it yet.

3.3. Creating a File System in the LUKS Partition

Now, we’ll create a file system in the LUKS partition using the mkfs.xfs command:

$ sudo mkfs.xfs /dev/mapper/luks_disk >& /dev/null

The mkfs.xfs command is used for creating an XFS file system. We create the XFS file system on /dev/mapper/luks_disk in the above command, and we redirect the output of the command to /dev/null to skip viewing the details.

Although we use XFS in our example, we can use any other file system — for example, EXT4.

3.4. Mounting the File System

The final step is to mount the file system:

$ sudo mkdir /mnt/luks_mount
$ sudo mount /dev/mapper/luks_disk /mnt/luks_mount

Here, we mount the /dev/mapper/luks_disk file system to the /mnt/luks_mount directory.

Let’s check the file system on /dev/sdb once more:

$ lsblk -f /dev/sdb
NAME        FSTYPE      LABEL UUID                                 MOUNTPOINT
sdb         crypto_LUKS       c39f7404-6fa3-4c39-ba81-0a3fe41cb642 
└─luks_disk xfs               4238dadf-7abf-41e1-89b8-b54363e21fc1 /mnt/luks_mount

Now, the /dev/sdb LUKS-encrypted device has an XFS file system on it, and its mount point is /mnt/luks_mount, as expected.

4. Changing the LUKS Passphrase

Next, we’ll change the passphrase that was provided when creating the LUKS partition using cryptsetup luksFormat. This passphrase actually corresponds to that of the first key slot.

Before changing the passphrase of the first key slot, let’s check the header of the LUKS partition:

$ sudo cryptsetup luksDump /dev/sdb
LUKS header information
Version:       	2
Epoch:         	3
Metadata area: 	16384 [bytes]
Keyslots area: 	16744448 [bytes]
UUID:          	c39f7404-6fa3-4c39-ba81-0a3fe41cb642
Label:         	(no label)
Subsystem:     	(no subsystem)
Flags:       	(no flags)

Data segments:
  0: crypt
	offset: 16777216 [bytes]
	length: (whole device)
	cipher: aes-xts-plain64
	sector: 512 [bytes]

Keyslots:
  0: luks2
	Key:        512 bits
	Priority:   normal
	Cipher:     aes-xts-plain64
	Cipher key: 512 bits
	PBKDF:      argon2i
	Time cost:  4
	Memory:     930152
	Threads:    2
	Salt:       22 77 54 98 4e a6 5c fa 51 21 49 7f 7d 10 21 dd 
	            ab 27 83 c3 73 f4 99 44 d2 af ee ba 9b 9b 26 c9 
	AF stripes: 4000
	AF hash:    sha256
	Area offset:32768 [bytes]
	Area length:258048 [bytes]
	Digest ID:  0
Tokens:
Digests:
  0: pbkdf2
	Hash:       sha256
	Iterations: 177845
	Salt:       8a f0 cd 5b 9a 1f 45 ec a3 11 99 dd 5c 5e c7 0c 
	            78 c8 75 5d c8 24 cb 2f 80 18 52 16 d4 9a bb db 
	Digest:     b9 49 dc a0 53 49 ea fe 1f f5 bf ac c8 10 b1 f5 
	            e8 b8 06 85 b2 8f 43 8c 9d 5b 69 17 4b 87 09 1f

We use the cryptsetup luksDump command for displaying the LUKS header, passing the block device to it as an argument.

As we see from the output, we have only one key slot.

4.1. Single Key Slot Case

We can change the existing passphrase using the cryptsetup luksChangeKey command:

$ sudo cryptsetup luksChangeKey /dev/sdb
Enter passphrase to be changed: 
Enter new passphrase: 
Verify passphrase:

We pass the /dev/sdb device as an argument to the cryptsetup luksChangeKey command. The command asks for the current passphrase, and once we enter it correctly, it asks for the new passphrase.

4.2. Multiple Key Slots Case

Earlier, we didn’t have to specify a key slot while changing the passphrase as there’s only one key slot in the LUKS partition. However, LUKS supports multiple key slots. How do we specify the key slot in that case?

Let’s add a new key slot using the cryptsetup luksAddKey command:

$ sudo cryptsetup luksAddKey /dev/sdb
Enter any existing passphrase: 
Enter new passphrase for key slot: 
Verify passphrase:

The cryptsetup luksAddKey command first asks for an existing passphrase. Since there’s only one key slot, we enter the corresponding passphrase. Once we enter the passphrase for the first key slot correctly, it prompts us to provide a new passphrase for the new key slot and then wants us to verify the new passphrase.

We can use the -S option of cryptsetup luksChangeKey to select a specific key slot. The numbering of key slots starts from 0, so the number of the second key slot is 1.

Let’s change the passphrase of the second key slot we’ve just added:

$ sudo cryptsetup luksChangeKey /dev/sdb -S 1
Enter passphrase to be changed: 
Enter new passphrase: 
Verify passphrase:

Now, we must first enter the passphrase of the second key slot. Once we enter the passphrase of the second key slot correctly, we’re asked to enter and verify the new passphrase.

Equivalently, we can also use the –key-slot option instead of -S.

We can remove a passphrase using the cryptsetup luksRemoveKey command:

$ sudo cryptsetup luksRemoveKey /dev/sdb
Enter passphrase to be deleted:

We don’t have to specify the slot number while deleting a passphrase. Providing the passphrase of the second slot removes the second slot from the device.

5. Conclusion

In this article, we discussed how to change a LUKS passphrase.

First, we gave a brief introduction to LUKS. Then, we created a LUKS partition to demonstrate adding and changing key slots.

Finally, we learned how to change the passphrase of an existing key slot using the cryptsetup luksChangeKey command. We saw that we can use the -S option to specify the key slot number when there are multiple key slots.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.