Created
September 17, 2010 21:15
-
-
Save chrisa/584970 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff -urN XML-Sig-0.22/lib/XML/Sig.pm XML-Sig-0.22+fixes/lib/XML/Sig.pm | |
| --- XML-Sig-0.22/lib/XML/Sig.pm 2009-12-08 17:57:08.000000000 +0000 | |
| +++ XML-Sig-0.22+fixes/lib/XML/Sig.pm 2010-09-17 20:42:45.000000000 +0100 | |
| @@ -105,27 +105,32 @@ | |
| my ($xml) = @_; | |
| $self->{ parser } = XML::XPath->new( xml => $xml ); | |
| + $self->{parser}->set_namespace('ds', 'http://www.w3.org/2000/09/xmldsig#'); | |
| + | |
| + my $signature = _trim($self->{parser}->findvalue('//ds:Signature/ds:SignatureValue')); | |
| + my $signed_info = $self->_get_node_as_text('//ds:Signature/ds:SignedInfo'); | |
| + | |
| + # reapply the namespace decl, or XML::CanonicalizeXML will remove all the namespace prefixes | |
| + $signed_info =~ s!<ds:SignedInfo!<ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"!; | |
| - my $signature = _trim($self->{parser}->findvalue('//Signature/SignatureValue')); | |
| - my $signed_info = $self->_get_node_as_text('//Signature/SignedInfo'); | |
| my $signed_info_canon = $self->_canonicalize_xml( $signed_info ); | |
| my $keyinfo_node; | |
| - if ($keyinfo_node = $self->{parser}->find('//Signature/KeyInfo/X509Data')) { | |
| + if ($keyinfo_node = $self->{parser}->find('//ds:Signature/ds:KeyInfo/ds:X509Data')) { | |
| return 0 unless $self->_verify_x509($keyinfo_node,$signed_info_canon,$signature); | |
| } | |
| - elsif ($keyinfo_node = $self->{parser}->find('//Signature/KeyInfo/KeyValue/RSAKeyValue')) { | |
| + elsif ($keyinfo_node = $self->{parser}->find('//ds:Signature/ds:KeyInfo/ds:KeyValue/ds:RSAKeyValue')) { | |
| return 0 unless $self->_verify_rsa($keyinfo_node,$signed_info_canon,$signature); | |
| } | |
| - elsif ($keyinfo_node = $self->{parser}->find('//Signature/KeyInfo/KeyValue/DSAKeyValue')) { | |
| + elsif ($keyinfo_node = $self->{parser}->find('//ds:Signature/ds:KeyInfo/ds:KeyValue/ds:DSAKeyValue')) { | |
| return 0 unless $self->_verify_dsa($keyinfo_node,$signed_info_canon,$signature); | |
| } | |
| else { | |
| die "Unrecognized key type in signature."; | |
| } | |
| - my $digest_method = $self->{parser}->findvalue('//Signature/SignedInfo/Reference/DigestMethod/@Algorithm'); | |
| - my $digest = _trim($self->{parser}->findvalue('//Signature/SignedInfo/Reference/DigestValue')); | |
| + my $digest_method = $self->{parser}->findvalue('//ds:Signature/ds:SignedInfo/ds:Reference/ds:DigestMethod/@Algorithm'); | |
| + my $digest = _trim($self->{parser}->findvalue('//ds:Signature/ds:SignedInfo/ds:Reference/ds:DigestValue')); | |
| my $signed_xml = $self->_get_signed_xml(); | |
| my $canonical = $self->_transform( $signed_xml ); | |
| @@ -146,7 +151,7 @@ | |
| sub _get_signed_xml { | |
| my $self = shift; | |
| - my $id = $self->{parser}->findvalue('//Signature/SignedInfo/Reference/@URI'); | |
| + my $id = $self->{parser}->findvalue('//ds:Signature/ds:SignedInfo/ds:Reference/@URI'); | |
| $id =~ s/^#//; | |
| $self->{'sign_id'} = $id; | |
| my $xpath = "//*[\@ID='$id']"; | |
| @@ -156,11 +161,11 @@ | |
| sub _transform { | |
| my $self = shift; | |
| my ($xml) = @_; | |
| - foreach my $node ($self->{parser}->find('//Transform/@Algorithm')->get_nodelist) { | |
| + foreach my $node ($self->{parser}->find('//ds:Transform/@Algorithm')->get_nodelist) { | |
| my $alg = $node->getNodeValue; | |
| if ($alg eq TRANSFORM_ENV_SIG) { $xml = $self->_transform_env_sig($xml); } | |
| - elsif ($alg eq TRANSFORM_EXC_C14N) { $xml = $self->_canonicalize($xml,0); } | |
| - elsif ($alg eq TRANSFORM_EXC_C14N_COMMENTS) { $xml = $self->canonicalize($xml,1); } | |
| + elsif ($alg eq TRANSFORM_EXC_C14N) { $xml = $self->_canonicalize_xml($xml,0); } | |
| + elsif ($alg eq TRANSFORM_EXC_C14N_COMMENTS) { $xml = $self->canonicalize_xml($xml,1); } | |
| else { die "Unsupported transform: $alg"; } | |
| } | |
| return $xml; | |
| @@ -171,9 +176,9 @@ | |
| my ($context,$canonical,$sig) = @_; | |
| # Generate Public Key from XML | |
| - my $mod = _trim($self->{parser}->findvalue('//Signature/KeyInfo/KeyValue/RSAKeyValue/Modulus')); | |
| + my $mod = _trim($self->{parser}->findvalue('//ds:Signature/ds:KeyInfo/ds:KeyValue/ds:RSAKeyValue/ds:Modulus')); | |
| my $modBin = decode_base64( $mod ); | |
| - my $exp = _trim($self->{parser}->findvalue('//Signature/KeyInfo/KeyValue/RSAKeyValue/Exponent')); | |
| + my $exp = _trim($self->{parser}->findvalue('//ds:Signature/ds:KeyInfo/ds:KeyValue/ds:RSAKeyValue/ds:Exponent')); | |
| my $expBin = decode_base64( $exp ); | |
| my $n = Crypt::OpenSSL::Bignum->new_from_bin($modBin); | |
| my $e = Crypt::OpenSSL::Bignum->new_from_bin($expBin); | |
| @@ -188,11 +193,7 @@ | |
| sub _clean_x509 { | |
| my $self = shift; | |
| my ($cert) = @_; | |
| - $cert =~ s/\n//g; | |
| -# my $n = 64; # $n is group size. | |
| -# my @parts = unpack "a$n" x ((length($cert)/$n)-0) . "a*", $cert; | |
| -# $cert = join("\n",@parts); | |
| - $cert = "-----BEGIN PUBLIC KEY-----\n" . $cert . "\n-----END PUBLIC KEY-----\n"; | |
| + $cert = "-----BEGIN CERTIFICATE-----\n" . $cert . "\n-----END CERTIFICATE-----\n"; | |
| return $cert; | |
| } | |
| @@ -206,11 +207,13 @@ | |
| }; | |
| # Generate Public Key from XML | |
| - my $certificate = _trim($self->{parser}->findvalue('//Signature/KeyInfo/X509Data/X509Certificate')); | |
| + my $certificate = _trim($self->{parser}->findvalue('//ds:Signature/ds:KeyInfo/ds:X509Data/ds:X509Certificate')); | |
| + | |
| # This is added because the X509 parser requires it for self-identification | |
| $certificate = $self->_clean_x509($certificate); | |
| - my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($certificate); | |
| + my $cert = Crypt::OpenSSL::X509->new_from_string($certificate); | |
| + my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($cert->pubkey); | |
| # Decode signature and verify | |
| my $bin_signature = decode_base64($sig); | |
| @@ -257,13 +260,29 @@ | |
| sub _get_node_as_text { | |
| my $self = shift; | |
| - return XML::XPath::XMLParser::as_string( $self->_get_node(@_) ); | |
| + my ($xpath) = @_; | |
| + | |
| + | |
| + my $results = $self->{parser}->find($xpath); | |
| + | |
| + if ($results->isa('XML::XPath::NodeSet')) { | |
| + return join('', map { $_->toString } $results->get_nodelist); | |
| + } | |
| + elsif ($results->isa('XML::XPath::Node')) { | |
| + return $results->toString; | |
| + } | |
| + else { | |
| + return XML::XPath::Node::XMLescape($results->value); | |
| + } | |
| + | |
| + #return XML::XPath::XMLParser::as_string( $node ); | |
| + #return $self->{parser}->findnodes_as_string($xpath); | |
| } | |
| sub _transform_env_sig { | |
| my $self = shift; | |
| my ($str) = @_; | |
| - $str =~ s/(<Signature(.*?)>(.*?)\<\/Signature>)//igs; | |
| + $str =~ s/(<ds:Signature(.*?)>(.*?)\<\/ds:Signature>)//igs; | |
| return $str; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment