44 const template =
"<xenc:EncryptedData xmlns:xenc='http://www.w3.org/2001/04/xmlenc#'> 46 <xenc:CipherValue></xenc:CipherValue> 48 </xenc:EncryptedData>";
49 const Element =
'http://www.w3.org/2001/04/xmlenc#Element';
50 const Content =
'http://www.w3.org/2001/04/xmlenc#Content';
52 const XMLENCNS =
'http://www.w3.org/2001/04/xmlenc#';
55 private $encdoc = null;
58 private $rawNode = null;
64 public $encKey = null;
67 private $references = array ();
69 public function __construct()
71 $this->_resetTemplate ();
74 private function _resetTemplate()
77 $this->encdoc->loadXML ( self::template );
89 if (! $node instanceof DOMNode)
91 throw new Exception (
'$node is not of type DOMNode' );
93 $curencdoc = $this->encdoc;
94 $this->_resetTemplate ();
95 $encdoc = $this->encdoc;
96 $this->encdoc = $curencdoc;
98 $element = $encdoc->documentElement;
99 $element->setAttribute (
"Id", $refuri );
100 $this->references [$name] = array (
103 "encnode" => $encdoc,
114 $this->rawNode = $node;
131 if (empty ( $this->rawNode ))
133 throw new Exception (
'Node to encrypt has not been set' );
139 $doc = $this->rawNode->ownerDocument;
140 $xPath =
new DOMXPath ( $this->encdoc );
141 $objList = $xPath->query (
'/xenc:EncryptedData/xenc:CipherData/xenc:CipherValue' );
142 $cipherValue = $objList->item ( 0 );
143 if ($cipherValue == null)
145 throw new Exception (
'Error locating CipherValue element within template' );
149 case (self::Element) :
150 $data = $doc->saveXML ( $this->rawNode );
151 $this->encdoc->documentElement->setAttribute (
'Type', self::Element );
153 case (self::Content) :
154 $children = $this->rawNode->childNodes;
155 foreach ( $children as $child )
157 $data .= $doc->saveXML ( $child );
159 $this->encdoc->documentElement->setAttribute (
'Type', self::Content );
162 throw new Exception (
'Type is currently not supported' );
164 $encMethod = $this->encdoc->documentElement->appendChild ( $this->encdoc->createElementNS ( self::XMLENCNS,
'xenc:EncryptionMethod' ) );
165 $encMethod->setAttribute (
'Algorithm', $objKey->getAlgorithm () );
166 $cipherValue->parentNode->parentNode->insertBefore ( $encMethod, $cipherValue->parentNode->parentNode->firstChild );
167 $strEncrypt = base64_encode ( $objKey->encryptData ( $data ) );
168 $value = $this->encdoc->createTextNode ( $strEncrypt );
169 $cipherValue->appendChild ( $value );
174 case (self::Element) :
175 if ($this->rawNode->nodeType == XML_DOCUMENT_NODE)
177 return $this->encdoc;
179 $importEnc = $this->rawNode->ownerDocument->importNode ( $this->encdoc->documentElement,
true );
180 $this->rawNode->parentNode->replaceChild ( $importEnc, $this->rawNode );
182 case (self::Content) :
183 $importEnc = $this->rawNode->ownerDocument->importNode ( $this->encdoc->documentElement,
true );
184 while ( $this->rawNode->firstChild )
186 $this->rawNode->removeChild ( $this->rawNode->firstChild );
188 $this->rawNode->appendChild ( $importEnc );
194 return $this->encdoc->documentElement;
205 $curRawNode = $this->rawNode;
206 $curType = $this->type;
207 foreach ( $this->references as $name => $reference )
209 $this->encdoc = $reference [
"encnode"];
210 $this->rawNode = $reference [
"node"];
211 $this->type = $reference [
"type"];
215 $this->references [$name] [
"encnode"] = $encNode;
219 $this->rawNode = $curRawNode;
220 $this->type = $curType;
224 $this->rawNode = $curRawNode;
225 $this->type = $curType;
236 if (empty ( $this->rawNode ))
238 throw new Exception (
'Node to decrypt has not been set' );
240 $doc = $this->rawNode->ownerDocument;
241 $xPath =
new DOMXPath ( $doc );
242 $xPath->registerNamespace (
'xmlencr', self::XMLENCNS );
244 $query =
"./xmlencr:CipherData/xmlencr:CipherValue";
245 $nodeset = $xPath->query ( $query, $this->rawNode );
246 $node = $nodeset->item ( 0 );
251 return base64_decode ( $node->nodeValue );
278 $decrypted = $objKey->decryptData ( $encryptedData );
283 case (self::Element) :
285 $newdoc->loadXML ( $decrypted );
286 if ($this->rawNode->nodeType == XML_DOCUMENT_NODE)
290 $importEnc = $this->rawNode->ownerDocument->importNode ( $newdoc->documentElement,
true );
291 $this->rawNode->parentNode->replaceChild ( $importEnc, $this->rawNode );
293 case (self::Content) :
294 if ($this->rawNode->nodeType == XML_DOCUMENT_NODE)
296 $doc = $this->rawNode;
300 $doc = $this->rawNode->ownerDocument;
302 $newFrag = $doc->createDocumentFragment ();
303 $newFrag->appendXML ( $decrypted );
304 $parent = $this->rawNode->parentNode;
305 $parent->replaceChild ( $newFrag, $this->rawNode );
318 throw new Exception (
"Cannot locate encrypted data" );
336 $strEncKey = base64_encode ( $srcKey->encryptData ( $rawKey->key ) );
337 $root = $this->encdoc->documentElement;
338 $encKey = $this->encdoc->createElementNS ( self::XMLENCNS,
'xenc:EncryptedKey' );
341 $keyInfo = $root->insertBefore ( $this->encdoc->createElementNS (
'http://www.w3.org/2000/09/xmldsig#',
'dsig:KeyInfo' ), $root->firstChild );
342 $keyInfo->appendChild ( $encKey );
346 $this->encKey = $encKey;
348 $encMethod = $encKey->appendChild ( $this->encdoc->createElementNS ( self::XMLENCNS,
'xenc:EncryptionMethod' ) );
349 $encMethod->setAttribute (
'Algorithm', $srcKey->getAlgorith () );
350 if (! empty ( $srcKey->name ))
352 $keyInfo = $encKey->appendChild ( $this->encdoc->createElementNS (
'http://www.w3.org/2000/09/xmldsig#',
'dsig:KeyInfo' ) );
353 $keyInfo->appendChild ( $this->encdoc->createElementNS (
'http://www.w3.org/2000/09/xmldsig#',
'dsig:KeyName', $srcKey->name ) );
355 $cipherData = $encKey->appendChild ( $this->encdoc->createElementNS ( self::XMLENCNS,
'xenc:CipherData' ) );
356 $cipherData->appendChild ( $this->encdoc->createElementNS ( self::XMLENCNS,
'xenc:CipherValue', $strEncKey ) );
357 if (is_array ( $this->references ) && count ( $this->references ) > 0)
359 $refList = $encKey->appendChild ( $this->encdoc->createElementNS ( self::XMLENCNS,
'xenc:ReferenceList' ) );
360 foreach ( $this->references as $reference )
362 $refuri = $reference [
"refuri"];
363 $dataRef = $refList->appendChild ( $this->encdoc->createElementNS ( self::XMLENCNS,
'xenc:DataReference' ) );
364 $dataRef->setAttribute (
"URI",
'#' . $refuri );
378 if (! $encKey->isEncrypted)
380 throw new Exception (
"Key is not Encrypted" );
382 if (empty ( $encKey->key ))
384 throw new Exception (
"Key is missing data to perform the decryption" );
402 $doc = $element->ownerDocument;
406 $xpath =
new DOMXPath ( $doc );
407 $query =
"//*[local-name()='EncryptedData' and namespace-uri()='" . self::XMLENCNS .
"']";
408 $nodeset = $xpath->query ( $query );
409 return $nodeset->item ( 0 );
424 $node = $this->rawNode;
426 if (! $node instanceof DOMNode)
430 if ($doc = $node->ownerDocument)
432 $xpath =
new DOMXPath ( $doc );
433 $xpath->registerNamespace (
'xmlsecenc', self::XMLENCNS );
434 $query =
".//xmlsecenc:EncryptionMethod";
435 $nodeset = $xpath->query ( $query, $node );
436 if ($encmeth = $nodeset->item ( 0 ))
438 $attrAlgorithm = $encmeth->getAttribute (
"Algorithm" );
464 if (empty ( $node ) || (! $node instanceof DOMNode))
468 $doc = $node->ownerDocument;
473 $xpath =
new DOMXPath ( $doc );
474 $xpath->registerNamespace (
'xmlsecenc', self::XMLENCNS );
475 $xpath->registerNamespace (
'xmlsecdsig', XMLSecurityDSig::XMLDSIGNS );
476 $query =
"./xmlsecdsig:KeyInfo";
477 $nodeset = $xpath->query ( $query, $node );
478 $encmeth = $nodeset->item ( 0 );
484 foreach ( $encmeth->childNodes as $child )
486 switch ($child->localName)
489 if (! empty ( $objBaseKey ))
491 $objBaseKey->name = $child->nodeValue;
495 foreach ( $child->childNodes as $keyval )
497 switch ($keyval->localName)
500 throw new Exception (
"DSAKeyValue currently not supported" );
504 if ($modulusNode = $keyval->getElementsByTagName (
'Modulus' )->item ( 0 ))
506 $modulus = base64_decode ( $modulusNode->nodeValue );
508 if ($exponentNode = $keyval->getElementsByTagName (
'Exponent' )->item ( 0 ))
510 $exponent = base64_decode ( $exponentNode->nodeValue );
512 if (empty ( $modulus ) || empty ( $exponent ))
514 throw new Exception (
"Missing Modulus or Exponent" );
517 $objBaseKey->loadKey ( $publicKey );
522 case 'RetrievalMethod' :
523 $type = $child->getAttribute (
'Type' );
524 if ($type !==
'http://www.w3.org/2001/04/xmlenc#EncryptedKey')
529 $uri = $child->getAttribute (
'URI' );
530 if ($uri [0] !==
'#')
535 $id = substr ( $uri, 1 );
536 $query =
"//xmlsecenc:EncryptedKey[@Id='$id']";
537 $keyElement = $xpath->query ( $query )->item ( 0 );
540 throw new Exception (
"Unable to locate EncryptedKey with @Id='$id'." );
543 case 'EncryptedKey' :
546 if ($x509certNodes = $child->getElementsByTagName (
'X509Certificate' ))
548 if ($x509certNodes->length > 0)
550 $x509cert = $x509certNodes->item ( 0 )->textContent;
551 $x509cert = str_replace ( array (
556 $x509cert =
"-----BEGIN CERTIFICATE-----\n" . chunk_split ( $x509cert, 64,
"\n" ) .
"-----END CERTIFICATE-----\n";
557 $objBaseKey->loadKey ( $x509cert,
false,
true );
576 $node = $this->rawNode;
578 return self::staticLocateKeyInfo ( $objBaseKey, $node );
static convertRSA($modulus, $exponent)
locateKeyInfo($objBaseKey=null, $node=null)
encryptKey($srcKey, $rawKey, $append=true)
encryptNode($objKey, $replace=true)
encryptReferences($objKey)
static staticLocateKeyInfo($objBaseKey=null, $node=null)
decryptNode($objKey, $replace=true)
static fromEncryptedKeyElement(DOMElement $element)
addReference($name, $node, $type)
static generateGUID($prefix='pfx')
locateEncryptedData($element)