public static function addSign($xml, $key, $cert, $signAlgorithm = XMLSecurityKey::RSA_SHA1)
{
if ($xml instanceof DOMDocument) {
$dom = $xml;
} else {
$dom = new DOMDocument();
$dom = self::loadXML($dom, $xml);
if (!$dom) {
throw new Exception('Error parsing xml string');
}
}
/* Load the private key. */
$objKey = new XMLSecurityKey($signAlgorithm, array('type' => 'private'));
$objKey->loadKey($key, false);
/* Get the EntityDescriptor node we should sign. */
$rootNode = $dom->firstChild;
/* Sign the metadata with our private key. */
$objXMLSecDSig = new XMLSecurityDSig();
$objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
$objXMLSecDSig->addReferenceList(array($rootNode), XMLSecurityDSig::SHA1, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N), array('id_name' => 'ID'));
$objXMLSecDSig->sign($objKey);
/* Add the certificate to the signature. */
$objXMLSecDSig->add509Cert($cert, true);
$insertBefore = $rootNode->firstChild;
$messageTypes = array('AuthnRequest', 'Response', 'LogoutRequest', 'LogoutResponse');
if (in_array($rootNode->localName, $messageTypes)) {
$issuerNodes = self::query($dom, '/' . $rootNode->tagName . '/saml:Issuer');
if ($issuerNodes->length == 1) {
$insertBefore = $issuerNodes->item(0)->nextSibling;
}
}
/* Add the signature. */
$objXMLSecDSig->insertSignature($rootNode, $insertBefore);
/* Return the DOM tree as a string. */
$signedxml = $dom->saveXML();
return $signedxml;
}