@@ -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,37 @@ 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+
199232=back
200233
201234=cut
@@ -225,8 +258,12 @@ sub new {
225258 my $key_method = exists ($params -> {' key_transport' }) ? $params -> {' key_transport' } : ' rsa-oaep-mgf1p ' ;
226259 $self -> {' key_transport' } = $self -> _setKeyEncryptionMethod($key_method );
227260
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 );
261+ if (exists $params -> {' oaep_mgf_alg' }) {
262+ $self -> {' oaep_mgf_alg' } = $self -> _setOAEPAlgorithm($params -> {' oaep_mgf_alg' });
263+ }
264+ if (exists $params -> {' oaep_label_hash' } ) {
265+ $self -> {' oaep_label_hash' } = $self -> _setOAEPDigest($params -> {' oaep_label_hash' });
266+ }
230267
231268 $self -> {' oaep_params' } = exists ($params -> {' oaep_params' }) ? $params -> {' oaep_params' } : ' ' ;
232269
@@ -576,6 +613,36 @@ sub _getOAEPAlgorithm {
576613 return $OAEPAlgorithm -> {$method } // ' SHA1' ;
577614}
578615
616+ sub _setOAEPDigest {
617+ my $self = shift ;
618+ my $method = shift ;
619+
620+ state $OAEPDigest = {
621+ ' sha1' => ' http://www.w3.org/2000/09/xmldsig#sha1' ,
622+ ' sha224' => ' http://www.w3.org/2001/04/xmldsig-more#sha224' ,
623+ ' sha256' => ' http://www.w3.org/2001/04/xmlenc#sha256' ,
624+ ' sha384' => ' http://www.w3.org/2001/04/xmldsig-more#sha384' ,
625+ ' sha512' => ' http://www.w3.org/2001/04/xmlenc#sha512' ,
626+ };
627+
628+ return $OAEPDigest -> {$method } // $OAEPDigest -> {' sha256' };
629+ }
630+
631+ sub _getParamsAlgorithm {
632+ my $self = shift ;
633+ my $method = shift ;
634+
635+ state $ParamsAlgorithm = {
636+ ' http://www.w3.org/2000/09/xmldsig#sha1' => ' SHA1' ,
637+ ' http://www.w3.org/2001/04/xmldsig-more#sha224' => ' SHA224' ,
638+ ' http://www.w3.org/2001/04/xmlenc#sha256' => ' SHA256' ,
639+ ' http://www.w3.org/2001/04/xmldsig-more#sha384' => ' SHA384' ,
640+ ' http://www.w3.org/2001/04/xmlenc#sha512' => ' SHA512' ,
641+ };
642+
643+ return $ParamsAlgorithm -> {$method } // $ParamsAlgorithm -> {' http://www.w3.org/2000/09/xmldsig#sha1' };
644+ }
645+
579646sub _setKeyEncryptionMethod {
580647 my $self = shift ;
581648 my $method = shift ;
@@ -681,23 +748,45 @@ sub _decrypt_key {
681748 if ($algo eq ' http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' ) {
682749 return _decrypt(
683750 sub {
684- $self -> {key_obj }-> decrypt(
685- $key , ' oaep' ,
686- $digest_name // ' SHA1' ,
687- $oaep // ' '
688- );
751+ if ($CryptX::VERSION le 0.081) {
752+ # print "Caller: _decrypt_key rsa-oaep-mgf1p\n";
753+ $self -> {key_obj }-> decrypt(
754+ $key , ' oaep' ,
755+ # $self->_getOAEPAlgorithm($mgf),
756+ $digest_name // ' SHA1' ,
757+ $oaep // ' ' ,
758+ );
759+ } else {
760+ # print "Caller: _decrypt_key rsa-oaep-mgf1p\n";
761+ # print "digest_name: ", $digest_name, "\n";
762+ $self -> {key_obj }-> decrypt(
763+ $key , ' oaep' ,
764+ $mgf // ' SHA1' ,
765+ $oaep // ' ' ,
766+ $digest_name // ' SHA1' ,
767+ );
768+ }
689769 }
690770 );
691771 }
692772
693773 if ($algo eq ' http://www.w3.org/2009/xmlenc11#rsa-oaep' ) {
694774 return _decrypt(
695775 sub {
696- $self -> {key_obj }-> decrypt(
697- $key , ' oaep' ,
698- $self -> _getOAEPAlgorithm($mgf ),
699- $oaep // ' ' ,
700- );
776+ if ($CryptX::VERSION le 0.081) {
777+ $self -> {key_obj }-> decrypt(
778+ $key , ' oaep' ,
779+ $self -> _getOAEPAlgorithm($mgf ),
780+ $oaep // ' ' ,
781+ );
782+ } else {
783+ $self -> {key_obj }-> decrypt(
784+ $key , ' oaep' ,
785+ $self -> _getOAEPAlgorithm($mgf ),
786+ $oaep // ' ' ,
787+ $digest_name // ' ' ,
788+ );
789+ }
701790 }
702791 );
703792 }
@@ -712,14 +801,29 @@ sub _EncryptKey {
712801
713802 my $rsa_pub = $self -> {cert_obj };
714803
804+ # FIXME: this could use some refactoring and some simplfication
715805 if ($keymethod eq ' http://www.w3.org/2001/04/xmlenc#rsa-1_5' ) {
716806 ${$key} = $rsa_pub -> encrypt(${$key} , ' v1.5' );
717807 }
718808 elsif ($keymethod eq ' http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' ) {
719- ${$key} = $rsa_pub -> encrypt(${$key} , ' oaep' , ' SHA1' , $self -> {oaep_params });
809+ if ($CryptX::VERSION le 0.081) {
810+ ${$key} = $rsa_pub -> encrypt(${$key} , ' oaep' , ' SHA1' , $self -> {oaep_params });
811+ } else {
812+ my $oaep_label_hash = (defined $self -> {oaep_label_hash } && $self -> {oaep_label_hash } ne ' ' ) ?
813+ $self -> _getParamsAlgorithm($self -> {oaep_label_hash }) : ' SHA1' ;
814+ ${$key} = $rsa_pub -> encrypt(${$key} , ' oaep' , ' SHA1' , $self -> {oaep_params }, $oaep_label_hash );
815+ }
720816 }
721817 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 });
818+ my $mgf_hash = defined $self -> {oaep_mgf_alg } ?
819+ $self -> _getOAEPAlgorithm($self -> {oaep_mgf_alg }) : undef ;
820+ if ($CryptX::VERSION le 0.081) {
821+ ${$key} = $rsa_pub -> encrypt(${$key} , ' oaep' , $mgf_hash , $self -> {oaep_params });
822+ } else {
823+ my $oaep_label_hash = (defined $self -> {oaep_label_hash } && $self -> {oaep_label_hash } ne ' ' ) ?
824+ $self -> _getParamsAlgorithm($self -> {oaep_label_hash }) : $mgf_hash ;
825+ ${$key} = $rsa_pub -> encrypt(${$key} , ' oaep' , $mgf_hash , $self -> {oaep_params }, $oaep_label_hash );
826+ }
723827 } else {
724828 die " Unsupported algorithm for key encyption $keymethod }" ;
725829 }
@@ -1030,6 +1134,20 @@ sub _create_encrypted_data_xml {
10301134 }
10311135 );
10321136
1137+ if ($self -> {key_transport } eq ' http://www.w3.org/2009/xmlenc11#rsa-oaep' ||
1138+ $self -> {key_transport } eq ' http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' &&
1139+ $self -> {oaep_label_hash }) {
1140+ my $digestmethod = $self -> _create_node(
1141+ $doc ,
1142+ $dsigns ,
1143+ $kencmethod ,
1144+ ' dsig:DigestMethod' ,
1145+ {
1146+ Algorithm => $self -> {oaep_label_hash },
1147+ }
1148+ );
1149+ };
1150+
10331151 if ($self -> {' oaep_params' } ne ' ' ) {
10341152 my $oaep_params = $self -> _create_node(
10351153 $doc ,
@@ -1039,7 +1157,8 @@ sub _create_encrypted_data_xml {
10391157 );
10401158 };
10411159
1042- if ($self -> {key_transport } eq ' http://www.w3.org/2009/xmlenc11#rsa-oaep' ) {
1160+ if ($self -> {key_transport } eq ' http://www.w3.org/2009/xmlenc11#rsa-oaep' &&
1161+ $self -> {oaep_mgf_alg }) {
10431162 my $oaepmethod = $self -> _create_node(
10441163 $doc ,
10451164 $xenc11ns ,
0 commit comments