Subject: | SHA256 Digest not supported |
Date: | Tue, 13 Feb 2018 16:08:45 +0200 |
To: | bug-Net-SAML2 [...] rt.cpan.org |
From: | Noam Rathaus <noamr [...] beyondsecurity.com> |
Hi,
The SHA256 digest is not supported, the following code adds it:
--- Sig.pm-original 2012-01-13 16:00:44.000000000 +0000
+++ Sig.pm-patched 2018-02-13 14:04:07.848241300 +0000
@@ -17,7 +17,7 @@
use strict;
-use Digest::SHA1 qw(sha1 sha1_base64);
+use Digest::SHA qw(sha1 sha256);
use XML::XPath;
use MIME::Base64;
use Carp;
@@ -132,19 +132,22 @@
if (scalar @{ $signed_info_node->getNamespaces } == 0) {
$signed_info_node->appendNamespace($ns);
}
-
+
+ my $signatureMethod =
$self->{parser}->find('//dsig:Signature/dsig:SignedInfo/dsig:SignatureMethod/@Algorithm');
+ if ($signatureMethod =~ /#(.*)/) { # Capture everything after the #
+ $signatureMethod = $1;
+ }
+
my $signed_info = XML::XPath::XMLParser::as_string($signed_info_node);
my $signed_info_canon = $self->_canonicalize_xml( $signed_info );
if (defined $self->{cert_obj}) {
- # use the provided cert to verify
return 0 unless
$self->_verify_x509_cert($self->{cert_obj},$signed_info_canon,$signature);
}
else {
- # extract the certficate or key from the document
my $keyinfo_node;
if ($keyinfo_node =
$self->{parser}->find('//dsig:Signature/dsig:KeyInfo/dsig:X509Data')) {
- return 0 unless
$self->_verify_x509($keyinfo_node,$signed_info_canon,$signature);
+ return 0 unless
$self->_verify_x509($keyinfo_node,$signed_info_canon,$signature,$signatureMethod);
}
elsif ($keyinfo_node =
$self->{parser}->find('//dsig:Signature/dsig:KeyInfo/dsig:KeyValue/dsig:RSAKeyValue'))
{
return 0 unless
$self->_verify_rsa($keyinfo_node,$signed_info_canon,$signature);
@@ -158,11 +161,20 @@
}
my $digest_method =
$self->{parser}->findvalue('//dsig:Signature/dsig:SignedInfo/dsig:Reference/dsig:DigestMethod/@Algorithm');
+ if ($digest_method =~ /#(.*)/) {
+ $digest_method = $1;
+ }
+
my $digest =
_trim($self->{parser}->findvalue('//dsig:Signature/dsig:SignedInfo/dsig:Reference/dsig:DigestValue'));
my $signed_xml = $self->_get_signed_xml();
my $canonical = $self->_transform($signed_xml, $signature_node);
- my $digest_bin = sha1($canonical);
+ my $digest_bin = '';
+ if ($digest_method eq 'sha256') {
+ $digest_bin = sha256($canonical);
+ } else {
+ $digest_bin = sha1($canonical);
+ }
return 1 if ($digest eq _trim(encode_base64($digest_bin)));
return 0;
@@ -269,7 +281,7 @@
sub _verify_x509 {
my $self = shift;
- my ($context,$canonical,$sig) = @_;
+ my ($context,$canonical,$sig,$signatureMethod) = @_;
eval {
require Crypt::OpenSSL::X509;
@@ -283,12 +295,12 @@
$certificate = $self->_clean_x509($certificate);
my $cert = Crypt::OpenSSL::X509->new_from_string($certificate);
- return $self->_verify_x509_cert($cert, $canonical, $sig);
+ return $self->_verify_x509_cert($cert, $canonical, $sig,
$signatureMethod);
}
sub _verify_x509_cert {
my $self = shift;
- my ($cert, $canonical, $sig) = @_;
+ my ($cert, $canonical, $sig, $signatureMethod) = @_;
eval {
require Crypt::OpenSSL::RSA;
@@ -299,6 +311,9 @@
my $bin_signature = decode_base64($sig);
# If successful verify, store the signer's cert for validation
+ if ($signatureMethod eq 'rsa-sha256') {
+ $rsa_pub->use_sha256_hash();
+ }
if ($rsa_pub->verify( $canonical, $bin_signature )) {
$self->{signer_cert} = $cert;
return 1;
--
Thanks,
Noam Rathaus
Beyond Security
PGP Key ID: 2D24B275B1EB4475 (Exp 2018-03)