根据 PHP 中的证书验证 SAML 响应中的数字签名


Verify digital signature in SAML response against certificate in PHP

我是SSL证书的新手。 所以对我到目前为止所做的事情有点谨慎。我正在创建一个使用 SSO 对使用 PHP 5.4 的用户进行身份验证的应用程序。我有什么: 当事人提供的证书 (.pfx)。 在 POST 变量中加密 SAML。

解密的 xml 几乎类似于 SAML:为什么证书在签名中?

我需要验证响应是否来自经过验证的提供商。我在谷歌搜索时了解到我需要 .pem 而不是 .pfx,所以我使用 ssl 命令将 .pfx 文件转换为 .pem。我使用了 http://www.php.net/manual/es/function.openssl-verify.php#62526 的代码。这是我的代码。

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

所以我应该忽略嵌入在 xml 中的 X509 证书,还是也需要检查它......openssl_verify够吗?我走在正确的道路上吗?请提供任何指导,我们将不胜感激。

使用 xmldsig 语法签名的 XML 有 3 个重要部分:

  1. Signature -> KeyInfo包含有关从用于对数据进行签名的私钥派生的公钥的信息
  2. Signature -> SignedInfo包含将使用上述私钥签名的数据;数据包含有关如何计算验证的信息,例如:CanonicalizationMethodSignatureMethodReference
  3. Signature -> SignatureValue包含通过使用私钥对Signature -> SignedInfo进行签名生成的签名的值

从理论上讲,这就是代码应该如何寻找rsa-sha1算法(由Signature -> SignedInfo -> SignatureMethod指定),具有以下规范化方法:独占XML规范化1.0(省略注释)和提供的x509证书:

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

这个库在php:xmlseclibs中实现xmldsig方面做得很好;如何验证xmldsig的示例可以在这里找到:https://github.com/robrichards/xmlseclibs/blob/master/tests/xmlsec-verify.phpt。该库还验证了 Signature -> SignedInfo -> Reference 的摘要值,这是我上面省略的步骤。

我建议你使用 https://github.com/lightSAML/lightSAML。它使用 xmlseclibs 并实现完整的 SAML SSO SP 配置文件。从 HTTP POST 接收 SAML 响应并验证其签名样本在 LightSAML 说明书中给出 http://www.lightsaml.com/LightSAML-Core/Cookbook/How-to-receive-SAML-message/和 http://www.lightsaml.com/LightSAML-Core/Cookbook/How-to-verify-signature-of-SAML-message/整个代码如下所示

$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";
}

通过完整的SAML SSO配置文件特定操作处理响应的意义远不止于此,对于这些详细信息,您可以在 https://github.com/lightSAML/lightSAML/blob/master/web/sp/acs.php 中检查示例,或者如果您使用的是Symfony https://github.com/lightSAML/SpBundle