LUKS¶
LUKS (Linux Unified Key Setup) is the standard for Linux disk encryption. cryptsetup accepts keyfiles or passphrases on stdin, both of which cryptkey can drive directly — no temp files, no process-substitution gymnastics.
Note
cryptsetup operations require root, so every command below goes through sudo. The cryptkey derive --raw -- sudo … pattern sequences cryptkey's provider prompts ahead of sudo's password prompt so they don't race for /dev/tty. The VeraCrypt example goes into more depth on why that matters.
Preferred: keyfile on stdin¶
cryptsetup reads a keyfile from stdin when --key-file - is passed. cryptkey's -- <cmd> exec sends the derived key to the child's stdin, so the pair composes cleanly:
# Format a new volume
cryptkey derive --raw -- sudo cryptsetup luksFormat /dev/sdX --key-file -
# Open it
cryptkey derive --raw -- sudo cryptsetup luksOpen /dev/sdX encrypted --key-file -
# Close when done
sudo cryptsetup luksClose encrypted
The key flows through the pipe in memory only — no /tmp, no /dev/shm, no shred step.
Mount and unmount¶
sudo mount /dev/mapper/encrypted /mnt/encrypted
# ... use the filesystem ...
sudo umount /mnt/encrypted
sudo cryptsetup luksClose encrypted
Passphrase-style invocation¶
cryptsetup's stdin reader treats the bytes as a passphrase by default, so you can also pipe the hex-encoded output (no --raw):
cryptkey derive -- sudo cryptsetup luksFormat /dev/sdX
cryptkey derive -- sudo cryptsetup luksOpen /dev/sdX encrypted
This still invokes LUKS's PBKDF2/Argon2 stretching on the hex string — slightly slower on open than the raw-keyfile form but equivalent in security.
Unlock helper¶
#!/bin/bash
# unlock.sh — open an encrypted volume using cryptkey.
set -euo pipefail
DEVICE="/dev/sdX"
MAPPER_NAME="encrypted"
MOUNT_POINT="/mnt/encrypted"
cryptkey derive --raw -- sudo cryptsetup luksOpen \
"$DEVICE" "$MAPPER_NAME" --key-file -
sudo mount "/dev/mapper/$MAPPER_NAME" "$MOUNT_POINT"
echo "Mounted at $MOUNT_POINT"
No temp file, no trap, no cleanup step — the key never leaves cryptkey's memory and the pipe buffer.
Multiple key slots¶
LUKS volumes have up to 8 key slots; you can add independent keys with luksAddKey. Two useful patterns:
Different --use label on the same profile¶
# Slot 0 was created with the default-use key above; add a second slot
# keyed by a different --use label on the same cryptkey profile.
cryptkey derive --raw -- sudo cryptsetup luksAddKey /dev/sdX \
--key-file <(cryptkey derive --raw --use luks-backup)
The outer cryptkey derive --raw -- sudo … provides the existing key that authenticates luksAddKey (cryptsetup reads stdin for that). The <(cryptkey derive --raw --use luks-backup) process substitution provides the new key to add. Two independent HKDF outputs, one profile, one auth flow per derive. (See the VeraCrypt process-substitution notes for why <() works here with sudo — same caveats apply.)
A separate profile for the backup slot¶
When you want the backup slot to be unlockable by a different set of providers entirely, enroll a second profile with its own provider set, then compose:
cryptkey init luks-backup --add fido2:backup-yubikey --add recovery:paper
# ...later, add its key to the LUKS volume:
cryptkey derive --raw -- sudo cryptsetup luksAddKey /dev/sdX \
--key-file <(cryptkey derive luks-backup --raw)
Notes¶
- LUKS runs its own key stretching (PBKDF2 on LUKS1, Argon2id on LUKS2) over whatever you feed
--key-file. The keyfile can be any length; what matters is entropy, not byte count. cryptkey's 32 bytes of output are 256 bits of entropy — plenty for any LUKS cipher. --key-size 512(if you set it) refers to the cipher's internal key material (AES-XTS uses two 256-bit keys = 512 bits), not the keyfile length. Pass it toluksFormatonly if you want to override the cipher default; leave it off for default behavior.- LUKS2 is the default on modern distros and uses Argon2id for its KDF by default.
- Your LUKS header (containing the encrypted volume key plus the hashed keyfile slots) lives on the disk itself; cryptkey's profile doesn't need to back it up, but a
cryptsetup luksHeaderBackupof the LUKS header is still worth doing — profile loss and LUKS-header loss are separate failure modes.