Crypt::KeyWrap(3pm)

NAME
Crypt::KeyWrap - Key management/wrapping algorithms defined in RFC7518 (JWA)

SYNOPSIS
   # A192KW wrapping
   use Crypt::KeyWrap qw(aes_key_wrap);
   my $kek     = pack("H*", "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8"); # key encryption key
   my $cek     = pack("H*", "c37b7e6492584340bed12207808941155068f738"); # content encryption key
   my $enc_cek = aes_key_wrap($kek, $pt_data); # encrypted content encryption key

   # A192KW unwrapping
   use Crypt::KeyWrap qw(aes_key_unwrap);
   my $kek     = pack("H*", "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8");
   my $enc_cek = pack("H*", "138bdeaa9b8fa7fc61f97742e72248ee5ae6ae5360d1ae6a5f54f373fa543b6a");
   my $cek     = aes_key_unwrap($kek, $enc_cek);

DESCRIPTION
Implements key management algorithms defined in <https://tools.ietf.org/html/rfc7518>.

These functions are the low-level primitives that Crypt::JWT dispatches to when handling JWE "alg" values. If you are building or consuming JWE tokens, use Crypt::JWT instead - it covers algorithm selection, header handling, and serialization on top of these wrappers.

BEWARE: experimental, interface of this module might change!

Supported algorithms (all defined in RFC7518):

 A128KW                 see: aes_key_wrap() + aes_key_unwrap()
 A192KW                 see: aes_key_wrap() + aes_key_unwrap()
 A256KW                 see: aes_key_wrap() + aes_key_unwrap()
 A128GCMKW              see: gcm_key_wrap() + gcm_key_unwrap()
 A192GCMKW              see: gcm_key_wrap() + gcm_key_unwrap()
 A256GCMKW              see: gcm_key_wrap() + gcm_key_unwrap()
 PBES2-HS256+A128KW     see: pbes2_key_wrap() + pbes2_key_unwrap()
 PBES2-HS384+A192KW     see: pbes2_key_wrap() + pbes2_key_unwrap()
 PBES2-HS512+A256KW     see: pbes2_key_wrap() + pbes2_key_unwrap()
 RSA-OAEP               see: rsa_key_wrap() + rsa_key_unwrap()
 RSA-OAEP-256           see: rsa_key_wrap() + rsa_key_unwrap()
 RSA1_5                 see: rsa_key_wrap() + rsa_key_unwrap()
 ECDH-ES+A128KW         see: ecdhaes_key_wrap() + ecdhaes_key_unwrap()
 ECDH-ES+A192KW         see: ecdhaes_key_wrap() + ecdhaes_key_unwrap()
 ECDH-ES+A256KW         see: ecdhaes_key_wrap() + ecdhaes_key_unwrap()
 ECDH-ES                see: ecdh_key_wrap() + ecdh_key_unwrap()

EXPORT
Nothing is exported by default.

You can export selected functions:

  use Crypt::KeyWrap qw(aes_key_wrap gcm_key_wrap pbes2_key_wrap);

Or all of them at once:

  use Crypt::KeyWrap ':all';

FUNCTIONS

  aes_key_wrap
AES Key Wrap. Implements "A128KW", "A192KW", "A256KW" from RFC 7518 section 4.4 (<https://tools.ietf.org/html/rfc7518#section-4.4>) and the underlying RFC 3394 (<https://tools.ietf.org/html/rfc3394>) and RFC 5649 (<https://tools.ietf.org/html/rfc5649>) constructions. Also compatible with NIST SP 800-38F (KW, KWP, and TDEA/DES_EDE-based TKW).

   $enc_cek = aes_key_wrap($kek, $cek);
   # or
   $enc_cek = aes_key_wrap($kek, $cek, $cipher, $padding, $inverse);

   # params:
   #  $kek     .. key encryption key (16 bytes for AES128, 24 for AES192, 32 for AES256)
   #  $cek     .. content encryption key
   # optional params:
   #  $cipher  .. 'AES' (default) or 'DES_EDE'
   #  $padding .. 1 (default) -> KWP (RFC 5649): always uses the alternate
   #              IV (A65959A6 || msg-len) and pads $cek to a multiple of 8
   #              (relevant for AES only)
   #              0 -> KW (RFC 3394): uses the standard all-A6 IV; $cek must
   #              already be a multiple of 8 (AES) or 4 (DES_EDE)
   #  $inverse .. 0 (default) or 1 - use cipher in inverse mode as defined by SP 800-38F

$enc_cek, $cek, and $kek are binary octets.

Since: 0.038 KW ("$padding=0") and KWP ("$padding=1") are strictly separated; KWP always emits the alternate IV even for already-aligned input. JWE callers (A*KW, PBES2-*+A*KW, ECDH-ES+A*KW) all use "$padding=0" per RFC 7518.

  aes_key_unwrap
AES Key Unwrap. Inverse of "aes_key_wrap"; implements "A128KW", "A192KW", "A256KW" from RFC 7518 section 4.4 (<https://tools.ietf.org/html/rfc7518#section-4.4>).

   $cek = aes_key_unwrap($kek, $enc_cek);
   # or
   $cek = aes_key_unwrap($kek, $enc_cek, $cipher, $padding, $inverse);

   # params:
   #  $kek     .. key encryption key (16 bytes for AES128, 24 for AES192, 32 for AES256)
   #  $enc_cek .. encrypted content encryption key
   # optional params:
   #  $cipher  .. 'AES' (default) or 'DES_EDE'
   #  $padding .. 1 (default) -> KWP (RFC 5649): expects the alternate IV
   #              (A65959A6 || msg-len) and strips zero padding
   #              (relevant for AES only)
   #              0 -> KW (RFC 3394): expects the standard all-A6 IV
   #  $inverse .. 0 (default) or 1 - use cipher in inverse mode as defined by SP 800-38F

$enc_cek, $cek, and $kek are binary octets.

Since: 0.038 The two modes are strict and reject the other mode's IV form. Croaks with "aes_key_unwrap: ct too short" or "ct length not a multiple of $blck" on malformed input lengths.

  gcm_key_wrap
AES GCM key wrap algorithm as defined in <https://tools.ietf.org/html/rfc7518#section-4.7> (implements algorithms "A128GCMKW", "A192GCMKW", "A256GCMKW").

   ($enc_cek, $tag, $iv) = gcm_key_wrap($kek, $cek);
   #or
   ($enc_cek, $tag, $iv) = gcm_key_wrap($kek, $cek, $aad);
   #or
   ($enc_cek, $tag, $iv) = gcm_key_wrap($kek, $cek, $aad, $cipher, $iv);

   # params:
   #  $kek     .. key encryption key (16bytes for AES128, 24 for AES192, 32 for AES256)
   #  $cek     .. content encryption key
   # optional params:
   #  $aad     .. additional authenticated data, default: '' (empty string)
   #  $cipher  .. cipher to be used by GCM, default: 'AES'
   #  $iv      .. initialization vector (if not defined a random IV is generated)

Values $enc_cek, $cek, $aad, $iv, $tag and $kek are binary octets.

  gcm_key_unwrap
AES GCM key unwrap algorithm as defined in <https://tools.ietf.org/html/rfc7518#section-4.7> (implements algorithms "A128GCMKW", "A192GCMKW", "A256GCMKW").

   $cek = gcm_key_unwrap($kek, $enc_cek, $tag, $iv);
   # or
   $cek = gcm_key_unwrap($kek, $enc_cek, $tag, $iv, $aad);
   # or
   $cek = gcm_key_unwrap($kek, $enc_cek, $tag, $iv, $aad, $cipher);

   # params:
   #  $kek     .. key encryption key (16bytes for AES128, 24 for AES192, 32 for AES256)
   #  $enc_cek .. encrypted content encryption key
   #  $tag     .. GCM's tag
   #  $iv      .. initialization vector
   # optional params:
   #  $aad     .. additional authenticated data, default: '' (empty string)
   #  $cipher  .. cipher to be used by GCM, default: 'AES'

Values $enc_cek, $cek, $aad, $iv, $tag and $kek are binary octets.

  pbes2_key_wrap
PBES2 key wrap algorithm as defined in <https://tools.ietf.org/html/rfc7518#section-4.8> (implements algorithms "PBES2-HS256+A128KW", "PBES2-HS384+A192KW", "PBES2-HS512+A256KW").

   $enc_cek = pbes2_key_wrap($kek, $cek, $alg, $salt, $iter);

   # params:
   #  $kek     .. key encryption key (arbitrary length)
   #  $cek     .. content encryption key
   #  $alg     .. algorithm name e.g. 'PBES2-HS256+A128KW' (see rfc7518)
   #  $salt    .. pbkdf2 salt
   #  $iter    .. pbkdf2 iteration count

Values $enc_cek, $cek, $salt and $kek are binary octets.

  pbes2_key_unwrap
PBES2 key unwrap algorithm. Inverse of "pbes2_key_wrap"; implements "PBES2-HS256+A128KW", "PBES2-HS384+A192KW", "PBES2-HS512+A256KW" from RFC 7518 section 4.8 (<https://tools.ietf.org/html/rfc7518#section-4.8>).

   $cek = pbes2_key_unwrap($kek, $enc_cek, $alg, $salt, $iter);

   # params:
   #  $kek     .. key encryption key (arbitrary length)
   #  $enc_cek .. encrypted content encryption key
   #  $alg     .. algorithm name e.g. 'PBES2-HS256+A128KW' (see rfc7518)
   #  $salt    .. pbkdf2 salt
   #  $iter    .. pbkdf2 iteration count

Values $enc_cek, $cek, $salt and $kek are binary octets.

  rsa_key_wrap
RSA key wrap algorithm. Implements "RSA1_5", "RSA-OAEP", and "RSA-OAEP-256" from RFC 7518 sections 4.2 and 4.3 (<https://tools.ietf.org/html/rfc7518#section-4.2>, <https://tools.ietf.org/html/rfc7518#section-4.3>).

   $enc_cek = rsa_key_wrap($kek, $cek, $alg);

   # params:
   #  $kek     .. RSA public key - Crypt::PK::RSA instance
   #  $cek     .. content encryption key
   #  $alg     .. algorithm name e.g. 'RSA-OAEP' (see rfc7518)

Values $enc_cek and $cek are binary octets.

  rsa_key_unwrap
RSA key unwrap algorithm. Inverse of "rsa_key_wrap"; implements "RSA1_5", "RSA-OAEP", and "RSA-OAEP-256" from RFC 7518 sections 4.2 and 4.3.

   $cek = rsa_key_unwrap($kek, $enc_cek, $alg);

   # params:
   #  $kek     .. RSA private key - Crypt::PK::RSA instance
   #  $enc_cek .. encrypted content encryption key
   #  $alg     .. algorithm name e.g. 'RSA-OAEP' (see rfc7518)

Values $enc_cek and $cek are binary octets.

  ecdhaes_key_wrap
ECDH+AESKW key agreement/wrap algorithm as defined in <https://tools.ietf.org/html/rfc7518#section-4.6> (implements algorithms "ECDH-ES+A128KW", "ECDH-ES+A192KW", "ECDH-ES+A256KW").

   ($enc_cek, $epk) = ecdhaes_key_wrap($kek, $cek, $alg, $apu, $apv);

   # params:
   #  $kek     .. ECC public key - Crypt::PK::ECC|X25519 instance
   #  $cek     .. content encryption key
   #  $alg     .. algorithm name e.g. 'ECDH-ES+A256KW' (see rfc7518)
   # optional params:
   #  $apu     .. base64url-encoded Agreement PartyUInfo Header Parameter
   #  $apv     .. base64url-encoded Agreement PartyVInfo Header Parameter

Values $enc_cek and $cek are binary octets.

  ecdhaes_key_unwrap
ECDH+AESKW key agreement/unwrap algorithm as defined in <https://tools.ietf.org/html/rfc7518#section-4.6> (implements algorithms "ECDH-ES+A128KW", "ECDH-ES+A192KW", "ECDH-ES+A256KW").

   $cek = ecdhaes_key_unwrap($kek, $enc_cek, $alg, $epk, $apu, $apv);

   # params:
   #  $kek     .. ECC private key - Crypt::PK::ECC|X25519 instance
   #  $enc_cek .. encrypted content encryption key
   #  $alg     .. algorithm name e.g. 'ECDH-ES+A256KW' (see rfc7518)
   #  $epk     .. ephemeral ECC public key (JWK/JSON or Crypt::PK::ECC|X25519)
   # optional params:
   #  $apu     .. base64url-encoded Agreement PartyUInfo Header Parameter
   #  $apv     .. base64url-encoded Agreement PartyVInfo Header Parameter

Values $enc_cek and $cek are binary octets.

  ecdh_key_wrap
ECDH (Ephemeral Static) key agreement/wrap algorithm as defined in <https://tools.ietf.org/html/rfc7518#section-4.6> (implements algorithm "ECDH-ES").

   ($cek, $epk) = ecdh_key_wrap($kek, $enc, $apu, $apv);

   # params:
   #  $kek     .. ECC public key - Crypt::PK::ECC|X25519 instance
   #  $enc     .. encryption algorithm name e.g. 'A256GCM' (see rfc7518)
   # optional params:
   #  $apu     .. base64url-encoded Agreement PartyUInfo Header Parameter
   #  $apv     .. base64url-encoded Agreement PartyVInfo Header Parameter

$cek is binary octets; $epk is a JWK/JSON string with the ephemeral ECC public key.

  ecdh_key_unwrap
ECDH (Ephemeral Static) key agreement/unwrap algorithm as defined in <https://tools.ietf.org/html/rfc7518#section-4.6> (implements algorithm "ECDH-ES").

   $cek = ecdh_key_unwrap($kek, $enc, $epk, $apu, $apv);

   # params:
   #  $kek     .. ECC private key - Crypt::PK::ECC|X25519 instance
   #  $enc     .. encryption algorithm name e.g. 'A256GCM' (see rfc7518)
   #  $epk     .. ephemeral ECC public key (JWK/JSON or Crypt::PK::ECC|X25519)
   # optional params:
   #  $apu     .. base64url-encoded Agreement PartyUInfo Header Parameter
   #  $apv     .. base64url-encoded Agreement PartyVInfo Header Parameter

Value $cek - binary octets.

SEE ALSO
Crypt::JWT, Crypt::Cipher::AES, Crypt::AuthEnc::GCM, Crypt::PK::RSA, Crypt::KeyDerivation

LICENSE
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

COPYRIGHT
Copyright (c) 2015-2026 DCIT, a.s. <https://www.dcit.cz> / Karel Miko