@@ -9,12 +9,13 @@ use Carp;
99use XML::LibXML;
1010use Crypt::OpenSSL::RSA;
1111use Crypt::Mode::CBC;
12+ use Crypt::AuthEnc::GCM;
1213use MIME::Base64 qw/ decode_base64 encode_base64/ ;
1314use Crypt::Random qw( makerandom_octet ) ;
1415
1516use vars qw( $VERSION @EXPORT_OK %EXPORT_TAGS $DEBUG) ;
1617
17- our $VERSION = ' 0.03 ' ;
18+ our $VERSION = ' 0.04 ' ;
1819
1920our $DEBUG = 0;
2021
@@ -52,10 +53,37 @@ XML::Enc - XML Encryption
5253# 5.2.2 AES - 128 bit initialization vector (IV) (16 bytes)
5354
5455my %encmethods = (
55- ' http://www.w3.org/2001/04/xmlenc#tripledes-cbc' => { ivsize => 8, keysize => 24, modename => ' DES_EDE' },
56- ' http://www.w3.org/2001/04/xmlenc#aes128-cbc' => { ivsize => ' 16' , keysize => 16, modename => ' AES' },
57- ' http://www.w3.org/2001/04/xmlenc#aes192-cbc' => { ivsize => ' 16' , keysize => 24, modename => ' AES' },
58- ' http://www.w3.org/2001/04/xmlenc#aes256-cbc' => { ivsize => ' 16' , keysize => 32, modename => ' AES' },
56+ ' http://www.w3.org/2001/04/xmlenc#tripledes-cbc' => {
57+ ivsize => 8,
58+ keysize => 24,
59+ modename => ' DES_EDE' },
60+ ' http://www.w3.org/2001/04/xmlenc#aes128-cbc' => {
61+ ivsize => ' 16' ,
62+ keysize => 16,
63+ modename => ' AES' },
64+ ' http://www.w3.org/2001/04/xmlenc#aes192-cbc' => {
65+ ivsize => ' 16' ,
66+ keysize => 24,
67+ modename => ' AES' },
68+ ' http://www.w3.org/2001/04/xmlenc#aes256-cbc' => {
69+ ivsize => ' 16' ,
70+ keysize => 32,
71+ modename => ' AES' },
72+ ' http://www.w3.org/2009/xmlenc11#aes128-gcm' => {
73+ ivsize => ' 12' ,
74+ keysize => 16,
75+ modename => ' AES' ,
76+ tagsize => 16 },
77+ ' http://www.w3.org/2009/xmlenc11#aes192-gcm' => {
78+ ivsize => ' 12' ,
79+ keysize => 24,
80+ modename => ' AES' ,
81+ tagsize => 16 },
82+ ' http://www.w3.org/2009/xmlenc11#aes256-gcm' => {
83+ ivsize => ' 12' ,
84+ keysize => 32,
85+ modename => ' AES' ,
86+ tagsize => 16 },
5987 );
6088
6189=head2 new( ... )
@@ -293,6 +321,9 @@ sub _setEncryptionMethod {
293321 ' aes192-cbc' => ' http://www.w3.org/2001/04/xmlenc#aes192-cbc' ,
294322 ' aes256-cbc' => ' http://www.w3.org/2001/04/xmlenc#aes256-cbc' ,
295323 ' tripledes-cbc' => ' http://www.w3.org/2001/04/xmlenc#tripledes-cbc' ,
324+ ' aes128-gcm' => ' http://www.w3.org/2009/xmlenc11#aes128-gcm' ,
325+ ' aes192-gcm' => ' http://www.w3.org/2009/xmlenc11#aes192-gcm' ,
326+ ' aes256-gcm' => ' http://www.w3.org/2009/xmlenc11#aes256-gcm' ,
296327 );
297328
298329 return exists ($methods {$method }) ? $methods {$method } : $methods {' aes256-cbc' };
@@ -327,7 +358,7 @@ sub _setKeyEncryptionMethod {
327358 ' rsa-oaep-mgf1p' => ' http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' ,
328359 );
329360
330- return exists ($methods {$method }) ? $methods {$method } : $methods {' rsa-1_5 ' };
361+ return exists ($methods {$method }) ? $methods {$method } : $methods {' rsa-oaep-mgf1p ' };
331362}
332363
333364sub _DecryptData {
@@ -338,23 +369,35 @@ sub _DecryptData {
338369
339370 my $iv ;
340371 my $encrypted ;
341- my $cbc ;
372+ my $plaintext ;
373+
374+ my $ivsize = $encmethods {$method }-> {ivsize };
375+ my $tagsize = $encmethods {$method }-> {tagsize };
376+
377+ $iv = substr $encrypteddata , 0, $ivsize ;
378+ $encrypted = substr $encrypteddata , $ivsize ;
342379
343380 # XML Encryption 5.2 Block Encryption Algorithms
344381 # The resulting cipher text is prefixed by the IV.
345- if (defined $encmethods {$method }){
346- my $blksize = $encmethods {$method }-> {ivsize };
347- # print "Block Size: ", $blksize;
348- $iv = substr $encrypteddata , 0, $blksize ;
349- $encrypted = substr $encrypteddata , $blksize ;
350- $cbc = Crypt::Mode::CBC-> new($encmethods {$method }-> {modename }, 0);
382+ if (defined $encmethods {$method } & $method !~ / gcm/ ){
383+ my $cbc = Crypt::Mode::CBC-> new($encmethods {$method }-> {modename }, 0);
384+ $plaintext = $self -> _remove_padding($cbc -> decrypt($encrypted , $key , $iv ));
385+ } elsif (defined $encmethods {$method } & $method =~ / gcm/ ){
386+ my $gcm = Crypt::AuthEnc::GCM-> new(" AES" , $key , $iv );
387+
388+ # Note that GCM support for additional authentication
389+ # data is not used in the XML specification.
390+ my $tag = substr $encrypted , - $tagsize ;
391+ $encrypted = substr $encrypted , 0, (length $encrypted ) - $tagsize ;
392+ $plaintext = $gcm -> decrypt_add($encrypted );
393+ if ( ! $gcm -> decrypt_done($tag ) ) {
394+ die " Tag expected did not match returned Tag" ;
395+ }
351396 } else {
352397 die " Unsupported Encryption Algorithm" ;
353398 }
354399
355- my $plaintext = $cbc -> decrypt($encrypted , $key , $iv );
356-
357- return $self -> _remove_padding($plaintext );
400+ return $plaintext ;
358401}
359402
360403sub _EncryptData {
@@ -363,25 +406,33 @@ sub _EncryptData {
363406 my $data = shift ;
364407 my $key = shift ;
365408
366- my $iv ;
367- my $cbc ;
409+ my $cipherdata ;
410+ my $ivsize = $encmethods {$method }-> {ivsize };
411+ my $keysize = $encmethods {$method }-> {keysize };
368412
369- # XML Encryption 5.2 Block Encryption Algorithms
370- # The resulting cipher text is prefixed by the IV.
371- if (defined $encmethods {$method }){
372- my $blksize = $encmethods {$method }-> {ivsize };
373- my $keysize = $encmethods {$method }-> {keysize };
374- $iv = makerandom_octet ( Length => $blksize );
375- ${$key} = makerandom_octet ( Length => $keysize );
376- $data = $self -> _add_padding($data , $blksize );
377- $cbc = Crypt::Mode::CBC-> new($encmethods {$method }-> {modename }, 0);
413+ my $iv = makerandom_octet ( Length => $ivsize );
414+ ${$key} = makerandom_octet ( Length => $keysize );
415+
416+ if (defined $encmethods {$method } & $method !~ / gcm/ ){
417+ my $cbc = Crypt::Mode::CBC-> new($encmethods {$method }-> {modename }, 0);
418+ # XML Encryption 5.2 Block Encryption Algorithms
419+ # The resulting cipher text is prefixed by the IV.
420+ $data = $self -> _add_padding($data , $ivsize );
421+ $cipherdata = $iv . $cbc -> encrypt($data , ${$key} , $iv );
422+ } elsif (defined $encmethods {$method } & $method =~ / gcm/ ){
423+ my $gcm = Crypt::AuthEnc::GCM-> new($encmethods {$method }-> {modename }, ${$key} , $iv );
424+
425+ # Note that GCM support for additional authentication
426+ # data is not used in the XML specification.
427+ my $encrypted = $gcm -> encrypt_add($data );
428+ my $tag = $gcm -> encrypt_done();
429+
430+ $cipherdata = $iv . $encrypted . $tag ;
378431 } else {
379432 die " Unsupported Encryption Algorithm" ;
380433 }
381434
382- my $encrypted = $iv . $cbc -> encrypt($data , ${$key} , $iv );
383-
384- return $encrypted ;
435+ return $cipherdata ;
385436}
386437
387438sub _DecryptKey {
0 commit comments