NAME

Crypt::Sodium::XS::hkdf - HMAC-based Extract-and-Expand Key Derivation Function

SYNOPSIS

use Crypt::Sodium::XS::hkdf ":all";

my $ikm = "any source and length of data with reasonable entropy";
my $salt = "salt is optional.";

my $prk = hkdf_sha256_extract($ikm, $salt);

my $application_key_1 = hkdf_sha256_expand($prk, "application one");
my $application_key_2 = hkdf_sha256_expand($prk, "application two");

my $multipart = hkdf_sha256_extract_init($salt);
$multipart->update("input");
$multipart->update(" keying material", " added in parts");
$prk = $multipart->final;
...

DESCRIPTION

Note: Secret keys used to encrypt or sign confidential data have to be chosen from a very large keyspace. However, passwords are usually short, human-generated strings, making dictionary attacks practical. If you are intending to derive keys from a password, see Crypt::Sodium::XS::pwhash instead.

HKDF (HMAC-based Extract-and-Expand Key Derivation Function) is a key derivation function used by many standard protocols. It actually includes two operations:

extract

This operation absorbs an arbitrary-long sequence of bytes (also known as input keying material, or IKM) and outputs a fixed-size master key (also known as PRK), suitable for use with the second function (expand).

expand

This operation generates an variable size subkey given a master key (also known as PRK) and a description of a key (or “context”) to derive from it. That operation can be repeated with different descriptions in order to derive as many keys as necessary.

Expand can be performed without extract, if a randomly sampled key of the right size is already available, such as from "hkdf_keygen".

The generated keys satifsy the typical requirements of keys used for symmetric cryptography. In particular, they appear to be sampled from a uniform distribution over the entire range of possible keys. Contexts don’t have to secret. They just need to be distinct in order to produce distinct keys from the same master key.

Any "hkdf_<primitive>_KEYBYTES" bytes key that appears to be sampled from a uniform distribution can be used for the PRK. For example, the output of a key exchange mechanism (such as from Crypt::Sodium::XS::kx) can be used as a master key. For convenience, the "hkdf_<primitive>_keygen" functions create a random PRK. The master key should remain secret.

Note that in libsodium, HKDF functions are prefixed kdf_hkdf_. In this library, they are prefixed with only hkdf_.

FUNCTIONS

Nothing is exported by default. A :features tag imports the hkdf_available feature test function. A separate :<primitive> import tag is provided for each of the primitives listed in "PRIMITIVES". These tags import the hkdf_<primitive>_* functions and constants for that primitive. A :all tag imports everything.

Note: Crypt::Sodium::XS::hkdf, like libsodium, does not provide generic functions for HKDF. Only the primitive-specific functions are available, so there is no :default tag.

hkdf_available

my $has_hkdf = hkdf_available();

Returns true if Crypt::Sodium::XS supports HKDF, false otherwise. HKDF will only be supported if Crypt::Sodium::XS was built with a new enough version of libsodium headers. A newer dynamic library at runtime will not enable support.

hkdf_<primitive>_expand

my $subkey = hkdf_sha256_expand($prk, $out_len, $context, $flags);

$prk is a PRK (master key). It must be "hkdf_<primitive<gt"_KEYBYTES> bytes. It may be a Crypt::Sodium::XS::MemVault.

$out_len is the size, in bytes, of the subkey output. It must be in the range of "hkdf_<primitive>_BYTES_MIN" to "hkdf_<primitive>_BYTES_MAX", inclusive.

$context is optional. It is an arbitrary-size string, which can be used to generate distinct subkeys from the same master key.

$flags is optional. It is the flags used for the $subkey Crypt::Sodium::XS::MemVault. See Crypt::Sodium::XS::ProtMem.

Returns a Crypt::Sodium::XS::MemVault: a subkey of the requested size.

hkdf_<primitive>_extract

my $prk = hkdf_sha256_extract($ikm, $salt, $flags);

$ikm is the input keying material from which to extract a PRK (master key).

$salt is optional. It can be a public, unique identifier for a protocol or application. Its purpose is to ensure that distinct keys will be created even if the input keying material is accidentally reused across protocols.

$flags is optional. It is the flags used for the $prk Crypt::Sodium::XS::MemVault. See Crypt::Sodium::XS::ProtMem.

Returns a Crypt::Sodium::XS::MemVault: a master key of the requested size.

    A UUID is a decent example of a salt. There is no minimum size.

    If input keying material cannot be accidentally reused, using an empty (undef or empty string) salt is perfectly acceptable. IKM is an arbitrary-long byte sequence. The bytes don’t have to be sampled from a uniform distribution. It can be any combination of text and binary data.

    But the overall sequence needs to include some entropy.

    The resulting PRK will roughly have the same entropy. The extract operation effectively extracts the entropy and packs it into a fixed-size key, but it doesn’t add any entropy.

hkdf_<primitive>_extract_init

my $multipart = hkdf_sha256_extract_init($salt, $flags);

$salt is optional. It can be a public, unique identifier for a protocol or application. Its purpose is to ensure that distinct keys will be created even if the input keying material is accidentally reused across protocols.

$flags is optional. It is the flags used for the multipart protected memory object. See Crypt::Sodium::XS::ProtMem.

Returns an opaque protected memory object: a multipart hkdf object. See "MULTI-PART INTERFACE".

Also see the notes for "hkdf_<primitive>_extract".

hkdf_<primitive>_keygen

my $prk = hkdf_sha256_keygen($flags);

$flags is optional. It is the flags used for the $prk Crypt::Sodium::XS::MemVault. See Crypt::Sodium::XS::ProtMem.

Returns a Crypt::Sodium::XS::MemVault: a PRK (master key) of "hkdf_<primitive>_KEYBYTES" bytes.

MULTI-PART INTERFACE

To extract a pseudorandom key from an arbitrary size of input keying material, you may wish to use the multi-part interface. A multipart hkdf object is created by calling the "hkdf_<primitive>_extract_init" function with optional salt. Key material can be added by calling the </update> method of that object as many times as desired. An output PRK (master key) is generated by calling its "final" method. Do not continue to use the object after calling "final".

The precalculated hkdf object is an opaque protected memory object which provides the following methods:

final

my $prk = $multipart->final($flags);

$flags is optional. It is the flags used for the $prk Crypt::Sodium::XS::MemVault. See Crypt::Sodium::XS::ProtMem.

Returns a Crypt::Sodium::XS::MemVault: a PRK (master key) of "hkdf_<primitive>_KEYBYTES" bytes.

Once final has been called, the multipart object must not be used further.

update

$multipart->update(@key_data);

Adds all given arguments (stringified) to input keying material. Any argument may be a Crypt::Sodium::XS::MemVault.

CONSTANTS

hkdf_<primitive>_BYTES_MAX

Returns the maximum size, in bytes, of output from "hkdf_<primitive>_expand".

hkdf_<primitive>_BYTES_MIN

Defined by libsodium to be 0.

hkdf_<primitive>_KEYBYTES

Returns the size, in bytes, of a secret key (both PRK and subkey).

ALGORITHMS

All constants and functions have hkdf_<algorithm>-prefixed couterparts (e.g., hkdf_sha256_expand, hkdf_sha512_BYTES_MAX).

  • sha256

  • sha512

SEE ALSO

Crypt::Sodium::XS
Crypt::Sodium::XS::OO::hkdf
https://doc.libsodium.org/key_derivation/hkdf

FEEDBACK

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

AUTHOR

Brad Barden <perlmodules@5c30.org>

COPYRIGHT & LICENSE

Copyright (c) 2024 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.