@@ -9,7 +9,7 @@ package XML::Enc;
99use Carp;
1010use Crypt::AuthEnc::GCM 0.062;
1111use Crypt::Mode::CBC;
12- use Crypt::PK::RSA;
12+ use Crypt::PK::RSA 0.081 ;
1313use Crypt::PRNG qw( random_bytes ) ;
1414use MIME::Base64 qw/ decode_base64 encode_base64/ ;
1515use XML::LibXML;
@@ -107,8 +107,10 @@ sub _assert_encryption_digest {
107107 state $ENC_DIGEST = {
108108 ' http://www.w3.org/2000/09/xmldsig#sha1' => ' SHA1' ,
109109 ' http://www.w3.org/2001/04/xmlenc#sha256' => ' SHA256' ,
110+ ' http://www.w3.org/2001/04/xmldsig-more#sha224' => ' SHA224' ,
111+ ' http://www.w3.org/2001/04/xmldsig-more#sha384' => ' SHA384' ,
112+ ' http://www.w3.org/2001/04/xmlenc#sha512' => ' SHA512' ,
110113 };
111-
112114 die " Unsupported encryption digest algo $algo " unless $ENC_DIGEST -> { $algo };
113115 return $ENC_DIGEST -> { $algo };
114116}
@@ -196,6 +198,44 @@ Used in encryption. Optional. Default method: mgf1sha1
196198
197199=back
198200
201+ =item B<oaep_params >
202+
203+ Specify the OAEPparams value to use as part of the mask generation function (MGF).
204+ It is optional but can be specified for rsa-oaep and rsa-oaep-mgf1p EncryptionMethods.
205+
206+ It is base64 encoded and stored in the XML as OAEPparams.
207+
208+ If specified you MAY specify the oaep_label_hash that should be used. You should note
209+ that not all implementations support an oaep_label_hash that differs from that of the
210+ MGF specified in the xenc11:MGF element or the default MGF1 with SHA1.
211+
212+ The oaep_label_hash is stored in the DigestMethod child element of the EncryptionMethod.
213+
214+ =item B<oaep_label_hash >
215+
216+ Specify the Hash Algorithm to use for the rsa-oaep label as specified by oaep_params.
217+
218+ The default is sha1. Supported algorithms are:
219+
220+ =over
221+
222+ =item * L<sha1|http://www.w3.org/2000/09/xmldsig#sha1>
223+
224+ =item * L<sha224|http://www.w3.org/2001/04/xmldsig-more#sha224>
225+
226+ =item * L<sha256|http://www.w3.org/2001/04/xmlenc#sha256>
227+
228+ =item * L<sha384|http://www.w3.org/2001/04/xmldsig-more#sha384>
229+
230+ =item * L<sha512|http://www.w3.org/2001/04/xmlenc#sha512>
231+
232+ =back
233+
234+ =item B<key_name >
235+
236+ Specify a key name to add to the KeyName element. If it is not specified then no
237+ KeyName element is added to the KeyInfo
238+
199239=back
200240
201241=cut
@@ -225,11 +265,17 @@ sub new {
225265 my $key_method = exists ($params -> {' key_transport' }) ? $params -> {' key_transport' } : ' rsa-oaep-mgf1p ' ;
226266 $self -> {' key_transport' } = $self -> _setKeyEncryptionMethod($key_method );
227267
228- my $oaep_mgf_alg = exists ($params -> {' oaep_mgf_alg' }) ? $params -> {' oaep_mgf_alg' } : ' http://www.w3.org/2009/xmlenc11#mgf1sha1' ;
229- $self -> {' oaep_mgf_alg' } = $self -> _setOAEPAlgorithm($oaep_mgf_alg );
268+ if (exists $params -> {' oaep_mgf_alg' }) {
269+ $self -> {' oaep_mgf_alg' } = $self -> _setOAEPAlgorithm($params -> {' oaep_mgf_alg' });
270+ }
271+ if (exists $params -> {' oaep_label_hash' } ) {
272+ $self -> {' oaep_label_hash' } = $self -> _setOAEPDigest($params -> {' oaep_label_hash' });
273+ }
230274
231275 $self -> {' oaep_params' } = exists ($params -> {' oaep_params' }) ? $params -> {' oaep_params' } : ' ' ;
232276
277+ $self -> {' key_name' } = $params -> {' key_name' } if exists ($params -> {' key_name' });
278+
233279 return $self ;
234280}
235281
@@ -502,6 +548,11 @@ sub encrypt {
502548 my $base64_key = encode_base64($key );
503549 my $base64_data = encode_base64($encrypteddata );
504550
551+ # Insert KeyName into the XML
552+ if (defined $self -> {key_name } and $self -> {key_name } ne ' ' ) {
553+ $encrypted = $self -> _setKeyName($encrypted , $xpc , $self -> {key_name });
554+ }
555+
505556 # Insert OAEPparams into the XML
506557 if ($self -> {oaep_params } ne ' ' ) {
507558 $encrypted = $self -> _setOAEPparams($encrypted , $xpc , encode_base64($self -> {oaep_params }));
@@ -533,6 +584,19 @@ sub _setEncryptionMethod {
533584 return exists ($methods {$method }) ? $methods {$method } : $methods {' aes256-cbc' };
534585}
535586
587+ sub _setKeyName {
588+ my $self = shift ;
589+ my $context = shift ;
590+ my $xpc = shift ;
591+ my $keyname = shift ;
592+
593+ my $node = $xpc -> findnodes(' //xenc:EncryptedKey/dsig:KeyInfo/dsig:KeyName' , $context );
594+
595+ $node -> [0]-> removeChildNodes();
596+ $node -> [0]-> appendText(defined $keyname ? $keyname : ' key_name' );
597+ return $context ;
598+ }
599+
536600sub _setOAEPparams {
537601 my $self = shift ;
538602 my $context = shift ;
@@ -576,6 +640,36 @@ sub _getOAEPAlgorithm {
576640 return $OAEPAlgorithm -> {$method } // ' SHA1' ;
577641}
578642
643+ sub _setOAEPDigest {
644+ my $self = shift ;
645+ my $method = shift ;
646+
647+ state $OAEPDigest = {
648+ ' sha1' => ' http://www.w3.org/2000/09/xmldsig#sha1' ,
649+ ' sha224' => ' http://www.w3.org/2001/04/xmldsig-more#sha224' ,
650+ ' sha256' => ' http://www.w3.org/2001/04/xmlenc#sha256' ,
651+ ' sha384' => ' http://www.w3.org/2001/04/xmldsig-more#sha384' ,
652+ ' sha512' => ' http://www.w3.org/2001/04/xmlenc#sha512' ,
653+ };
654+
655+ return $OAEPDigest -> {$method } // $OAEPDigest -> {' sha256' };
656+ }
657+
658+ sub _getParamsAlgorithm {
659+ my $self = shift ;
660+ my $method = shift ;
661+
662+ state $ParamsAlgorithm = {
663+ ' http://www.w3.org/2000/09/xmldsig#sha1' => ' SHA1' ,
664+ ' http://www.w3.org/2001/04/xmldsig-more#sha224' => ' SHA224' ,
665+ ' http://www.w3.org/2001/04/xmlenc#sha256' => ' SHA256' ,
666+ ' http://www.w3.org/2001/04/xmldsig-more#sha384' => ' SHA384' ,
667+ ' http://www.w3.org/2001/04/xmlenc#sha512' => ' SHA512' ,
668+ };
669+
670+ return $ParamsAlgorithm -> {$method } // $ParamsAlgorithm -> {' http://www.w3.org/2000/09/xmldsig#sha1' };
671+ }
672+
579673sub _setKeyEncryptionMethod {
580674 my $self = shift ;
581675 my $method = shift ;
@@ -681,23 +775,45 @@ sub _decrypt_key {
681775 if ($algo eq ' http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' ) {
682776 return _decrypt(
683777 sub {
684- $self -> {key_obj }-> decrypt(
685- $key , ' oaep' ,
686- $digest_name // ' SHA1' ,
687- $oaep // ' '
688- );
778+ if ($CryptX::VERSION le 0.081) {
779+ # print "Caller: _decrypt_key rsa-oaep-mgf1p\n";
780+ $self -> {key_obj }-> decrypt(
781+ $key , ' oaep' ,
782+ # $self->_getOAEPAlgorithm($mgf),
783+ $digest_name // ' SHA1' ,
784+ $oaep // ' ' ,
785+ );
786+ } else {
787+ # print "Caller: _decrypt_key rsa-oaep-mgf1p\n";
788+ # print "digest_name: ", $digest_name, "\n";
789+ $self -> {key_obj }-> decrypt(
790+ $key , ' oaep' ,
791+ $mgf // ' SHA1' ,
792+ $oaep // ' ' ,
793+ $digest_name // ' SHA1' ,
794+ );
795+ }
689796 }
690797 );
691798 }
692799
693800 if ($algo eq ' http://www.w3.org/2009/xmlenc11#rsa-oaep' ) {
694801 return _decrypt(
695802 sub {
696- $self -> {key_obj }-> decrypt(
697- $key , ' oaep' ,
698- $self -> _getOAEPAlgorithm($mgf ),
699- $oaep // ' ' ,
700- );
803+ if ($CryptX::VERSION le 0.081) {
804+ $self -> {key_obj }-> decrypt(
805+ $key , ' oaep' ,
806+ $self -> _getOAEPAlgorithm($mgf ),
807+ $oaep // ' ' ,
808+ );
809+ } else {
810+ $self -> {key_obj }-> decrypt(
811+ $key , ' oaep' ,
812+ $self -> _getOAEPAlgorithm($mgf ),
813+ $oaep // ' ' ,
814+ $digest_name // ' ' ,
815+ );
816+ }
701817 }
702818 );
703819 }
@@ -712,14 +828,29 @@ sub _EncryptKey {
712828
713829 my $rsa_pub = $self -> {cert_obj };
714830
831+ # FIXME: this could use some refactoring and some simplfication
715832 if ($keymethod eq ' http://www.w3.org/2001/04/xmlenc#rsa-1_5' ) {
716833 ${$key} = $rsa_pub -> encrypt(${$key} , ' v1.5' );
717834 }
718835 elsif ($keymethod eq ' http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' ) {
719- ${$key} = $rsa_pub -> encrypt(${$key} , ' oaep' , ' SHA1' , $self -> {oaep_params });
836+ if ($CryptX::VERSION le 0.081) {
837+ ${$key} = $rsa_pub -> encrypt(${$key} , ' oaep' , ' SHA1' , $self -> {oaep_params });
838+ } else {
839+ my $oaep_label_hash = (defined $self -> {oaep_label_hash } && $self -> {oaep_label_hash } ne ' ' ) ?
840+ $self -> _getParamsAlgorithm($self -> {oaep_label_hash }) : ' SHA1' ;
841+ ${$key} = $rsa_pub -> encrypt(${$key} , ' oaep' , ' SHA1' , $self -> {oaep_params }, $oaep_label_hash );
842+ }
720843 }
721844 elsif ($keymethod eq ' http://www.w3.org/2009/xmlenc11#rsa-oaep' ) {
722- ${$key} = $rsa_pub -> encrypt(${$key} , ' oaep' , $self -> _getOAEPAlgorithm($self -> {oaep_mgf_alg }), $self -> {oaep_params });
845+ my $mgf_hash = defined $self -> {oaep_mgf_alg } ?
846+ $self -> _getOAEPAlgorithm($self -> {oaep_mgf_alg }) : undef ;
847+ if ($CryptX::VERSION le 0.081) {
848+ ${$key} = $rsa_pub -> encrypt(${$key} , ' oaep' , $mgf_hash , $self -> {oaep_params });
849+ } else {
850+ my $oaep_label_hash = (defined $self -> {oaep_label_hash } && $self -> {oaep_label_hash } ne ' ' ) ?
851+ $self -> _getParamsAlgorithm($self -> {oaep_label_hash }) : $mgf_hash ;
852+ ${$key} = $rsa_pub -> encrypt(${$key} , ' oaep' , $mgf_hash , $self -> {oaep_params }, $oaep_label_hash );
853+ }
723854 } else {
724855 die " Unsupported algorithm for key encyption $keymethod }" ;
725856 }
@@ -1030,6 +1161,20 @@ sub _create_encrypted_data_xml {
10301161 }
10311162 );
10321163
1164+ if ($self -> {key_transport } eq ' http://www.w3.org/2009/xmlenc11#rsa-oaep' ||
1165+ $self -> {key_transport } eq ' http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' &&
1166+ $self -> {oaep_label_hash }) {
1167+ my $digestmethod = $self -> _create_node(
1168+ $doc ,
1169+ $dsigns ,
1170+ $kencmethod ,
1171+ ' dsig:DigestMethod' ,
1172+ {
1173+ Algorithm => $self -> {oaep_label_hash },
1174+ }
1175+ );
1176+ };
1177+
10331178 if ($self -> {' oaep_params' } ne ' ' ) {
10341179 my $oaep_params = $self -> _create_node(
10351180 $doc ,
@@ -1039,7 +1184,8 @@ sub _create_encrypted_data_xml {
10391184 );
10401185 };
10411186
1042- if ($self -> {key_transport } eq ' http://www.w3.org/2009/xmlenc11#rsa-oaep' ) {
1187+ if ($self -> {key_transport } eq ' http://www.w3.org/2009/xmlenc11#rsa-oaep' &&
1188+ $self -> {oaep_mgf_alg }) {
10431189 my $oaepmethod = $self -> _create_node(
10441190 $doc ,
10451191 $xenc11ns ,
@@ -1058,12 +1204,14 @@ sub _create_encrypted_data_xml {
10581204 ' dsig:KeyInfo' ,
10591205 );
10601206
1061- my $keyname = $self -> _create_node(
1207+ if (defined $self -> {key_name }) {
1208+ my $keyname = $self -> _create_node(
10621209 $doc ,
10631210 $dsigns ,
10641211 $keyinfo2 ,
10651212 ' dsig:KeyName' ,
10661213 );
1214+ };
10671215
10681216 my $keycipherdata = $self -> _create_node(
10691217 $doc ,
0 commit comments