File Coverage

blib/lib/Crypt/KeyWrap.pm
Criterion Covered Total %
statement 214 219 97.7
branch 103 146 70.5
condition 21 29 72.4
subroutine 26 26 100.0
pod 12 12 100.0
total 376 432 87.0


line stmt bran cond sub pod time code
1             package Crypt::KeyWrap;
2              
3 13     13   429669 use strict;
  13         81  
  13         378  
4 13     13   81 use warnings;
  13         31  
  13         567  
5              
6             our $VERSION = '0.035';
7              
8 13     13   66 use Exporter 'import';
  13         54  
  13         1411  
9             our %EXPORT_TAGS = ( all => [qw(aes_key_wrap aes_key_unwrap gcm_key_wrap gcm_key_unwrap pbes2_key_wrap pbes2_key_unwrap ecdh_key_wrap ecdh_key_unwrap ecdhaes_key_wrap ecdhaes_key_unwrap rsa_key_wrap rsa_key_unwrap)] );
10             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
11             our @EXPORT = qw();
12              
13 13     13   108 use Carp;
  13         32  
  13         938  
14 13     13   3488 use Crypt::Mode::ECB;
  13         112426  
  13         548  
15 13     13   6344 use Crypt::AuthEnc::GCM qw(gcm_encrypt_authenticate gcm_decrypt_verify);
  13         4472  
  13         793  
16 13     13   3248 use Crypt::PRNG qw(random_bytes);
  13         6594  
  13         663  
17 13     13   5651 use Crypt::KeyDerivation qw(pbkdf2);
  13         4057  
  13         736  
18 13     13   3244 use Crypt::Digest qw(digest_data);
  13         5236  
  13         624  
19 13     13   79 use Config;
  13         27  
  13         42094  
20              
21             # JWS: https://tools.ietf.org/html/rfc7515
22             # JWE: https://tools.ietf.org/html/rfc7516
23             # JWK: https://tools.ietf.org/html/rfc7517
24             # JWA: https://tools.ietf.org/html/rfc7518 - !!! this is important !!!
25              
26             sub _LSB {
27 12541     12541   19055 my ($bytes, $data) = @_;
28 12541         15599 my $len = length $data;
29 12541 50       38339 return $len > $bytes ? substr($data, $len-$bytes, $bytes) : $data;
30             }
31              
32             sub _MSB {
33 12541     12541   21191 my ($bytes, $data) = @_;
34 12541         15971 my $len = length $data;
35 12541 50       31105 return $len > $bytes ? substr($data, 0, $bytes) : $data;
36             }
37              
38             sub _N2RAW {
39 12528     12528   18618 my ($bytes, $n) = @_;
40 12528 100       21084 if ($bytes == 8) {
41 10656 50       47279 return pack("N", 0) . pack("N", $n) if $Config{uvsize} == 4; #workaround
42 10656         48508 return pack("N", $n >> 32) . pack("N", $n & 0xFFFFFFFF);
43             }
44 1872 50       6417 return pack("N", $n & 0xFFFFFFFF) if $bytes == 4;
45             }
46              
47             sub aes_key_wrap {
48 138     138 1 41951 my ($kek, $pt_data, $cipher, $padding, $inverse) = @_;
49 138 100       421 $cipher = 'AES' unless defined $cipher;
50 138 50       404 $padding = $cipher eq 'AES' ? 1 : 0 unless defined $padding;
    100          
51              
52 138         229 my ($A, $B, $P, $R);
53              
54 138 50       273 croak "aes_key_wrap: no KEK" unless defined $kek;
55 138 50       292 croak "aes_key_wrap: no PT data" unless defined $pt_data;
56 138         203 my $klen = length $kek;
57 138 50 100     674 croak "aes_key_wrap: invalid KEK length" unless $klen == 16 || $klen == 24 || $klen == 32;
      66        
58 138 50 66     375 croak "aes_key_wrap: cipher must be AES or DES_EDE" unless $cipher eq 'AES' || $cipher eq 'DES_EDE';
59 138 50 66     479 croak "aes_key_wrap: padding not allowed with DES_EDE" if $padding && $cipher eq 'DES_EDE';
60              
61 138         1024 my $ECB = Crypt::Mode::ECB->new($cipher, 0);
62 138 100       348 my $blck = $cipher eq 'DES_EDE' ? 4 : 8; # semiblock size in bytes, for AES 8, for 3DES 4
63              
64 138         536 my $IV = pack("H*", "A6" x $blck);
65 138         233 my $len = length $pt_data;
66 138 100       363 if ($len % $blck > 0) {
67 33 50       65 croak "aes_key_wrap: pt_data length not multiply of $blck" if !$padding;
68 33         75 $pt_data .= chr(0) x ($blck - ($len % $blck));
69 33         74 $IV = pack("H*", "A65959A6") . pack("N", $len);
70             }
71              
72 138         308 my $n = length($pt_data) / $blck;
73 138         1258 $P->[$_] = substr($pt_data, $_*$blck, $blck) for (0..$n-1);
74              
75 138 100       369 if ($n == 1) {
76 13 100       74 return $inverse ? $ECB->decrypt($IV . $P->[0], $kek)
77             : $ECB->encrypt($IV . $P->[0], $kek);
78             }
79              
80 125         202 $A = $IV;
81 125         687 $R->[$_] = $P->[$_] for (0..$n-1);
82              
83 125         264 for my $j (0..5) {
84 750         1408 for my $i (0..$n-1) {
85 6012 100       17308 $B = $inverse ? $ECB->decrypt($A . $R->[$i], $kek)
86             : $ECB->encrypt($A . $R->[$i], $kek);
87 6012         93308 $A = _MSB($blck, $B) ^ _N2RAW($blck, ($n*$j)+$i+1);
88 6012         11398 $R->[$i] = _LSB($blck, $B);
89             }
90             }
91              
92 125         233 my $rv = $A;
93 125         630 $rv .= $R->[$_] for (0..$n-1);
94 125         884 return $rv;
95             }
96              
97             sub aes_key_unwrap {
98 163     163 1 41685 my ($kek, $ct_data, $cipher, $padding, $inverse) = @_;
99 163 100       450 $cipher = 'AES' unless defined $cipher;
100 163 50       492 $padding = $cipher eq 'AES' ? 1 : 0 unless defined $padding;
    100          
101              
102 163         315 my ($A, $B, $C, $P, $R);
103              
104 163 50       354 croak "aes_key_unwrap: no KEK" unless defined $kek;
105 163 50       349 croak "aes_key_unwrap: no CT data" unless defined $ct_data;
106 163         246 my $klen = length $kek;
107 163 50 100     705 croak "aes_key_unwrap: invalid KEK length" unless $klen == 16 || $klen == 24 || $klen == 32;
      66        
108 163 50 66     431 croak "aes_key_unwrap: cipher must be AES or DES_EDE" unless $cipher eq 'AES' || $cipher eq 'DES_EDE';
109 163 50 66     660 croak "aes_key_unwrap: padding not allowed with DES_EDE" if $padding && $cipher eq 'DES_EDE';
110              
111 163         1207 my $ECB = Crypt::Mode::ECB->new($cipher, 0);
112 163 100       397 my $blck = $cipher eq 'DES_EDE' ? 4 : 8; # semiblock size in bytes, for AES 8, for 3DES 4
113              
114 163         495 my $n = length($ct_data) / $blck - 1;
115 163         1422 $C->[$_] = substr($ct_data, $_*$blck, $blck) for (0..$n); # n+1 semiblocks
116              
117 163 100       421 if ($n==1) {
118 13 100       71 $B = $inverse ? $ECB->encrypt($C->[0] . $C->[1], $kek)
119             : $ECB->decrypt($C->[0] . $C->[1], $kek);
120 13         247 $A = _MSB($blck, $B);
121 13         32 $R->[0] = _LSB($blck, $B);
122             }
123             else {
124 150         295 $A = $C->[0];
125 150         856 $R->[$_] = $C->[$_+1] for (0..$n-1);
126 150         475 for(my $j=5; $j>=0; $j--) {
127 900         1872 for(my $i=$n-1; $i>=0; $i--) {
128 6516 100       15286 $B = $inverse ? $ECB->encrypt(($A ^ _N2RAW($blck, $n*$j+$i+1)) . $R->[$i], $kek)
129             : $ECB->decrypt(($A ^ _N2RAW($blck, $n*$j+$i+1)) . $R->[$i], $kek);
130 6516         101097 $A = _MSB($blck, $B);
131 6516         10546 $R->[$i] = _LSB($blck, $B);
132             }
133             }
134             }
135              
136 163         335 my $rv = '';
137 163         773 $rv .= $R->[$_] for (0..$n-1);
138              
139 163         575 my $A_hex = unpack("H*", $A);
140 163 100 33     691 if ($A_hex eq 'a6'x$blck) {
    50          
141 130         955 return $rv;
142             }
143             elsif ($A_hex =~ /^a65959a6/ && $blck == 8) {
144 33 50       69 warn "key_unwrap: unexpected padding" unless $padding;
145 33         83 my $n = unpack("N", substr($A, 4, 4));
146 33         56 my $z = length($rv) - $n;
147 33         78 my $tail = unpack("H*", substr($rv, -$z));
148 33 50       80 croak "aes_key_unwrap: invalid data" unless $tail eq "00"x$z;
149 33         203 return substr($rv, 0, $n);
150             }
151 0         0 croak "aes_key_unwrap: unexpected data [$cipher/$A_hex]";
152             }
153              
154             # AES GCM KW - https://tools.ietf.org/html/rfc7518#section-4.7
155              
156             sub gcm_key_wrap {
157 19     19 1 824 my ($kek, $pt_data, $aad, $cipher, $iv) = @_;
158 19 100       52 $cipher = 'AES' unless defined $cipher;
159 19 100       52 $iv = random_bytes(12) unless defined $iv; # 96 bits REQUIRED by RFC7518
160 19         4333 my ($ct_data, $tag) = gcm_encrypt_authenticate($cipher, $kek, $iv, $aad, $pt_data);
161 19         88 return ($ct_data, $tag, $iv);
162             }
163              
164             sub gcm_key_unwrap {
165 23     23 1 153 my ($kek, $ct_data, $tag, $iv, $aad, $cipher) = @_;
166 23   100     105 $cipher ||= 'AES';
167 23         4926 my $pt_data = gcm_decrypt_verify($cipher, $kek, $iv, $aad, $ct_data, $tag);
168 23         101 return $pt_data;
169             }
170              
171             # PBES2/PBKDF2 KW - https://tools.ietf.org/html/rfc7518#section-4.8
172              
173             sub pbes2_key_wrap {
174 25     25 1 922 my ($kek, $pt_data, $alg, $salt, $iter) = @_;
175 25         46 my ($hash_name, $len);
176 25 50       158 if ($alg =~ /^PBES2-HS(256|384|512)\+A(128|192|256)KW$/) {
177 25         73 $hash_name = "SHA$1";
178 25         69 $len = $2/8;
179 25         518384 my $aes_key = pbkdf2($kek, $alg."\x00".$salt, $iter, $hash_name, $len);
180 25         232 my $ct_data = aes_key_wrap($aes_key, $pt_data);
181 25         115 return $ct_data;
182             }
183 0         0 croak "pbes2_key_wrap: invalid alg '$alg'";
184 0         0 return undef;
185             }
186              
187             sub pbes2_key_unwrap {
188 40     40 1 384 my ($kek, $ct_data, $alg, $salt, $iter) = @_;
189 40         109 my ($hash_name, $len);
190 40 50       214 if ($alg =~ /^PBES2-HS(256|384|512)\+A(128|192|256)KW$/) {
191 40         110 $hash_name = "SHA$1";
192 40         130 $len = $2/8;
193 40         852740 my $aes_key = pbkdf2($kek, $alg."\x00".$salt, $iter, $hash_name, $len);
194 40         335 my $pt_data = aes_key_unwrap($aes_key, $ct_data);
195 40         232 return $pt_data;
196             }
197 0         0 croak "pbes2_key_unwrap: invalid alg '$alg'";
198 0         0 return undef;
199             }
200              
201             # RSA KW
202             # https://tools.ietf.org/html/rfc7518#section-4.2
203             # https://tools.ietf.org/html/rfc7518#section-4.3
204              
205             sub rsa_key_wrap {
206 21     21 1 2060 my ($kek_public, $pt_data, $alg) = @_;
207 21 50       50 croak "rsa_key_wrap: no Crypt::PK::RSA" unless ref $kek_public eq 'Crypt::PK::RSA';
208 21         43 my ($padding, $hash_name);
209 21 100       62 if ($alg eq 'RSA-OAEP') { ($padding, $hash_name) = ('oaep', 'SHA1') }
  7 100       15  
    50          
210 7         13 elsif ($alg eq 'RSA-OAEP-256') { ($padding, $hash_name) = ('oaep', 'SHA256') }
211 7         14 elsif ($alg eq 'RSA1_5') { $padding = 'v1.5' }
212 21 50       44 croak "rsa_key_wrap: invalid algorithm '$alg'" unless $padding;
213 21         4673 my $ct_data = $kek_public->encrypt($pt_data, $padding, $hash_name);
214 21         82 return $ct_data;
215             }
216              
217             sub rsa_key_unwrap {
218 39     39 1 840 my ($kek_private, $ct_data, $alg) = @_;
219 39 50       140 croak "rsa_key_unwrap: no Crypt::PK::RSA" unless ref $kek_private eq 'Crypt::PK::RSA';
220 39 50       139 croak "rsa_key_unwrap: no private key" unless $kek_private->is_private;
221 39         56 my ($padding, $hash_name);
222 39 100       126 if ($alg eq 'RSA-OAEP') { ($padding, $hash_name) = ('oaep', 'SHA1') }
  14 100       31  
    50          
223 10         21 elsif ($alg eq 'RSA-OAEP-256') { ($padding, $hash_name) = ('oaep', 'SHA256') }
224 15         26 elsif ($alg eq 'RSA1_5') { $padding = 'v1.5' }
225 39 50       69 croak "rsa_key_unwrap: invalid algorithm '$alg'" unless $padding;
226 39         206444 my $pt_data = $kek_private->decrypt($ct_data, $padding, $hash_name);
227 39         393 return $pt_data;
228             }
229              
230             # ConcatKDF - http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf
231             # ECDH KW - https://tools.ietf.org/html/rfc7518#section-4.6
232              
233             sub _concat_kdf {
234 68     68   251 my ($hash_name, $key_size, $shared_secret, $algorithm, $apu, $apv) = @_;
235 68 50       224 $apu = '' unless defined $apu;
236 68 50       163 $apv = '' unless defined $apv;
237 68         345 my $hsize = Crypt::Digest->hashsize($hash_name);
238 68         167 my $count = int($key_size / $hsize);
239 68 100       225 $count++ if ($key_size % $hsize) > 0;
240 68         107 my $data = '';
241 68         196 for my $i (1..$count) {
242 72         911 $data .= digest_data('SHA256', pack("N", 1) .
243             $shared_secret .
244             pack("N", length($algorithm)) . $algorithm .
245             pack("N", length($apu)) . $apu .
246             pack("N", length($apv)) . $apv .
247             pack("N", 8 *$key_size));
248             }
249 68         261 return substr($data, 0, $key_size);
250             }
251              
252             sub ecdh_key_wrap {
253 7     7 1 3711 my ($kek_public, $enc, $apu, $apv) = @_;
254 7 50       24 croak "ecdh_key_wrap: no Crypt::PK::ECC" unless ref $kek_public eq 'Crypt::PK::ECC';
255 7         13 my $encryption_key_size = 256;
256 7 100       53 if ($enc =~ /^A(128|192|256)CBC-HS/) {
257 3         8 $encryption_key_size = $1*2;
258             }
259 7 100       51 if ($enc =~ /^A(128|192|256)GCM/) {
260 4         11 $encryption_key_size = $1;
261             }
262 7         34 my $ephemeral = Crypt::PK::ECC->new()->generate_key($kek_public->curve2hash);
263 7         41069 my $shared_secret = $ephemeral->shared_secret($kek_public);
264 7         69 my $ct_data = _concat_kdf('SHA256', $encryption_key_size/8, $shared_secret, $enc, $apu, $apv);
265 7         39 return ($ct_data, $ephemeral->export_key_jwk('public'));
266             }
267              
268             sub ecdh_key_unwrap {
269 15     15 1 8285 my ($kek_private, $enc, $epk, $apu, $apv) = @_;
270 15 50       68 croak "ecdh_key_unwrap: no Crypt::PK::ECC" unless ref $kek_private eq 'Crypt::PK::ECC';
271 15 50       68 croak "ecdh_key_unwrap: no private key" unless $kek_private->is_private;
272 15         25 my $encryption_key_size = 256;
273 15 100       74 if ($enc =~ /^A(128|192|256)CBC-HS/) {
274 5         22 $encryption_key_size = $1*2;
275             }
276 15 100       72 if ($enc =~ /^A(128|192|256)GCM/) {
277 10         28 $encryption_key_size = $1;
278             }
279 15 100       86 my $ephemeral = ref($epk) eq 'Crypt::PK::ECC' ? $epk : Crypt::PK::ECC->new(ref $epk ? $epk : \$epk);
    50          
280 15         88087 my $shared_secret = $kek_private->shared_secret($ephemeral);
281 15         99 my $pt_data = _concat_kdf('SHA256', $encryption_key_size/8, $shared_secret, $enc, $apu, $apv);
282 15         185 return $pt_data;
283             }
284              
285             sub ecdhaes_key_wrap {
286 20     20 1 3797 my ($kek_public, $pt_data, $alg, $apu, $apv) = @_;
287 20 50       112 croak "ecdhaes_key_wrap: no Crypt::PK::(ECC|X25519)" unless ref($kek_public) =~ /^Crypt::PK::(ECC|X25519)$/;
288 20         41 my $encryption_key_size = 256;
289 20 50       84 if ($alg =~ /^ECDH-ES\+A(128|192|256)KW$/) {
290 20         48 $encryption_key_size = $1;
291             }
292 20         32 my $ephemeral;
293 20 100       68 if (ref($kek_public) eq 'Crypt::PK::ECC') {
294 19         87 $ephemeral = Crypt::PK::ECC->new->generate_key($kek_public->curve2hash);
295             }
296             else {
297 1         4 $ephemeral = Crypt::PK::X25519->new->generate_key();
298             }
299 20         222612 my $shared_secret = $ephemeral->shared_secret($kek_public);
300 20         177 my $kek = _concat_kdf('SHA256', $encryption_key_size/8, $shared_secret, $alg, $apu, $apv);
301 20         92 return (aes_key_wrap($kek, $pt_data), $ephemeral->export_key_jwk('public'));
302             }
303              
304             sub ecdhaes_key_unwrap {
305 26     26 1 8262 my ($kek_private, $ct_data, $alg, $epk, $apu, $apv) = @_;
306 26 50       158 croak "ecdhaes_key_unwrap: no Crypt::PK::(ECC|X25519)" unless ref($kek_private) =~ /^Crypt::PK::(ECC|X25519)$/;
307 26 50       118 croak "ecdhaes_key_unwrap: no private key" unless $kek_private->is_private;
308 26         47 my $encryption_key_size = 256;
309 26 50       133 if ($alg =~ /^ECDH-ES\+A(128|192|256)KW$/) {
310 26         62 $encryption_key_size = $1;
311             }
312 26         40 my $ephemeral;
313 26 100       112 if (ref($kek_private) eq 'Crypt::PK::ECC') {
314 25 100       162 $ephemeral = ref($epk) eq 'Crypt::PK::ECC' ? $epk : Crypt::PK::ECC->new(ref $epk ? $epk : \$epk);
    50          
315             }
316             else {
317 1 50       9 $ephemeral = ref($epk) eq 'Crypt::PK::X25519' ? $epk : Crypt::PK::X25519->new(ref $epk ? $epk : \$epk);
    50          
318             }
319 26         256115 my $shared_secret = $kek_private->shared_secret($ephemeral);
320 26         218 my $kek = _concat_kdf('SHA256', $encryption_key_size/8, $shared_secret, $alg, $apu, $apv);
321 26         91 my $pt_data = aes_key_unwrap($kek, $ct_data);
322 26         282 return $pt_data;
323             }
324              
325             1;
326              
327             =pod
328              
329             =head1 NAME
330              
331             Crypt::KeyWrap - Key management/wrapping algorithms defined in RFC7518 (JWA)
332              
333             =head1 SYNOPSIS
334              
335             # A192KW wrapping
336             use Crypt::KeyWrap qw(aes_key_wrap);
337             my $kek = pack("H*", "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8"); # key encryption key
338             my $cek = pack("H*", "c37b7e6492584340bed12207808941155068f738"); # content encryption key
339             my $enc_cek = aes_key_wrap($kek, $pt_data); # encrypted content encryption key
340              
341             # A192KW unwrapping
342             use Crypt::KeyWrap qw(aes_key_unwrap);
343             my $kek = pack("H*", "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8");
344             my $enc_cek = pack("H*", "138bdeaa9b8fa7fc61f97742e72248ee5ae6ae5360d1ae6a5f54f373fa543b6a");
345             my $cek = aes_key_unwrap($kek, $pt_data);
346              
347             =head1 DESCRIPTION
348              
349             Implements key management algorithms defined in L
350              
351             BEWARE: experimental, interface of this module might change!
352              
353             Supported algorithms (all defined in RFC7518):
354              
355             A128KW see: aes_key_wrap() + aes_key_unwrap()
356             A192KW see: aes_key_wrap() + aes_key_unwrap()
357             A256KW see: aes_key_wrap() + aes_key_unwrap()
358             A128GCMKW see: gcm_key_wrap() + gcm_key_unwrap()
359             A192GCMKW see: gcm_key_wrap() + gcm_key_unwrap()
360             A256GCMKW see: gcm_key_wrap() + gcm_key_unwrap()
361             PBES2-HS256+A128KW see: pbes2_key_wrap() + pbes2_key_unwrap()
362             PBES2-HS384+A192KW see: pbes2_key_wrap() + pbes2_key_unwrap()
363             PBES2-HS512+A256KW see: pbes2_key_wrap() + pbes2_key_unwrap()
364             RSA-OAEP see: rsa_key_wrap() + rsa_key_unwrap()
365             RSA-OAEP-256 see: rsa_key_wrap() + rsa_key_unwrap()
366             RSA1_5 see: rsa_key_wrap() + rsa_key_unwrap()
367             ECDH-ES+A128KW see: ecdhaes_key_wrap() + ecdhaes_key_unwrap()
368             ECDH-ES+A192KW see: ecdhaes_key_wrap() + ecdhaes_key_unwrap()
369             ECDH-ES+A256KW see: ecdhaes_key_wrap() + ecdhaes_key_unwrap()
370             ECDH-ES see: ecdh_key_wrap() + ecdh_key_unwrap()
371              
372             =head1 EXPORT
373              
374             Nothing is exported by default.
375              
376             You can export selected functions:
377              
378             use Crypt::KeyWrap qw(aes_key_wrap gcm_key_wrap pbes2_key_wrap);
379              
380             Or all of them at once:
381              
382             use Crypt::KeyWrap ':all';
383              
384             =head1 FUNCTIONS
385              
386             =head2 aes_key_wrap
387              
388             AES key wrap algorithm as defined in L
389             (implements algorithms C, C, C).
390              
391             Implementation follows L and L.
392              
393             The implementation is also compatible with L
394             (it supports AES based KW, KWP + TDEA/DES_EDE based TKW).
395              
396             AES Key Wrap algorithm.
397              
398             $enc_cek = aes_key_wrap($kek, $cek);
399             # or
400             $enc_cek = aes_key_wrap($kek, $cek, $cipher, $padding, $inverse);
401              
402             # params:
403             # $kek .. key encryption key (16bytes for AES128, 24 for AES192, 32 for AES256)
404             # $cek .. content encryption key
405             # optional params:
406             # $cipher .. 'AES' (default) or 'DES_EDE'
407             # $padding .. 1 (default) or 0 handle $cek padding (relevant for AES only)
408             # $inverse .. 0 (default) or 1 use cipher in inverse mode as defined by SP.800-38F
409              
410             Values C<$enc_cek>, C<$cek> and C<$kek> are binary octets. If you disable padding you have to make sure that
411             C<$cek> length is multiply of 8 (for AES) or multiply of 4 (for DES_EDE);
412              
413             =head2 aes_key_unwrap
414              
415             AES key unwrap algorithm as defined in L
416             (implements algorithms C, C, C).
417              
418             AES Key Unwrap algorithm.
419              
420             $cek = aes_key_unwrap($kek, $enc_cek);
421             # or
422             $cek = aes_key_unwrap($kek, $enc_cek, $cipher, $padding, $inverse);
423              
424             # params:
425             # $kek .. key encryption key (16bytes for AES128, 24 for AES192, 32 for AES256)
426             # $enc_cek .. encrypted content encryption key
427             # optional params:
428             # $cipher .. 'AES' (default) or 'DES_EDE'
429             # $padding .. 1 (default) or 0 - use $cek padding (relevant for AES only)
430             # $inverse .. 0 (default) or 1 - use cipher in inverse mode as defined by SP.800-38F
431              
432             Values C<$enc_cek>, C<$cek> and C<$kek> are binary octets.
433              
434             =head2 gcm_key_wrap
435              
436             AES GCM key wrap algorithm as defined in L
437             (implements algorithms C, C, C).
438              
439             ($enc_cek, $tag, $iv) = gcm_key_wrap($kek, $cek);
440             #or
441             ($enc_cek, $tag, $iv) = gcm_key_wrap($kek, $cek, $aad);
442             #or
443             ($enc_cek, $tag, $iv) = gcm_key_wrap($kek, $cek, $aad, $cipher, $iv);
444              
445             # params:
446             # $kek .. key encryption key (16bytes for AES128, 24 for AES192, 32 for AES256)
447             # $cek .. content encryption key
448             # optional params:
449             # $aad .. additional authenticated data, DEFAULT is '' (empty string)
450             # $cipher .. cipher to be used by GCM, DEFAULT is 'AES'
451             # $iv .. initialization vector (if not defined a random IV is generated)
452              
453             Values C<$enc_cek>, C<$cek>, C<$aad>, C<$iv>, C<$tag> and C<$kek> are binary octets.
454              
455             =head2 gcm_key_unwrap
456              
457             AES GCM key unwrap algorithm as defined in L
458             (implements algorithms C, C, C).
459              
460             $cek = gcm_key_unwrap($kek, $enc_cek, $tag, $iv);
461             # or
462             $cek = gcm_key_unwrap($kek, $enc_cek, $tag, $iv, $aad);
463             # or
464             $cek = gcm_key_unwrap($kek, $enc_cek, $tag, $iv, $aad, $cipher);
465              
466             # params:
467             # $kek .. key encryption key (16bytes for AES128, 24 for AES192, 32 for AES256)
468             # $enc_cek .. encrypted content encryption key
469             # $tag .. GCM's tag
470             # $iv .. initialization vector
471             # optional params:
472             # $aad .. additional authenticated data, DEFAULT is '' (empty string)
473             # $cipher .. cipher to be used by GCM, DEFAULT is 'AES'
474              
475             Values C<$enc_cek>, C<$cek>, C<$aad>, C<$iv>, C<$tag> and C<$kek> are binary octets.
476              
477             =head2 pbes2_key_wrap
478              
479             PBES2 key wrap algorithm as defined in L
480             (implements algorithms C, C, C).
481              
482             $enc_cek = pbes2_key_wrap($kek, $cek, $alg, $salt, $iter);
483              
484             # params:
485             # $kek .. key encryption key (arbitrary length)
486             # $cek .. content encryption key
487             # $alg .. algorithm name e.g. 'PBES2-HS256+A128KW' (see rfc7518)
488             # $salt .. pbkdf2 salt
489             # $iter .. pbkdf2 iteration count
490              
491             Values C<$enc_cek>, C<$cek>, C<$salt> and C<$kek> are binary octets.
492              
493             =head2 pbes2_key_unwrap
494              
495             PBES2 key unwrap algorithm as defined in L
496             (implements algorithms C, C, C).
497              
498             $cek = pbes2_key_unwrap($kek, $enc_cek, $alg, $salt, $iter);
499              
500             # params:
501             # $kek .. key encryption key (arbitrary length)
502             # $enc_cek .. encrypted content encryption key
503             # $alg .. algorithm name e.g. 'PBES2-HS256+A128KW' (see rfc7518)
504             # $salt .. pbkdf2 salt
505             # $iter .. pbkdf2 iteration count
506              
507             Values C<$enc_cek>, C<$cek>, C<$salt> and C<$kek> are binary octets.
508              
509             =head2 rsa_key_wrap
510              
511             PBES2 key wrap algorithm as defined in L and
512             L (implements algorithms C, C, C).
513              
514             $enc_cek = rsa_key_wrap($kek, $cek, $alg);
515              
516             # params:
517             # $kek .. RSA public key - Crypt::PK::RSA instance
518             # $cek .. content encryption key
519             # $alg .. algorithm name e.g. 'RSA-OAEP' (see rfc7518)
520              
521             Values C<$enc_cek> and C<$cek> are binary octets.
522              
523             =head2 rsa_key_unwrap
524              
525             PBES2 key wrap algorithm as defined in L and
526             L (implements algorithms C, C, C).
527              
528             $cek = rsa_key_unwrap($kek, $enc_cek, $alg);
529              
530             # params:
531             # $kek .. RSA private key - Crypt::PK::RSA instance
532             # $enc_cek .. encrypted content encryption key
533             # $alg .. algorithm name e.g. 'RSA-OAEP' (see rfc7518)
534              
535             Values C<$enc_cek> and C<$cek> are binary octets.
536              
537             =head2 ecdhaes_key_wrap
538              
539             ECDH+AESKW key agreement/wrap algorithm as defined in L
540             (implements algorithms C, C, C).
541              
542             ($enc_cek, $epk) = ecdhaes_key_wrap($kek, $cek, $alg, $apu, $apv);
543              
544             # params:
545             # $kek .. ECC public key - Crypt::PK::ECC|X25519 instance
546             # $cek .. content encryption key
547             # $alg .. algorithm name e.g. 'ECDH-ES+A256KW' (see rfc7518)
548             # optional params:
549             # $apu .. Agreement PartyUInfo Header Parameter
550             # $apv .. Agreement PartyVInfo Header Parameter
551              
552             Values C<$enc_cek> and C<$cek> are binary octets.
553              
554             =head2 ecdhaes_key_unwrap
555              
556             ECDH+AESKW key agreement/unwrap algorithm as defined in L
557             (implements algorithms C, C, C).
558              
559             $cek = ecdhaes_key_unwrap($kek, $enc_cek, $alg, $epk, $apu, $apv);
560              
561             # params:
562             # $kek .. ECC private key - Crypt::PK::ECC|X25519 instance
563             # $enc_cek .. encrypted content encryption key
564             # $alg .. algorithm name e.g. 'ECDH-ES+A256KW' (see rfc7518)
565             # $epk .. ephemeral ECC public key (JWK/JSON or Crypt::PK::ECC|X25519)
566             # optional params:
567             # $apu .. Agreement PartyUInfo Header Parameter
568             # $apv .. Agreement PartyVInfo Header Parameter
569              
570             Values C<$enc_cek> and C<$cek> are binary octets.
571              
572             =head2 ecdh_key_wrap
573              
574             ECDH (Ephememeral Static) key agreement/wrap algorithm as defined in L
575             (implements algorithm C).
576              
577             ($cek, $epk) = ecdh_key_wrap($kek, $enc, $apu, $apv);
578              
579             # params:
580             # $kek .. ECC public key - Crypt::PK::ECC|X25519 instance
581             # $enc .. encryption algorithm name e.g. 'A256GCM' (see rfc7518)
582             # optional params:
583             # $apu .. Agreement PartyUInfo Header Parameter
584             # $apv .. Agreement PartyVInfo Header Parameter
585              
586             Value C<$cek> - binary octets, C<$epk> JWK/JSON string with ephemeral ECC public key.
587              
588             =head2 ecdh_key_unwrap
589              
590             ECDH (Ephememeral Static) key agreement/unwrap algorithm as defined in L
591             (implements algorithm C).
592              
593             $cek = ecdh_key_unwrap($kek, $enc, $epk, $apu, $apv);
594              
595             # params:
596             # $kek .. ECC private key - Crypt::PK::ECC|X25519 instance
597             # $enc .. encryption algorithm name e.g. 'A256GCM' (see rfc7518)
598             # $epk .. ephemeral ECC public key (JWK/JSON or Crypt::PK::ECC|X25519)
599             # optional params:
600             # $apu .. Agreement PartyUInfo Header Parameter
601             # $apv .. Agreement PartyVInfo Header Parameter
602              
603             Value C<$cek> - binary octets.
604              
605             =head1 SEE ALSO
606              
607             L, L, L, L
608              
609             =head1 LICENSE
610              
611             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
612              
613             =head1 COPYRIGHT
614              
615             Copyright (c) 2015-2023 DCIT, a.s. L / Karel Miko