Manage LUKS2 Tokens Safely with cryptsetup token
You will finish with a repeatable way to inspect, export, import, bind and remove token metadata in a LUKS2 header. The examples use cryptsetup-bin 2:2.7.0-1ubuntu4.2, providing cryptsetup 2.7.0. Allow about fifteen minutes, and work with a LUKS2 test volume or a volume whose header backup you have already verified.
The route
Jump straight to the step you need, or tick off Done means at the end.
Most commands below read or rewrite the LUKS2 header, so they normally need elevated privileges. Replace /dev/mapper/example with the underlying LUKS2 device, not a mounted filesystem or an arbitrary path. A token is metadata used by an activation mechanism; it is not a passphrase and it is not itself a keyslot.
1. Check the installed contract
Start with read-only checks. This confirms the program and package version without opening or changing a volume:
$ cryptsetup --version
cryptsetup 2.7.0
$ dpkg-query -W -f='${Package} ${Version}\n' cryptsetup-bin
cryptsetup-bin 2:2.7.0-1ubuntu4.2
$ cryptsetup token --help
The supported actions on this installation are add, remove, import, export and unassign. The command only supports LUKS2. Check the format before going further:
$ sudo cryptsetup isLuks /dev/mapper/example
$ sudo cryptsetup luksDump /dev/mapper/example | sed -n '1,12p'
An exit status of zero from isLuks confirms a LUKS header, but not that it is LUKS2. The luksDump output should identify Version: 2. Stop if this is a LUKS1 volume.
2. Export a token before changing anything
Export is the safest way to see the JSON for one token. First list the token section and choose an ID that actually exists:
$ sudo cryptsetup luksDump /dev/mapper/example
...
Tokens:
0: systemd-tpm2
Keyslots:
The token type and output are host-specific. Do not assume that token 0 exists. Once you have an ID, export it to standard output:
$ sudo cryptsetup token export --token-id 0 --json-file=- /dev/mapper/example
{
"type":"systemd-tpm2",
"keyslots":["0"],
"tpm2-pcrs":"..."
}
The fields above are illustrative, not a template to paste back into a header. Your token may be supplied by a different plugin and have different fields. To preserve the exact JSON for review, use a root-readable file in a protected directory:
$ sudo install -d -m 0700 /root/luks-token-backups
$ sudo cryptsetup token export --token-id 0 \
--json-file=/root/luks-token-backups/token-0.json /dev/mapper/example
$ sudo cryptsetup token export --token-id 0 --json-file=- /dev/mapper/example \
| diff -u /root/luks-token-backups/token-0.json -
Checkpoint: the final command should produce no diff and return zero. Treat exported token JSON as security-sensitive metadata. It can reveal how automatic activation is configured, and an imported token can alter how a volume is unlocked.
3. Understand the binding before editing it
A token can be assigned to one keyslot, several keyslots, or no keyslot. The keyslot is where encrypted volume-key material is stored. The token is a separate JSON object that tells a token handler how to use a keyslot. Use luksDump to compare the Tokens and Keyslots sections before deciding what to change.
For a keyring token, add requires --key-description. Without --key-slot, the new token is assigned to all active keyslots. That default is easy to miss: specify a slot when the token must be tied to one particular slot.
Adding a token changes the LUKS2 header. Make a header backup first, and verify where the backup was written:
$ sudo cryptsetup luksHeaderBackup /dev/mapper/example \
--header-backup-file /root/luks-token-backups/example-header.img
$ sudo test -s /root/luks-token-backups/example-header.img && \
echo 'header backup exists'
header backup exists
Do not put that backup in an unprotected shared directory. It contains keyslot metadata and is part of the recovery material for the volume.
4. Add or unassign a keyring token
Adding a keyring token associates a keyring description with the selected keyslot. The passphrase itself must already be stored in the user or user-session keyring under that description; this command does not ask for, create or print that passphrase.
$ sudo cryptsetup token add \
--key-description='example-volume-passphrase' \
--key-slot=0 \
/dev/mapper/example
If the command succeeds, inspect the token section and record the ID chosen by cryptsetup. With no --token-id, the first unused token ID is selected:
$ sudo cryptsetup luksDump /dev/mapper/example | sed -n '/Tokens:/,/Keyslots:/p'
To keep the token but remove its relationship with keyslot 0, both identifiers are mandatory:
$ sudo cryptsetup token unassign \
--token-id 1 --key-slot 0 /dev/mapper/example
Replace 1 with the ID you recorded. Unassigning is not the same as removing: it removes one binding while leaving the token JSON in the header. Re-run luksDump to confirm the binding changed.
5. Import, replace or remove token JSON
Import accepts valid token JSON from a file or standard input. Prefer a file whose contents came from a trusted export or the documentation for the installed token handler:
$ sudo cryptsetup token import \
--json-file=/root/luks-token-backups/token-0.json \
--key-slot=0 /dev/mapper/example
If you specify --token-id and that ID is already occupied, import refuses to replace it unless you also specify --token-replace. Replacement is destructive to the old JSON at that ID. Export it first, then use the explicit ID only when you have checked the new JSON:
$ sudo cryptsetup token import --token-id 1 --token-replace \
--json-file=/root/luks-token-backups/reviewed-token.json \
--key-slot=0 /dev/mapper/example
There is no undo flag for an import or replacement. To recover, restore the verified header backup, or import the previously exported JSON with the correct ID and binding. Do not restore a header while the volume is actively being changed.
Remove is broader than its name may suggest. It removes any token type at the selected ID, not just a keyring token:
$ sudo cryptsetup token remove --token-id 1 /dev/mapper/example
$ sudo cryptsetup luksDump /dev/mapper/example | sed -n '/Tokens:/,/Keyslots:/p'
Check the ID carefully before pressing Enter. Removing a token can break automatic activation even though passphrase-based unlocking still works. If you need to remove a token from one keyslot but keep it for another, use unassign instead.
Common failure traps
- Wrong format: the token actions are for LUKS2 only. Confirm the version instead of trying options until one happens to work.
- Wrong object: use the LUKS device or detached-header arrangement documented for your volume. A filesystem path and a mapper name are not interchangeable.
- Wrong default: omitting
--key-slotwhen adding or importing binds the token to all active keyslots. Omitting--token-idselects the first unused ID. - Plugin confusion:
--disable-external-tokensprevents external token handlers loading. Do not use it when testing a token that depends on a plugin. - Lock bypass:
--disable-locksdisables metadata locking and is intended only for restricted environments where/runcannot be used. It is not a general fix for a lock error.
Done means
- The target is confirmed as a LUKS2 volume and the installed cryptsetup version is known.
- The original token JSON and a verified LUKS2 header backup are stored securely.
- Every changed token ID and keyslot binding was checked with
luksDump. - Any import used trusted, valid JSON, and any replacement was preceded by an export.
- Automatic activation was tested separately from ordinary passphrase unlocking.