在PHP中验证SAML响应中的数字签名与证书

MJ *_*han 21 php ssl saml ssl-certificate

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

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

我需要验证响应是来自经过验证的提供者.我在google搜索时已经知道我需要.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);
Run Code Online (Sandbox Code Playgroud)

所以我应该忽略嵌入在xml中的X509Certificate还是我需要检查它... openssl_verify会不会足够?我是在正确的道路上吗?请任何指导将不胜感激.

god*_*ity 20

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

  1. Signature -> KeyInfo 包含有关从用于签名数据的私钥派生的公钥的信息
  2. Signature -> SignedInfo包含将使用上述私钥签名的数据; 该数据包含有关验证应如何计算的信息,如:CanonicalizationMethod,SignatureMethod,Reference
  3. Signature -> SignatureValue包含Signature -> SignedInfo使用私钥签名生成的签名的值

从理论上讲,这是代码应该如何查找rsa-sha1算法(由...指定Signature -> SignedInfo -> SignatureMethod),具有以下规范化方法:独有的XML Canonicalization 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);    
Run Code Online (Sandbox Code Playgroud)

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

  • 此代码对我有用 - 但您可能需要设置openssl_verify()的第4个参数以匹配SAML响应文档中SignatureMethod算法标记中定义的加密方法. (3认同)
  • 最后一个答案:) ..但我不再在这个项目上工作..但它可能对其他人有帮助..我不确定如果其他人可以将此标记为答案,如果它有效. (2认同)