Skip to content

Instantly share code, notes, and snippets.

@zmousm
Forked from aduitsis/gist:5101097
Last active December 14, 2015 15:38
Show Gist options
  • Save zmousm/5108930 to your computer and use it in GitHub Desktop.
Save zmousm/5108930 to your computer and use it in GitHub Desktop.
#!/usr/bin/perl -w
use strict;
use warnings;
use Carp;
use MIME::Base64;
use Compress::Zlib;
use URI;
use URI::QueryParam;
use XML::Canonical;
use URI::Escape;
use Crypt::OpenSSL::X509;
use Crypt::OpenSSL::RSA;
print STDERR "Please paste a SAMLRequest URL, then press enter, then press Ctrl-D\n";
my $slurp = do { local $/; <STDIN> };
my $u = URI->new($slurp, 'http');
for my $key ($u->query_param) {
print "$key: ", join(", ", $u->query_param($key)), "\n";
}
#SAMLRequest:
#RelayState:
#SigAlg: http://www.w3.org/2000/09/xmldsig#rsa-sha1
#Signature:
#
###print decode_base64($slurp);
if( defined $u->query_param('SAMLRequest') ) {
my ( $i, $status ) = inflateInit( -windowBits => -&MAX_WBITS );
if ( $status == Z_OK && $i ) {
my $buffer;
$$buffer = decode_base64($u->query_param('SAMLRequest'));
#print $$buffer;
#exit;
my ( $uncompressed, $status ) = $i->inflate( $buffer );
if ( ($status != Z_OK) && ($status != Z_STREAM_END) ) {
croak $i->gzerror() ;
}
my $canon = XML::Canonical->new(comments => 1);
print "\n\n";
print $canon->canonicalize_string($uncompressed);
print $uncompressed;
print "\n\n";
if (!defined $u->query_param('SigAlg') ||
$u->query_param('SigAlg') ne "http://www.w3.org/2000/09/xmldsig#rsa-sha1") {
croak 'Need RSA SHA1';
}
if (!defined $u->query_param('Signature')) {
croak 'No signature';
}
open my $handl, "<", $ARGV[0] or die "Failed to read $ARGV[0]";
my $certext = '';
{
local $/;
$certext = <$handl>;
}
close $handl or die "Failed to close $ARGV[0]";
my $cert = Crypt::OpenSSL::X509->new_from_string($certext, Crypt::OpenSSL::X509::FORMAT_PEM)
or die "Could not read certificate";
my $certpk = $cert->pubkey();
my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($certpk);
my $sigQue = '';
my %par;
for my $param (split('&', $u->query)) {
my ($key, $val) = split('=', $param);
$par{uri_unescape($key)} = uri_unescape($val);
if (grep { $_ eq $key } ('SAMLRequest', 'RelayState', 'SigAlg')) {
if ($sigQue ne '') { $sigQue .= '&' };
$sigQue .= $key . '=' . $val;
}
}
print "Verified signature? ";
print do {
$rsa_pub->verify($sigQue,
decode_base64($par{'Signature'})) ?
"YES" : "NO"
} . "\n";
}
else {
print STDERR 'SAMLRequest is missing from this URL';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment