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

Crypt::Sodium::XS
https://libsodium.gitbook.io/doc/hashing/xof

FEEDBACK

For reporting bugs, giving feedback, submitting patches, etc. please use the following:

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.