/**
* Adds signature key and senders certificate to an element (Message or Assertion).
*
* @param string|DomDocument $xml The element we should sign
* @param string $key The private key
* @param string $cert The public
*/
public static function addSign($xml, $key, $cert)
{
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(XMLSecurityKey::RSA_SHA1, 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('samlp:AuthnRequest', 'samlp:Response', 'samlp:LogoutRequest', 'samlp:LogoutResponse');
if (in_array($rootNode->tagName, $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;
}