The Argon2 variable-length hash function uses BLAKE2b directly if the user requests an output less than or equal to 64 bytes in length. However, if the user requests an output longer than this, each BLAKE2b-512 hash is truncated to become BLAKE2b-512-256. From Wikipedia:
// If the requested digestSize is 64-bytes or lower, then we use Blake2b directly
if (digestSize <= 64) then
// concatenate 32-bit little endian digestSize with the message bytes
return Blake2b(digestSize ∥ message, digestSize)
// For desired hashes over 64-bytes (e.g. 1024 bytes for Argon2 blocks),
// we use Blake2b to generate twice the number of needed 64-byte blocks,
// and then only use 32-bytes from each block
// Calculate the number of whole blocks (knowing we're only going to use 32-bytes from each)
r ← Ceil(digestSize/32)-2;
// Generate r whole blocks.
// Initial block is generated from message
V1 ← Blake2b(digestSize ∥ message, 64);
// Subsequent blocks are generated from previous blocks
for i ← 2 to r do
Vi ← Blake2b(Vi-1, 64)
// Generate the final (possibly partial) block
partialBytesNeeded ← digestSize – 32*r;
Vr+1 ← Blake2b(Vr, partialBytesNeeded)
// Concatenate the first 32-bytes of each block Vi
// (except the possibly partial last block, which we take the whole thing)
// Let Ai represent the lower 32-bytes of block Vi
return A1 ∥ A2 ∥ ... ∥ Ar ∥ Vr+1
I didn't see any rationale for this glancing at the specification and RFC. Why are they not using full BLAKE2b-512 outputs?