用秘钥给XML报文添加签名域(具体用到什么样的签名方式请看 github 上面的测试用例)
首先
需要安装扩展 xmlseclibs
地址:https://github.com/robrichards/xmlseclibs
然后
看下面示例(github上面也有测试的调用示例)
/**
* generateXMLSignFields XML生成签名域
* Use sha256withrsa algorithm to generate XML internal signature
* @param $xml
* @return string
* @throws \Exception
* @author liuml <liumenglei0211@163.com>
* @DateTime 2018/12/21 16:37
*/
protected function generateXMLSignFields($xml, $prefix = 'ds')
{
// 加载要签名的XML
$doc = new \DOMDocument();
$doc->loadXML($xml);
// 创建一个新的安全对象
$objDSig = new XMLSecurityDSig($prefix);
// 使用c14n专属规范化
$objDSig->setCanonicalMethod(XMLSecurityDSig::C14N);
// 签名使用 SHA-256
$objDSig->addReference(
$doc,
XMLSecurityDSig::SHA1,
['http://www.w3.org/2000/09/xmldsig#enveloped-signature'],
['force_uri' => true]
);
// 创建一个新的(私有)安全密钥
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, ['type' => 'private']);
// 如果密钥有密码,则使用它进行设置
// $objKey->passphrase = '<passphrase>';
// 加载私钥
$objKey->loadKey("-----BEGIN RSA PRIVATE KEY-----\n" . wordwrap($this->privateKey, 64, "\n", true) . "\n-----END RSA PRIVATE KEY-----\n");
// 对XML文件签名
$objDSig->sign($objKey);
// 将关联的公钥添加到签名
// $objDSig->add509Cert("-----BEGIN PUBLIC KEY-----\n" . wordwrap($this->publicKey, 64, "\n", true) . "\n-----END PUBLIC KEY-----\n");
// 将签名附加到XML
$objDSig->appendSignature($doc->documentElement);
// saveXML 里面 LIBXML_NOEMPTYTAG 是为了不简写空值的标签。例:(<test /> => <test></test>)
// 也可以直接这样写 return $doc->saveXML();
return $doc->saveXML($doc->documentElement, LIBXML_NOEMPTYTAG);
}
/**
* checkResponseSign 验证签名
* Validate signatures in XML
* @param $xml
* @return bool
* @throws \Exception
* @author liuml <liumenglei0211@163.com>
* @DateTime 2018/12/21 17:51
*/
protected function checkResponseSign($xml)
{
$doc = new \DOMDocument();
$doc->loadXML($xml);
$objXMLSecDSig = new XMLSecurityDSig();
$objDSig = $objXMLSecDSig->locateSignature($doc);
if (!$objDSig) {
throw new \Exception("Cannot locate Signature Node");
}
$objXMLSecDSig->canonicalizeSignedInfo();
$objXMLSecDSig->idKeys = array('wsu:Id');
$objXMLSecDSig->idNS = array('wsu' => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd');
$retVal = $objXMLSecDSig->validateReference();
if (!$retVal) {
throw new \Exception("Reference Validation Failed");
}
$objKey = $objXMLSecDSig->locateKey();
if (!$objKey) {
throw new \Exception("We have no idea about the key");
}
$key = NULL;
$objKeyInfo = XMLSecEnc::staticLocateKeyInfo($objKey, $objDSig);
if (!$objKeyInfo->key && empty($key)) {
$objKey->loadKey("-----BEGIN PUBLIC KEY-----\n" . wordwrap($this->myBankPublicKey, 64, "\n",true) . "\n-----END PUBLIC KEY-----\n");
}
if ($objXMLSecDSig->verify($objKey) === 1) {
return true;
} else {
return false;
}
}