/** * @param XMLSecurityKey|null $objBaseKey * @param DOMNode|null $node * * @return null|XMLSecurityKey * @throws Exception */ static function staticLocateKeyInfo(XMLSecurityKey $objBaseKey = null, DOMNode $node = null) { if (empty($node) || !$node instanceof DOMNode) { return null; } $doc = $node->ownerDocument; if (!$doc) { return null; } $xpath = new DOMXPath($doc); $xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS); $xpath->registerNamespace('xmlsecdsig', XMLSecurityDSig::XMLDSIGNS); $query = "./xmlsecdsig:KeyInfo"; $nodeset = $xpath->query($query, $node); $encmeth = $nodeset->item(0); if (!$encmeth) { /* No KeyInfo in EncryptedData / EncryptedKey. */ return $objBaseKey; } /** @var DOMElement $child */ foreach ($encmeth->childNodes as $child) { switch ($child->localName) { case 'KeyName': if (!empty($objBaseKey)) { $objBaseKey->name = $child->nodeValue; } break; case 'KeyValue': /** @var DOMElement $keyval */ foreach ($child->childNodes as $keyval) { switch ($keyval->localName) { case 'DSAKeyValue': throw new Exception("DSAKeyValue currently not supported"); break; case 'RSAKeyValue': $modulus = null; $exponent = null; if ($modulusNode = $keyval->getElementsByTagName('Modulus')->item(0)) { $modulus = base64_decode($modulusNode->nodeValue); } if ($exponentNode = $keyval->getElementsByTagName('Exponent')->item(0)) { $exponent = base64_decode($exponentNode->nodeValue); } if (empty($modulus) || empty($exponent)) { throw new Exception("Missing Modulus or Exponent"); } $publicKey = XMLSecurityKey::convertRSA($modulus, $exponent); $objBaseKey->loadKey($publicKey); break; } } break; case 'RetrievalMethod': $type = $child->getAttribute('Type'); if ($type !== 'http://www.w3.org/2001/04/xmlenc#EncryptedKey') { /* Unsupported key type. */ break; } $uri = $child->getAttribute('URI'); if ($uri[0] !== '#') { /* URI not a reference - unsupported. */ break; } $id = substr($uri, 1); $query = "//xmlsecenc:EncryptedKey[@Id='{$id}']"; /** @var DOMElement $keyElement */ $keyElement = $xpath->query($query)->item(0); if (!$keyElement) { throw new Exception("Unable to locate EncryptedKey with @Id='{$id}'."); } return XMLSecurityKey::fromEncryptedKeyElement($keyElement); case 'EncryptedKey': return XMLSecurityKey::fromEncryptedKeyElement($child); case 'X509Data': if ($x509certNodes = $child->getElementsByTagName('X509Certificate')) { if ($x509certNodes->length > 0) { $x509cert = $x509certNodes->item(0)->textContent; $x509cert = str_replace(array("\r", "\n"), "", $x509cert); $x509cert = "-----BEGIN CERTIFICATE-----\n" . chunk_split($x509cert, 64, "\n") . "-----END CERTIFICATE-----\n"; $objBaseKey->loadKey($x509cert, false, true); } } break; } } return $objBaseKey; }