For instance, if we choose --pbkdf argon2id
and --hash blake2b-512
,
# printf 'YES' | cryptsetup luksFormat \
--type luks2 --key-file /tmp/keyfile \
--header /tmp/luks.header \
--cipher serpent-xts-plain64 --key-size 512 \
--use-random \
--hash blake2b-512 --pbkdf argon2id \
--pbkdf-force-iterations 4 \
--pbkdf-memory 32 --pbkdf-parallel 1 \
/dev/loop0
From the header, argon2id
goes to the keyslot. And blake2b-512
is the hash used for Digest.
What does digest do indeed? From the LUKS2 specification, it states digests are used to verify that keys decrypted from keyslots are correct. If I get it correctly, the digest is only used to verify our passphrase/keyfile, but it has nothing to do with generating the volume master key.
# cryptsetup luksDump /tmp/luks.header
LUKS header information
Version: 2
Epoch: 3
Metadata area: 16384 [bytes]
Keyslots area: 16744448 [bytes]
UUID: fa2562ec-b396-43b7-8d81-e5f4ffb96bb0
Label: (no label)
Subsystem: (no subsystem)
Flags: (no flags)
Data segments:
0: crypt
offset: 0 [bytes]
length: (whole device)
cipher: serpent-xts-plain64
sector: 4096 [bytes]
Keyslots:
0: luks2
Key: 512 bits
Priority: normal
Cipher: serpent-xts-plain64
Cipher key: 512 bits
PBKDF: argon2id
Time cost: 4
Memory: 32
Threads: 1
Salt: ab bc 1b 5b d9 19 2b ce 04 59 1c 31 97 cc 03 d9
13 5a 6f 54 6a 1b 81 b8 c6 93 0e 19 d1 a0 0c 15
AF stripes: 4000
AF hash: blake2b-512
Area offset:32768 [bytes]
Area length:258048 [bytes]
Digest ID: 0
Tokens:
Digests:
0: pbkdf2
Hash: blake2b-512
Iterations: 1000
Salt: 78 4e 17 12 70 f5 63 18 49 bf 79 24 9f 35 d2 7e
b0 e3 3e b2 85 5e 0e 64 9a 2e 31 9e 76 13 4e 24
Digest: bf 97 93 6b 6a 0c b6 58 bd c6 1e 3d 7b ec d3 d5
52 4d f7 f2 b5 9d 19 69 7d dd 7f aa 0c 90 bc 7e
4d 4c ad 2a 3a 4f dd 92 d7 d2 16 df ca 3b 57 8d
85 99 76 48 f6 59 fa 6a e2 dc 64 80 5f bc cc 35
With luksDump --dump-master-key
, we can view the 512 bits volume master key in plain hex.
# printf 'YES' | cryptsetup luksDump --dump-master-key --key-file /tmp/keyfile /tmp/luks.header
LUKS header information for /tmp/luks.header
Cipher name: serpent
Cipher mode: xts-plain64
Payload offset: 0
UUID: fa2562ec-b396-43b7-8d81-e5f4ffb96bb0
MK bits: 512
MK dump: 84 c3 c7 1d 8b bd f8 cd 29 5d 5d ee 08 10 da 70
0c 8e 45 af 9f 58 80 3d 49 46 e4 4d fe 75 37 c0
89 30 d4 fe a8 27 76 71 16 0c f2 4e aa d8 27 b4
6e c2 e4 f0 c6 5a 86 cf fe 35 ff fd f0 df e6 62
I try to use the Argon2 program, with the known salt, to generate the volume master key. With the same settings in Argon (iteration count=4
, memory cost=32
, and parallel cost=1
), I cannot get the same hash result.
# eval 'cat /tmp/keyfile | argon2 '$(printf "\xab\xbc\x1b\x5b\xd9\x19\x2b\xce\x04\x59\x1c\x31\x97\xcc\x03\xd9\x13\x5a\x6f\x54\x6a\x1b\x81\xb8\xc6\x93\x0e\x19\xd1\xa0\x0c\x15")' -id -t 4 -m 5 -p 1 -l 64'
Type: Argon2id
Iterations: 4
Memory: 32 KiB
Parallelism: 1
Hash: 83ed8343d0539ba4f44fd79ac1becce1c7dd5001b7098f0cfb6a6cc7a07123890ccafb4cf8b7a8cb3ba1475e738f1268fb66eb89c42faf8460272878781cd952
Encoded: $argon2id$v=19$m=32,t=4,p=1$q7wbW9kZK84EWRwxl8wD2RNab1RqG4G4xpMOGdGgDBU$g+2DQ9BTm6T0T9eawb7M4cfdUAG3CY8M+2psx6BxI4kMyvtM+LeoyzuhR15zjxJo+2bricQvr4RgJyh4eBzZUg
0.000 seconds
Verification ok
How does LUKS make use of our passphrase, processed by the Argon PBKDF with salt, then obtain the volume master key?