Skip to content

Allow recieving sha256 sigs and make IdP SLO/Art urls optional #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/Net/SAML2/Binding/POST.pm
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ sub handle_response {

# unpack and check the signature
my $xml = decode_base64($response);
my $x = Net::SAML2::XML::Sig->new({ x509 => 1 });
my $x = Net::SAML2::XML::Sig->new({ x509 => 1, cert => $self->cacert });
my $ret = $x->verify($xml);
die "signature check failed" unless $ret;

Expand Down
13 changes: 8 additions & 5 deletions lib/Net/SAML2/Binding/Redirect.pm
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,16 @@ sub verify {
my $u = URI->new($url);

# verify the response
my $sigalg = $u->query_param('SigAlg');
die "can't verify '$sigalg' signatures"
unless $sigalg eq 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';

my $cert = Crypt::OpenSSL::X509->new_from_string($self->cert);
my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($cert->pubkey);


my $sigalg = $u->query_param('SigAlg');
if ($sigalg eq 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256') {
$rsa_pub->use_sha256_hash();
} else {
die "can't verify '$sigalg' signatures"
unless $sigalg eq 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
}
my $sig = decode_base64($u->query_param_delete('Signature'));
my $signed = $u->query;
die "bad sig" unless $rsa_pub->verify($signed, $sig);
Expand Down
8 changes: 4 additions & 4 deletions lib/Net/SAML2/IdP.pm
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ Constructor
has 'entityid' => (isa => Str, is => 'ro', required => 1);
has 'cacert' => (isa => Str, is => 'ro', required => 1);
has 'sso_urls' => (isa => HashRef[Str], is => 'ro', required => 1);
has 'slo_urls' => (isa => HashRef[Str], is => 'ro', required => 1);
has 'art_urls' => (isa => HashRef[Str], is => 'ro', required => 1);
has 'slo_urls' => (isa => HashRef[Str], is => 'ro');
has 'art_urls' => (isa => HashRef[Str], is => 'ro');
has 'certs' => (isa => HashRef[Str], is => 'ro', required => 1);
has 'formats' => (isa => HashRef[Str], is => 'ro', required => 1);
has 'default_format' => (isa => Str, is => 'ro', required => 1);
Expand Down Expand Up @@ -123,8 +123,8 @@ sub new_from_xml {
my $self = $class->new(
entityid => $xpath->findvalue('//md:EntityDescriptor/@entityID')->value,
sso_urls => $data->{SSO},
slo_urls => $data->{SLO},
art_urls => $data->{Art},
(defined $data->{SLO} ? (slo_urls => $data->{SLO}) : () ),
(defined $data->{Art} ? (art_urls => $data->{Art}) : () ),
certs => $data->{Cert},
formats => $data->{NameIDFormat},
default_format => $data->{DefaultFormat},
Expand Down
2 changes: 1 addition & 1 deletion lib/Net/SAML2/Role/ProtocolMessage.pm
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ around 'BUILDARGS' => sub {
my %args = @_;

# random ID for this message
$args{id} ||= unpack 'H*', Crypt::OpenSSL::Random::random_pseudo_bytes(16);
$args{id} ||='_' . unpack 'H*', Crypt::OpenSSL::Random::random_pseudo_bytes(16);

# IssueInstant in UTC
my $dt = DateTime->now( time_zone => 'UTC' );
Expand Down
35 changes: 23 additions & 12 deletions lib/Net/SAML2/XML/Sig.pm
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use base qw/Exporter/;

use strict;

use Digest::SHA1 qw(sha1 sha1_base64);
use Digest::SHA qw(sha1 sha256);
use XML::XPath;
use MIME::Base64;
use Carp;
Expand Down Expand Up @@ -136,9 +136,24 @@ sub verify {
my $signed_info = XML::XPath::XMLParser::as_string($signed_info_node);
my $signed_info_canon = $self->_canonicalize_xml( $signed_info );

my $sigalg = $self->{parser}->findvalue('//dsig:Signature/dsig:SignedInfo/dsig:SignatureMethod/@Algorithm');
my $digest_method = $self->{parser}->findvalue('//dsig:Signature/dsig:SignedInfo/dsig:Reference/dsig:DigestMethod/@Algorithm');
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;
if ($digest_method eq 'http://www.w3.org/2000/09/xmldsig#sha1') {
$digest_bin = sha1($canonical);
} elsif ($digest_method eq 'http://www.w3.org/2001/04/xmlenc#sha256') {
$digest_bin = sha256($canonical);
}

return 0 unless ($digest eq _trim(encode_base64($digest_bin)));

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);
return 0 unless $self->_verify_x509_cert($self->{cert_obj},$signed_info_canon,$signature,$sigalg);
}
else {
# extract the certficate or key from the document
Expand All @@ -157,15 +172,7 @@ sub verify {
}
}

my $digest_method = $self->{parser}->findvalue('//dsig:Signature/dsig:SignedInfo/dsig:Reference/dsig:DigestMethod/@Algorithm');
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);

return 1 if ($digest eq _trim(encode_base64($digest_bin)));
return 0;
return 1;
}

sub signer_cert {
Expand Down Expand Up @@ -288,13 +295,17 @@ sub _verify_x509 {

sub _verify_x509_cert {
my $self = shift;
my ($cert, $canonical, $sig) = @_;
my ($cert, $canonical, $sig, $sigalg) = @_;

eval {
require Crypt::OpenSSL::RSA;
};
my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($cert->pubkey);

if ($sigalg eq 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256') {
$rsa_pub->use_sha256_hash();
}

# Decode signature and verify
my $bin_signature = decode_base64($sig);

Expand Down