NAME
Crypt::Sodium::XS::xof - Extendable output functions
SYNOPSIS
use Crypt::Sodium::XS;
use Crypt::Sodium::XS::xof;
die "no xof support" unless Crypt::Sodium::XS::xof->available;
my $xof = Crypt::Sodium::XS->xof(primitive => 'turboshake128');
# one-shot
my $out = $xof->xof("foobar", 32);
print unpack("H*", $out), "\n";
$out = $xof->xof("foobar", 64);
print unpack("H*", $out), "\n"; # note first 32 bytes are identical
# multipart
my $mp = $xof->init;
$mp->update(qw(foo bar));
$mp->update('baz');
print unpack("H*", $mp->squeeze(32)), "\n" for (1 .. 3);
# different domain produces unrelated output
$mp = $xof->init(0x7e);
$mp->update(qw(foo bar baz));
print unpack("H*", $mp->squeeze(32)), "\n" for (1 .. 3);
my $more_output = $mp->squeeze(42);
# for key derivation, use protected memory objects for output
my $out_memvault = $mp->squeeze_key(99);
DESCRIPTION
An extendable output function (XOF) is similar to a hash function, but its output can be extended to any desired length.
Unlike a hash function where the output size is fixed, a XOF can produce output of arbitrary length from the same input, making it useful for key derivation, stream generation, and applications where variable-length output is needed.
libsodium provides two families of XOFs:
SHAKE
NIST-standardized XOFs from FIPS 202
TurboSHAKE
Faster variants using reduced-round Keccak, standardized in RFC 9861
XOFs can be used as:
Hash functions
Producing fixed-length digests
Key derivation functions
Deriving multiple keys from a seed
Deterministic random generators
Expanding a seed into arbitrary-length output
Domain-separated hashing
Using custom domain separators
Hash-to-curve or hash-to-field
XOFs simplify protocols that need to hash into mathematical structures by providing arbitrary-length output without awkward padding or multiple hash calls
Replacing HKDF-Expand
When you have a uniformly random key and need to derive multiple outputs, a XOF is simpler than HKDF
CONSTRUCTOR
The constructor is called with the Crypt::Sodium::XS->xof method.
my $xof = Crypt::Sodium::XS->xof(primitive => 'shake128');
Returns a new xof object. The primitive attribute is required.
Implementation detail: the returned object is blessed into Crypt::Sodium::XS::OO::xof.
ATTRIBUTES
primitive
my $primitive = $xof->primitive;
$xof->primitive('shake256');
Gets or sets the primitive used for all operations by this object. It must be one of the primitives listed in "PRIMITIVES". For this module there is no default primitive, and this attribute is always identical to "PRIMITIVE".
METHODS
available
my $has_xof = $xof->available;
my $has_xof = Crypt::Sodium::XS::xof->available;
Returns true if Crypt::Sodium::XS supports XOF, false otherwise. XOF will only be supported if Crypt::Sodium::XS was built with a new enough version of libsodium (at least 1.0.21).
Can be called as a class method.
primitives
my @primitives = $xof->primitives;
my @primitives = Crypt::Sodium::XS::xof->primitives;
Returns a list of all supported primitive names.
Can be called as a class method.
PRIMITIVE
my $primitive = $xof->PRIMITIVE;
Returns the primitive used for all operations by this object. For this module, always identical to the "primitive" attribute.
init
my $multipart = $xof->init($domain, $flags);
$domain is optional. It must be an integer value between 1 and 127. Different values of $domain will create unrelated output, allowing different applications to use the same underlying XOF without risk of collisions. If not provided or undefined, the default of "DOMAIN_STANDARD" is used.
$flags is optional. It is the flags used for the multipart protected memory object. See Crypt::Sodium::XS::ProtMem.
Returns a multipart xof object. See "MULTI-PART INTERFACE".
xof
my $out = $xof->xof($msg, $size);
$msg is the input data to the XOF. It may be a Crypt::Sodium::XS::MemVault.
$size is the desired output length, in bytes.
Returns the xof output of $size bytes.
xof_key
my $out_mv = $xof->xof_key($msg, $size, $flags);
$msg is the input data to the XOF. It may be a Crypt::Sodium::XS::MemVault.
$size is the desired output length, in bytes.
$flags is optional. It is the flags used for the $out Crypt::Sodium::XS::MemVault. See Crypt::Sodium::XS::ProtMem.
Returns a Crypt::Sodium::XS::MemVault: the xof output of $size bytes.
This is identical to "xof", but intended for sensitive output such as using XOF for key derivation.
BLOCKBYTES
Returns the internal block size, in bytes. Rarely useful.
DOMAIN_STANDARD
Returns the default domain value used for "init".
STATEBYTES
Returns the internal hash state size, in bytes. Rarely useful.
MULTI-PART INTERFACE
The multi-part API allows hashing data provided in chunks, and squeezing output incrementally.
A multipart xof object is created by calling the "init" method. Data is absorbed by one or more calls to the "update" method of that object. Once all data has been absorbed, "squeeze" can be called repeatedly to produce output.
After squeezing begins, no more data can be absorbed into the object.
The xof object is an opaque memory protected object which provides the following methods:
clone
my $mp2 = $multipart->clone;
Returns a cloned copy of the multipart xof object, duplicating its internal state.
squeeze
my $out = $multipart->squeeze($size);
Returns the next $size bytes of output squeezed from absorbed data.
If the output is sensitive (e.g., key derivation), you should prefer "squeeze_key" instead.
Do not call "update" on the same object after calling this method.
squeeze_key
my $out_mv = $multipart->squeeze_key($size, $flags);
$flags is optional. It is the flags used for the $out_mv Crypt::Sodium::XS::MemVault. See Crypt::Sodium::XS::ProtMem.
Returns a Crypt::Sodium::XS::MemVault: the next $size bytes of output squeezed from absorbed data.
This is identical to "squeeze", but intended for sensitive output such as using XOF for key derivation.
Do not call "update" on the same object after calling this method.
update
$multipart->update(@messages);
Adds all given arguments (stringified) to absorbed data. Any argument may be a Crypt::Sodium::XS::MemVault.
Do not call "update" on the same object after any data has been output with "squeeze" or "squeeze_key".
PRIMITIVES
shake128
shake256
turboshake128
turboshake256
SHAKE128 and SHAKE256 are XOFs defined in FIPS 202, based on the Keccak permutation with 24 rounds.
TurboSHAKE128 and TurboSHAKE256 are faster variants of SHAKE that use 12 rounds of the Keccak permutation instead of 24. They are roughly twice as fast as SHAKE while maintaining the same security claims.
TurboSHAKE is the underlying function of KangarooTwelve. Both are standardized in RFC 9861.
TurboSHAKE128 is the recommended choice for most applications. It offers:
Great performance (~2x faster than SHAKE)
128-bit security, which is more than sufficient for virtually all use cases
Built-in domain separation support
Standardized in RFC 9861
Use a different variant only if you have specific requirements:
SHAKE256 or TurboSHAKE256: When you need 256-bit collision resistance
SHAKE128/SHAKE256: When NIST FIPS 202 compliance is mandated
The “128” and “256” in the names refer to security levels, not output sizes. All variants can produce output of any length.
SECURITY CONSIDERATIONS
When using a XOF as a hash function (collision resistance matters), the output should be at least twice the security level. TurboSHAKE128 with a 32-byte output provides full 128-bit collision resistance. Shorter outputs reduce collision resistance proportionally: a 16-byte output only provides 64-bit collision resistance.
When using a XOF for key derivation or as a PRF (preimage resistance matters), the output length doesn’t affect security as long as you’re using it correctly. TurboSHAKE128 provides 128-bit preimage resistance regardless of output length.
XOFs differ from hash functions in an important way: for the same input, requesting different output lengths produces related outputs. Specifically, shorter outputs are prefixes of longer outputs. If this property is undesirable for your application, include the intended output length in the input.
The state should not be used after the object has been squeezed unless it is reinitialized using the init function.
These functions are deterministic: the same input always produces the same output. They are not suitable for password hashing. For that purpose, use Crypt::Sodium::XS::pwhash.
FUNCTIONS
The object API above is the recommended way to use this module. The functions and constants documented below can be imported instead or in addition.
Nothing is exported by default. A separate :<primitive> import tag is provided for each of the primitives listed in "PRIMITIVES". These tags import the xof_<primitive>_* functions and constants for that primitive. A :all tag imports everything.
Note: Crypt::Sodium::XS::xof, like libsodium, does not provide generic functions for XOF. Only the primitive-specific functions are available, so there is no :default tag.
xof_<primitive<Egt>
my $out = xof_shake128($msg, $size);
Same as "xof".
xof_<primitive<Egt>_key
my $out = xof_shake128_key($msg, $size);
Same as "xof_key".
CONSTANTS
xof_<primitive>_BLOCKBYTES
Same as "BLOCKBYTES".
xof_<primitive>_DOMAIN_STANDARD
Same as "DOMAIN_STANDARD".
xof_<primitive>_STATEBYTES
Same as "STATEBYTES".
SEE ALSO
FEEDBACK
For reporting bugs, giving feedback, submitting patches, etc. please use the following:
RT queue at https://rt.cpan.org/Dist/Display.html?Name=Crypt-Sodium-XS
IRC channel
#sodiumonirc.perl.org.Email the author directly.
AUTHOR
Brad Barden <perlmodules@5c30.org>
COPYRIGHT & LICENSE
Copyright (c) 2026 Brad Barden. All rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.