How to recover lost LUKS key or passphrase

Solution Verified - Updated -

Environment

  • Red Hat Enterprise Linux 5
  • Red Hat Enterprise Linux 6
  • Red Hat Enterprise Linux 7

Issue

  • I lost my LUKS key. How can I recover my data?
  • I forgot the passphrase to my LUKS-encrypted drive. What can I do?
  • How can I recover my data if forgot luks password ?

Resolution

(A) Are any other passphrases or keyfiles available?

LUKS allows for up to 8 keys (derived from passphrases or files) per device

  1. Find the device name with blkid
    This command will only show LUKS devices

    blkid -t TYPE=crypto_LUKS -o device
    

    Example:

    [root]# blkid -t TYPE=crypto_LUKS -o device
    /dev/vdb1
    
  2. Inspect the LUKS header to see how many key-slots are populated
    Use the device name from the previous step

    cryptsetup luksDump /dev/<NAME> | grep Key.Slot
    

    Example:

    [root]# cryptsetup luksDump /dev/vdb1 | grep Key.Slot
    Key Slot 0: ENABLED
    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
    
  3. If more than one key slot is enabled, perhaps someone else has a valid key ...?

(B) Is the device still open?

If the system is still up and the device is currently opened (unlocked), root can use the master key to add a new key

(RHEL 5 caveat: root can extract the master key to a file; however, cryptsetup in RHEL 5 doesn't support reading the master key to add a new key. Instead, the disk itself will need to be closed and moved to a RHEL 6 or RHEL 7 machine [along with the master key file].)

  1. Check for open crypt devices
    This command will only show open maps to LUKS-encrypted devices

    dmsetup ls --target crypt
    

    Example:

    [root]# dmsetup ls --target crypt
    vdc-decrypted    (253, 2)
    luks-ec013cf7-ad72-4dcf-8a1e-0548016a3e2c    (253, 1)
    

    The first column is the map filename (<MAP>) without the /dev/mapper/ prefix
    If no output is seen, go to (C)

  2. Find desired open map in above output and make note of its name (<MAP>)
    If system has only ever had one LUKS device, go to next step
    If there are [or should be] multiple LUKS devices on system, use lsblk, findmnt, df, mount, or /etc/fstab to determine the right device

    Examples:

    [root]# mount | grep vdc
    /dev/mapper/vdc-decrypted on /opt type xfs (rw,relatime,seclabel,attr2,inode64,noquota)
    [root]# lsblk | grep -B1 luks-ec013cf7-ad72-4dcf-8a1e-0548016a3e2c
    └─vdb1                                        252:17   0 1023M  0 part
      └─luks-ec013cf7-ad72-4dcf-8a1e-0548016a3e2c 253:1    0 1021M  0 crypt /cryptstor
    [root]# lsblk /dev/vdc
    NAME            MAJ:MIN RM SIZE RO TYPE  MOUNTPOINT
    vdc             252:32   0   2G  0 disk
    └─vdc-decrypted 253:2    0   2G  0 crypt /opt
    [root]# findmnt /dev/mapper/luks-ec013cf7-ad72-4dcf-8a1e-0548016a3e2c
    TARGET     SOURCE                                                FSTYPE OPTIONS
    /cryptstor /dev/mapper/luks-ec013cf7-ad72-4dcf-8a1e-0548016a3e2c ext4   rw,relatime,seclabel,data=ordered
    
  3. Extract the LUKS master key and use it to add a new key
    Be careful with the master key -- it allows full access to the device

    dmsetup table <MAP> --showkeys
    

    The master key is the hex string in the 5th column; however, to use it with cryptsetup luksAddkey <DEVICE> --master-key-file, it must be converted to binary

    • RHEL 6 and RHEL 7:
      The master key can be extracted, converted to binary, and piped directly to luksAddKey with the following command

      cryptsetup luksAddKey <DEVICE> --master-key-file <(dmsetup table --showkey /dev/mapper/<MAP> | awk '{print$5}' | xxd -r -p)
      

      Example:

      [root]# lsblk | grep -B1 luks-ec013cf7-ad72-4dcf-8a1e-0548016a3e2c
      └─vdb1                                        252:17   0 1023M  0 part
        └─luks-ec013cf7-ad72-4dcf-8a1e-0548016a3e2c 253:1    0 1021M  0 crypt /cryptstor
      [root]# cryptsetup luksAddKey /dev/vdb1 --master-key-file <(dmsetup table --showkey /dev/mapper/luks-ec013cf7-ad72-4dcf-8a1e-0548016a3e2c | awk '{print$5}' | xxd -r -p)
      Enter new passphrase for key slot:
      Verify passphrase:
      [root]# cryptsetup luksDump /dev/vdb1 | grep ENABLED
      Key Slot 0: ENABLED
      Key Slot 1: ENABLED
      
    • RHEL 5:
      Save the key to a gpg-encrypted file for transfer to a RHEL 6 or RHEL 7 system where the final steps can be done

      Example:

      [root@rhel5]# dmsetup table --showkey vdb-open | awk '{print $5}'
      3c8e2d74f66d684547fdb0421cb3ced6
      [root@rhel5]# dmsetup table --showkey vdb-open | awk '{print $5}' | gpg -aco  masterkey.gpg --force-mdc --cipher-algo aes256
      Enter passphrase:
      Repeat passphrase:
      [root@rhel5]# cat masterkey.gpg
      -----BEGIN PGP MESSAGE-----
      Version: GnuPG v1.4.5 (GNU/Linux)
      
      jA0ECQMClT4LaE+j9PNg0lYBM0QAV1jOEPVIZuEhOnB2iStT+51BTzMxlg99uu9L
      FmynvHQZ71M/0JXoEpBmEvJUXS0NB1deTCFfNb7BDGuYQZDKSCunQo/F0o2m1l5x
      ZLq83BcDdg==
      =p7Zd
      -----END PGP MESSAGE-----
      
              Transfer masterkey.gpg to RHEL 6/7 system.
              Make sure masterkey.gpg can be decrypted on other system.
      
      [root@rhel6]# gpg -d masterkey.gpg
      gpg: AES256 encrypted data
      gpg: encrypted with 1 passphrase
      3c8e2d74f66d684547fdb0421cb3ced6
      
              Once certain masterkey is intact on other system, close the
              LUKS device on the RHEL 5 system and move/migrate the disk
              to the new system.
      
      [root@rhel5]# cryptsetup luksClose vdb-open
      
              After that, add a new key using the decrypted master key.
      
      [root@rhel6]# blkid -t TYPE=crypto_LUKS -o device
      /dev/vdb
      [root@rhel6]# cryptsetup luksAddKey /dev/vdb --master-key-file <(gpg -d masterkey.gpg | xxd -r -p)gpg: AES256 encrypted data
      gpg: encrypted with 1 passphrase
      Enter new passphrase for key slot:
      Verify passphrase:
      [root@rhel6]# cryptsetup luksDump /dev/vdb | grep ENABLED
      Key Slot 0: ENABLED
      Key Slot 1: ENABLED
      
              After adding new key, close the device and move it back
              to the RHEL 5 system, if desired.
      

(C) None of that helped!

  • The whole point of encryption is to protect data. If there are no known keys and the device is not unlocked, the data is as good as gone.

  • Barring future discoveries of cryptographic weaknesses in the current LUKS/dm-crypt implementation and barring availability of advanced quantum computers, the only option likely within the realm of possibility is a brute-force dictionary attack, i.e., password-guessing.

  • The feasibility of a dictionary attack depends entirely on the mind that created the key(s), since LUKS allows enormous (512 characters in RHEL 7) plaintext passphrases, not to mention insanely large (8 MiB in RHEL 7) keyfiles [which can contain newlines or even arbitrary binary data].

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

3 Comments

Small typo for this line:

cryptsetup luksAddKey <DEVICE> --master-key-file <(dmsetup table --showkey /dev/mapper/<MAP> | awk '{print$5}' | xxd -r -p)

It should be

cryptsetup luksAddKey <DEVICE> --master-key-file <(dmsetup table /dev/mapper/<MAP> --showkey | awk '{print$5}' | xxd -r -p)

It's actually not a typo. dmsetup uses standard forgiving gnu-style cmdline opt parsing -- it lets you use --showkey (or --showkeys) before or after the map-name. You also don't need to specify the /dev/mapper part.

Will it be safe in this example to delete slot 0 if the passphrase was not known and a new key slot was added with a new passphrase? Will the extracted master-key-file stop working if key slot 0 is deleted or will it know to use slot 1 going forward?