validar openssl_sign openssl_algo_sha1 online generar firmar firma fiel electronica con php ssl ssl-certificate saml

openssl_sign - Verificar firma digital en respuesta SAML contra certificado en PHP



sign php (2)

Le sugiero que utilice https://github.com/lightSAML/lightSAML . Está utilizando xmlseclibs e implementa el perfil completo de SAML SSO SP. La recepción simple de la respuesta SAML del HTTP POST y la verificación de sus muestras de firma se encuentran en el libro de recetas LightSAML http://www.lightsaml.com/LightSAML-Core/Cookbook/How-to-receive-SAML-message/ y http://www.lightsaml.com/LightSAML-Core/Cookbook/How-to-verify-signature-of-SAML-message/ y el código completo se vería así

$request = /Symfony/Component/HttpFoundation/Request::createFromGlobals(); $bindingFactory = new /LightSaml/Binding/BindingFactory(); $binding = $bindingFactory->getBindingByRequest($request); $messageContext = new /LightSaml/Context/Profile/MessageContext(); /** @var /LightSaml/Model/Protocol/Response $response */ $response = $binding->receive($request, $messageContext); $key = /LightSaml/Credential/KeyHelper::createPublicKey( /LightSaml/Credential/X509Certificate::fromFile(__DIR__.''/../web/sp/saml.crt'') ); /** @var /LightSaml/Model/XmlDSig/SignatureXmlReader $signatureReader */ $signatureReader = $authnRequest->getSignature(); try { $ok = $signatureReader->validate($key); if ($ok) { print "Signaure OK/n"; } else { print "Signature not validated"; } } catch (/Exception $ex) { print "Signature validation failed/n"; }

El manejo de la Respuesta por la acción específica del perfil de SSO de SAML es un poco más que eso; para esos detalles, puede consultar la muestra en https://github.com/lightSAML/lightSAML/blob/master/web/sp/acs.php o si estás usando Symfony https://github.com/lightSAML/SpBundle

Soy un novato para el certificado SSL. Así que un poco cauteloso sobre lo que he hecho hasta ahora. Estoy creando una aplicación que usa SSO para autenticar a los usuarios que usan PHP 5.4. Lo que tengo: un certificado (.pfx) proporcionado por la parte. SAML encriptado en la variable POST.

El xml descifrado es casi similar a SAML: ¿Por qué el certificado está dentro de la firma?

Necesito verificar que la respuesta sea del proveedor verificado. Llegué a saber mientras buscaba en Google que necesito .pem en lugar de .pfx, así que he convertido el archivo .pfx a .pem usando los comandos ssl. He usado el código de http://www.php.net/manual/es/function.openssl-verify.php#62526 . Aquí está mi código.

$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);

Entonces, ¿debería ignorar el certificado X509 incrustado en xml o debo verificarlo también ... será suficiente openssl_verify? y estoy en el camino correcto? Por favor, cualquier orientación será apreciada.


Un XML firmado con la sintaxis xmldsig tiene 3 partes importantes:

  1. Signature -> KeyInfo contiene información sobre la clave pública derivada de la clave privada utilizada para firmar los datos
  2. Signature -> SignedInfo contiene los datos que se firmarán con la clave privada mencionada anteriormente; los datos contienen información sobre cómo se debe calcular la verificación, como: CanonicalizationMethod , CanonicalizationMethod SignatureMethod , Reference
  3. Signature -> SignatureValue contiene el valor de la firma generada al firmar Signature -> SignedInfo con la clave privada

Teóricamente, así es como el código debe buscar un algoritmo rsa-sha1 (especificado por Signature -> SignedInfo -> SignatureMethod ), con el siguiente método de canonicalización: XML Canonicalization 1.0 exclusivo (omite los comentarios) y el certificado x509 proporcionado:

$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);

Esta biblioteca hace un buen trabajo implementando xmldsig en php: xmlseclibs ; un ejemplo de cómo verificar un xmldsig se puede encontrar aquí: https://github.com/robrichards/xmlseclibs/blob/master/tests/xmlsec-verify.phpt . Esta biblioteca también valida el valor de resumen de Signature -> SignedInfo -> Reference , un paso que omití anteriormente.