I am a newbie to SSL certificate thing. so a little cautious about what I've done so far. I am creating an application that uses SSO to authenticate the users using PHP 5.4. What I have: a certificate (.pfx) provided by the party. encrypted SAML in POST variable.
The de-crypted xml is almost similar to SAML: Why is the certificate within the Signature?
I need to verify that the response is from verified provider.. I have come to know while googling around that I need .pem instead of .pfx, So I have converted the .pfx file to .pem using ssl commands. I've used the code from http://www.php.net/manual/es/function.openssl-verify.php#62526. Here is my code.
$encxml=$_POST['SAMLResponse'];
$xml = new SimpleXMLElement(base64_decode($encxml));
$signature = ((string)$xml->Signature->SignatureValue);
var_dump($signature);
//do I need to do something with this X509Certificate value embedded in xml??
$cert = ((string)$xml->Signature->KeyInfo->X509Data->X509Certificate);
var_dump($cert);
//Or I need
$fp = fopen("xyz.pem", "r");
$priv_key = fread($fp, 8192);
fclose($fp);
print_r($priv_key);
$ok = openssl_verify($xml, $signature, $priv_key);
So should I ignore the X509Certificate embedded in xml or I need to check it as well... will openssl_verify suffice? and am I on the right path? please any guidance will be appreciated.
In order to validate the signature, the X. 509 public certificate of the Identity Provider is required Check signature inside the assertion: Select assertion option if the signature will be present inside the SAML assertion itself. Base64. SAML protocol uses the base64 encoding algorithm when exchanging SAML messages.
A SAML (Security Assertions Markup Language) authentication assertion is issued as proof of an authentication event. Typically an end-user will authenticate to an intermediary, who generates a SAML authentication assertion to prove that it has authenticated the user.
From Setup, enter Single Sign-On Settings in the Quick Find box, select Single Sign-On Settings, then click SAML Assertion Validator. Enter the SAML assertion into the text box, and click Validate. Note If your org has multiple SAML SSO configurations, the validator tries to detect the right one.
An XML signed using xmldsig syntax has 3 important parts:
Signature -> KeyInfo
contains information about the public key derived from the private key used to sign the dataSignature -> SignedInfo
contains the data which is gonna be signed using the private key mentioned above; the data contains information about how the verification should be computed, such as: CanonicalizationMethod
, SignatureMethod
, Reference
Signature -> SignatureValue
contains the value of the signature generated by signing Signature -> SignedInfo
with the private keyTheoretically this is how the code should look for an rsa-sha1 algorithm(specified by Signature -> SignedInfo -> SignatureMethod
), having the following canonicalization method: Exclusive XML Canonicalization 1.0 (omits comments), and the x509 certificate provided:
$xmlDoc = new DOMDocument();
$xmlDoc->loadXML($xmlString);
$xpath = new DOMXPath($xmlDoc);
$xpath->registerNamespace('secdsig', 'http://www.w3.org/2000/09/xmldsig#');
// fetch Signature node from XML
$query = ".//secdsig:Signature";
$nodeset = $xpath->query($query, $xmlDoc);
$signatureNode = $nodeset->item(0);
// fetch SignedInfo node from XML
$query = "./secdsig:SignedInfo";
$nodeset = $xpath->query($query, $signatureNode);
$signedInfoNode = $nodeset->item(0);
// canonicalize SignedInfo using the method descried in
// ./secdsig:SignedInfo/secdsig:CanonicalizationMethod/@Algorithm
$signedInfoNodeCanonicalized = $signedInfoNode->C14N(true, false);
// fetch the x509 certificate from XML
$query = 'string(./secdsig:KeyInfo/secdsig:X509Data/secdsig:X509Certificate)';
$x509cert = $xpath->evaluate($query, $signatureNode);
// we have to re-wrap the certificate from XML to respect the PEM standard
$x509cert = "-----BEGIN CERTIFICATE-----\n"
. $x509cert . "\n"
. "-----END CERTIFICATE-----";
// fetch public key from x509 certificate
$publicKey = openssl_get_publickey($x509cert);
// fetch the signature from XML
$query = 'string(./secdsig:SignatureValue)';
$signature = base64_decode($xpath->evaluate($query, $signatureNode));
// verify the signature
$ok = openssl_verify($signedInfoNodeCanonicalized, $signature, $publicKey);
This lib does a good job at implementing xmldsig in php: xmlseclibs; an example of how to verify an xmldsig can be found here: https://github.com/robrichards/xmlseclibs/blob/master/tests/xmlsec-verify.phpt. This library also validates the digest value from Signature -> SignedInfo -> Reference
, a step which I omitted above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With