/** * @param XMLSecurityKey $key * * @return bool * * @throws LightSamlSecurityException */ public function validate(XMLSecurityKey $key) { if (null == $this->signature) { return false; } if (false == $this->signature->validateReference()) { throw new LightSamlSecurityException('Digest validation failed'); } $key = $this->castKeyIfNecessary($key); if (false == $this->signature->verify($key)) { throw new LightSamlSecurityException('Unable to verify Signature'); } return true; }
/** * Check the Signature in a XML element. * * This function expects the XML element to contain a Signature-element * which contains a reference to the XML-element. This is common for both * messages and assertions. * * Note that this function only validates the element itself. It does not * check this against any local keys. * * If no Signature-element is located, this function will return false. All * other validation errors result in an exception. On successful validation * an array will be returned. This array contains the information required to * check the signature against a public key. * * @param \DOMElement $root The element which should be validated. * @return array|bool An array with information about the Signature-element. * @throws \Exception */ public static function validateElement(\DOMElement $root) { /* Create an XML security object. */ $objXMLSecDSig = new XMLSecurityDSig(); /* Both SAML messages and SAML assertions use the 'ID' attribute. */ $objXMLSecDSig->idKeys[] = 'ID'; /* Locate the XMLDSig Signature element to be used. */ $signatureElement = self::xpQuery($root, './ds:Signature'); if (count($signatureElement) === 0) { /* We don't have a signature element ot validate. */ return false; } elseif (count($signatureElement) > 1) { throw new \Exception('XMLSec: more than one signature element in root.'); } $signatureElement = $signatureElement[0]; $objXMLSecDSig->sigNode = $signatureElement; /* Canonicalize the XMLDSig SignedInfo element in the message. */ $objXMLSecDSig->canonicalizeSignedInfo(); /* Validate referenced xml nodes. */ if (!$objXMLSecDSig->validateReference()) { throw new \Exception('XMLsec: digest validation failed'); } /* Check that $root is one of the signed nodes. */ $rootSigned = false; /** @var \DOMNode $signedNode */ foreach ($objXMLSecDSig->getValidatedNodes() as $signedNode) { if ($signedNode->isSameNode($root)) { $rootSigned = true; break; } elseif ($root->parentNode instanceof \DOMDocument && $signedNode->isSameNode($root->ownerDocument)) { /* $root is the root element of a signed document. */ $rootSigned = true; break; } } if (!$rootSigned) { throw new \Exception('XMLSec: The root element is not signed.'); } /* Now we extract all available X509 certificates in the signature element. */ $certificates = array(); foreach (self::xpQuery($signatureElement, './ds:KeyInfo/ds:X509Data/ds:X509Certificate') as $certNode) { $certData = trim($certNode->textContent); $certData = str_replace(array("\r", "\n", "\t", ' '), '', $certData); $certificates[] = $certData; } $ret = array('Signature' => $objXMLSecDSig, 'Certificates' => $certificates); return $ret; }
public function verify(DOMDocument $data) { $objKey = null; $objXMLSecDSig = new XMLSecurityDSig(); $objDSig = $objXMLSecDSig->locateSignature($data); if (!$objDSig) { throw new UnexpectedValueException('Signature DOM element not found.'); } $objXMLSecDSig->canonicalizeSignedInfo(); if (!$this->getPublicKey()) { // try to get the public key from the certificate $objKey = $objXMLSecDSig->locateKey(); if (!$objKey) { throw new RuntimeException('There is no set either private key or public key for signature verification.'); } XMLSecEnc::staticLocateKeyInfo($objKey, $objDSig); $this->publicKey = $objKey->getX509Certificate(); $this->keyAlgorithm = $objKey->getAlgorith(); } if (!$objKey) { $objKey = new XMLSecurityKey($this->keyAlgorithm, ['type' => 'public']); $objKey->loadKey($this->getPublicKey()); } // Check signature if (1 !== $objXMLSecDSig->verify($objKey)) { return false; } // Check references (data) try { $objXMLSecDSig->validateReference(); } catch (\Exception $e) { return false; } return true; }
/** * Validate the receipt contained in the given XML element using the * certificate provided. * * @param DOMDocument $dom * @param resource $certificate * @return bool */ protected function validateXml(DOMDocument $dom, $certificate) { $secDsig = new XMLSecurityDSig(); // Locate the signature in the receipt XML. $dsig = $secDsig->locateSignature($dom); if ($dsig === null) { throw new RunTimeException('Cannot locate receipt signature'); } $secDsig->canonicalizeSignedInfo(); $secDsig->idKeys = array('wsu:Id'); $secDsig->idNS = array('wsu' => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'); if (!$secDsig->validateReference()) { throw new RunTimeException('Reference validation failed'); } $key = $secDsig->locateKey(); if ($key === null) { throw new RunTimeException('Could not locate key in receipt'); } $keyInfo = XMLSecEnc::staticLocateKeyInfo($key, $dsig); if (!$keyInfo->key) { $key->loadKey($certificate); } return $secDsig->verify($key) == 1; }
public function processSignature($refNode) { $objXMLSecDSig = new XMLSecurityDSig(); $objXMLSecDSig->idKeys[] = 'wswsu:Id'; $objXMLSecDSig->idNS['wswsu'] = self::WSUNS; $objXMLSecDSig->sigNode = $refNode; /* Canonicalize the signed info */ $objXMLSecDSig->canonicalizeSignedInfo(); $retVal = $objXMLSecDSig->validateReference(); if (!$retVal) { throw new Exception('Validation Failed'); } $key = null; $objKey = $objXMLSecDSig->locateKey(); if ($objKey) { if ($objKeyInfo = XMLSecEnc::staticLocateKeyInfo($objKey, $refNode)) { /* Handle any additional key processing such as encrypted keys here */ } } if (empty($objKey)) { throw new Exception('Error loading key to handle Signature'); } do { if (empty($objKey->key)) { $this->SOAPXPath->registerNamespace('xmlsecdsig', XMLSecurityDSig::XMLDSIGNS); $query = './xmlsecdsig:KeyInfo/wswsse:SecurityTokenReference/wswsse:Reference'; $nodeset = $this->SOAPXPath->query($query, $refNode); if ($encmeth = $nodeset->item(0)) { if ($uri = $encmeth->getAttribute('URI')) { $arUrl = parse_url($uri); if (empty($arUrl['path']) && ($identifier = $arUrl['fragment'])) { $query = '//wswsse:BinarySecurityToken[@wswsu:Id="' . $identifier . '"]'; $nodeset = $this->SOAPXPath->query($query); if ($encmeth = $nodeset->item(0)) { $x509cert = $encmeth->textContent; $x509cert = str_replace(array("\r", "\n"), '', $x509cert); $x509cert = "-----BEGIN CERTIFICATE-----\n" . chunk_split($x509cert, 64, "\n") . "-----END CERTIFICATE-----\n"; $objKey->loadKey($x509cert); break; } } } } throw new Exception('Error loading key to handle Signature'); } } while (0); if (!$objXMLSecDSig->verify($objKey)) { throw new Exception('Unable to validate Signature'); } return true; }