in reply to Re^3: Validating XML Signatures / SSL Certificate question (using Net::SAML)
in thread Validating XML Signatures / SSL Certificate question (using Net::SAML)

Thanks again Hippo!

I've gone right down to basics now and made my own script without XML::Sig but nabbed some bits from it, which is working absolutely fine. This will encrypt a string with the public key and decrypt it with the private. Also sign it with the private and verify it with the public. Im using my own keys and so far so good and getting me understanding what's going on.

One thing has amazed me however - this line - my $cert = Crypt::OpenSSL::X509->new_from_string($certificate);- I can access the public key from the certificate after this line by using $cert->pubkey. It's different to my own public key however... but still works! How and why I have no idea.. wondering if this might be a clue as to what's going wrong with the SAML.. Can there be multiple public keys??! I may try getting the public key directly from the SAML provider tomorrow, also checking what hashing they are using. Another thread I saw suggested a possible platform difference regarding big and little endian data..

Cheers :)

#!/usr/bin/perl use Crypt::OpenSSL::Random; use Crypt::OpenSSL::RSA; use Crypt::OpenSSL::X509; use MIME::Base64; use strict; my $debug = 0; local $/ = undef; my $public_key= "/data/pubkey.pem"; open (FILE, $public_key) or die ("Cant open public key file"); my $public_key_string = <FILE>; close(FILE); my $private_key = "/data/private.pem"; open (FILE, $private_key) or die ("Cant open private key file"); my $private_key_string = <FILE>; close(FILE); my $public_cert = "/data/x509-public.pem"; open (FILE, $public_cert) or die ("Cant open certificate file"); my $certificate = <FILE>; close(FILE); print $certificate; my $cert = Crypt::OpenSSL::X509->new_from_string($certificate); print $cert->pubkey; print $public_key_string; # they're different $public_key_string=$cert->pubkey; # it's different to the one loaded f +rom file, but still works with my existing private key in the rest of + the code - remove this line to test the old $public_key_string value print $public_key_string; my $plaintext = "Some text here"; my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($public_key_string) +; my $rsa_priv = Crypt::OpenSSL::RSA->new_private_key($private_key_strin +g); my $ciphertext = $rsa_pub->encrypt($plaintext); # encrypt with th +e public key my $plaintext_back = $rsa_priv->decrypt($ciphertext); # decrypt with +the private key print "Plain text back is " . $plaintext_back . "\n"; # Works fine if ($debug){ # debugging only print "private key is:\n", $rsa_priv->get_private_key_string() +; print "public key (in PKCS1 format) is:\n", $rsa_pub->get_public_key_string(); print "public key (in X509 format) is:\n", $rsa_pub->get_public_key_x509_string(); } $rsa_priv->use_md5_hash(); # use_sha1_hash is the default $rsa_pub->use_md5_hash(); my $signature = $rsa_priv->sign($plaintext); # sign with private key if ($rsa_pub->verify($plaintext, $signature)) { # verify with public k +ey print "Signature Verified successfully"; } else { print " *** Not verified"; }

Replies are listed 'Best First'.
Re^5: Validating XML Signatures / SSL Certificate question (using Net::SAML)
by hippo (Archbishop) on Apr 06, 2017 at 08:55 UTC
    It's different to my own public key however

    Is it a different public key or merely a different representation of the same public key? How did you generate the contents of /data/pubkey.pem in the first place?

    Good to hear you are making solid progress regardless. My experience of working with SAML has taught me that it is essentially a war of attrition. If you persist you will eventually succeed (although you will curse both the spec designers and the platform implementers before you are through).

      Hi Hippo,

      This is still going on! Currently there seems to be a difference between what is being signed by the NSL team and what the code is expecting - the Net::SAML modules were expecting the assertion node to be signed, we are receiving a signed full XML document.

      With amended XML (a signed assertion node) we got through the part where XML::Sig was failing -  if ($rsa_pub->verify( $canonical,  $bin_signature )) { - I'm not sure if this is verifying the signature or just the certificate somehow, it's good that it passes now but there are however several steps after this where it fails. It proceeds to perform transforms on the XML before running  if ($digest eq _trim(encode_base64($digest_bin))); - we're now failing at this point with two completely different strings.

      Which one of these tests actually verifies the signature I'm not sure, nor why there are these two tests, I don't suppose you have any idea?

      Either way, getting there (very, very slowly)

      Cheers,
      Matt

        Which one of these tests actually verifies the signature I'm not sure, nor why there are these two tests, I don't suppose you have any idea?

        The former test verifies that the signature is a valid signature of the dataset by the equivalent private key, so this is the attribution part of the verification if you like. However, since what has actually been signed isn't normally the full SAML request but rather a digest of it you then need the latter test to confirm that the digest is in fact valid for the full SAML request too.

        If the signature test fails, then either the digest has been monkeyed with or the wrong (impostor?) key has been used. If the signature test passes but the digest fails then someone has amended the XML payload after the signature has been made (or copied a valid signature from some other frame, etc.). Only if both tests pass can you be sure that the entire SAML message is valid.

        Don't forget to check the timestamps too if you are rolling it yourself.