Skip to content

Instantly share code, notes, and snippets.

@chrisa
Created September 17, 2010 21:15
Show Gist options
  • Select an option

  • Save chrisa/584970 to your computer and use it in GitHub Desktop.

Select an option

Save chrisa/584970 to your computer and use it in GitHub Desktop.
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