19

How can I change the hash-spec and iter-time of an existing dm-crypt LUKS device?

Clearly I can pass the options if I create a new device, for example something like this:

 sudo cryptsetup luksFormat --cipher aes-cbc-essiv:sha256 --key-size 256 --iter-time 2100 --hash sha512 /dev/loop0

But if the device already exists, how can I change for example sha256 to sha1 or change the iteration time without "destroying" the device. (Clearly you would have to retype your password since a new hash will be generated.)

6
  • Might be just me, but I consider it impolite to ask a 1 sentence Q w/o at least referencing a man page or a tutorial or something that you're attempting to follow with specifics such as what hash-spec is or iter-time settings are more specifically.
    – slm
    Nov 15, 2013 at 21:27
  • I guess we've worked together before on Q's (and you usually put excellent details in them) and it caught me off guard that this time you didn't.
    – slm
    Nov 15, 2013 at 21:28
  • I don't have more info in this case and didn't find what I want in the man page...
    – student
    Nov 15, 2013 at 21:30
  • Fair enough! What about the ArchWiki page? wiki.archlinux.org/index.php/Dm-crypt_with_LUKS
    – slm
    Nov 15, 2013 at 21:33
  • 2
    Also there is mention of another tool, cryptsetup-reencrypt. The bullet list sounds like what you're attempting to do to me: "change arbitrary encryption parameters".
    – slm
    Nov 15, 2013 at 21:37

2 Answers 2

15

If all you want to change is the hash, there is no need to re-encrypt. You still have to build a new LUKS header though. Same cipher, same master key, same offset, different hash.

You can try this for yourself. First we set up a LUKS device with standard settings and lousy iter counts:

# truncate -s 8M /dev/shm/foobar
# cryptsetup --iter-time=42 luksFormat /dev/shm/foobar

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

Are you sure? (Type uppercase yes): YES
Enter passphrase: 
Verify passphrase: 
# cryptsetup luksOpen /dev/shm/foobar foobar
Enter passphrase for /dev/shm/foobar: 
# shred -z /dev/mapper/foobar
# echo Hello World I am LUKS > /dev/mapper/foobar
# strings /dev/mapper/foobar
Hello World I am LUKS
# cryptsetup luksClose foobar

At this point we have a LUKS device with the encrypted data "Hello World I am LUKS". In particular it looks like this:

# cryptsetup luksDump /dev/shm/foobar
LUKS header information for /dev/shm/foobar

Version:        1
Cipher name:    aes
Cipher mode:    xts-plain64
Hash spec:      sha1
Payload offset: 4096
MK bits:        256
MK digest:      30 87 62 81 8e 8f a9 15 68 e0 82 c0 dc ee 19 54 9b f2 eb 5c 
MK salt:        c3 e0 28 53 67 10 13 d4 43 e3 7b d1 ce 62 6b e3 
                58 85 ee 67 71 76 b6 48 78 a8 34 71 58 71 21 f8 
MK iterations:  6175
UUID:           14a0a11d-0890-433e-bdcb-d2d1f5281bc2

Key Slot 0: ENABLED
    Iterations:             26033
    Salt:                   a1 7b 2b 5b 3d 8c 3c d1 3b 57 61 5a df 25 47 c8 
                            29 97 62 09 08 2b e1 b2 af 61 56 80 2f af a6 ae 
    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

As you can see, lousy iteration counts, standard sha1 hashes.

In order to switch that to high iteration counts and sha512 hash, without re-encrypting, we need a new LUKS header using the same master key, the same cipher, and the same payload offset.

Obtaining the master key: (Warning: this example leaks your master key to a world-readable file, to the process list, as well as to your shell's history. To be safe, do it in RAM / on a Live CD / whatever)

# cryptsetup --dump-master-key luksDump /dev/shm/foobar

WARNING!
========
Header dump with volume key is sensitive information
which allows access to encrypted partition without passphrase.
This dump should be always stored encrypted on safe place.

Are you sure? (Type uppercase yes): YES
Enter passphrase: 
LUKS header information for /dev/shm/foobar
Cipher name:    aes
Cipher mode:    xts-plain64
Payload offset: 4096
UUID:           14a0a11d-0890-433e-bdcb-d2d1f5281bc2
MK bits:        256
MK dump:    eb aa 57 2d 42 93 fe 90 00 b9 d2 e0 e0 7b 73 26 
            4b 64 1b 8b 8e 61 75 84 1b c3 d6 f7 3f 03 d2 14 

# printf '\xeb\xaa\x57\x2d\x42\x93\xfe\x90\x00\xb9\xd2\xe0\xe0\x7b\x73\x26\x4b\x64\x1b\x8b\x8e\x61\x75\x84\x1b\xc3\xd6\xf7\x3f\x03\xd2\x14' > /dev/shm/masterkey
# hexdump -C /dev/shm/masterkey
00000000  eb aa 57 2d 42 93 fe 90  00 b9 d2 e0 e0 7b 73 26  |..W-B........{s&|
00000010  4b 64 1b 8b 8e 61 75 84  1b c3 d6 f7 3f 03 d2 14  |Kd...au.....?...|
00000020

Create the new LUKS header using this key: (failure is possible - make a backup of your old LUKS header first!)

# cryptsetup --master-key-file=/dev/shm/masterkey --iter-time=5000 --hash=sha512 luksFormat /dev/shm/foobar

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

Are you sure? (Type uppercase yes): YES
Enter passphrase: 
Verify passphrase: 

And here's what it looks like:

# cryptsetup luksDump /dev/shm/foobar
LUKS header information for /dev/shm/foobar

Version:        1
Cipher name:    aes
Cipher mode:    xts-plain64
Hash spec:      sha512
Payload offset: 4096
MK bits:        256
MK digest:      47 ab 7b c6 41 b0 7c d8 af 3c a0 a4 23 e6 72 87 9c 0f c6 a0 
MK salt:        32 49 a5 b5 cb 4d 8a d7 25 69 72 ae e5 b2 9e 9d 
                14 09 00 1d 01 f3 c9 99 da e1 6c fc 69 78 e4 64 
MK iterations:  393750
UUID:           fd554ae8-a862-4609-8327-c6dd65ee9a83

Key Slot 0: ENABLED
    Iterations:             1578295
    Salt:                   e5 75 1c 1f 63 1d c6 0b d9 27 1a b1 27 85 b9 c1 
                            89 e8 57 95 2a c8 a0 24 9c 29 c0 f2 27 d7 2f 9a 
    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

Now we have it. Same cipher, offset [if they differ you must specify them along with the luksFormat], new hash and proper number of iterations.

But is the content still there?

# cryptsetup luksOpen /dev/shm/foobar foobar
Enter passphrase for /dev/shm/foobar: 
# strings /dev/mapper/foobar
Hello World I am LUKS

There you go.

1
  • 9
    cryptsetup-reencrypt --keep-key --hash sha512 does the same thing. Jan 28, 2015 at 14:39
9

Each key slot has its own iteration time. If you want to change the number of iterations, create a new slot with the same passphrase and a new number of iterations, then remove the old slot.

cryptsetup -i 100000 --key-slot 2 luksAddKey $device
cryptsetup luksKillSlot $device 1

I think the hash algorithm cannot be configured per slot, it's always PBKDF2 with a globally-chosen hash function.

Recent versions of cryptsetup include a tool cryptsetup-reencrypt, which can change the main encryption key and all the parameters, but it is considered experimental (and it reencrypts the whole device even though this would not be necessary to merely change the password-based key derivation function).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .