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   414440 use strict;
  13         78  
  13         389  
4 13     13   68 use warnings;
  13         23  
  13         561  
5              
6             our $VERSION = '0.033';
7              
8 13     13   76 use Exporter 'import';
  13         23  
  13         1247  
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   115 use Carp;
  13         28  
  13         874  
14 13     13   3517 use Crypt::Mode::ECB;
  13         66083  
  13         448  
15 13     13   6799 use Crypt::AuthEnc::GCM qw(gcm_encrypt_authenticate gcm_decrypt_verify);
  13         4321  
  13         788  
16 13     13   3428 use Crypt::PRNG qw(random_bytes);
  13         6296  
  13         680  
17 13     13   6011 use Crypt::KeyDerivation qw(pbkdf2);
  13         4260  
  13         714  
18 13     13   3226 use Crypt::Digest qw(digest_data);
  13         4844  
  13         593  
19 13     13   82 use Config;
  13         28  
  13         39993  
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   19172 my ($bytes, $data) = @_;
28 12541         15999 my $len = length $data;
29 12541 50       36857 return $len > $bytes ? substr($data, $len-$bytes, $bytes) : $data;
30             }
31              
32             sub _MSB {
33 12541     12541   20717 my ($bytes, $data) = @_;
34 12541         16825 my $len = length $data;
35 12541 50       29735 return $len > $bytes ? substr($data, 0, $bytes) : $data;
36             }
37              
38             sub _N2RAW {
39 12528     12528   19217 my ($bytes, $n) = @_;
40 12528 100       21143 if ($bytes == 8) {
41 10656 50       47296 return pack("N", 0) . pack("N", $n) if $Config{uvsize} == 4; #workaround
42 10656         47888 return pack("N", $n >> 32) . pack("N", $n & 0xFFFFFFFF);
43             }
44 1872 50       6541 return pack("N", $n & 0xFFFFFFFF) if $bytes == 4;
45             }
46              
47             sub aes_key_wrap {
48 138     138 1 41410 my ($kek, $pt_data, $cipher, $padding, $inverse) = @_;
49 138 100       436 $cipher = 'AES' unless defined $cipher;
50 138 50       389 $padding = $cipher eq 'AES' ? 1 : 0 unless defined $padding;
    100          
51              
52 138         240 my ($A, $B, $P, $R);
53              
54 138 50       302 croak "aes_key_wrap: no KEK" unless defined $kek;
55 138 50       312 croak "aes_key_wrap: no PT data" unless defined $pt_data;
56 138         240 my $klen = length $kek;
57 138 50 100     729 croak "aes_key_wrap: invalid KEK length" unless $klen == 16 || $klen == 24 || $klen == 32;
      66        
58 138 50 66     397 croak "aes_key_wrap: cipher must be AES or DES_EDE" unless $cipher eq 'AES' || $cipher eq 'DES_EDE';
59 138 50 66     480 croak "aes_key_wrap: padding not allowed with DES_EDE" if $padding && $cipher eq 'DES_EDE';
60              
61 138         1201 my $ECB = Crypt::Mode::ECB->new($cipher, 0);
62 138 100       377 my $blck = $cipher eq 'DES_EDE' ? 4 : 8; # semiblock size in bytes, for AES 8, for 3DES 4
63              
64 138         568 my $IV = pack("H*", "A6" x $blck);
65 138         225 my $len = length $pt_data;
66 138 100       383 if ($len % $blck > 0) {
67 33 50       69 croak "aes_key_wrap: pt_data length not multiply of $blck" if !$padding;
68 33         77 $pt_data .= chr(0) x ($blck - ($len % $blck));
69 33         78 $IV = pack("H*", "A65959A6") . pack("N", $len);
70             }
71              
72 138         345 my $n = length($pt_data) / $blck;
73 138         1272 $P->[$_] = substr($pt_data, $_*$blck, $blck) for (0..$n-1);
74              
75 138 100       361 if ($n == 1) {
76 13 100       60 return $inverse ? $ECB->decrypt($IV . $P->[0], $kek)
77             : $ECB->encrypt($IV . $P->[0], $kek);
78             }
79              
80 125         220 $A = $IV;
81 125         693 $R->[$_] = $P->[$_] for (0..$n-1);
82              
83 125         249 for my $j (0..5) {
84 750         1460 for my $i (0..$n-1) {
85 6012 100       16821 $B = $inverse ? $ECB->decrypt($A . $R->[$i], $kek)
86             : $ECB->encrypt($A . $R->[$i], $kek);
87 6012         89292 $A = _MSB($blck, $B) ^ _N2RAW($blck, ($n*$j)+$i+1);
88 6012         11422 $R->[$i] = _LSB($blck, $B);
89             }
90             }
91              
92 125         224 my $rv = $A;
93 125         594 $rv .= $R->[$_] for (0..$n-1);
94 125         937 return $rv;
95             }
96              
97             sub aes_key_unwrap {
98 163     163 1 41514 my ($kek, $ct_data, $cipher, $padding, $inverse) = @_;
99 163 100       543 $cipher = 'AES' unless defined $cipher;
100 163 50       546 $padding = $cipher eq 'AES' ? 1 : 0 unless defined $padding;
    100          
101              
102 163         298 my ($A, $B, $C, $P, $R);
103              
104 163 50       383 croak "aes_key_unwrap: no KEK" unless defined $kek;
105 163 50       365 croak "aes_key_unwrap: no CT data" unless defined $ct_data;
106 163         265 my $klen = length $kek;
107 163 50 100     765 croak "aes_key_unwrap: invalid KEK length" unless $klen == 16 || $klen == 24 || $klen == 32;
      66        
108 163 50 66     475 croak "aes_key_unwrap: cipher must be AES or DES_EDE" unless $cipher eq 'AES' || $cipher eq 'DES_EDE';
109 163 50 66     676 croak "aes_key_unwrap: padding not allowed with DES_EDE" if $padding && $cipher eq 'DES_EDE';
110              
111 163         1477 my $ECB = Crypt::Mode::ECB->new($cipher, 0);
112 163 100       494 my $blck = $cipher eq 'DES_EDE' ? 4 : 8; # semiblock size in bytes, for AES 8, for 3DES 4
113              
114 163         500 my $n = length($ct_data) / $blck - 1;
115 163         1508 $C->[$_] = substr($ct_data, $_*$blck, $blck) for (0..$n); # n+1 semiblocks
116              
117 163 100       430 if ($n==1) {
118 13 100       64 $B = $inverse ? $ECB->encrypt($C->[0] . $C->[1], $kek)
119             : $ECB->decrypt($C->[0] . $C->[1], $kek);
120 13         237 $A = _MSB($blck, $B);
121 13         30 $R->[0] = _LSB($blck, $B);
122             }
123             else {
124 150         294 $A = $C->[0];
125 150         871 $R->[$_] = $C->[$_+1] for (0..$n-1);
126 150         455 for(my $j=5; $j>=0; $j--) {
127 900         1924 for(my $i=$n-1; $i>=0; $i--) {
128 6516 100       15117 $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         97801 $A = _MSB($blck, $B);
131 6516         10647 $R->[$i] = _LSB($blck, $B);
132             }
133             }
134             }
135              
136 163         277 my $rv = '';
137 163         757 $rv .= $R->[$_] for (0..$n-1);
138              
139 163         567 my $A_hex = unpack("H*", $A);
140 163 100 33     717 if ($A_hex eq 'a6'x$blck) {
    50          
141 130         979 return $rv;
142             }
143             elsif ($A_hex =~ /^a65959a6/ && $blck == 8) {
144 33 50       77 warn "key_unwrap: unexpected padding" unless $padding;
145 33         82 my $n = unpack("N", substr($A, 4, 4));
146 33         59 my $z = length($rv) - $n;
147 33         76 my $tail = unpack("H*", substr($rv, -$z));
148 33 50       79 croak "aes_key_unwrap: invalid data" unless $tail eq "00"x$z;
149 33         220 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 853 my ($kek, $pt_data, $aad, $cipher, $iv) = @_;
158 19 100       46 $cipher = 'AES' unless defined $cipher;
159 19 100       49 $iv = random_bytes(12) unless defined $iv; # 96 bits REQUIRED by RFC7518
160 19         4066 my ($ct_data, $tag) = gcm_encrypt_authenticate($cipher, $kek, $iv, $aad, $pt_data);
161 19         103 return ($ct_data, $tag, $iv);
162             }
163              
164             sub gcm_key_unwrap {
165 23     23 1 151 my ($kek, $ct_data, $tag, $iv, $aad, $cipher) = @_;
166 23   100     107 $cipher ||= 'AES';
167 23         4565 my $pt_data = gcm_decrypt_verify($cipher, $kek, $iv, $aad, $ct_data, $tag);
168 23         112 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 860 my ($kek, $pt_data, $alg, $salt, $iter) = @_;
175 25         53 my ($hash_name, $len);
176 25 50       170 if ($alg =~ /^PBES2-HS(256|384|512)\+A(128|192|256)KW$/) {
177 25         75 $hash_name = "SHA$1";
178 25         65 $len = $2/8;
179 25         473232 my $aes_key = pbkdf2($kek, $alg."\x00".$salt, $iter, $hash_name, $len);
180 25         249 my $ct_data = aes_key_wrap($aes_key, $pt_data);
181 25         131 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 323 my ($kek, $ct_data, $alg, $salt, $iter) = @_;
189 40         84 my ($hash_name, $len);
190 40 50       259 if ($alg =~ /^PBES2-HS(256|384|512)\+A(128|192|256)KW$/) {
191 40         129 $hash_name = "SHA$1";
192 40         126 $len = $2/8;
193 40         783519 my $aes_key = pbkdf2($kek, $alg."\x00".$salt, $iter, $hash_name, $len);
194 40         446 my $pt_data = aes_key_unwrap($aes_key, $ct_data);
195 40         315 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 2712 my ($kek_public, $pt_data, $alg) = @_;
207 21 50       93 croak "rsa_key_wrap: no Crypt::PK::RSA" unless ref $kek_public eq 'Crypt::PK::RSA';
208 21         48 my ($padding, $hash_name);
209 21 100       100 if ($alg eq 'RSA-OAEP') { ($padding, $hash_name) = ('oaep', 'SHA1') }
  7 100       21  
    50          
210 7         24 elsif ($alg eq 'RSA-OAEP-256') { ($padding, $hash_name) = ('oaep', 'SHA256') }
211 7         45 elsif ($alg eq 'RSA1_5') { $padding = 'v1.5' }
212 21 50       65 croak "rsa_key_wrap: invalid algorithm '$alg'" unless $padding;
213 21         4887 my $ct_data = $kek_public->encrypt($pt_data, $padding, $hash_name);
214 21         91 return $ct_data;
215             }
216              
217             sub rsa_key_unwrap {
218 39     39 1 753 my ($kek_private, $ct_data, $alg) = @_;
219 39 50       145 croak "rsa_key_unwrap: no Crypt::PK::RSA" unless ref $kek_private eq 'Crypt::PK::RSA';
220 39 50       199 croak "rsa_key_unwrap: no private key" unless $kek_private->is_private;
221 39         76 my ($padding, $hash_name);
222 39 100       151 if ($alg eq 'RSA-OAEP') { ($padding, $hash_name) = ('oaep', 'SHA1') }
  14 100       33  
    50          
223 10         28 elsif ($alg eq 'RSA-OAEP-256') { ($padding, $hash_name) = ('oaep', 'SHA256') }
224 15         29 elsif ($alg eq 'RSA1_5') { $padding = 'v1.5' }
225 39 50       106 croak "rsa_key_unwrap: invalid algorithm '$alg'" unless $padding;
226 39         211495 my $pt_data = $kek_private->decrypt($ct_data, $padding, $hash_name);
227 39         804 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   291 my ($hash_name, $key_size, $shared_secret, $algorithm, $apu, $apv) = @_;
235 68 50       266 $apu = '' unless defined $apu;
236 68 50       183 $apv = '' unless defined $apv;
237 68         413 my $hsize = Crypt::Digest->hashsize($hash_name);
238 68         191 my $count = int($key_size / $hsize);
239 68 100       242 $count++ if ($key_size % $hsize) > 0;
240 68         127 my $data = '';
241 68         208 for my $i (1..$count) {
242 72         991 $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         288 return substr($data, 0, $key_size);
250             }
251              
252             sub ecdh_key_wrap {
253 7     7 1 4600 my ($kek_public, $enc, $apu, $apv) = @_;
254 7 50       31 croak "ecdh_key_wrap: no Crypt::PK::ECC" unless ref $kek_public eq 'Crypt::PK::ECC';
255 7         16 my $encryption_key_size = 256;
256 7 100       30 if ($enc =~ /^A(128|192|256)CBC-HS/) {
257 3         9 $encryption_key_size = $1*2;
258             }
259 7 100       91 if ($enc =~ /^A(128|192|256)GCM/) {
260 4         31 $encryption_key_size = $1;
261             }
262 7         35 my $ephemeral = Crypt::PK::ECC->new()->generate_key($kek_public->curve2hash);
263 7         41843 my $shared_secret = $ephemeral->shared_secret($kek_public);
264 7         63 my $ct_data = _concat_kdf('SHA256', $encryption_key_size/8, $shared_secret, $enc, $apu, $apv);
265 7         45 return ($ct_data, $ephemeral->export_key_jwk('public'));
266             }
267              
268             sub ecdh_key_unwrap {
269 15     15 1 9418 my ($kek_private, $enc, $epk, $apu, $apv) = @_;
270 15 50       91 croak "ecdh_key_unwrap: no Crypt::PK::ECC" unless ref $kek_private eq 'Crypt::PK::ECC';
271 15 50       93 croak "ecdh_key_unwrap: no private key" unless $kek_private->is_private;
272 15         29 my $encryption_key_size = 256;
273 15 100       71 if ($enc =~ /^A(128|192|256)CBC-HS/) {
274 5         24 $encryption_key_size = $1*2;
275             }
276 15 100       96 if ($enc =~ /^A(128|192|256)GCM/) {
277 10         34 $encryption_key_size = $1;
278             }
279 15 100       120 my $ephemeral = ref($epk) eq 'Crypt::PK::ECC' ? $epk : Crypt::PK::ECC->new(ref $epk ? $epk : \$epk);
    50          
280 15         90471 my $shared_secret = $kek_private->shared_secret($ephemeral);
281 15         166 my $pt_data = _concat_kdf('SHA256', $encryption_key_size/8, $shared_secret, $enc, $apu, $apv);
282 15         225 return $pt_data;
283             }
284              
285             sub ecdhaes_key_wrap {
286 20     20 1 3920 my ($kek_public, $pt_data, $alg, $apu, $apv) = @_;
287 20 50       110 croak "ecdhaes_key_wrap: no Crypt::PK::(ECC|X25519)" unless ref($kek_public) =~ /^Crypt::PK::(ECC|X25519)$/;
288 20         40 my $encryption_key_size = 256;
289 20 50       76 if ($alg =~ /^ECDH-ES\+A(128|192|256)KW$/) {
290 20         45 $encryption_key_size = $1;
291             }
292 20         29 my $ephemeral;
293 20 100       84 if (ref($kek_public) eq 'Crypt::PK::ECC') {
294 19         76 $ephemeral = Crypt::PK::ECC->new->generate_key($kek_public->curve2hash);
295             }
296             else {
297 1         5 $ephemeral = Crypt::PK::X25519->new->generate_key();
298             }
299 20         222920 my $shared_secret = $ephemeral->shared_secret($kek_public);
300 20         161 my $kek = _concat_kdf('SHA256', $encryption_key_size/8, $shared_secret, $alg, $apu, $apv);
301 20         80 return (aes_key_wrap($kek, $pt_data), $ephemeral->export_key_jwk('public'));
302             }
303              
304             sub ecdhaes_key_unwrap {
305 26     26 1 8134 my ($kek_private, $ct_data, $alg, $epk, $apu, $apv) = @_;
306 26 50       193 croak "ecdhaes_key_unwrap: no Crypt::PK::(ECC|X25519)" unless ref($kek_private) =~ /^Crypt::PK::(ECC|X25519)$/;
307 26 50       131 croak "ecdhaes_key_unwrap: no private key" unless $kek_private->is_private;
308 26         48 my $encryption_key_size = 256;
309 26 50       123 if ($alg =~ /^ECDH-ES\+A(128|192|256)KW$/) {
310 26         78 $encryption_key_size = $1;
311             }
312 26         37 my $ephemeral;
313 26 100       70 if (ref($kek_private) eq 'Crypt::PK::ECC') {
314 25 100       161 $ephemeral = ref($epk) eq 'Crypt::PK::ECC' ? $epk : Crypt::PK::ECC->new(ref $epk ? $epk : \$epk);
    50          
315             }
316             else {
317 1 50       13 $ephemeral = ref($epk) eq 'Crypt::PK::X25519' ? $epk : Crypt::PK::X25519->new(ref $epk ? $epk : \$epk);
    50          
318             }
319 26         256622 my $shared_secret = $kek_private->shared_secret($ephemeral);
320 26         234 my $kek = _concat_kdf('SHA256', $encryption_key_size/8, $shared_secret, $alg, $apu, $apv);
321 26         111 my $pt_data = aes_key_unwrap($kek, $ct_data);
322 26         318 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-2021 DCIT, a.s. L / Karel Miko