diff --git a/lib/SimpleSAML/Bindings/Shib13/HTTPPost.php b/lib/SimpleSAML/Bindings/Shib13/HTTPPost.php
index edd4b2c126cb628625338892a89b6c7b2682633b..e57968c569e83647f05f0693b05eed1870841b07 100644
--- a/lib/SimpleSAML/Bindings/Shib13/HTTPPost.php
+++ b/lib/SimpleSAML/Bindings/Shib13/HTTPPost.php
@@ -80,7 +80,9 @@ class SimpleSAML_Bindings_Shib13_HTTPPost {
 	
 		$privatekey = $this->configuration->getBaseDir() . '/cert/' . $idpmd['privatekey'];
 		$publiccert = $this->configuration->getBaseDir() . '/cert/' . $idpmd['certificate'];
+		$certchain_pem_file = $this->configuration->getBaseDir() . '/cert/' . $idpmd['certificatechain'];
 
+		$privatek = file_get_contents($privatekey);
 		
 		if (strstr($claimedacs, $destination) == 0) {
 			$destination = $claimedacs;
@@ -89,6 +91,8 @@ class SimpleSAML_Bindings_Shib13_HTTPPost {
 		}
 		
 		
+		
+		
 		/*
 		 * XMLDSig. Sign the complete request with the key stored in cert/server.pem
 		 */
@@ -107,7 +111,14 @@ class SimpleSAML_Bindings_Shib13_HTTPPost {
 		//$assertionroot = $responsedom->getElementsByTagName('Assertion')->item(1);
 		$firstassertionroot = $responsedom->getElementsByTagName('Assertion')->item(0);
 		
-		$objXMLSecDSig->addReferenceList(array($responseroot), XMLSecurityDSig::SHA1, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature'), null, 'ResponseID');
+		#$objXMLSecDSig->addReferenceList(array($responseroot), XMLSecurityDSig::SHA1, #array('http://www.w3.org/2000/09/xmldsig#enveloped-signature'), null, 'ResponseID');
+		
+		$objXMLSecDSig->addReferenceList(array($responseroot), XMLSecurityDSig::SHA1,
+			array('http://www.w3.org/2000/09/xmldsig#enveloped-signature'),
+			array('id_name' => 'ResponseID'));
+			
+			// TODO: Add option to sign assertion versus response
+
 		#$objXMLSecDSig->addReferenceList(array($firstassertionroot), XMLSecurityDSig::SHA1, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature',
 		#	'http://www.w3.org/2001/10/xml-exc-c14n#'));
 		
@@ -116,17 +127,33 @@ class SimpleSAML_Bindings_Shib13_HTTPPost {
 		/* create new XMLSecKey using RSA-SHA-1 and type is private key */
 		$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'private'));
 		
+		//$objKey->passphrase = '1234';
+		
 		/* load the private key from file - last arg is bool if key in file (TRUE) or is string (FALSE) */
-		$objKey->loadKey($privatekey,TRUE);
+		#$objKey->loadKey($privatekey_pem,false);
+		$objKey->loadKey($privatek,false);
 		
+		// TODO: Check for whether cert files exists or not.
 		
+		$objXMLSecDSig->sign($objKey);
 		
+		$public_cert = file_get_contents($publiccert);
 		
+		//echo '<pre>publiccert:' . $public_cert . '</pre>';
 		
-		$objXMLSecDSig->sign($objKey);
 		
-		$public_cert = file_get_contents($publiccert);
 		$objXMLSecDSig->add509Cert($public_cert, true);
+		
+		if (isset($certchain_pem_file)) {
+			$certchain_pem = file_get_contents($certchain_pem_file);
+		
+			//echo '<pre>chain:' . $certchain_pem . '</pre>';
+			$certchain = XMLSecurityDSig::staticGet509XCerts($certchain_pem);
+#			foreach ($certchain AS $scert) {
+				$objXMLSecDSig->add509Cert($certchain_pem, true);
+#			}
+		}
+		
 		/*
 		$public_cert = file_get_contents("cert/edugain/public2.pem");
 		$objXMLSecDSig->add509Cert($public_cert, true);
diff --git a/lib/xmlseclibs.php b/lib/xmlseclibs.php
index e78e2ea9615c2995cde02c1e69843758fbf5ae7f..eab4a9c06e4bb5a814325dfe771976e23606dd06 100644
--- a/lib/xmlseclibs.php
+++ b/lib/xmlseclibs.php
@@ -1,1430 +1,1468 @@
-<?php 
-/**
- * xmlseclibs.php
- *
- * Copyright (c) 2007, Robert Richards <rrichards@ctindustries.net>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   * Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   * Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in
- *     the documentation and/or other materials provided with the
- *     distribution.
- *
- *   * Neither the name of Robert Richards nor the names of his
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * @author     Robert Richards <rrichards@ctindustries.net>
- * @copyright  2007 Robert Richards <rrichards@ctindustries.net>
- * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
- * @version    1.0.0
- */
- 
-/*
-Functions to generate simple cases of Exclusive Canonical XML - Callable function is C14NGeneral() 
-i.e.: $canonical = C14NGeneral($domelement, TRUE);
-*/
-
-/* helper function */
-function sortAndAddAttrs($element, $arAtts) {
-   $newAtts = array();
-   foreach ($arAtts AS $attnode) {
-      $newAtts[$attnode->nodeName] = $attnode;
-   }
-   ksort($newAtts);
-   foreach ($newAtts as $attnode) {
-      $element->setAttribute($attnode->nodeName, $attnode->nodeValue);
-   }
-}
-
-/* helper function */
-function canonical($tree, $element, $withcomments) {
-	if ($tree->nodeType != XML_DOCUMENT_NODE) {
-		$dom = $tree->ownerDocument;
-	} else {
-		$dom = $tree;
-	}
-	if ($element->nodeType != XML_ELEMENT_NODE) {
-		if ($element->nodeType == XML_COMMENT_NODE && ! $withcomments) {
-			return;
-		}
-		$tree->appendChild($dom->importNode($element, TRUE));
-		return;
-	}
-	$arNS = array();
-	if ($element->namespaceURI != "") {
-		if ($element->prefix == "") {
-			$elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName);
-		} else {
-			$prefix = $tree->lookupPrefix($element->namespaceURI);
-			if ($prefix == $element->prefix) {
-				$elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName);
-			} else {
-				$elCopy = $dom->createElement($element->nodeName);
-				$arNS[$element->namespaceURI] = $element->prefix;
-			}
-		}
-	} else {
-		$elCopy = $dom->createElement($element->nodeName);
-	}
-	$tree->appendChild($elCopy);
-
-	/* Create DOMXPath based on original document */
-	$xPath = new DOMXPath($element->ownerDocument);
-
-	/* Get namespaced attributes */
-	$arAtts = $xPath->query('attribute::*[namespace-uri(.) != ""]', $element);
-
-	/* Create an array with namespace URIs as keys, and sort them */
-	foreach ($arAtts AS $attnode) {
-		if (array_key_exists($attnode->namespaceURI, $arNS) && 
-			($arNS[$attnode->namespaceURI] == $attnode->prefix)) {
-			continue;
-		}
-		$prefix = $tree->lookupPrefix($attnode->namespaceURI);
-		if ($prefix != $attnode->prefix) {
-		   $arNS[$attnode->namespaceURI] = $attnode->prefix;
-		} else {
-			$arNS[$attnode->namespaceURI] = NULL;
-		}
-	}
-	if (count($arNS) > 0) {
-		asort($arNS);
-	}
-
-	/* Add namespace nodes */
-	foreach ($arNS AS $namespaceURI=>$prefix) {
-		if ($prefix != NULL) {
-	      	$elCopy->setAttributeNS("http://www.w3.org/2000/xmlns/",
-                               "xmlns:".$prefix, $namespaceURI);
-		}
-	}
-	if (count($arNS) > 0) {
-		ksort($arNS);
-	}
-
-	/* Get attributes not in a namespace, and then sort and add them */
-	$arAtts = $xPath->query('attribute::*[namespace-uri(.) = ""]', $element);
-	sortAndAddAttrs($elCopy, $arAtts);
-
-	/* Loop through the URIs, and then sort and add attributes within that namespace */
-	foreach ($arNS as $nsURI=>$prefix) {
-	   $arAtts = $xPath->query('attribute::*[namespace-uri(.) = "'.$nsURI.'"]', $element);
-	   sortAndAddAttrs($elCopy, $arAtts);
-	}
-
-	foreach ($element->childNodes AS $node) {
-		canonical($elCopy, $node, $withcomments);
-	}
-}
-
-/*
-$element - DOMElement for which to produce the canonical version of
-$exclusive - boolean to indicate exclusive canonicalization (must pass TRUE)
-$withcomments - boolean indicating wether or not to include comments in canonicalized form
-*/
-function C14NGeneral($element, $exclusive=FALSE, $withcomments=FALSE) {
-	/* IF PHP 5.2+ then use built in canonical functionality */
-	$php_version = explode('.', PHP_VERSION);
-	if (($php_version[0] > 5) || ($php_version[0] == 5 && $php_version[1] >= 2) ) {
-		return $element->C14N($exclusive, $withcomments);
-	}
-
-	/* Must be element */
-	if (! $element instanceof DOMElement) {
-		return NULL;
-	}
-	/* Currently only exclusive XML is supported */
-	if ($exclusive == FALSE) {
-		throw new Exception("Only exclusive canonicalization is supported in this version of PHP");
-	}
-	
-	$copyDoc = new DOMDocument();
-	canonical($copyDoc, $element, $withcomments);
-	return $copyDoc->saveXML($copyDoc->documentElement, LIBXML_NOEMPTYTAG);
-}
-
-class XMLSecurityKey {
-	const TRIPLEDES_CBC = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
-	const AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
-	const AES192_CBC = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
-	const AES256_CBC = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
-	const RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
-	const RSA_OAEP_MGF1P = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
-	const RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
-	const DSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1';
-
-	private $cryptParams = array();
-	public $type = 0;
-	public $key = NULL;
-	public $passphrase = "";
-	public $iv = NULL;
-	public $name = NULL;
-	public $keyChain = NULL;
-	public $isEncrypted = FALSE;
-	public $encryptedCtx = NULL;
-	public $guid = NULL;
-
-	public function __construct($type, $params=NULL) {
-		switch ($type) {
-			case (XMLSecurityKey::TRIPLEDES_CBC):
-				$this->cryptParams['library'] = 'mcrypt';
-				$this->cryptParams['cipher'] = MCRYPT_TRIPLEDES;
-				$this->cryptParams['mode'] = MCRYPT_MODE_CBC;
-				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
-				break;
-			case (XMLSecurityKey::AES128_CBC):
-				$this->cryptParams['library'] = 'mcrypt';
-				$this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
-				$this->cryptParams['mode'] = MCRYPT_MODE_CBC;
-				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
-				break;
-			case (XMLSecurityKey::AES192_CBC):
-				$this->cryptParams['library'] = 'mcrypt';
-				$this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
-				$this->cryptParams['mode'] = MCRYPT_MODE_CBC;
-				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
-				break;
-			case (XMLSecurityKey::AES256_CBC):
-				$this->cryptParams['library'] = 'mcrypt';
-				$this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
-				$this->cryptParams['mode'] = MCRYPT_MODE_CBC;
-				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
-				break;
-			case (XMLSecurityKey::RSA_1_5):
-				$this->cryptParams['library'] = 'openssl';
-				$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
-				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
-				if (is_array($params) && ! empty($params['type'])) {
-					if ($params['type'] == 'public' || $params['type'] == 'private') {
-						$this->cryptParams['type'] = $params['type'];
-						break;
-					}
-				}
-				throw new Exception('Certificate "type" (private/public) must be passed via parameters');
-				return;
-			case (XMLSecurityKey::RSA_OAEP_MGF1P):
-				$this->cryptParams['library'] = 'openssl';
-				$this->cryptParams['padding'] = OPENSSL_PKCS1_OAEP_PADDING;
-				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
-				$this->cryptParams['hash'] = NULL;
-				if (is_array($params) && ! empty($params['type'])) {
-					if ($params['type'] == 'public' || $params['type'] == 'private') {
-						$this->cryptParams['type'] = $params['type'];
-						break;
-					}
-				}
-				throw new Exception('Certificate "type" (private/public) must be passed via parameters');
-				return;
-			case (XMLSecurityKey::RSA_SHA1):
-				$this->cryptParams['library'] = 'openssl';
-				$this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
-				if (is_array($params) && ! empty($params['type'])) {
-					if ($params['type'] == 'public' || $params['type'] == 'private') {
-						$this->cryptParams['type'] = $params['type'];
-						break;
-					}
-				}
-				throw new Exception('Certificate "type" (private/public) must be passed via parameters');
-				break;
-			default:
-				throw new Exception('Invalid Key Type');
-				return;
-		}
-		$this->type = $type;
-	}
-
-	public function generateSessionKey() {
-		$key = '';
-		if (! empty($this->cryptParams['cipher']) && ! empty($this->cryptParams['mode'])) {
-			$keysize = mcrypt_module_get_algo_key_size($this->cryptParams['cipher']);
-			/* Generating random key using iv generation routines */
-			if (($keysize > 0) && ($td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '',$this->cryptParams['mode'], ''))) {
-				if ($this->cryptParams['cipher'] == MCRYPT_RIJNDAEL_128) {
-					$keysize = 16;
-					if ($this->type == XMLSecurityKey::AES256_CBC) {
-						$keysize = 32;
-					} elseif ($this->type == XMLSecurityKey::AES192_CBC) {
-						$keysize = 24;
-					}
-				}
-				while (strlen($key) < $keysize) {
-					$key .= mcrypt_create_iv(mcrypt_enc_get_iv_size ($td),MCRYPT_RAND);
-				}
-				mcrypt_module_close($td);
-				$key = substr($key, 0, $keysize);
-				$this->key = $key;
-			}
-		}
-		return $key;
-	}
-
-	public function loadKey($key, $isFile=FALSE, $isCert = FALSE) {
-		if ($isFile) {
-			$this->key = file_get_contents($key);
-		} else {
-			$this->key = $key;
-		}
-		if ($isCert) {
-			$this->key = openssl_x509_read($this->key);
-			openssl_x509_export($this->key, $str_cert);
-			$this->key = $str_cert;
-		}
-		if ($this->cryptParams['library'] == 'openssl') {
-			if ($this->cryptParams['type'] == 'public') {
-				$this->key = openssl_get_publickey($this->key);
-			} else {
-				$this->key = openssl_get_privatekey($this->key, $this->passphrase);
-			}
-		} else if ($this->cryptParams['cipher'] == MCRYPT_RIJNDAEL_128) {
-			/* Check key length */
-			switch ($this->type) {
-				case (XMLSecurityKey::AES256_CBC):
-					if (strlen($this->key) < 25) {
-						throw new Exception('Key must contain at least 25 characters for this cipher');
-					}
-					break;
-				case (XMLSecurityKey::AES192_CBC):
-					if (strlen($this->key) < 17) {
-						throw new Exception('Key must contain at least 17 characters for this cipher');
-					}
-					break;
-			}
-		}
-	}
-
-	private function encryptMcrypt($data) {
-    	$td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
-	    $this->iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
-	    mcrypt_generic_init($td, $this->key, $this->iv);
-    	$encrypted_data = $this->iv.mcrypt_generic($td, $data);
-	    mcrypt_generic_deinit($td);
-    	mcrypt_module_close($td);
-		return $encrypted_data;
-	}
-
-	private function decryptMcrypt($data) {
-    	$td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
-		$iv_length = mcrypt_enc_get_iv_size($td);
-
-		$this->iv = substr($data, 0, $iv_length);
-		$data = substr($data, $iv_length);
-
-	    mcrypt_generic_init($td, $this->key, $this->iv);
-    	$decrypted_data = mdecrypt_generic($td, $data);
-	    mcrypt_generic_deinit($td);
-    	mcrypt_module_close($td);
-		if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) {
-	        $dataLen = strlen($decrypted_data);
-			$paddingLength = substr($decrypted_data, $dataLen - 1, 1);
-        	$decrypted_data = substr($decrypted_data, 0, $dataLen - ord($paddingLength));
-		}
-		return $decrypted_data;
-	}
-
-	private function encryptOpenSSL($data) {
-		if ($this->cryptParams['type'] == 'public') {
-			if (! openssl_public_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
-				throw new Exception('Failure encrypting Data');
-				return;
-			}
-		} else {
-			if (! openssl_private_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
-				throw new Exception('Failure encrypting Data');
-				return;
-			}
-		}
-		return $encrypted_data;
-	}
-
-	private function decryptOpenSSL($data) {
-		if ($this->cryptParams['type'] == 'public') {
-			if (! openssl_public_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
-				throw new Exception('Failure decrypting Data');
-				return;
-			}
-		} else {
-			if (! openssl_private_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
-				throw new Exception('Failure decrypting Data');
-				return;
-			}
-		}
-		return $decrypted;
-	}
-
-	private function signOpenSSL($data) {
-		if (! openssl_sign ($data, $signature, $this->key)) {
-			throw new Exception('Failure Signing Data');
-			return;
-		}
-		return $signature;
-	}
-
-	private function verifyOpenSSL($data, $signature) {
-		return openssl_verify ($data, $signature, $this->key);
-	}
-
-	public function encryptData($data) {
-		switch ($this->cryptParams['library']) {
-			case 'mcrypt':
-				return $this->encryptMcrypt($data);
-				break;
-			case 'openssl':
-				return $this->encryptOpenSSL($data);
-				break;
-		}
-	}
-
-	public function decryptData($data) {
-		switch ($this->cryptParams['library']) {
-			case 'mcrypt':
-				return $this->decryptMcrypt($data);
-				break;
-			case 'openssl':
-				return $this->decryptOpenSSL($data);
-				break;
-		}
-	}
-
-	public function signData($data) {
-		switch ($this->cryptParams['library']) {
-			case 'openssl':
-				return $this->signOpenSSL($data);
-				break;
-		}
-	}
-
-	public function verifySignature($data, $signature) {
-		switch ($this->cryptParams['library']) {
-			case 'openssl':
-				return $this->verifyOpenSSL($data, $signature);
-				break;
-		}
-	}
-
-	public function getAlgorith() {
-		return $this->cryptParams['method'];
-	}
-
-	static function makeAsnSegment($type, $string) {
-		switch ($type){
-			case 0x02:
-				if (ord($string) > 0x7f)
-					$string = chr(0).$string;
-				break;
-			case 0x03:
-				$string = chr(0).$string;
-				break;
-		}
-	
-		$length = strlen($string);
-	
-		if ($length < 128){
-		   $output = sprintf("%c%c%s", $type, $length, $string);
-		} else if ($length < 0x0100){
-		   $output = sprintf("%c%c%c%s", $type, 0x81, $length, $string);
-		} else if ($length < 0x010000) {
-		   $output = sprintf("%c%c%c%c%s", $type, 0x82, $length/0x0100, $length%0x0100, $string);
-		} else {
-			$output = NULL;
-		}
-		return($output);
-	}
-
-	/* Modulus and Exponent must already be base64 decoded */
-	static function convertRSA($modulus, $exponent) {
-		/* make an ASN publicKeyInfo */
-		$exponentEncoding = XMLSecurityKey::makeAsnSegment(0x02, $exponent);    
-		$modulusEncoding = XMLSecurityKey::makeAsnSegment(0x02, $modulus);    
-		$sequenceEncoding = XMLSecurityKey:: makeAsnSegment(0x30, $modulusEncoding.$exponentEncoding);
-		$bitstringEncoding = XMLSecurityKey::makeAsnSegment(0x03, $sequenceEncoding);
-		$rsaAlgorithmIdentifier = pack("H*", "300D06092A864886F70D0101010500"); 
-		$publicKeyInfo = XMLSecurityKey::makeAsnSegment (0x30, $rsaAlgorithmIdentifier.$bitstringEncoding);
-
-		/* encode the publicKeyInfo in base64 and add PEM brackets */
-		$publicKeyInfoBase64 = base64_encode($publicKeyInfo);    
-		$encoding = "-----BEGIN PUBLIC KEY-----\n";
-		$offset = 0;
-		while ($segment=substr($publicKeyInfoBase64, $offset, 64)){
-		   $encoding = $encoding.$segment."\n";
-		   $offset += 64;
-		}
-		return $encoding."-----END PUBLIC KEY-----\n";
-	}
-	
-	public function serializeKey($parent) {
-		
-	}
-}
-
-class XMLSecurityDSig {
-	const XMLDSIGNS = 'http://www.w3.org/2000/09/xmldsig#';
-	const SHA1 = 'http://www.w3.org/2000/09/xmldsig#sha1';
-	const SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256';
-	const SHA512 = 'http://www.w3.org/2001/04/xmlenc#sha512';
-	const RIPEMD160 = 'http://www.w3.org/2001/04/xmlenc#ripemd160';
-
-	const C14N = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
-	const C14N_COMMENTS = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments';
-	const EXC_C14N = 'http://www.w3.org/2001/10/xml-exc-c14n#';
-	const EXC_C14N_COMMENTS = 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments';
-
-	const template = '<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
-  <ds:SignedInfo>
-    <ds:SignatureMethod />
-  </ds:SignedInfo>
-</ds:Signature>';
-	
-	public $sigNode = NULL;
-	public $idKeys = array();
-	public $idNS = array();
-	private $signedInfo = NULL;
-	private $xPathCtx = NULL;
-	private $canonicalMethod = NULL;
-	private $prefix = 'ds';
-	private $searchpfx = 'secdsig';
-
-	public function __construct() {
-		$sigdoc = new DOMDocument();
-		$sigdoc->loadXML(XMLSecurityDSig::template);
-		$this->sigNode = $sigdoc->documentElement;
-	}
-
-	private function getXPathObj() {
-		if (empty($this->xPathCtx) && ! empty($this->sigNode)) {
-			$xpath = new DOMXPath($this->sigNode->ownerDocument);
-			$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
-
-			$this->xPathCtx = $xpath;
-		}
-		return $this->xPathCtx;
-	}
-
-	static function generate_GUID($prefix='_pfx') {
-		$uuid = md5(uniqid(rand(), true));
-		$guid =  $prefix.substr($uuid,0,8)."-".
-				substr($uuid,8,4)."-".
-				substr($uuid,12,4)."-".
-				substr($uuid,16,4)."-".
-				substr($uuid,20,12);
-		return $guid;
-	}
-
-	public function locateSignature($objDoc) {
-		if ($objDoc instanceof DOMDocument) {
-			$doc = $objDoc;
-		} else {
-			$doc = $objDoc->ownerDocument;
-		}
-		if ($doc) {
-			$xpath = new DOMXPath($doc);
-			$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
-			$query = ".//secdsig:Signature";
-			$nodeset = $xpath->query($query, $objDoc);
-			
-
-			$this->sigNode = $nodeset->item(0);
-			return $this->sigNode;
-		}
-		return NULL;
-	}
-
-	public function createNewSignNode($name, $value=NULL) {
-		$doc = $this->sigNode->ownerDocument;
-		if (! is_null($value)) {
-			$node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $this->prefix.':'.$name, $value);
-		} else {
-			$node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $this->prefix.':'.$name);
-		}
-		return $node;
-	}
-
-	public function setCanonicalMethod($method) {
-		switch ($method) {
-			case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
-			case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
-			case 'http://www.w3.org/2001/10/xml-exc-c14n#':
-			case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
-				$this->canonicalMethod = $method;
-				break;
-			default:
-				throw new Exception('Invalid Canonical Method');
-		}
-		if ($xpath = $this->getXPathObj()) {
-			$query = './'.$this->searchpfx.':SignedInfo';
-			$nodeset = $xpath->query($query, $this->sigNode);
-			if ($sinfo = $nodeset->item(0)) {
-				$query = './'.$this->searchpfx.'CanonicalizationMethod';
-				$nodeset = $xpath->query($query, $sinfo);
-				if (! ($canonNode = $nodeset->item(0))) {
-					$canonNode = $this->createNewSignNode('CanonicalizationMethod');
-					$sinfo->insertBefore($canonNode, $sinfo->firstChild);
-				}
-				$canonNode->setAttribute('Algorithm', $this->canonicalMethod);
-			}
-		}
-	}
-
-	private function canonicalizeData($node, $canonicalmethod, $arXPath=NULL, $prefixList=NULL) {
-		$exclusive = FALSE;
-		$withComments = FALSE;
-		switch ($canonicalmethod) {
-			case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
-				$exclusive = FALSE;
-				$withComments = FALSE;
-				break;
-			case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
-				$withComments = TRUE;
-				break;
-			case 'http://www.w3.org/2001/10/xml-exc-c14n#':
-				$exclusive = TRUE;
-				break;
-			case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
-				$exclusive = TRUE;
-				$withComments = TRUE;
-				break;
-		}
-/* Support PHP versions < 5.2 not containing C14N methods in DOM extension */
-		$php_version = explode('.', PHP_VERSION);
-		if (($php_version[0] < 5) || ($php_version[0] == 5 && $php_version[1] < 2) ) {
-			if (! is_null($arXPath)) {
-				throw new Exception("PHP 5.2.0 or higher is required to perform XPath Transformations");
-			}
-			return C14NGeneral($node, $exclusive, $withComments);
-		}
-		return $node->C14N($exclusive, $withComments, $arXPath, $prefixList);
-	}
-
-	public function canonicalizeSignedInfo() {
-
-		$doc = $this->sigNode->ownerDocument;
-		$canonicalmethod = NULL;
-		if ($doc) {
-			$xpath = $this->getXPathObj();
-			$query = "./secdsig:SignedInfo";
-			$nodeset = $xpath->query($query, $this->sigNode);
-			if ($signInfoNode = $nodeset->item(0)) {
-				$query = "./secdsig:CanonicalizationMethod";
-				$nodeset = $xpath->query($query, $signInfoNode);
-				if ($canonNode = $nodeset->item(0)) {
-					$canonicalmethod = $canonNode->getAttribute('Algorithm');
-				}
-				$this->signedInfo = $this->canonicalizeData($signInfoNode, $canonicalmethod);
-				return $this->signedInfo;
-			}
-		}
-		return NULL;
-	}
-
-	public function calculateDigest ($digestAlgorithm, $data) {
-		switch ($digestAlgorithm) {
-			case XMLSecurityDSig::SHA1:
-				$alg = 'sha1';
-				break;
-			case XMLSecurityDSig::SHA256:
-				$alg = 'sha256';
-				break;
-			case XMLSecurityDSig::SHA512:
-				$alg = 'sha512';
-				break;
-			case XMLSecurityDSig::RIPEMD160:
-				$alg = 'ripemd160';
-				break;
-			default:
-				throw new Exception("Cannot validate digest: Unsupported Algorith <$digestAlgorithm>");
-		}
-		return base64_encode(hash($alg, $data, TRUE));
-	}
-
-	public function validateDigest($refNode, $data) {
-		$xpath = new DOMXPath($refNode->ownerDocument);
-		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
-		$query = 'string(./secdsig:DigestMethod/@Algorithm)';
-		$digestAlgorithm = $xpath->evaluate($query, $refNode);
-		$digValue = $this->calculateDigest($digestAlgorithm, $data);
-		$query = 'string(./secdsig:DigestValue)';
-		$digestValue = $xpath->evaluate($query, $refNode);
-		return ($digValue == $digestValue);
-	}
-
-	public function processTransforms($refNode, $objData) {
-		$data = $objData;
-		$xpath = new DOMXPath($refNode->ownerDocument);
-		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
-		$query = './secdsig:Transforms/secdsig:Transform';
-		$nodelist = $xpath->query($query, $refNode);
-		$canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
-		$arXPath = NULL;
-		$prefixList = NULL;
-		foreach ($nodelist AS $transform) {
-			$algorithm = $transform->getAttribute("Algorithm");
-			switch ($algorithm) {
-				case 'http://www.w3.org/2001/10/xml-exc-c14n#':
-				case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
-					$node = $transform->firstChild;
-					while ($node) {
-						if ($node->localName == 'InclusiveNamespaces') {
-							if ($pfx = $node->getAttribute('PrefixList')) {
-								$arpfx = array();
-								$pfxlist = split(" ", $pfx);
-								foreach ($pfxlist AS $pfx) {
-									$val = trim($pfx);
-									if (! empty($val)) {
-										$arpfx[] = $val;
-									}
-								}
-								if (count($arpfx) > 0) {
-									$prefixList = $arpfx;
-								}
-							}
-							break;
-						}
-						$node = $node->nextSibling;
-					}
-				case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
-				case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
-					$canonicalMethod = $algorithm;
-					break;
-				case 'http://www.w3.org/TR/1999/REC-xpath-19991116':
-					$node = $transform->firstChild;
-					while ($node) {
-						if ($node->localName == 'XPath') {
-							$arXPath = array();
-							$arXPath['query'] = '(.//. | .//@* | .//namespace::*)['.$node->nodeValue.']';
-							$arXpath['namespaces'] = array();
-							$nslist = $xpath->query('./namespace::*', $node);
-							foreach ($nslist AS $nsnode) {
-								if ($nsnode->localName != "xml") {
-									$arXPath['namespaces'][$nsnode->localName] = $nsnode->nodeValue;
-								}
-							}
-							break;
-						}
-						$node = $node->nextSibling;
-					}
-					break;
-			}
-		}
-		if ($data instanceof DOMNode) {
-			$data = $this->canonicalizeData($objData, $canonicalMethod, $arXPath, $prefixList);
-		}
-		return $data;
-	}
-
-	public function processRefNode($refNode) {
-		$dataObject = NULL;
-		if ($uri = $refNode->getAttribute("URI")) {
-			$arUrl = parse_url($uri);
-			if (empty($arUrl['path'])) {
-				if ($identifier = $arUrl['fragment']) {
-					$xPath = new DOMXPath($refNode->ownerDocument);
-					if ($this->idNS && is_array($this->idNS)) {
-						foreach ($this->idNS AS $nspf=>$ns) {
-							$xPath->registerNamespace($nspf, $ns);
-						}
-					}
-					$iDlist = '@Id="'.$identifier.'"';
-					if (is_array($this->idKeys)) {
-						foreach ($this->idKeys AS $idKey) {
-							$iDlist .= " or @$idKey='$identifier'";
-						}
-					}
-					$query = '//*['.$iDlist.']';
-					$dataObject = $xPath->query($query)->item(0);
-				} else {
-					$dataObject = $refNode->ownerDocument;
-				}
-			} else {
-				$dataObject = file_get_contents($arUrl);
-			}
-		} else {
-			$dataObject = $refNode->ownerDocument;
-		}
-		$data = $this->processTransforms($refNode, $dataObject);
-		return $this->validateDigest($refNode, $data);
-	}
-	
-	public function getRefNodeID($refNode) {
-		if ($uri = $refNode->getAttribute("URI")) {
-			$arUrl = parse_url($uri);
-			if (empty($arUrl['path'])) {
-				if ($identifier = $arUrl['fragment']) {
-					return $identifier;
-				}
-			}
-		}
-		return null;
-	}
-	
-	public function getRefIDs() {
-		$refids = array();
-		$doc = $this->sigNode->ownerDocument;
-
-		$xpath = $this->getXPathObj();
-		$query = "./secdsig:SignedInfo/secdsig:Reference";
-		$nodeset = $xpath->query($query, $this->sigNode);
-		if ($nodeset->length == 0) {
-			throw new Exception("Reference nodes not found");
-		}
-		foreach ($nodeset AS $refNode) {
-			$refids[] = $this->getRefNodeID($refNode);
-		}
-		return $refids;
-	}
-
-	public function validateReference() {
-		$doc = $this->sigNode->ownerDocument;
-		if (! $doc->isSameNode($this->sigNode)) {
-			$this->sigNode->parentNode->removeChild($this->sigNode);
-		}
-		$xpath = $this->getXPathObj();
-		$query = "./secdsig:SignedInfo/secdsig:Reference";
-		$nodeset = $xpath->query($query, $this->sigNode);
-		if ($nodeset->length == 0) {
-			throw new Exception("Reference nodes not found");
-		}
-		foreach ($nodeset AS $refNode) {
-			if (! $this->processRefNode($refNode)) {
-				throw new Exception("Reference validation failed");
-			}
-		}
-		return TRUE;
-	}
-
-	private function addRefInternal($sinfoNode, $node, $algorithm, $arTransforms=NULL, $options=NULL, $id_name = 'ID') {
-		$prefix = NULL;
-		$prefix_ns = NULL;
-
-
-		if (is_array($options)) {
-			$prefix = empty($options['prefix'])?NULL:$options['prefix'];
-			$prefix_ns = empty($options['prefix_ns'])?NULL:$options['prefix_ns'];
-			$id_name = empty($options['id_name'])?'Id':$options['id_name'];
-		}
-
-		$refNode = $this->createNewSignNode('Reference');
-		$sinfoNode->appendChild($refNode);
-
-		if ($node instanceof DOMDocument) {
-			$uri = NULL;
-		} else {
-/* Do wer really need to set a prefix? */
-			$uri = XMLSecurityDSig::generate_GUID();
-			$refNode->setAttribute("URI", '#'.$uri);
-			//$refNode->setAttribute("URI", '');
-		}
-
-		$transNodes = $this->createNewSignNode('Transforms');
-		$refNode->appendChild($transNodes);
-
-		if (is_array($arTransforms)) {
-			foreach ($arTransforms AS $transform) {
-				$transNode = $this->createNewSignNode('Transform');
-				$transNodes->appendChild($transNode);
-				$transNode->setAttribute('Algorithm', $transform);
-			}
-		} elseif (! empty($this->canonicalMethod)) {
-			$transNode = $this->createNewSignNode('Transform');
-			$transNodes->appendChild($transNode);
-			$transNode->setAttribute('Algorithm', $this->canonicalMethod);
-		}
-		
-		if (! empty($uri)) {
-			$attname = $id_name;
-			if (! empty($prefix)) {
-				$attname = $prefix.':'.$attname;
-			}
-			$node->setAttributeNS($prefix_ns, $attname, $uri);
-		}
-		
-		$canonicalData = $this->processTransforms($refNode, $node);
-		$digValue = $this->calculateDigest($algorithm, $canonicalData);
-		
-		$digestMethod = $this->createNewSignNode('DigestMethod');
-		$refNode->appendChild($digestMethod);
-		$digestMethod->setAttribute('Algorithm', $algorithm);
-
-		$digestValue = $this->createNewSignNode('DigestValue', $digValue);
-		$refNode->appendChild($digestValue);
-	}
-
-	public function addReference($node, $algorithm, $arTransforms=NULL, $options=NULL, $idname = 'ID') {
-		if ($xpath = $this->getXPathObj()) {
-			$query = "./secdsig:SignedInfo";
-			$nodeset = $xpath->query($query, $this->sigNode);
-			if ($sInfo = $nodeset->item(0)) {
-				$this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options, $idname);
-			}
-		}
-	}
-
-	public function addReferenceList($arNodes, $algorithm, $arTransforms=NULL, $options=NULL, $idname = 'ID') {
-		if ($xpath = $this->getXPathObj()) {
-			$query = "./secdsig:SignedInfo";
-			$nodeset = $xpath->query($query, $this->sigNode);
-			if ($sInfo = $nodeset->item(0)) {
-				foreach ($arNodes AS $node) {
-					$this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options, $idname);
-				}
-			}
-		}
-	}
-
-   public function addObject($data, $mimetype=NULL, $encoding=NULL) {
-      $objNode = $this->createNewSignNode('Object');
-      $this->sigNode->appendChild($objNode);
-      if (! empty($mimetype)) {
-         $objNode->setAtribute('MimeType', $mimetype);
-      }
-      if (! empty($encoding)) {
-         $objNode->setAttribute('Encoding', $encoding);
-      }
-      
-      if ($data instanceof DOMElement) {
-         $newData = $this->sigNode->ownerDocument->importNode($data, TRUE);
-      } else {
-         $newData = $this->sigNode->ownerDocument->createTextNode($data);
-      }
-      $objNode->appendChild($newData);
-
-      return $objNode;
-   }
-
-	public function locateKey($node=NULL) {
-		if (empty($node)) {
-			$node = $this->sigNode;
-		}
-		if (! $node instanceof DOMNode) {
-			return NULL;
-		}
-		if ($doc = $node->ownerDocument) {
-			$xpath = new DOMXPath($doc);
-			$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
-			$query = "string(./secdsig:SignedInfo/secdsig:SignatureMethod/@Algorithm)";
-			$algorithm = $xpath->evaluate($query, $node);
-			if ($algorithm) {
-				try {
-					$objKey = new XMLSecurityKey($algorithm, array('type'=>'public'));
-				} catch (Exception $e) {
-					return NULL;
-				}
-				return $objKey;
-			}
-		}
-		return NULL;
-	}
-	
-	public function verify($objKey) {
-		$doc = $this->sigNode->ownerDocument;
-		$xpath = new DOMXPath($doc);
-		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
-		$query = "string(./secdsig:SignatureValue)";
-		$sigValue = $xpath->evaluate($query, $this->sigNode);
-		if (empty($sigValue)) {
-			throw new Exception("Unable to locate SignatureValue");
-		}
-		return $objKey->verifySignature($this->signedInfo, base64_decode($sigValue));
-	}
-	
-	public function signData($objKey, $data) {
-		return $objKey->signData($data);
-	}
-	
-	public function sign($objKey) {
-		if ($xpath = $this->getXPathObj()) {
-			$query = "./secdsig:SignedInfo";
-			$nodeset = $xpath->query($query, $this->sigNode);
-			if ($sInfo = $nodeset->item(0)) {
-				$query = "./secdsig:SignatureMethod";
-				$nodeset = $xpath->query($query, $sInfo);
-				$sMethod = $nodeset->item(0);
-				$sMethod->setAttribute('Algorithm', $objKey->type);
-				$data = $this->canonicalizeData($sInfo, $this->canonicalMethod);
-				$sigValue = base64_encode($this->signData($objKey, $data));
-				$sigValueNode = $this->createNewSignNode('SignatureValue', $sigValue);
-				if ($infoSibling = $sInfo->nextSibling) {
-					$infoSibling->parentNode->insertBefore($sigValueNode, $infoSibling);
-				} else {
-					$this->sigNode->appendChild($sigValueNode);
-				}
-			}
-		}
-	}
-
-	public function appendCert() {
-		
-	}
-
-	public function appendKey($objKey, $parent=NULL) {
-		$objKey->serializeKey($parent);
-	}
-
-
-	public function appendSignatureShib($parentNode, $insertBefore = FALSE, $assertion = false) {
-		$baseDoc = ($parentNode instanceof DOMDocument)?$parentNode:$parentNode->ownerDocument;
-		$newSig = $baseDoc->importNode($this->sigNode, TRUE);
-
-	
-	
-		$xnode = null;
-		
-		$xpath = new DOMXPath($baseDoc);
-		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
-		$xpath->registerNamespace('samlp', 'urn:oasis:names:tc:SAML:1.0:protocol');
-		$xpath->registerNamespace('saml', 'urn:oasis:names:tc:SAML:1.0:assertion');
-
-
-		if ($insertBefore && !$assertion) {
-
-			$query = "//samlp:Status";
-			$nodeset = $xpath->query($query, $parentNode);
-
-			$xnode = $nodeset->item(0);
-			if (!$xnode)
-				throw new Exception("Could not find node to sign before (Root signing mode)");
-		
-			$parentNode->insertBefore($newSig, $xnode);
-			
-		} elseif ($insertBefore) {
-			
-			$query = "//saml:Assertion/saml:Subject";
-			$nodeset = $xpath->query($query, $parentNode);
-
-			$xnode = $nodeset->item(0);
-			if (!$xnode)
-				throw new Exception("Could not find node to sign before (Assertion signing mode)");
-
-			$parentNode->insertBefore($newSig, $xnode);
-		} else {
-			$parentNode->appendChild($newSig);
-		}
-	}
-	
-	
-
-	public function appendSignature($parentNode, $insertBefore = false, $assertion = false) {
-		$baseDoc = ($parentNode instanceof DOMDocument)?$parentNode:$parentNode->ownerDocument;
-		$newSig = $baseDoc->importNode($this->sigNode, TRUE);
-
-	
-	
-		$xnode = null;
-		
-		$xpath = new DOMXPath($baseDoc);
-		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
-		$xpath->registerNamespace('samlp', 'urn:oasis:names:tc:SAML:2.0:protocol');
-		$xpath->registerNamespace('saml', 'urn:oasis:names:tc:SAML:2.0:assertion');
-
-
-		if ($insertBefore && !$assertion) {
-
-			$query = "//samlp:Status";
-			$nodeset = $xpath->query($query, $parentNode);
-
-			$xnode = $nodeset->item(0);
-			if (!$xnode)
-				throw new Exception("Could not find node to sign before (Root signing mode)");
-		
-			$parentNode->insertBefore($newSig, $xnode);
-			
-		} elseif ($insertBefore) {
-			
-			$query = "//saml:Assertion/saml:Subject";
-			$nodeset = $xpath->query($query, $parentNode);
-
-			$xnode = $nodeset->item(0);
-			if (!$xnode)
-				throw new Exception("Could not find node to sign before (Assertion signing mode)");
-
-			$parentNode->insertBefore($newSig, $xnode);
-		} else {
-			$parentNode->appendChild($newSig);
-		}
-	}
-	
-	static function get509XCert($cert, $isPEMFormat=TRUE) {
-		if ($isPEMFormat) {
-			$data = '';
-			$arCert = explode("\n", $cert);
-			$inData = FALSE;
-			foreach ($arCert AS $curData) {
-				if (! $inData) {
-					if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
-						$inData = TRUE;
-					}
-				} else {
-					if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
-						break;
-					}
-					$data .= trim($curData) . "\n";
-				}
-			}
-		} else {
-			$data = $cert;
-		}
-		return $data;
-	}
-	
-	static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=TRUE, $isURL=False, $xpath=NULL) {
-          if ($isURL) {
-            $cert = file_get_contents($cert);
-          }
-          if (! $parentRef instanceof DOMElement) {
-            throw new Exception('Invalid parent Node parameter');
-          }
-          $baseDoc = $parentRef->ownerDocument;
-
-          if (empty($xpath)) {
-              $xpath = new DOMXPath($parentRef->ownerDocument);
-              $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
-          }
-          $data = XMLSecurityDSig::get509XCert($cert, $isPEMFormat);
-
-         $query = "./secdsig:KeyInfo";
-         $nodeset = $xpath->query($query, $parentRef);
-         $keyInfo = $nodeset->item(0);
-         if (! $keyInfo) {
-              $inserted = FALSE;
-              $keyInfo = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:KeyInfo');
-
-               $query = "./secdsig:Object";
-               $nodeset = $xpath->query($query, $parentRef);
-               if ($sObject = $nodeset->item(0)) {
-                    $sObject->parentNode->insertBefore($keyInfo, $sObject);
-                    $inserted = TRUE;
-               }
-
-              if (! $inserted) {
-                   $parentRef->appendChild($keyInfo);
-              }
-         }
-         $x509DataNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Data');
-         $keyInfo->appendChild($x509DataNode);
-         $x509CertNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Certificate', $data);
-         $x509DataNode->appendChild($x509CertNode);
-
-     }
-
-	public function add509Cert($cert, $isPEMFormat=TRUE, $isURL=False) {
-         if ($xpath = $this->getXPathObj()) {
-            self::staticAdd509Cert($this->sigNode, $cert, $isPEMFormat, $isURL, $xpath);
-         }
-	}
-}
-
-class XMLSecEnc {
-	const template = "<xenc:EncryptedData xmlns:xenc='http://www.w3.org/2001/04/xmlenc#'>
-   <xenc:CipherData>
-      <xenc:CipherValue></xenc:CipherValue>
-   </xenc:CipherData>
-</xenc:EncryptedData>";
-
-	const Element = 'http://www.w3.org/2001/04/xmlenc#Element';
-	const Content = 'http://www.w3.org/2001/04/xmlenc#Content';
-	const URI = 3;
-	const XMLENCNS = 'http://www.w3.org/2001/04/xmlenc#';
-
-	private $encdoc = NULL;
-	private $rawNode = NULL;
-	public $type = NULL;
-	public $encKey = NULL;
-	
-	public function __construct() {
-		$this->encdoc = new DOMDocument();
-		$this->encdoc->loadXML(XMLSecEnc::template);
-	}
-	
-	public function setNode($node) {
-		$this->rawNode = $node;
-	}
-
-	public function encryptNode($objKey, $replace=TRUE) {
-		$data = '';
-		if (empty($this->rawNode)) {
-			throw new Exception('Node to encrypt has not been set');
-		}
-		if (! $objKey instanceof XMLSecurityKey) {
-			throw new Exception('Invalid Key');
-		}
-		$doc = $this->rawNode->ownerDocument;
-		$xPath = new DOMXPath($this->encdoc);
-		$objList = $xPath->query('/xenc:EncryptedData/xenc:CipherData/xenc:CipherValue');
-		$cipherValue = $objList->item(0);
-		if ($cipherValue == NULL) {
-			throw new Exception('Error locating CipherValue element within template');
-		}
-		switch ($this->type) {
-			case (XMLSecEnc::Element):
-				$data = $doc->saveXML($this->rawNode);
-				$this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Element);
-				break;
-			case (XMLSecEnc::Content):
-				$children = $this->rawNode->childNodes;
-				foreach ($children AS $child) {
-					$data .= $doc->saveXML($child);
-				}
-				$this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Content);
-				break;
-			default:
-				throw new Exception('Type is currently not supported');
-				return;
-		}
-		
-		$encMethod = $this->encdoc->documentElement->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
-		$encMethod->setAttribute('Algorithm', $objKey->getAlgorith());
-		$cipherValue->parentNode->parentNode->insertBefore($encMethod, $cipherValue->parentNode);
-		
-		$strEncrypt = base64_encode($objKey->encryptData($data));
-		$value = $this->encdoc->createTextNode($strEncrypt);
-		$cipherValue->appendChild($value);
-
-		if ($replace) {
-			switch ($this->type) {
-				case (XMLSecEnc::Element):
-					if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
-						return $this->encdoc;
-					}
-					$importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE);
-					$this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
-					return $importEnc;
-					break;
-				case (XMLSecEnc::Content):
-					$importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE);
-					while($this->rawNode->firstChild) {
-						$this->rawNode->removeChild($this->rawNode->firstChild);
-					}
-					$this->rawNode->appendChild($importEnc);
-					return $importEnc;
-					break;
-			}
-		}
-	}
-
-	public function decryptNode($objKey, $replace=TRUE) {
-		$data = '';
-		if (empty($this->rawNode)) {
-			throw new Exception('Node to decrypt has not been set');
-		}
-		if (! $objKey instanceof XMLSecurityKey) {
-			throw new Exception('Invalid Key');
-		}
-		$doc = $this->rawNode->ownerDocument;
-		$xPath = new DOMXPath($doc);
-		$xPath->registerNamespace('xmlencr', XMLSecEnc::XMLENCNS);
-		/* Only handles embedded content right now and not a reference */
-		$query = "./xmlencr:CipherData/xmlencr:CipherValue";
-		$nodeset = $xPath->query($query, $this->rawNode);
-
-		if ($node = $nodeset->item(0)) {
-			$encryptedData = base64_decode($node->nodeValue);
-			$decrypted = $objKey->decryptData($encryptedData);
-			if ($replace) {
-				switch ($this->type) {
-					case (XMLSecEnc::Element):
-						$newdoc = new DOMDocument();
-						$newdoc->loadXML($decrypted);
-						if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
-							return $newdoc;
-						}
-						$importEnc = $this->rawNode->ownerDocument->importNode($newdoc->documentElement, TRUE);
-						$this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
-						return $importEnc;
-						break;
-					case (XMLSecEnc::Content):
-						if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
-							$doc = $this->rawNode;
-						} else {
-							$doc = $this->rawNode->ownerDocument;
-						}
-						$newFrag = $doc->createDOMDocumentFragment();
-						$newFrag->appendXML($decrypted);
-						$this->rawNode->parentNode->replaceChild($newFrag, $this->rawNode);
-						return $this->rawNode->parentNode;
-						break;
-					default:
-						return $decrypted;
-				}
-			} else {
-				return $decrypted;
-			}
-		} else {
-			throw new Exception("Cannot locate encrypted data");
-		}
-	}
-
-	public function encryptKey($srcKey, $rawKey, $append=TRUE) {
-		if ((! $srcKey instanceof XMLSecurityKey) || (! $rawKey instanceof XMLSecurityKey)) {
-			throw new Exception('Invalid Key');
-		}
-		$strEncKey = base64_encode($srcKey->encryptData($rawKey->key));
-		$root = $this->encdoc->documentElement;
-		$encKey = $this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptedKey');
-		if ($append) {
-			$keyInfo = $root->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'));
-			$keyInfo->appendChild($encKey);
-		} else {
-			$this->encKey = $encKey;
-		}
-		$encMethod = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
-		$encMethod->setAttribute('Algorithm', $srcKey->getAlgorith());
-		if (! empty($srcKey->name)) {
-			$keyInfo = $encKey->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'));
-			$keyInfo->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyName', $srcKey->name));
-		}
-		$cipherData = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherData'));
-		$cipherData->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherValue', $strEncKey));
-		return;
-	}
-	
-	public function decryptKey($encKey) {
-		if (! $encKey->isEncrypted) {
-			throw new Exception("Key is not Encrypted");
-		}
-		if (empty($encKey->key)) {
-			throw new Exception("Key is missing data to perform the decryption");
-		}
-		return $this->decryptNode($encKey, FALSE);
-	}
-	
-	public function locateEncryptedData($element) {
-		if ($element instanceof DOMDocument) {
-			$doc = $element;
-		} else {
-			$doc = $element->ownerDocument;
-		}
-		if ($doc) {
-			$xpath = new DOMXPath($doc);
-			$query = "//*[local-name()='EncryptedData' and namespace-uri()='".XMLSecEnc::XMLENCNS."']";
-			$nodeset = $xpath->query($query);
-			return $nodeset->item(0);
-		}
-		return NULL;
-	}
-	
-	public function locateKey($node=NULL) {
-		if (empty($node)) {
-			$node = $this->rawNode;
-		}
-		if (! $node instanceof DOMNode) {
-			return NULL;
-		}
-		if ($doc = $node->ownerDocument) {
-			$xpath = new DOMXPath($doc);
-			$xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
-			$query = ".//xmlsecenc:EncryptionMethod";
-			$nodeset = $xpath->query($query, $node);
-			if ($encmeth = $nodeset->item(0)) {
-   				$attrAlgorithm = $encmeth->getAttribute("Algorithm");
-				try {
-					$objKey = new XMLSecurityKey($attrAlgorithm, array('type'=>'private'));
-				} catch (Exception $e) {
-					return NULL;
-				}
-				return $objKey;
-			}
-		}
-		return NULL;
-	}
-	
-	static function staticLocateKeyInfo($objBaseKey=NULL, $node=NULL) {
-		if (empty($node) || (! $node instanceof DOMNode)) {
-			return NULL;
-		}
-		if ($doc = $node->ownerDocument) {
-			$xpath = new DOMXPath($doc);
-			$xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
-			$xpath->registerNamespace('xmlsecdsig', XMLSecurityDSig::XMLDSIGNS);
-			$query = "./xmlsecdsig:KeyInfo";
-			$nodeset = $xpath->query($query, $node);
-			if ($encmeth = $nodeset->item(0)) {
-				foreach ($encmeth->childNodes AS $child) {
-					switch ($child->localName) {
-						case 'KeyName':
-							if (! empty($objBaseKey)) {
-								$objBaseKey->name = $child->nodeValue;
-							}
-							break;
-						case 'KeyValue':
-							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':
-							/* Not currently supported */
-							break;
-						case 'EncryptedKey':
-							$objenc = new XMLSecEnc();
-							$objenc->setNode($child);
-							if (! $objKey = $objenc->locateKey()) {
-								throw new Exception("Unable to locate algorithm for this Encrypted Key");
-							}
-							$objKey->isEncrypted = TRUE;
-							$objKey->encryptedCtx = $objenc;
-							XMLSecEnc::staticLocateKeyInfo($objKey, $child);
-							return $objKey;
-							break;
-						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);
-								}
-							}
-							break;
-					}
-				}
-			}
-			return $objBaseKey;
-		}
-		return NULL;
-	}
-	
-	public function locateKeyInfo($objBaseKey=NULL, $node=NULL) {
-		if (empty($node)) {
-			$node = $this->rawNode;
-		}
-		return XMLSecEnc::staticLocateKeyInfo($objBaseKey, $node);
-	}
-}
+<?php
+/**
+ * xmlseclibs.php
+ *
+ * Copyright (c) 2007, Robert Richards <rrichards@cdatazone.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *
+ *   * Neither the name of Robert Richards nor the names of his
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @author     Robert Richards <rrichards@cdatazone.org>
+ * @copyright  2007 Robert Richards <rrichards@cdatazone.org>
+ * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
+ * @version    1.2.0
+ */
+
+/*
+Functions to generate simple cases of Exclusive Canonical XML - Callable function is C14NGeneral()
+i.e.: $canonical = C14NGeneral($domelement, TRUE);
+*/
+
+/* helper function */
+function sortAndAddAttrs($element, $arAtts) {
+   $newAtts = array();
+   foreach ($arAtts AS $attnode) {
+      $newAtts[$attnode->nodeName] = $attnode;
+   }
+   ksort($newAtts);
+   foreach ($newAtts as $attnode) {
+      $element->setAttribute($attnode->nodeName, $attnode->nodeValue);
+   }
+}
+
+/* helper function */
+function canonical($tree, $element, $withcomments) {
+    if ($tree->nodeType != XML_DOCUMENT_NODE) {
+        $dom = $tree->ownerDocument;
+    } else {
+        $dom = $tree;
+    }
+    if ($element->nodeType != XML_ELEMENT_NODE) {
+        if ($element->nodeType == XML_COMMENT_NODE && ! $withcomments) {
+            return;
+        }
+        $tree->appendChild($dom->importNode($element, TRUE));
+        return;
+    }
+    $arNS = array();
+    if ($element->namespaceURI != "") {
+        if ($element->prefix == "") {
+            $elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName);
+        } else {
+            $prefix = $tree->lookupPrefix($element->namespaceURI);
+            if ($prefix == $element->prefix) {
+                $elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName);
+            } else {
+                $elCopy = $dom->createElement($element->nodeName);
+                $arNS[$element->namespaceURI] = $element->prefix;
+            }
+        }
+    } else {
+        $elCopy = $dom->createElement($element->nodeName);
+    }
+    $tree->appendChild($elCopy);
+
+    /* Create DOMXPath based on original document */
+    $xPath = new DOMXPath($element->ownerDocument);
+
+    /* Get namespaced attributes */
+    $arAtts = $xPath->query('attribute::*[namespace-uri(.) != ""]', $element);
+
+    /* Create an array with namespace URIs as keys, and sort them */
+    foreach ($arAtts AS $attnode) {
+        if (array_key_exists($attnode->namespaceURI, $arNS) &&
+            ($arNS[$attnode->namespaceURI] == $attnode->prefix)) {
+            continue;
+        }
+        $prefix = $tree->lookupPrefix($attnode->namespaceURI);
+        if ($prefix != $attnode->prefix) {
+           $arNS[$attnode->namespaceURI] = $attnode->prefix;
+        } else {
+            $arNS[$attnode->namespaceURI] = NULL;
+        }
+    }
+    if (count($arNS) > 0) {
+        asort($arNS);
+    }
+
+    /* Add namespace nodes */
+    foreach ($arNS AS $namespaceURI=>$prefix) {
+        if ($prefix != NULL) {
+              $elCopy->setAttributeNS("http://www.w3.org/2000/xmlns/",
+                               "xmlns:".$prefix, $namespaceURI);
+        }
+    }
+    if (count($arNS) > 0) {
+        ksort($arNS);
+    }
+
+    /* Get attributes not in a namespace, and then sort and add them */
+    $arAtts = $xPath->query('attribute::*[namespace-uri(.) = ""]', $element);
+    sortAndAddAttrs($elCopy, $arAtts);
+
+    /* Loop through the URIs, and then sort and add attributes within that namespace */
+    foreach ($arNS as $nsURI=>$prefix) {
+       $arAtts = $xPath->query('attribute::*[namespace-uri(.) = "'.$nsURI.'"]', $element);
+       sortAndAddAttrs($elCopy, $arAtts);
+    }
+
+    foreach ($element->childNodes AS $node) {
+        canonical($elCopy, $node, $withcomments);
+    }
+}
+
+/*
+$element - DOMElement for which to produce the canonical version of
+$exclusive - boolean to indicate exclusive canonicalization (must pass TRUE)
+$withcomments - boolean indicating wether or not to include comments in canonicalized form
+*/
+function C14NGeneral($element, $exclusive=FALSE, $withcomments=FALSE) {
+    /* IF PHP 5.2+ then use built in canonical functionality */
+    $php_version = explode('.', PHP_VERSION);
+    if (($php_version[0] > 5) || ($php_version[0] == 5 && $php_version[1] >= 2) ) {
+        return $element->C14N($exclusive, $withcomments);
+    }
+
+    /* Must be element */
+    if (! $element instanceof DOMElement) {
+        return NULL;
+    }
+    /* Currently only exclusive XML is supported */
+    if ($exclusive == FALSE) {
+        throw new Exception("Only exclusive canonicalization is supported in this version of PHP");
+    }
+
+    $copyDoc = new DOMDocument();
+    canonical($copyDoc, $element, $withcomments);
+    return $copyDoc->saveXML($copyDoc->documentElement, LIBXML_NOEMPTYTAG);
+}
+
+class XMLSecurityKey {
+    const TRIPLEDES_CBC = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
+    const AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
+    const AES192_CBC = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
+    const AES256_CBC = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
+    const RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
+    const RSA_OAEP_MGF1P = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
+    const RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
+    const DSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1';
+
+    private $cryptParams = array();
+    public $type = 0;
+    public $key = NULL;
+    public $passphrase = "";
+    public $iv = NULL;
+    public $name = NULL;
+    public $keyChain = NULL;
+    public $isEncrypted = FALSE;
+    public $encryptedCtx = NULL;
+    public $guid = NULL;
+
+    public function __construct($type, $params=NULL) {
+        srand();
+        switch ($type) {
+            case (XMLSecurityKey::TRIPLEDES_CBC):
+                $this->cryptParams['library'] = 'mcrypt';
+                $this->cryptParams['cipher'] = MCRYPT_TRIPLEDES;
+                $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
+                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
+                break;
+            case (XMLSecurityKey::AES128_CBC):
+                $this->cryptParams['library'] = 'mcrypt';
+                $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
+                $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
+                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
+                break;
+            case (XMLSecurityKey::AES192_CBC):
+                $this->cryptParams['library'] = 'mcrypt';
+                $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
+                $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
+                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
+                break;
+            case (XMLSecurityKey::AES256_CBC):
+                $this->cryptParams['library'] = 'mcrypt';
+                $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
+                $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
+                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
+                break;
+            case (XMLSecurityKey::RSA_1_5):
+                $this->cryptParams['library'] = 'openssl';
+                $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
+                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
+                if (is_array($params) && ! empty($params['type'])) {
+                    if ($params['type'] == 'public' || $params['type'] == 'private') {
+                        $this->cryptParams['type'] = $params['type'];
+                        break;
+                    }
+                }
+                throw new Exception('Certificate "type" (private/public) must be passed via parameters');
+                return;
+            case (XMLSecurityKey::RSA_OAEP_MGF1P):
+                $this->cryptParams['library'] = 'openssl';
+                $this->cryptParams['padding'] = OPENSSL_PKCS1_OAEP_PADDING;
+                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
+                $this->cryptParams['hash'] = NULL;
+                if (is_array($params) && ! empty($params['type'])) {
+                    if ($params['type'] == 'public' || $params['type'] == 'private') {
+                        $this->cryptParams['type'] = $params['type'];
+                        break;
+                    }
+                }
+                throw new Exception('Certificate "type" (private/public) must be passed via parameters');
+                return;
+            case (XMLSecurityKey::RSA_SHA1):
+                $this->cryptParams['library'] = 'openssl';
+                $this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
+                if (is_array($params) && ! empty($params['type'])) {
+                    if ($params['type'] == 'public' || $params['type'] == 'private') {
+                        $this->cryptParams['type'] = $params['type'];
+                        break;
+                    }
+                }
+                throw new Exception('Certificate "type" (private/public) must be passed via parameters');
+                break;
+            default:
+                throw new Exception('Invalid Key Type');
+                return;
+        }
+        $this->type = $type;
+    }
+
+    public function generateSessionKey() {
+        $key = '';
+        if (! empty($this->cryptParams['cipher']) && ! empty($this->cryptParams['mode'])) {
+            $keysize = mcrypt_module_get_algo_key_size($this->cryptParams['cipher']);
+            /* Generating random key using iv generation routines */
+            if (($keysize > 0) && ($td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '',$this->cryptParams['mode'], ''))) {
+                if ($this->cryptParams['cipher'] == MCRYPT_RIJNDAEL_128) {
+                    $keysize = 16;
+                    if ($this->type == XMLSecurityKey::AES256_CBC) {
+                        $keysize = 32;
+                    } elseif ($this->type == XMLSecurityKey::AES192_CBC) {
+                        $keysize = 24;
+                    }
+                }
+                while (strlen($key) < $keysize) {
+                    $key .= mcrypt_create_iv(mcrypt_enc_get_iv_size ($td),MCRYPT_RAND);
+                }
+                mcrypt_module_close($td);
+                $key = substr($key, 0, $keysize);
+                $this->key = $key;
+            }
+        }
+        return $key;
+    }
+
+    public function loadKey($key, $isFile=FALSE, $isCert = FALSE) {
+        if ($isFile) {
+            $this->key = file_get_contents($key);
+        } else {
+            $this->key = $key;
+        }
+        if ($isCert) {
+            $this->key = openssl_x509_read($this->key);
+            openssl_x509_export($this->key, $str_cert);
+            $this->key = $str_cert;
+        }
+        if ($this->cryptParams['library'] == 'openssl') {
+            if ($this->cryptParams['type'] == 'public') {
+                $this->key = openssl_get_publickey($this->key);
+            } else {
+                $this->key = openssl_get_privatekey($this->key, $this->passphrase);
+            }
+        } else if ($this->cryptParams['cipher'] == MCRYPT_RIJNDAEL_128) {
+            /* Check key length */
+            switch ($this->type) {
+                case (XMLSecurityKey::AES256_CBC):
+                    if (strlen($this->key) < 25) {
+                        throw new Exception('Key must contain at least 25 characters for this cipher');
+                    }
+                    break;
+                case (XMLSecurityKey::AES192_CBC):
+                    if (strlen($this->key) < 17) {
+                        throw new Exception('Key must contain at least 17 characters for this cipher');
+                    }
+                    break;
+            }
+        }
+    }
+
+    private function encryptMcrypt($data) {
+        $td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
+        $this->iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
+        mcrypt_generic_init($td, $this->key, $this->iv);
+        if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) {
+            $bs = mcrypt_enc_get_block_size($td);
+            for ($datalen0=$datalen=strlen($data); (($datalen%$bs)!=($bs-1)); $datalen++)
+                $data.=chr(rand(1, 127));
+            $data.=chr($datalen-$datalen0+1);
+        }
+        $encrypted_data = $this->iv.mcrypt_generic($td, $data);
+        mcrypt_generic_deinit($td);
+        mcrypt_module_close($td);
+        return $encrypted_data;
+    }
+
+    private function decryptMcrypt($data) {
+        $td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
+        $iv_length = mcrypt_enc_get_iv_size($td);
+
+        $this->iv = substr($data, 0, $iv_length);
+        $data = substr($data, $iv_length);
+
+        mcrypt_generic_init($td, $this->key, $this->iv);
+        $decrypted_data = mdecrypt_generic($td, $data);
+        mcrypt_generic_deinit($td);
+        mcrypt_module_close($td);
+        if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) {
+            $dataLen = strlen($decrypted_data);
+            $paddingLength = substr($decrypted_data, $dataLen - 1, 1);
+            $decrypted_data = substr($decrypted_data, 0, $dataLen - ord($paddingLength));
+        }
+        return $decrypted_data;
+    }
+
+    private function encryptOpenSSL($data) {
+        if ($this->cryptParams['type'] == 'public') {
+            if (! openssl_public_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
+                throw new Exception('Failure encrypting Data');
+                return;
+            }
+        } else {
+            if (! openssl_private_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
+                throw new Exception('Failure encrypting Data');
+                return;
+            }
+        }
+        return $encrypted_data;
+    }
+
+    private function decryptOpenSSL($data) {
+        if ($this->cryptParams['type'] == 'public') {
+            if (! openssl_public_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
+                throw new Exception('Failure decrypting Data');
+                return;
+            }
+        } else {
+            if (! openssl_private_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
+                throw new Exception('Failure decrypting Data');
+                return;
+            }
+        }
+        return $decrypted;
+    }
+
+    private function signOpenSSL($data) {
+        if (! openssl_sign ($data, $signature, $this->key)) {
+            throw new Exception('Failure Signing Data');
+            return;
+        }
+        return $signature;
+    }
+
+    private function verifyOpenSSL($data, $signature) {
+        return openssl_verify ($data, $signature, $this->key);
+    }
+
+    public function encryptData($data) {
+        switch ($this->cryptParams['library']) {
+            case 'mcrypt':
+                return $this->encryptMcrypt($data);
+                break;
+            case 'openssl':
+                return $this->encryptOpenSSL($data);
+                break;
+        }
+    }
+
+    public function decryptData($data) {
+        switch ($this->cryptParams['library']) {
+            case 'mcrypt':
+                return $this->decryptMcrypt($data);
+                break;
+            case 'openssl':
+                return $this->decryptOpenSSL($data);
+                break;
+        }
+    }
+
+    public function signData($data) {
+        switch ($this->cryptParams['library']) {
+            case 'openssl':
+                return $this->signOpenSSL($data);
+                break;
+        }
+    }
+
+    public function verifySignature($data, $signature) {
+        switch ($this->cryptParams['library']) {
+            case 'openssl':
+                return $this->verifyOpenSSL($data, $signature);
+                break;
+        }
+    }
+
+    public function getAlgorith() {
+        return $this->cryptParams['method'];
+    }
+
+    static function makeAsnSegment($type, $string) {
+        switch ($type){
+            case 0x02:
+                if (ord($string) > 0x7f)
+                    $string = chr(0).$string;
+                break;
+            case 0x03:
+                $string = chr(0).$string;
+                break;
+        }
+
+        $length = strlen($string);
+
+        if ($length < 128){
+           $output = sprintf("%c%c%s", $type, $length, $string);
+        } else if ($length < 0x0100){
+           $output = sprintf("%c%c%c%s", $type, 0x81, $length, $string);
+        } else if ($length < 0x010000) {
+           $output = sprintf("%c%c%c%c%s", $type, 0x82, $length/0x0100, $length%0x0100, $string);
+        } else {
+            $output = NULL;
+        }
+        return($output);
+    }
+
+    /* Modulus and Exponent must already be base64 decoded */
+    static function convertRSA($modulus, $exponent) {
+        /* make an ASN publicKeyInfo */
+        $exponentEncoding = XMLSecurityKey::makeAsnSegment(0x02, $exponent);
+        $modulusEncoding = XMLSecurityKey::makeAsnSegment(0x02, $modulus);
+        $sequenceEncoding = XMLSecurityKey:: makeAsnSegment(0x30, $modulusEncoding.$exponentEncoding);
+        $bitstringEncoding = XMLSecurityKey::makeAsnSegment(0x03, $sequenceEncoding);
+        $rsaAlgorithmIdentifier = pack("H*", "300D06092A864886F70D0101010500");
+        $publicKeyInfo = XMLSecurityKey::makeAsnSegment (0x30, $rsaAlgorithmIdentifier.$bitstringEncoding);
+
+        /* encode the publicKeyInfo in base64 and add PEM brackets */
+        $publicKeyInfoBase64 = base64_encode($publicKeyInfo);
+        $encoding = "-----BEGIN PUBLIC KEY-----\n";
+        $offset = 0;
+        while ($segment=substr($publicKeyInfoBase64, $offset, 64)){
+           $encoding = $encoding.$segment."\n";
+           $offset += 64;
+        }
+        return $encoding."-----END PUBLIC KEY-----\n";
+    }
+
+    public function serializeKey($parent) {
+
+    }
+}
+
+class XMLSecurityDSig {
+    const XMLDSIGNS = 'http://www.w3.org/2000/09/xmldsig#';
+    const SHA1 = 'http://www.w3.org/2000/09/xmldsig#sha1';
+    const SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256';
+    const SHA512 = 'http://www.w3.org/2001/04/xmlenc#sha512';
+    const RIPEMD160 = 'http://www.w3.org/2001/04/xmlenc#ripemd160';
+
+    const C14N = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
+    const C14N_COMMENTS = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments';
+    const EXC_C14N = 'http://www.w3.org/2001/10/xml-exc-c14n#';
+    const EXC_C14N_COMMENTS = 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments';
+
+    const template = '<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+  <ds:SignedInfo>
+    <ds:SignatureMethod />
+  </ds:SignedInfo>
+</ds:Signature>';
+
+    public $sigNode = NULL;
+    public $idKeys = array();
+    public $idNS = array();
+    private $signedInfo = NULL;
+    private $xPathCtx = NULL;
+    private $canonicalMethod = NULL;
+    private $prefix = 'ds';
+    private $searchpfx = 'secdsig';
+
+    public function __construct() {
+        $sigdoc = new DOMDocument();
+        $sigdoc->loadXML(XMLSecurityDSig::template);
+        $this->sigNode = $sigdoc->documentElement;
+    }
+
+    private function getXPathObj() {
+        if (empty($this->xPathCtx) && ! empty($this->sigNode)) {
+            $xpath = new DOMXPath($this->sigNode->ownerDocument);
+            $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+            $this->xPathCtx = $xpath;
+        }
+        return $this->xPathCtx;
+    }
+
+    static function generate_GUID($prefix='pfx') {
+        $uuid = md5(uniqid(rand(), true));
+        $guid =  $prefix.substr($uuid,0,8)."-".
+                substr($uuid,8,4)."-".
+                substr($uuid,12,4)."-".
+                substr($uuid,16,4)."-".
+                substr($uuid,20,12);
+        return $guid;
+    }
+
+    public function locateSignature($objDoc) {
+        if ($objDoc instanceof DOMDocument) {
+            $doc = $objDoc;
+        } else {
+            $doc = $objDoc->ownerDocument;
+        }
+        if ($doc) {
+            $xpath = new DOMXPath($doc);
+            $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+            $query = ".//secdsig:Signature";
+            $nodeset = $xpath->query($query, $objDoc);
+            $this->sigNode = $nodeset->item(0);
+            return $this->sigNode;
+        }
+        return NULL;
+    }
+
+    public function createNewSignNode($name, $value=NULL) {
+        $doc = $this->sigNode->ownerDocument;
+        if (! is_null($value)) {
+            $node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $this->prefix.':'.$name, $value);
+        } else {
+            $node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $this->prefix.':'.$name);
+        }
+        return $node;
+    }
+
+    public function setCanonicalMethod($method) {
+        switch ($method) {
+            case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
+            case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
+            case 'http://www.w3.org/2001/10/xml-exc-c14n#':
+            case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
+                $this->canonicalMethod = $method;
+                break;
+            default:
+                throw new Exception('Invalid Canonical Method');
+        }
+        if ($xpath = $this->getXPathObj()) {
+            $query = './'.$this->searchpfx.':SignedInfo';
+            $nodeset = $xpath->query($query, $this->sigNode);
+            if ($sinfo = $nodeset->item(0)) {
+                $query = './'.$this->searchpfx.'CanonicalizationMethod';
+                $nodeset = $xpath->query($query, $sinfo);
+                if (! ($canonNode = $nodeset->item(0))) {
+                    $canonNode = $this->createNewSignNode('CanonicalizationMethod');
+                    $sinfo->insertBefore($canonNode, $sinfo->firstChild);
+                }
+                $canonNode->setAttribute('Algorithm', $this->canonicalMethod);
+            }
+        }
+    }
+
+    private function canonicalizeData($node, $canonicalmethod, $arXPath=NULL, $prefixList=NULL) {
+        $exclusive = FALSE;
+        $withComments = FALSE;
+        switch ($canonicalmethod) {
+            case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
+                $exclusive = FALSE;
+                $withComments = FALSE;
+                break;
+            case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
+                $withComments = TRUE;
+                break;
+            case 'http://www.w3.org/2001/10/xml-exc-c14n#':
+                $exclusive = TRUE;
+                break;
+            case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
+                $exclusive = TRUE;
+                $withComments = TRUE;
+                break;
+        }
+/* Support PHP versions < 5.2 not containing C14N methods in DOM extension */
+        $php_version = explode('.', PHP_VERSION);
+        if (($php_version[0] < 5) || ($php_version[0] == 5 && $php_version[1] < 2) ) {
+            if (! is_null($arXPath)) {
+                throw new Exception("PHP 5.2.0 or higher is required to perform XPath Transformations");
+            }
+            return C14NGeneral($node, $exclusive, $withComments);
+        }
+        return $node->C14N($exclusive, $withComments, $arXPath, $prefixList);
+    }
+
+    public function canonicalizeSignedInfo() {
+
+        $doc = $this->sigNode->ownerDocument;
+        $canonicalmethod = NULL;
+        if ($doc) {
+            $xpath = $this->getXPathObj();
+            $query = "./secdsig:SignedInfo";
+            $nodeset = $xpath->query($query, $this->sigNode);
+            if ($signInfoNode = $nodeset->item(0)) {
+                $query = "./secdsig:CanonicalizationMethod";
+                $nodeset = $xpath->query($query, $signInfoNode);
+                if ($canonNode = $nodeset->item(0)) {
+                    $canonicalmethod = $canonNode->getAttribute('Algorithm');
+                }
+                $this->signedInfo = $this->canonicalizeData($signInfoNode, $canonicalmethod);
+                return $this->signedInfo;
+            }
+        }
+        return NULL;
+    }
+
+    public function calculateDigest ($digestAlgorithm, $data) {
+        switch ($digestAlgorithm) {
+            case XMLSecurityDSig::SHA1:
+                $alg = 'sha1';
+                break;
+            case XMLSecurityDSig::SHA256:
+                $alg = 'sha256';
+                break;
+            case XMLSecurityDSig::SHA512:
+                $alg = 'sha512';
+                break;
+            case XMLSecurityDSig::RIPEMD160:
+                $alg = 'ripemd160';
+                break;
+            default:
+                throw new Exception("Cannot validate digest: Unsupported Algorith <$digestAlgorithm>");
+        }
+        return base64_encode(hash($alg, $data, TRUE));
+    }
+
+    public function validateDigest($refNode, $data) {
+        $xpath = new DOMXPath($refNode->ownerDocument);
+        $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+        $query = 'string(./secdsig:DigestMethod/@Algorithm)';
+        $digestAlgorithm = $xpath->evaluate($query, $refNode);
+        $digValue = $this->calculateDigest($digestAlgorithm, $data);
+        $query = 'string(./secdsig:DigestValue)';
+        $digestValue = $xpath->evaluate($query, $refNode);
+        return ($digValue == $digestValue);
+    }
+
+    public function processTransforms($refNode, $objData) {
+        $data = $objData;
+        $xpath = new DOMXPath($refNode->ownerDocument);
+        $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+        $query = './secdsig:Transforms/secdsig:Transform';
+        $nodelist = $xpath->query($query, $refNode);
+        $canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
+        $arXPath = NULL;
+        $prefixList = NULL;
+        foreach ($nodelist AS $transform) {
+            $algorithm = $transform->getAttribute("Algorithm");
+            switch ($algorithm) {
+                case 'http://www.w3.org/2001/10/xml-exc-c14n#':
+                case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
+                    $node = $transform->firstChild;
+                    while ($node) {
+                        if ($node->localName == 'InclusiveNamespaces') {
+                            if ($pfx = $node->getAttribute('PrefixList')) {
+                                $arpfx = array();
+                                $pfxlist = split(" ", $pfx);
+                                foreach ($pfxlist AS $pfx) {
+                                    $val = trim($pfx);
+                                    if (! empty($val)) {
+                                        $arpfx[] = $val;
+                                    }
+                                }
+                                if (count($arpfx) > 0) {
+                                    $prefixList = $arpfx;
+                                }
+                            }
+                            break;
+                        }
+                        $node = $node->nextSibling;
+                    }
+                case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
+                case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
+                    $canonicalMethod = $algorithm;
+                    break;
+                case 'http://www.w3.org/TR/1999/REC-xpath-19991116':
+                    $node = $transform->firstChild;
+                    while ($node) {
+                        if ($node->localName == 'XPath') {
+                            $arXPath = array();
+                            $arXPath['query'] = '(.//. | .//@* | .//namespace::*)['.$node->nodeValue.']';
+                            $arXpath['namespaces'] = array();
+                            $nslist = $xpath->query('./namespace::*', $node);
+                            foreach ($nslist AS $nsnode) {
+                                if ($nsnode->localName != "xml") {
+                                    $arXPath['namespaces'][$nsnode->localName] = $nsnode->nodeValue;
+                                }
+                            }
+                            break;
+                        }
+                        $node = $node->nextSibling;
+                    }
+                    break;
+            }
+        }
+        if ($data instanceof DOMNode) {
+            $data = $this->canonicalizeData($objData, $canonicalMethod, $arXPath, $prefixList);
+        }
+        return $data;
+    }
+
+    public function processRefNode($refNode) {
+        $dataObject = NULL;
+        if ($uri = $refNode->getAttribute("URI")) {
+            $arUrl = parse_url($uri);
+            if (empty($arUrl['path'])) {
+                if ($identifier = $arUrl['fragment']) {
+                    $xPath = new DOMXPath($refNode->ownerDocument);
+                    if ($this->idNS && is_array($this->idNS)) {
+                        foreach ($this->idNS AS $nspf=>$ns) {
+                            $xPath->registerNamespace($nspf, $ns);
+                        }
+                    }
+                    $iDlist = '@Id="'.$identifier.'"';
+                    if (is_array($this->idKeys)) {
+                        foreach ($this->idKeys AS $idKey) {
+                            $iDlist .= " or @$idKey='$identifier'";
+                        }
+                    }
+                    $query = '//*['.$iDlist.']';
+                    $dataObject = $xPath->query($query)->item(0);
+                } else {
+                    $dataObject = $refNode->ownerDocument;
+                }
+            } else {
+                $dataObject = file_get_contents($arUrl);
+            }
+        } else {
+            $dataObject = $refNode->ownerDocument;
+        }
+        $data = $this->processTransforms($refNode, $dataObject);
+        return $this->validateDigest($refNode, $data);
+    }
+
+    public function getRefNodeID($refNode) {
+        if ($uri = $refNode->getAttribute("URI")) {
+            $arUrl = parse_url($uri);
+            if (empty($arUrl['path'])) {
+                if ($identifier = $arUrl['fragment']) {
+                    return $identifier;
+                }
+            }
+        }
+        return null;
+    }
+
+    public function getRefIDs() {
+        $refids = array();
+        $doc = $this->sigNode->ownerDocument;
+
+        $xpath = $this->getXPathObj();
+        $query = "./secdsig:SignedInfo/secdsig:Reference";
+        $nodeset = $xpath->query($query, $this->sigNode);
+        if ($nodeset->length == 0) {
+            throw new Exception("Reference nodes not found");
+        }
+        foreach ($nodeset AS $refNode) {
+            $refids[] = $this->getRefNodeID($refNode);
+        }
+        return $refids;
+    }
+
+    public function validateReference() {
+        $doc = $this->sigNode->ownerDocument;
+        if (! $doc->isSameNode($this->sigNode)) {
+            $this->sigNode->parentNode->removeChild($this->sigNode);
+        }
+        $xpath = $this->getXPathObj();
+        $query = "./secdsig:SignedInfo/secdsig:Reference";
+        $nodeset = $xpath->query($query, $this->sigNode);
+        if ($nodeset->length == 0) {
+            throw new Exception("Reference nodes not found");
+        }
+        foreach ($nodeset AS $refNode) {
+            if (! $this->processRefNode($refNode)) {
+                throw new Exception("Reference validation failed");
+            }
+        }
+        return TRUE;
+    }
+
+    private function addRefInternal($sinfoNode, $node, $algorithm, $arTransforms=NULL, $options=NULL) {
+        $prefix = NULL;
+        $prefix_ns = NULL;
+        $id_name = 'Id';
+        $overwrite_id  = TRUE;
+
+        if (is_array($options)) {
+            $prefix = empty($options['prefix'])?NULL:$options['prefix'];
+            $prefix_ns = empty($options['prefix_ns'])?NULL:$options['prefix_ns'];
+            $id_name = empty($options['id_name'])?'Id':$options['id_name'];
+            $overwrite_id = empty($options['overwrite'])?TRUE:(bool)$options['overwrite'];
+        }
+
+        $attname = $id_name;
+        if (! empty($prefix)) {
+            $attname = $prefix.':'.$attname;
+        }
+
+        $refNode = $this->createNewSignNode('Reference');
+        $sinfoNode->appendChild($refNode);
+
+        if (! $node instanceof DOMDocument) {
+            $uri = NULL;
+            if (! $overwrite_id) {
+                $uri = $node->getAttributeNS($prefix_ns, $attname);
+            }
+            if (empty($uri)) {
+                $uri = XMLSecurityDSig::generate_GUID();
+                $node->setAttributeNS($prefix_ns, $attname, $uri);
+            }
+            $refNode->setAttribute("URI", '#'.$uri);
+        }
+
+        $transNodes = $this->createNewSignNode('Transforms');
+        $refNode->appendChild($transNodes);
+
+        if (is_array($arTransforms)) {
+            foreach ($arTransforms AS $transform) {
+                $transNode = $this->createNewSignNode('Transform');
+                $transNodes->appendChild($transNode);
+                $transNode->setAttribute('Algorithm', $transform);
+            }
+        } elseif (! empty($this->canonicalMethod)) {
+            $transNode = $this->createNewSignNode('Transform');
+            $transNodes->appendChild($transNode);
+            $transNode->setAttribute('Algorithm', $this->canonicalMethod);
+        }
+
+        $canonicalData = $this->processTransforms($refNode, $node);
+        $digValue = $this->calculateDigest($algorithm, $canonicalData);
+
+        $digestMethod = $this->createNewSignNode('DigestMethod');
+        $refNode->appendChild($digestMethod);
+        $digestMethod->setAttribute('Algorithm', $algorithm);
+
+        $digestValue = $this->createNewSignNode('DigestValue', $digValue);
+        $refNode->appendChild($digestValue);
+    }
+
+    public function addReference($node, $algorithm, $arTransforms=NULL, $options=NULL) {
+        if ($xpath = $this->getXPathObj()) {
+            $query = "./secdsig:SignedInfo";
+            $nodeset = $xpath->query($query, $this->sigNode);
+            if ($sInfo = $nodeset->item(0)) {
+                $this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
+            }
+        }
+    }
+
+    public function addReferenceList($arNodes, $algorithm, $arTransforms=NULL, $options=NULL) {
+        if ($xpath = $this->getXPathObj()) {
+            $query = "./secdsig:SignedInfo";
+            $nodeset = $xpath->query($query, $this->sigNode);
+            if ($sInfo = $nodeset->item(0)) {
+                foreach ($arNodes AS $node) {
+                    $this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
+                }
+            }
+        }
+    }
+
+   public function addObject($data, $mimetype=NULL, $encoding=NULL) {
+      $objNode = $this->createNewSignNode('Object');
+      $this->sigNode->appendChild($objNode);
+      if (! empty($mimetype)) {
+         $objNode->setAtribute('MimeType', $mimetype);
+      }
+      if (! empty($encoding)) {
+         $objNode->setAttribute('Encoding', $encoding);
+      }
+
+      if ($data instanceof DOMElement) {
+         $newData = $this->sigNode->ownerDocument->importNode($data, TRUE);
+      } else {
+         $newData = $this->sigNode->ownerDocument->createTextNode($data);
+      }
+      $objNode->appendChild($newData);
+
+      return $objNode;
+   }
+
+    public function locateKey($node=NULL) {
+        if (empty($node)) {
+            $node = $this->sigNode;
+        }
+        if (! $node instanceof DOMNode) {
+            return NULL;
+        }
+        if ($doc = $node->ownerDocument) {
+            $xpath = new DOMXPath($doc);
+            $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+            $query = "string(./secdsig:SignedInfo/secdsig:SignatureMethod/@Algorithm)";
+            $algorithm = $xpath->evaluate($query, $node);
+            if ($algorithm) {
+                try {
+                    $objKey = new XMLSecurityKey($algorithm, array('type'=>'public'));
+                } catch (Exception $e) {
+                    return NULL;
+                }
+                return $objKey;
+            }
+        }
+        return NULL;
+    }
+
+    public function verify($objKey) {
+        $doc = $this->sigNode->ownerDocument;
+        $xpath = new DOMXPath($doc);
+        $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+        $query = "string(./secdsig:SignatureValue)";
+        $sigValue = $xpath->evaluate($query, $this->sigNode);
+        if (empty($sigValue)) {
+            throw new Exception("Unable to locate SignatureValue");
+        }
+        return $objKey->verifySignature($this->signedInfo, base64_decode($sigValue));
+    }
+
+    public function signData($objKey, $data) {
+        return $objKey->signData($data);
+    }
+
+    public function sign($objKey) {
+        if ($xpath = $this->getXPathObj()) {
+            $query = "./secdsig:SignedInfo";
+            $nodeset = $xpath->query($query, $this->sigNode);
+            if ($sInfo = $nodeset->item(0)) {
+                $query = "./secdsig:SignatureMethod";
+                $nodeset = $xpath->query($query, $sInfo);
+                $sMethod = $nodeset->item(0);
+                $sMethod->setAttribute('Algorithm', $objKey->type);
+                $data = $this->canonicalizeData($sInfo, $this->canonicalMethod);
+                $sigValue = base64_encode($this->signData($objKey, $data));
+                $sigValueNode = $this->createNewSignNode('SignatureValue', $sigValue);
+                if ($infoSibling = $sInfo->nextSibling) {
+                    $infoSibling->parentNode->insertBefore($sigValueNode, $infoSibling);
+                } else {
+                    $this->sigNode->appendChild($sigValueNode);
+                }
+            }
+        }
+    }
+
+    public function appendCert() {
+
+    }
+
+    public function appendKey($objKey, $parent=NULL) {
+        $objKey->serializeKey($parent);
+    }
+
+
+	/*
+    public function appendSignature($parentNode, $insertBefore = FALSE) {
+        $baseDoc = ($parentNode instanceof DOMDocument)?$parentNode:$parentNode->ownerDocument;
+        $newSig = $baseDoc->importNode($this->sigNode, TRUE);
+        if ($insertBefore) {
+            $parentNode->insertBefore($newSig, $parentNode->firstChild);
+        } else {
+            $parentNode->appendChild($newSig);
+        }
+    }
+	*/
+	
+
+	public function appendSignatureShib($parentNode, $insertBefore = FALSE, $assertion = false) {
+		$baseDoc = ($parentNode instanceof DOMDocument)?$parentNode:$parentNode->ownerDocument;
+		$newSig = $baseDoc->importNode($this->sigNode, TRUE);
+
+	
+	
+		$xnode = null;
+		
+		$xpath = new DOMXPath($baseDoc);
+		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+		$xpath->registerNamespace('samlp', 'urn:oasis:names:tc:SAML:1.0:protocol');
+		$xpath->registerNamespace('saml', 'urn:oasis:names:tc:SAML:1.0:assertion');
+
+
+		if ($insertBefore && !$assertion) {
+
+			$query = "//samlp:Status";
+			$nodeset = $xpath->query($query, $parentNode);
+
+			$xnode = $nodeset->item(0);
+			if (!$xnode)
+				throw new Exception("Could not find node to sign before (Root signing mode)");
+		
+			$parentNode->insertBefore($newSig, $xnode);
+			
+		} elseif ($insertBefore) {
+			
+			$query = "//saml:Assertion/saml:Subject";
+			$nodeset = $xpath->query($query, $parentNode);
+
+			$xnode = $nodeset->item(0);
+			if (!$xnode)
+				throw new Exception("Could not find node to sign before (Assertion signing mode)");
+
+			$parentNode->insertBefore($newSig, $xnode);
+		} else {
+			$parentNode->appendChild($newSig);
+		}
+	}
+	
+	
+
+	public function appendSignature($parentNode, $insertBefore = false, $assertion = false) {
+		$baseDoc = ($parentNode instanceof DOMDocument)?$parentNode:$parentNode->ownerDocument;
+		$newSig = $baseDoc->importNode($this->sigNode, TRUE);
+
+	
+	
+		$xnode = null;
+		
+		$xpath = new DOMXPath($baseDoc);
+		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+		$xpath->registerNamespace('samlp', 'urn:oasis:names:tc:SAML:2.0:protocol');
+		$xpath->registerNamespace('saml', 'urn:oasis:names:tc:SAML:2.0:assertion');
+
+
+		if ($insertBefore && !$assertion) {
+
+			$query = "//samlp:Status";
+			$nodeset = $xpath->query($query, $parentNode);
+
+			$xnode = $nodeset->item(0);
+			if (!$xnode)
+				throw new Exception("Could not find node to sign before (Root signing mode)");
+		
+			$parentNode->insertBefore($newSig, $xnode);
+			
+		} elseif ($insertBefore) {
+			
+			$query = "//saml:Assertion/saml:Subject";
+			$nodeset = $xpath->query($query, $parentNode);
+
+			$xnode = $nodeset->item(0);
+			if (!$xnode)
+				throw new Exception("Could not find node to sign before (Assertion signing mode)");
+
+			$parentNode->insertBefore($newSig, $xnode);
+		} else {
+			$parentNode->appendChild($newSig);
+		}
+	}
+	
+    static function get509XCert($cert, $isPEMFormat=TRUE) {
+        $certs = XMLSecurityDSig::staticGet509XCerts($cert, $isPEMFormat);
+        if (! empty($certs)) {
+            return $certs[0];
+        }
+        return '';
+    }
+
+    static function staticGet509XCerts($certs, $isPEMFormat=TRUE) {
+        if ($isPEMFormat) {
+            $data = '';
+            $certlist = array();
+            $arCert = explode("\n", $certs);
+            $inData = FALSE;
+            foreach ($arCert AS $curData) {
+                if (! $inData) {
+                    if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
+                        $inData = TRUE;
+                    }
+                } else {
+                    if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
+                        $inData = FALSE;
+                        $certlist[] = $data;
+                        $data = '';
+                        continue;
+                    }
+                    $data .= trim($curData);
+                }
+            }
+            return $certlist;
+        } else {
+            return array($certs);
+        }
+    }
+
+    static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=TRUE, $isURL=False, $xpath=NULL) {
+          if ($isURL) {
+            $cert = file_get_contents($cert);
+          }
+          if (! $parentRef instanceof DOMElement) {
+            throw new Exception('Invalid parent Node parameter');
+          }
+          $baseDoc = $parentRef->ownerDocument;
+
+          if (empty($xpath)) {
+              $xpath = new DOMXPath($parentRef->ownerDocument);
+              $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
+          }
+
+         $query = "./secdsig:KeyInfo";
+         $nodeset = $xpath->query($query, $parentRef);
+         $keyInfo = $nodeset->item(0);
+         if (! $keyInfo) {
+              $inserted = FALSE;
+              $keyInfo = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:KeyInfo');
+
+               $query = "./secdsig:Object";
+               $nodeset = $xpath->query($query, $parentRef);
+               if ($sObject = $nodeset->item(0)) {
+                    $sObject->parentNode->insertBefore($keyInfo, $sObject);
+                    $inserted = TRUE;
+               }
+
+              if (! $inserted) {
+                   $parentRef->appendChild($keyInfo);
+              }
+         }
+
+         // Add all certs if there are more than one
+         $certs = XMLSecurityDSig::staticGet509XCerts($cert, $isPEMFormat);
+
+         // Atach X509 data node
+         $x509DataNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Data');
+         $keyInfo->appendChild($x509DataNode);
+
+         // Atach all certificate nodes
+         foreach ($certs as $X509Cert){
+            $x509CertNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Certificate', $X509Cert);
+         $x509DataNode->appendChild($x509CertNode);
+         }
+     }
+
+    public function add509Cert($cert, $isPEMFormat=TRUE, $isURL=False) {
+         if ($xpath = $this->getXPathObj()) {
+            self::staticAdd509Cert($this->sigNode, $cert, $isPEMFormat, $isURL, $xpath);
+         }
+    }
+}
+
+class XMLSecEnc {
+    const template = "<xenc:EncryptedData xmlns:xenc='http://www.w3.org/2001/04/xmlenc#'>
+   <xenc:CipherData>
+      <xenc:CipherValue></xenc:CipherValue>
+   </xenc:CipherData>
+</xenc:EncryptedData>";
+
+    const Element = 'http://www.w3.org/2001/04/xmlenc#Element';
+    const Content = 'http://www.w3.org/2001/04/xmlenc#Content';
+    const URI = 3;
+    const XMLENCNS = 'http://www.w3.org/2001/04/xmlenc#';
+
+    private $encdoc = NULL;
+    private $rawNode = NULL;
+    public $type = NULL;
+    public $encKey = NULL;
+
+    public function __construct() {
+        $this->encdoc = new DOMDocument();
+        $this->encdoc->loadXML(XMLSecEnc::template);
+    }
+
+    public function setNode($node) {
+        $this->rawNode = $node;
+    }
+
+    public function encryptNode($objKey, $replace=TRUE) {
+        $data = '';
+        if (empty($this->rawNode)) {
+            throw new Exception('Node to encrypt has not been set');
+        }
+        if (! $objKey instanceof XMLSecurityKey) {
+            throw new Exception('Invalid Key');
+        }
+        $doc = $this->rawNode->ownerDocument;
+        $xPath = new DOMXPath($this->encdoc);
+        $objList = $xPath->query('/xenc:EncryptedData/xenc:CipherData/xenc:CipherValue');
+        $cipherValue = $objList->item(0);
+        if ($cipherValue == NULL) {
+            throw new Exception('Error locating CipherValue element within template');
+        }
+        switch ($this->type) {
+            case (XMLSecEnc::Element):
+                $data = $doc->saveXML($this->rawNode);
+                $this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Element);
+                break;
+            case (XMLSecEnc::Content):
+                $children = $this->rawNode->childNodes;
+                foreach ($children AS $child) {
+                    $data .= $doc->saveXML($child);
+                }
+                $this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Content);
+                break;
+            default:
+                throw new Exception('Type is currently not supported');
+                return;
+        }
+
+        $encMethod = $this->encdoc->documentElement->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
+        $encMethod->setAttribute('Algorithm', $objKey->getAlgorith());
+        $cipherValue->parentNode->parentNode->insertBefore($encMethod, $cipherValue->parentNode);
+
+        $strEncrypt = base64_encode($objKey->encryptData($data));
+        $value = $this->encdoc->createTextNode($strEncrypt);
+        $cipherValue->appendChild($value);
+
+        if ($replace) {
+            switch ($this->type) {
+                case (XMLSecEnc::Element):
+                    if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
+                        return $this->encdoc;
+                    }
+                    $importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE);
+                    $this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
+                    return $importEnc;
+                    break;
+                case (XMLSecEnc::Content):
+                    $importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE);
+                    while($this->rawNode->firstChild) {
+                        $this->rawNode->removeChild($this->rawNode->firstChild);
+                    }
+                    $this->rawNode->appendChild($importEnc);
+                    return $importEnc;
+                    break;
+            }
+        }
+    }
+
+    public function decryptNode($objKey, $replace=TRUE) {
+        $data = '';
+        if (empty($this->rawNode)) {
+            throw new Exception('Node to decrypt has not been set');
+        }
+        if (! $objKey instanceof XMLSecurityKey) {
+            throw new Exception('Invalid Key');
+        }
+        $doc = $this->rawNode->ownerDocument;
+        $xPath = new DOMXPath($doc);
+        $xPath->registerNamespace('xmlencr', XMLSecEnc::XMLENCNS);
+        /* Only handles embedded content right now and not a reference */
+        $query = "./xmlencr:CipherData/xmlencr:CipherValue";
+        $nodeset = $xPath->query($query, $this->rawNode);
+
+        if ($node = $nodeset->item(0)) {
+            $encryptedData = base64_decode($node->nodeValue);
+            $decrypted = $objKey->decryptData($encryptedData);
+            if ($replace) {
+                switch ($this->type) {
+                    case (XMLSecEnc::Element):
+                        $newdoc = new DOMDocument();
+                        $newdoc->loadXML($decrypted);
+                        if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
+                            return $newdoc;
+                        }
+                        $importEnc = $this->rawNode->ownerDocument->importNode($newdoc->documentElement, TRUE);
+                        $this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
+                        return $importEnc;
+                        break;
+                    case (XMLSecEnc::Content):
+                        if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
+                            $doc = $this->rawNode;
+                        } else {
+                            $doc = $this->rawNode->ownerDocument;
+                        }
+                        $newFrag = $doc->createDOMDocumentFragment();
+                        $newFrag->appendXML($decrypted);
+                        $this->rawNode->parentNode->replaceChild($newFrag, $this->rawNode);
+                        return $this->rawNode->parentNode;
+                        break;
+                    default:
+                        return $decrypted;
+                }
+            } else {
+                return $decrypted;
+            }
+        } else {
+            throw new Exception("Cannot locate encrypted data");
+        }
+    }
+
+    public function encryptKey($srcKey, $rawKey, $append=TRUE) {
+        if ((! $srcKey instanceof XMLSecurityKey) || (! $rawKey instanceof XMLSecurityKey)) {
+            throw new Exception('Invalid Key');
+        }
+        $strEncKey = base64_encode($srcKey->encryptData($rawKey->key));
+        $root = $this->encdoc->documentElement;
+        $encKey = $this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptedKey');
+        if ($append) {
+            $keyInfo = $root->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'));
+            $keyInfo->appendChild($encKey);
+        } else {
+            $this->encKey = $encKey;
+        }
+        $encMethod = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
+        $encMethod->setAttribute('Algorithm', $srcKey->getAlgorith());
+        if (! empty($srcKey->name)) {
+            $keyInfo = $encKey->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'));
+            $keyInfo->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyName', $srcKey->name));
+        }
+        $cipherData = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherData'));
+        $cipherData->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherValue', $strEncKey));
+        return;
+    }
+
+    public function decryptKey($encKey) {
+        if (! $encKey->isEncrypted) {
+            throw new Exception("Key is not Encrypted");
+        }
+        if (empty($encKey->key)) {
+            throw new Exception("Key is missing data to perform the decryption");
+        }
+        return $this->decryptNode($encKey, FALSE);
+    }
+
+    public function locateEncryptedData($element) {
+        if ($element instanceof DOMDocument) {
+            $doc = $element;
+        } else {
+            $doc = $element->ownerDocument;
+        }
+        if ($doc) {
+            $xpath = new DOMXPath($doc);
+            $query = "//*[local-name()='EncryptedData' and namespace-uri()='".XMLSecEnc::XMLENCNS."']";
+            $nodeset = $xpath->query($query);
+            return $nodeset->item(0);
+        }
+        return NULL;
+    }
+
+    public function locateKey($node=NULL) {
+        if (empty($node)) {
+            $node = $this->rawNode;
+        }
+        if (! $node instanceof DOMNode) {
+            return NULL;
+        }
+        if ($doc = $node->ownerDocument) {
+            $xpath = new DOMXPath($doc);
+            $xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
+            $query = ".//xmlsecenc:EncryptionMethod";
+            $nodeset = $xpath->query($query, $node);
+            if ($encmeth = $nodeset->item(0)) {
+                   $attrAlgorithm = $encmeth->getAttribute("Algorithm");
+                try {
+                    $objKey = new XMLSecurityKey($attrAlgorithm, array('type'=>'private'));
+                } catch (Exception $e) {
+                    return NULL;
+                }
+                return $objKey;
+            }
+        }
+        return NULL;
+    }
+
+    static function staticLocateKeyInfo($objBaseKey=NULL, $node=NULL) {
+        if (empty($node) || (! $node instanceof DOMNode)) {
+            return NULL;
+        }
+        if ($doc = $node->ownerDocument) {
+            $xpath = new DOMXPath($doc);
+            $xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
+            $xpath->registerNamespace('xmlsecdsig', XMLSecurityDSig::XMLDSIGNS);
+            $query = "./xmlsecdsig:KeyInfo";
+            $nodeset = $xpath->query($query, $node);
+            if ($encmeth = $nodeset->item(0)) {
+                foreach ($encmeth->childNodes AS $child) {
+                    switch ($child->localName) {
+                        case 'KeyName':
+                            if (! empty($objBaseKey)) {
+                                $objBaseKey->name = $child->nodeValue;
+                            }
+                            break;
+                        case 'KeyValue':
+                            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':
+                            /* Not currently supported */
+                            break;
+                        case 'EncryptedKey':
+                            $objenc = new XMLSecEnc();
+                            $objenc->setNode($child);
+                            if (! $objKey = $objenc->locateKey()) {
+                                throw new Exception("Unable to locate algorithm for this Encrypted Key");
+                            }
+                            $objKey->isEncrypted = TRUE;
+                            $objKey->encryptedCtx = $objenc;
+                            XMLSecEnc::staticLocateKeyInfo($objKey, $child);
+                            return $objKey;
+                            break;
+                        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);
+                                }
+                            }
+                            break;
+                    }
+                }
+            }
+            return $objBaseKey;
+        }
+        return NULL;
+    }
+
+    public function locateKeyInfo($objBaseKey=NULL, $node=NULL) {
+        if (empty($node)) {
+            $node = $this->rawNode;
+        }
+        return XMLSecEnc::staticLocateKeyInfo($objBaseKey, $node);
+    }
+}
 ?>
\ No newline at end of file