Passed
Branch develop (649d49)
by Remco
06:34
created
includes/xmlseclibs/xmlseclibs.php 1 patch
Indentation   +1659 added lines, -1659 removed lines patch added patch discarded remove patch
@@ -47,101 +47,101 @@  discard block
 block discarded – undo
47 47
 
48 48
 /* helper function */
49 49
 function sortAndAddAttrs($element, $arAtts) {
50
-    $newAtts = array();
51
-    foreach ($arAtts AS $attnode) {
52
-        $newAtts[$attnode->nodeName] = $attnode;
53
-    }
54
-    ksort($newAtts);
55
-    foreach ($newAtts as $attnode) {
56
-        $element->setAttribute($attnode->nodeName, $attnode->nodeValue);
57
-    }
50
+	$newAtts = array();
51
+	foreach ($arAtts AS $attnode) {
52
+		$newAtts[$attnode->nodeName] = $attnode;
53
+	}
54
+	ksort($newAtts);
55
+	foreach ($newAtts as $attnode) {
56
+		$element->setAttribute($attnode->nodeName, $attnode->nodeValue);
57
+	}
58 58
 }
59 59
 
60 60
 /* helper function */
61 61
 
62 62
 function canonical($tree, $element, $withcomments) {
63
-    if ($tree->nodeType != XML_DOCUMENT_NODE) {
64
-        $dom = $tree->ownerDocument;
65
-    } else {
66
-        $dom = $tree;
67
-    }
68
-    if ($element->nodeType != XML_ELEMENT_NODE) {
69
-        if ($element->nodeType == XML_DOCUMENT_NODE) {
70
-            foreach ($element->childNodes AS $node) {
71
-                canonical($dom, $node, $withcomments);
72
-            }
73
-            return;
74
-        }
75
-        if ($element->nodeType == XML_COMMENT_NODE && !$withcomments) {
76
-            return;
77
-        }
78
-        $tree->appendChild($dom->importNode($element, TRUE));
79
-        return;
80
-    }
81
-    $arNS = array();
82
-    if ($element->namespaceURI != "") {
83
-        if ($element->prefix == "") {
84
-            $elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName);
85
-        } else {
86
-            $prefix = $tree->lookupPrefix($element->namespaceURI);
87
-            if ($prefix == $element->prefix) {
88
-                $elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName);
89
-            } else {
90
-                $elCopy = $dom->createElement($element->nodeName);
91
-                $arNS[$element->namespaceURI] = $element->prefix;
92
-            }
93
-        }
94
-    } else {
95
-        $elCopy = $dom->createElement($element->nodeName);
96
-    }
97
-    $tree->appendChild($elCopy);
98
-
99
-    /* Create DOMXPath based on original document */
100
-    $xPath = new DOMXPath($element->ownerDocument);
101
-
102
-    /* Get namespaced attributes */
103
-    $arAtts = $xPath->query('attribute::*[namespace-uri(.) != ""]', $element);
104
-
105
-    /* Create an array with namespace URIs as keys, and sort them */
106
-    foreach ($arAtts AS $attnode) {
107
-        if (array_key_exists($attnode->namespaceURI, $arNS) &&
108
-                ($arNS[$attnode->namespaceURI] == $attnode->prefix)) {
109
-            continue;
110
-        }
111
-        $prefix = $tree->lookupPrefix($attnode->namespaceURI);
112
-        if ($prefix != $attnode->prefix) {
113
-            $arNS[$attnode->namespaceURI] = $attnode->prefix;
114
-        } else {
115
-            $arNS[$attnode->namespaceURI] = NULL;
116
-        }
117
-    }
118
-    if (count($arNS) > 0) {
119
-        asort($arNS);
120
-    }
121
-
122
-    /* Add namespace nodes */
123
-    foreach ($arNS AS $namespaceURI => $prefix) {
124
-        if ($prefix != NULL) {
125
-            $elCopy->setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:" . $prefix, $namespaceURI);
126
-        }
127
-    }
128
-    if (count($arNS) > 0) {
129
-        ksort($arNS);
130
-    }
131
-
132
-    /* Get attributes not in a namespace, and then sort and add them */
133
-    $arAtts = $xPath->query('attribute::*[namespace-uri(.) = ""]', $element);
134
-    sortAndAddAttrs($elCopy, $arAtts);
135
-
136
-    /* Loop through the URIs, and then sort and add attributes within that namespace */
137
-    foreach ($arNS as $nsURI => $prefix) {
138
-        $arAtts = $xPath->query('attribute::*[namespace-uri(.) = "' . $nsURI . '"]', $element);
139
-        sortAndAddAttrs($elCopy, $arAtts);
140
-    }
141
-
142
-    foreach ($element->childNodes AS $node) {
143
-        canonical($elCopy, $node, $withcomments);
144
-    }
63
+	if ($tree->nodeType != XML_DOCUMENT_NODE) {
64
+		$dom = $tree->ownerDocument;
65
+	} else {
66
+		$dom = $tree;
67
+	}
68
+	if ($element->nodeType != XML_ELEMENT_NODE) {
69
+		if ($element->nodeType == XML_DOCUMENT_NODE) {
70
+			foreach ($element->childNodes AS $node) {
71
+				canonical($dom, $node, $withcomments);
72
+			}
73
+			return;
74
+		}
75
+		if ($element->nodeType == XML_COMMENT_NODE && !$withcomments) {
76
+			return;
77
+		}
78
+		$tree->appendChild($dom->importNode($element, TRUE));
79
+		return;
80
+	}
81
+	$arNS = array();
82
+	if ($element->namespaceURI != "") {
83
+		if ($element->prefix == "") {
84
+			$elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName);
85
+		} else {
86
+			$prefix = $tree->lookupPrefix($element->namespaceURI);
87
+			if ($prefix == $element->prefix) {
88
+				$elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName);
89
+			} else {
90
+				$elCopy = $dom->createElement($element->nodeName);
91
+				$arNS[$element->namespaceURI] = $element->prefix;
92
+			}
93
+		}
94
+	} else {
95
+		$elCopy = $dom->createElement($element->nodeName);
96
+	}
97
+	$tree->appendChild($elCopy);
98
+
99
+	/* Create DOMXPath based on original document */
100
+	$xPath = new DOMXPath($element->ownerDocument);
101
+
102
+	/* Get namespaced attributes */
103
+	$arAtts = $xPath->query('attribute::*[namespace-uri(.) != ""]', $element);
104
+
105
+	/* Create an array with namespace URIs as keys, and sort them */
106
+	foreach ($arAtts AS $attnode) {
107
+		if (array_key_exists($attnode->namespaceURI, $arNS) &&
108
+				($arNS[$attnode->namespaceURI] == $attnode->prefix)) {
109
+			continue;
110
+		}
111
+		$prefix = $tree->lookupPrefix($attnode->namespaceURI);
112
+		if ($prefix != $attnode->prefix) {
113
+			$arNS[$attnode->namespaceURI] = $attnode->prefix;
114
+		} else {
115
+			$arNS[$attnode->namespaceURI] = NULL;
116
+		}
117
+	}
118
+	if (count($arNS) > 0) {
119
+		asort($arNS);
120
+	}
121
+
122
+	/* Add namespace nodes */
123
+	foreach ($arNS AS $namespaceURI => $prefix) {
124
+		if ($prefix != NULL) {
125
+			$elCopy->setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:" . $prefix, $namespaceURI);
126
+		}
127
+	}
128
+	if (count($arNS) > 0) {
129
+		ksort($arNS);
130
+	}
131
+
132
+	/* Get attributes not in a namespace, and then sort and add them */
133
+	$arAtts = $xPath->query('attribute::*[namespace-uri(.) = ""]', $element);
134
+	sortAndAddAttrs($elCopy, $arAtts);
135
+
136
+	/* Loop through the URIs, and then sort and add attributes within that namespace */
137
+	foreach ($arNS as $nsURI => $prefix) {
138
+		$arAtts = $xPath->query('attribute::*[namespace-uri(.) = "' . $nsURI . '"]', $element);
139
+		sortAndAddAttrs($elCopy, $arAtts);
140
+	}
141
+
142
+	foreach ($element->childNodes AS $node) {
143
+		canonical($elCopy, $node, $withcomments);
144
+	}
145 145
 }
146 146
 
147 147
 /*
@@ -151,1228 +151,1228 @@  discard block
 block discarded – undo
151 151
  */
152 152
 
153 153
 function C14NGeneral($element, $exclusive=FALSE, $withcomments=FALSE) {
154
-    /* IF PHP 5.2+ then use built in canonical functionality */
155
-    $php_version = explode('.', PHP_VERSION);
156
-    if (($php_version[0] > 5) || ($php_version[0] == 5 && $php_version[1] >= 2)) {
157
-        return $element->C14N($exclusive, $withcomments);
158
-    }
159
-
160
-    /* Must be element or document */
161
-    if (!$element instanceof DOMElement && !$element instanceof DOMDocument) {
162
-        return NULL;
163
-    }
164
-    /* Currently only exclusive XML is supported */
165
-    if ($exclusive == FALSE) {
166
-        throw new Exception("Only exclusive canonicalization is supported in this version of PHP");
167
-    }
168
-
169
-    $copyDoc = new DOMDocument();
170
-    canonical($copyDoc, $element, $withcomments);
171
-    return $copyDoc->saveXML($copyDoc->documentElement, LIBXML_NOEMPTYTAG);
154
+	/* IF PHP 5.2+ then use built in canonical functionality */
155
+	$php_version = explode('.', PHP_VERSION);
156
+	if (($php_version[0] > 5) || ($php_version[0] == 5 && $php_version[1] >= 2)) {
157
+		return $element->C14N($exclusive, $withcomments);
158
+	}
159
+
160
+	/* Must be element or document */
161
+	if (!$element instanceof DOMElement && !$element instanceof DOMDocument) {
162
+		return NULL;
163
+	}
164
+	/* Currently only exclusive XML is supported */
165
+	if ($exclusive == FALSE) {
166
+		throw new Exception("Only exclusive canonicalization is supported in this version of PHP");
167
+	}
168
+
169
+	$copyDoc = new DOMDocument();
170
+	canonical($copyDoc, $element, $withcomments);
171
+	return $copyDoc->saveXML($copyDoc->documentElement, LIBXML_NOEMPTYTAG);
172 172
 }
173 173
 
174 174
 class XMLSecurityKey {
175
-    const TRIPLEDES_CBC = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
176
-    const AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
177
-    const AES192_CBC = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
178
-    const AES256_CBC = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
179
-    const RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
180
-    const RSA_OAEP_MGF1P = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
181
-    const DSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1';
182
-    const RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
183
-    const RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
184
-
185
-    private $cryptParams = array();
186
-    public $type = 0;
187
-    public $key = NULL;
188
-    public $passphrase = "";
189
-    public $iv = NULL;
190
-    public $name = NULL;
191
-    public $keyChain = NULL;
192
-    public $isEncrypted = FALSE;
193
-    public $encryptedCtx = NULL;
194
-    public $guid = NULL;
195
-
196
-    /**
197
-     * This variable contains the certificate as a string if this key represents an X509-certificate.
198
-     * If this key doesn't represent a certificate, this will be NULL.
199
-     */
200
-    private $x509Certificate = NULL;
201
-
202
-    /* This variable contains the certificate thunbprint if we have loaded an X509-certificate. */
203
-    private $X509Thumbprint = NULL;
204
-
205
-    public function __construct($type, $params=NULL) {
206
-        srand();
207
-        switch ($type) {
208
-            case (XMLSecurityKey::TRIPLEDES_CBC):
209
-                $this->cryptParams['library'] = 'mcrypt';
210
-                $this->cryptParams['cipher'] = MCRYPT_TRIPLEDES;
211
-                $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
212
-                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
213
-                $this->cryptParams['keysize'] = 24;
214
-                break;
215
-            case (XMLSecurityKey::AES128_CBC):
216
-                $this->cryptParams['library'] = 'mcrypt';
217
-                $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
218
-                $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
219
-                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
220
-                $this->cryptParams['keysize'] = 16;
221
-                break;
222
-            case (XMLSecurityKey::AES192_CBC):
223
-                $this->cryptParams['library'] = 'mcrypt';
224
-                $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
225
-                $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
226
-                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
227
-                $this->cryptParams['keysize'] = 24;
228
-                break;
229
-            case (XMLSecurityKey::AES256_CBC):
230
-                $this->cryptParams['library'] = 'mcrypt';
231
-                $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
232
-                $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
233
-                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
234
-                $this->cryptParams['keysize'] = 32;
235
-                break;
236
-            case (XMLSecurityKey::RSA_1_5):
237
-                $this->cryptParams['library'] = 'openssl';
238
-                $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
239
-                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
240
-                if (is_array($params) && !empty($params['type'])) {
241
-                    if ($params['type'] == 'public' || $params['type'] == 'private') {
242
-                        $this->cryptParams['type'] = $params['type'];
243
-                        break;
244
-                    }
245
-                }
246
-                throw new Exception('Certificate "type" (private/public) must be passed via parameters');
247
-                return;
248
-            case (XMLSecurityKey::RSA_OAEP_MGF1P):
249
-                $this->cryptParams['library'] = 'openssl';
250
-                $this->cryptParams['padding'] = OPENSSL_PKCS1_OAEP_PADDING;
251
-                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
252
-                $this->cryptParams['hash'] = NULL;
253
-                if (is_array($params) && !empty($params['type'])) {
254
-                    if ($params['type'] == 'public' || $params['type'] == 'private') {
255
-                        $this->cryptParams['type'] = $params['type'];
256
-                        break;
257
-                    }
258
-                }
259
-                throw new Exception('Certificate "type" (private/public) must be passed via parameters');
260
-                return;
261
-            case (XMLSecurityKey::RSA_SHA1):
262
-                $this->cryptParams['library'] = 'openssl';
263
-                $this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
264
-                $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
265
-                if (is_array($params) && !empty($params['type'])) {
266
-                    if ($params['type'] == 'public' || $params['type'] == 'private') {
267
-                        $this->cryptParams['type'] = $params['type'];
268
-                        break;
269
-                    }
270
-                }
271
-                throw new Exception('Certificate "type" (private/public) must be passed via parameters');
272
-                break;
273
-            case (XMLSecurityKey::RSA_SHA256):
274
-                $this->cryptParams['library'] = 'openssl';
275
-                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
276
-                $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
277
-                $this->cryptParams['digest'] = 'SHA256';
278
-                if (is_array($params) && !empty($params['type'])) {
279
-                    if ($params['type'] == 'public' || $params['type'] == 'private') {
280
-                        $this->cryptParams['type'] = $params['type'];
281
-                        break;
282
-                    }
283
-                }
284
-                throw new Exception('Certificate "type" (private/public) must be passed via parameters');
285
-                break;
286
-            default:
287
-                throw new Exception('Invalid Key Type');
288
-                return;
289
-        }
290
-        $this->type = $type;
291
-    }
292
-
293
-    /**
294
-     * Retrieve the key size for the symmetric encryption algorithm..
295
-     *
296
-     * If the key size is unknown, or this isn't a symmetric encryption algorithm,
297
-     * NULL is returned.
298
-     *
299
-     * @return int|NULL  The number of bytes in the key.
300
-     */
301
-    public function getSymmetricKeySize() {
302
-        if (!isset($this->cryptParams['keysize'])) {
303
-            return NULL;
304
-        }
305
-        return $this->cryptParams['keysize'];
306
-    }
307
-
308
-    public function generateSessionKey() {
309
-        if (!isset($this->cryptParams['keysize'])) {
310
-            throw new Exception('Unknown key size for type "' . $this->type . '".');
311
-        }
312
-        $keysize = $this->cryptParams['keysize'];
313
-
314
-        if (function_exists('openssl_random_pseudo_bytes')) {
315
-            /* We have PHP >= 5.3 - use openssl to generate session key. */
316
-            $key = openssl_random_pseudo_bytes($keysize);
317
-        } else {
318
-            /* Generating random key using iv generation routines */
319
-            $key = mcrypt_create_iv($keysize, MCRYPT_RAND);
320
-        }
321
-
322
-        if ($this->type === XMLSecurityKey::TRIPLEDES_CBC) {
323
-            /* Make sure that the generated key has the proper parity bits set.
175
+	const TRIPLEDES_CBC = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
176
+	const AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
177
+	const AES192_CBC = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
178
+	const AES256_CBC = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
179
+	const RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
180
+	const RSA_OAEP_MGF1P = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
181
+	const DSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1';
182
+	const RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
183
+	const RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
184
+
185
+	private $cryptParams = array();
186
+	public $type = 0;
187
+	public $key = NULL;
188
+	public $passphrase = "";
189
+	public $iv = NULL;
190
+	public $name = NULL;
191
+	public $keyChain = NULL;
192
+	public $isEncrypted = FALSE;
193
+	public $encryptedCtx = NULL;
194
+	public $guid = NULL;
195
+
196
+	/**
197
+	 * This variable contains the certificate as a string if this key represents an X509-certificate.
198
+	 * If this key doesn't represent a certificate, this will be NULL.
199
+	 */
200
+	private $x509Certificate = NULL;
201
+
202
+	/* This variable contains the certificate thunbprint if we have loaded an X509-certificate. */
203
+	private $X509Thumbprint = NULL;
204
+
205
+	public function __construct($type, $params=NULL) {
206
+		srand();
207
+		switch ($type) {
208
+			case (XMLSecurityKey::TRIPLEDES_CBC):
209
+				$this->cryptParams['library'] = 'mcrypt';
210
+				$this->cryptParams['cipher'] = MCRYPT_TRIPLEDES;
211
+				$this->cryptParams['mode'] = MCRYPT_MODE_CBC;
212
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
213
+				$this->cryptParams['keysize'] = 24;
214
+				break;
215
+			case (XMLSecurityKey::AES128_CBC):
216
+				$this->cryptParams['library'] = 'mcrypt';
217
+				$this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
218
+				$this->cryptParams['mode'] = MCRYPT_MODE_CBC;
219
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
220
+				$this->cryptParams['keysize'] = 16;
221
+				break;
222
+			case (XMLSecurityKey::AES192_CBC):
223
+				$this->cryptParams['library'] = 'mcrypt';
224
+				$this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
225
+				$this->cryptParams['mode'] = MCRYPT_MODE_CBC;
226
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
227
+				$this->cryptParams['keysize'] = 24;
228
+				break;
229
+			case (XMLSecurityKey::AES256_CBC):
230
+				$this->cryptParams['library'] = 'mcrypt';
231
+				$this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
232
+				$this->cryptParams['mode'] = MCRYPT_MODE_CBC;
233
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
234
+				$this->cryptParams['keysize'] = 32;
235
+				break;
236
+			case (XMLSecurityKey::RSA_1_5):
237
+				$this->cryptParams['library'] = 'openssl';
238
+				$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
239
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
240
+				if (is_array($params) && !empty($params['type'])) {
241
+					if ($params['type'] == 'public' || $params['type'] == 'private') {
242
+						$this->cryptParams['type'] = $params['type'];
243
+						break;
244
+					}
245
+				}
246
+				throw new Exception('Certificate "type" (private/public) must be passed via parameters');
247
+				return;
248
+			case (XMLSecurityKey::RSA_OAEP_MGF1P):
249
+				$this->cryptParams['library'] = 'openssl';
250
+				$this->cryptParams['padding'] = OPENSSL_PKCS1_OAEP_PADDING;
251
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
252
+				$this->cryptParams['hash'] = NULL;
253
+				if (is_array($params) && !empty($params['type'])) {
254
+					if ($params['type'] == 'public' || $params['type'] == 'private') {
255
+						$this->cryptParams['type'] = $params['type'];
256
+						break;
257
+					}
258
+				}
259
+				throw new Exception('Certificate "type" (private/public) must be passed via parameters');
260
+				return;
261
+			case (XMLSecurityKey::RSA_SHA1):
262
+				$this->cryptParams['library'] = 'openssl';
263
+				$this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
264
+				$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
265
+				if (is_array($params) && !empty($params['type'])) {
266
+					if ($params['type'] == 'public' || $params['type'] == 'private') {
267
+						$this->cryptParams['type'] = $params['type'];
268
+						break;
269
+					}
270
+				}
271
+				throw new Exception('Certificate "type" (private/public) must be passed via parameters');
272
+				break;
273
+			case (XMLSecurityKey::RSA_SHA256):
274
+				$this->cryptParams['library'] = 'openssl';
275
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
276
+				$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
277
+				$this->cryptParams['digest'] = 'SHA256';
278
+				if (is_array($params) && !empty($params['type'])) {
279
+					if ($params['type'] == 'public' || $params['type'] == 'private') {
280
+						$this->cryptParams['type'] = $params['type'];
281
+						break;
282
+					}
283
+				}
284
+				throw new Exception('Certificate "type" (private/public) must be passed via parameters');
285
+				break;
286
+			default:
287
+				throw new Exception('Invalid Key Type');
288
+				return;
289
+		}
290
+		$this->type = $type;
291
+	}
292
+
293
+	/**
294
+	 * Retrieve the key size for the symmetric encryption algorithm..
295
+	 *
296
+	 * If the key size is unknown, or this isn't a symmetric encryption algorithm,
297
+	 * NULL is returned.
298
+	 *
299
+	 * @return int|NULL  The number of bytes in the key.
300
+	 */
301
+	public function getSymmetricKeySize() {
302
+		if (!isset($this->cryptParams['keysize'])) {
303
+			return NULL;
304
+		}
305
+		return $this->cryptParams['keysize'];
306
+	}
307
+
308
+	public function generateSessionKey() {
309
+		if (!isset($this->cryptParams['keysize'])) {
310
+			throw new Exception('Unknown key size for type "' . $this->type . '".');
311
+		}
312
+		$keysize = $this->cryptParams['keysize'];
313
+
314
+		if (function_exists('openssl_random_pseudo_bytes')) {
315
+			/* We have PHP >= 5.3 - use openssl to generate session key. */
316
+			$key = openssl_random_pseudo_bytes($keysize);
317
+		} else {
318
+			/* Generating random key using iv generation routines */
319
+			$key = mcrypt_create_iv($keysize, MCRYPT_RAND);
320
+		}
321
+
322
+		if ($this->type === XMLSecurityKey::TRIPLEDES_CBC) {
323
+			/* Make sure that the generated key has the proper parity bits set.
324 324
              * Mcrypt doesn't care about the parity bits, but others may care.
325 325
              */
326
-            for ($i = 0; $i < strlen($key); $i++) {
327
-                $byte = ord($key[$i]) & 0xfe;
328
-                $parity = 1;
329
-                for ($j = 1; $j < 8; $j++) {
330
-                    $parity ^= ($byte >> $j) & 1;
331
-                }
332
-                $byte |= $parity;
333
-                $key[$i] = chr($byte);
334
-            }
335
-        }
336
-
337
-        $this->key = $key;
338
-        return $key;
339
-    }
340
-
341
-    public static function getRawThumbprint($cert) {
342
-
343
-        $arCert = explode("\n", $cert);
344
-        $data = '';
345
-        $inData = FALSE;
346
-
347
-        foreach ($arCert AS $curData) {
348
-            if (!$inData) {
349
-                if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
350
-                    $inData = TRUE;
351
-                }
352
-            } else {
353
-                if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
354
-                    $inData = FALSE;
355
-                    break;
356
-                }
357
-                $data .= trim($curData);
358
-            }
359
-        }
360
-
361
-        if (!empty($data)) {
362
-            return strtolower(sha1(base64_decode($data)));
363
-        }
364
-
365
-        return NULL;
366
-    }
367
-
368
-    public function loadKey($key, $isFile=FALSE, $isCert = FALSE) {
369
-        if ($isFile) {
370
-            $this->key = file_get_contents($key);
371
-        } else {
372
-            $this->key = $key;
373
-        }
374
-        if ($isCert) {
375
-            $this->key = openssl_x509_read($this->key);
376
-            openssl_x509_export($this->key, $str_cert);
377
-            $this->x509Certificate = $str_cert;
378
-            $this->key = $str_cert;
379
-        } else {
380
-            $this->x509Certificate = NULL;
381
-        }
382
-        if ($this->cryptParams['library'] == 'openssl') {
383
-            if ($this->cryptParams['type'] == 'public') {
384
-                if ($isCert) {
385
-                    /* Load the thumbprint if this is an X509 certificate. */
386
-                    $this->X509Thumbprint = self::getRawThumbprint($this->key);
387
-                }
388
-                $this->key = openssl_get_publickey($this->key);
389
-            } else {
390
-                $this->key = openssl_get_privatekey($this->key, $this->passphrase);
391
-            }
392
-        } else if ($this->cryptParams['cipher'] == MCRYPT_RIJNDAEL_128) {
393
-            /* Check key length */
394
-            switch ($this->type) {
395
-                case (XMLSecurityKey::AES256_CBC):
396
-                    if (strlen($this->key) < 25) {
397
-                        throw new Exception('Key must contain at least 25 characters for this cipher');
398
-                    }
399
-                    break;
400
-                case (XMLSecurityKey::AES192_CBC):
401
-                    if (strlen($this->key) < 17) {
402
-                        throw new Exception('Key must contain at least 17 characters for this cipher');
403
-                    }
404
-                    break;
405
-            }
406
-        }
407
-    }
408
-
409
-    private function encryptMcrypt($data) {
410
-        $td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
411
-        $this->iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
412
-        mcrypt_generic_init($td, $this->key, $this->iv);
413
-        if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) {
414
-            $bs = mcrypt_enc_get_block_size($td);
415
-            for ($datalen0 = $datalen = strlen($data); (($datalen % $bs) != ($bs - 1)); $datalen++)
416
-                $data.=chr(rand(1, 127));
417
-            $data.=chr($datalen - $datalen0 + 1);
418
-        }
419
-        $encrypted_data = $this->iv . mcrypt_generic($td, $data);
420
-        mcrypt_generic_deinit($td);
421
-        mcrypt_module_close($td);
422
-        return $encrypted_data;
423
-    }
424
-
425
-    private function decryptMcrypt($data) {
426
-        $td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
427
-        $iv_length = mcrypt_enc_get_iv_size($td);
428
-
429
-        $this->iv = substr($data, 0, $iv_length);
430
-        $data = substr($data, $iv_length);
431
-
432
-        mcrypt_generic_init($td, $this->key, $this->iv);
433
-        $decrypted_data = mdecrypt_generic($td, $data);
434
-        mcrypt_generic_deinit($td);
435
-        mcrypt_module_close($td);
436
-        if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) {
437
-            $dataLen = strlen($decrypted_data);
438
-            $paddingLength = substr($decrypted_data, $dataLen - 1, 1);
439
-            $decrypted_data = substr($decrypted_data, 0, $dataLen - ord($paddingLength));
440
-        }
441
-        return $decrypted_data;
442
-    }
443
-
444
-    private function encryptOpenSSL($data) {
445
-        if ($this->cryptParams['type'] == 'public') {
446
-            if (!openssl_public_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
447
-                throw new Exception('Failure encrypting Data');
448
-                return;
449
-            }
450
-        } else {
451
-            if (!openssl_private_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
452
-                throw new Exception('Failure encrypting Data');
453
-                return;
454
-            }
455
-        }
456
-        return $encrypted_data;
457
-    }
458
-
459
-    private function decryptOpenSSL($data) {
460
-        if ($this->cryptParams['type'] == 'public') {
461
-            if (!openssl_public_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
462
-                throw new Exception('Failure decrypting Data');
463
-                return;
464
-            }
465
-        } else {
466
-            if (!openssl_private_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
467
-                throw new Exception('Failure decrypting Data');
468
-                return;
469
-            }
470
-        }
471
-        return $decrypted;
472
-    }
473
-
474
-    private function signOpenSSL($data) {
475
-        $algo = OPENSSL_ALGO_SHA1;
476
-        if (!empty($this->cryptParams['digest'])) {
477
-            $algo = $this->cryptParams['digest'];
478
-        }
479
-        if (!openssl_sign($data, $signature, $this->key, $algo)) {
480
-            throw new Exception('Failure Signing Data: ' . openssl_error_string() . ' - ' . $algo);
481
-            return;
482
-        }
483
-        return $signature;
484
-    }
485
-
486
-    private function verifyOpenSSL($data, $signature) {
487
-        $algo = OPENSSL_ALGO_SHA1;
488
-        if (!empty($this->cryptParams['digest'])) {
489
-            $algo = $this->cryptParams['digest'];
490
-        }
491
-        return openssl_verify($data, $signature, $this->key, $algo);
492
-    }
493
-
494
-    public function encryptData($data) {
495
-        switch ($this->cryptParams['library']) {
496
-            case 'mcrypt':
497
-                return $this->encryptMcrypt($data);
498
-                break;
499
-            case 'openssl':
500
-                return $this->encryptOpenSSL($data);
501
-                break;
502
-        }
503
-    }
504
-
505
-    public function decryptData($data) {
506
-        switch ($this->cryptParams['library']) {
507
-            case 'mcrypt':
508
-                return $this->decryptMcrypt($data);
509
-                break;
510
-            case 'openssl':
511
-                return $this->decryptOpenSSL($data);
512
-                break;
513
-        }
514
-    }
515
-
516
-    public function signData($data) {
517
-        switch ($this->cryptParams['library']) {
518
-            case 'openssl':
519
-                return $this->signOpenSSL($data);
520
-                break;
521
-        }
522
-    }
523
-
524
-    public function verifySignature($data, $signature) {
525
-        switch ($this->cryptParams['library']) {
526
-            case 'openssl':
527
-                return $this->verifyOpenSSL($data, $signature);
528
-                break;
529
-        }
530
-    }
531
-
532
-    public function getAlgorith() {
533
-        return $this->cryptParams['method'];
534
-    }
535
-
536
-    static function makeAsnSegment($type, $string) {
537
-        switch ($type) {
538
-            case 0x02:
539
-                if (ord($string) > 0x7f)
540
-                    $string = chr(0) . $string;
541
-                break;
542
-            case 0x03:
543
-                $string = chr(0) . $string;
544
-                break;
545
-        }
546
-
547
-        $length = strlen($string);
548
-
549
-        if ($length < 128) {
550
-            $output = sprintf("%c%c%s", $type, $length, $string);
551
-        } else if ($length < 0x0100) {
552
-            $output = sprintf("%c%c%c%s", $type, 0x81, $length, $string);
553
-        } else if ($length < 0x010000) {
554
-            $output = sprintf("%c%c%c%c%s", $type, 0x82, $length / 0x0100, $length % 0x0100, $string);
555
-        } else {
556
-            $output = NULL;
557
-        }
558
-        return($output);
559
-    }
560
-
561
-    /* Modulus and Exponent must already be base64 decoded */
562
-
563
-    static function convertRSA($modulus, $exponent) {
564
-        /* make an ASN publicKeyInfo */
565
-        $exponentEncoding = XMLSecurityKey::makeAsnSegment(0x02, $exponent);
566
-        $modulusEncoding = XMLSecurityKey::makeAsnSegment(0x02, $modulus);
567
-        $sequenceEncoding = XMLSecurityKey:: makeAsnSegment(0x30, $modulusEncoding . $exponentEncoding);
568
-        $bitstringEncoding = XMLSecurityKey::makeAsnSegment(0x03, $sequenceEncoding);
569
-        $rsaAlgorithmIdentifier = pack("H*", "300D06092A864886F70D0101010500");
570
-        $publicKeyInfo = XMLSecurityKey::makeAsnSegment(0x30, $rsaAlgorithmIdentifier . $bitstringEncoding);
571
-
572
-        /* encode the publicKeyInfo in base64 and add PEM brackets */
573
-        $publicKeyInfoBase64 = base64_encode($publicKeyInfo);
574
-        $encoding = "-----BEGIN PUBLIC KEY-----\n";
575
-        $offset = 0;
576
-        while ($segment = substr($publicKeyInfoBase64, $offset, 64)) {
577
-            $encoding = $encoding . $segment . "\n";
578
-            $offset += 64;
579
-        }
580
-        return $encoding . "-----END PUBLIC KEY-----\n";
581
-    }
582
-
583
-    public function serializeKey($parent) {
584
-
585
-    }
586
-
587
-    /**
588
-     * Retrieve the X509 certificate this key represents.
589
-     *
590
-     * Will return the X509 certificate in PEM-format if this key represents
591
-     * an X509 certificate.
592
-     *
593
-     * @return  The X509 certificate or NULL if this key doesn't represent an X509-certificate.
594
-     */
595
-    public function getX509Certificate() {
596
-        return $this->x509Certificate;
597
-    }
598
-
599
-    /* Get the thumbprint of this X509 certificate.
326
+			for ($i = 0; $i < strlen($key); $i++) {
327
+				$byte = ord($key[$i]) & 0xfe;
328
+				$parity = 1;
329
+				for ($j = 1; $j < 8; $j++) {
330
+					$parity ^= ($byte >> $j) & 1;
331
+				}
332
+				$byte |= $parity;
333
+				$key[$i] = chr($byte);
334
+			}
335
+		}
336
+
337
+		$this->key = $key;
338
+		return $key;
339
+	}
340
+
341
+	public static function getRawThumbprint($cert) {
342
+
343
+		$arCert = explode("\n", $cert);
344
+		$data = '';
345
+		$inData = FALSE;
346
+
347
+		foreach ($arCert AS $curData) {
348
+			if (!$inData) {
349
+				if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
350
+					$inData = TRUE;
351
+				}
352
+			} else {
353
+				if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
354
+					$inData = FALSE;
355
+					break;
356
+				}
357
+				$data .= trim($curData);
358
+			}
359
+		}
360
+
361
+		if (!empty($data)) {
362
+			return strtolower(sha1(base64_decode($data)));
363
+		}
364
+
365
+		return NULL;
366
+	}
367
+
368
+	public function loadKey($key, $isFile=FALSE, $isCert = FALSE) {
369
+		if ($isFile) {
370
+			$this->key = file_get_contents($key);
371
+		} else {
372
+			$this->key = $key;
373
+		}
374
+		if ($isCert) {
375
+			$this->key = openssl_x509_read($this->key);
376
+			openssl_x509_export($this->key, $str_cert);
377
+			$this->x509Certificate = $str_cert;
378
+			$this->key = $str_cert;
379
+		} else {
380
+			$this->x509Certificate = NULL;
381
+		}
382
+		if ($this->cryptParams['library'] == 'openssl') {
383
+			if ($this->cryptParams['type'] == 'public') {
384
+				if ($isCert) {
385
+					/* Load the thumbprint if this is an X509 certificate. */
386
+					$this->X509Thumbprint = self::getRawThumbprint($this->key);
387
+				}
388
+				$this->key = openssl_get_publickey($this->key);
389
+			} else {
390
+				$this->key = openssl_get_privatekey($this->key, $this->passphrase);
391
+			}
392
+		} else if ($this->cryptParams['cipher'] == MCRYPT_RIJNDAEL_128) {
393
+			/* Check key length */
394
+			switch ($this->type) {
395
+				case (XMLSecurityKey::AES256_CBC):
396
+					if (strlen($this->key) < 25) {
397
+						throw new Exception('Key must contain at least 25 characters for this cipher');
398
+					}
399
+					break;
400
+				case (XMLSecurityKey::AES192_CBC):
401
+					if (strlen($this->key) < 17) {
402
+						throw new Exception('Key must contain at least 17 characters for this cipher');
403
+					}
404
+					break;
405
+			}
406
+		}
407
+	}
408
+
409
+	private function encryptMcrypt($data) {
410
+		$td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
411
+		$this->iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
412
+		mcrypt_generic_init($td, $this->key, $this->iv);
413
+		if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) {
414
+			$bs = mcrypt_enc_get_block_size($td);
415
+			for ($datalen0 = $datalen = strlen($data); (($datalen % $bs) != ($bs - 1)); $datalen++)
416
+				$data.=chr(rand(1, 127));
417
+			$data.=chr($datalen - $datalen0 + 1);
418
+		}
419
+		$encrypted_data = $this->iv . mcrypt_generic($td, $data);
420
+		mcrypt_generic_deinit($td);
421
+		mcrypt_module_close($td);
422
+		return $encrypted_data;
423
+	}
424
+
425
+	private function decryptMcrypt($data) {
426
+		$td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
427
+		$iv_length = mcrypt_enc_get_iv_size($td);
428
+
429
+		$this->iv = substr($data, 0, $iv_length);
430
+		$data = substr($data, $iv_length);
431
+
432
+		mcrypt_generic_init($td, $this->key, $this->iv);
433
+		$decrypted_data = mdecrypt_generic($td, $data);
434
+		mcrypt_generic_deinit($td);
435
+		mcrypt_module_close($td);
436
+		if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) {
437
+			$dataLen = strlen($decrypted_data);
438
+			$paddingLength = substr($decrypted_data, $dataLen - 1, 1);
439
+			$decrypted_data = substr($decrypted_data, 0, $dataLen - ord($paddingLength));
440
+		}
441
+		return $decrypted_data;
442
+	}
443
+
444
+	private function encryptOpenSSL($data) {
445
+		if ($this->cryptParams['type'] == 'public') {
446
+			if (!openssl_public_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
447
+				throw new Exception('Failure encrypting Data');
448
+				return;
449
+			}
450
+		} else {
451
+			if (!openssl_private_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
452
+				throw new Exception('Failure encrypting Data');
453
+				return;
454
+			}
455
+		}
456
+		return $encrypted_data;
457
+	}
458
+
459
+	private function decryptOpenSSL($data) {
460
+		if ($this->cryptParams['type'] == 'public') {
461
+			if (!openssl_public_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
462
+				throw new Exception('Failure decrypting Data');
463
+				return;
464
+			}
465
+		} else {
466
+			if (!openssl_private_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
467
+				throw new Exception('Failure decrypting Data');
468
+				return;
469
+			}
470
+		}
471
+		return $decrypted;
472
+	}
473
+
474
+	private function signOpenSSL($data) {
475
+		$algo = OPENSSL_ALGO_SHA1;
476
+		if (!empty($this->cryptParams['digest'])) {
477
+			$algo = $this->cryptParams['digest'];
478
+		}
479
+		if (!openssl_sign($data, $signature, $this->key, $algo)) {
480
+			throw new Exception('Failure Signing Data: ' . openssl_error_string() . ' - ' . $algo);
481
+			return;
482
+		}
483
+		return $signature;
484
+	}
485
+
486
+	private function verifyOpenSSL($data, $signature) {
487
+		$algo = OPENSSL_ALGO_SHA1;
488
+		if (!empty($this->cryptParams['digest'])) {
489
+			$algo = $this->cryptParams['digest'];
490
+		}
491
+		return openssl_verify($data, $signature, $this->key, $algo);
492
+	}
493
+
494
+	public function encryptData($data) {
495
+		switch ($this->cryptParams['library']) {
496
+			case 'mcrypt':
497
+				return $this->encryptMcrypt($data);
498
+				break;
499
+			case 'openssl':
500
+				return $this->encryptOpenSSL($data);
501
+				break;
502
+		}
503
+	}
504
+
505
+	public function decryptData($data) {
506
+		switch ($this->cryptParams['library']) {
507
+			case 'mcrypt':
508
+				return $this->decryptMcrypt($data);
509
+				break;
510
+			case 'openssl':
511
+				return $this->decryptOpenSSL($data);
512
+				break;
513
+		}
514
+	}
515
+
516
+	public function signData($data) {
517
+		switch ($this->cryptParams['library']) {
518
+			case 'openssl':
519
+				return $this->signOpenSSL($data);
520
+				break;
521
+		}
522
+	}
523
+
524
+	public function verifySignature($data, $signature) {
525
+		switch ($this->cryptParams['library']) {
526
+			case 'openssl':
527
+				return $this->verifyOpenSSL($data, $signature);
528
+				break;
529
+		}
530
+	}
531
+
532
+	public function getAlgorith() {
533
+		return $this->cryptParams['method'];
534
+	}
535
+
536
+	static function makeAsnSegment($type, $string) {
537
+		switch ($type) {
538
+			case 0x02:
539
+				if (ord($string) > 0x7f)
540
+					$string = chr(0) . $string;
541
+				break;
542
+			case 0x03:
543
+				$string = chr(0) . $string;
544
+				break;
545
+		}
546
+
547
+		$length = strlen($string);
548
+
549
+		if ($length < 128) {
550
+			$output = sprintf("%c%c%s", $type, $length, $string);
551
+		} else if ($length < 0x0100) {
552
+			$output = sprintf("%c%c%c%s", $type, 0x81, $length, $string);
553
+		} else if ($length < 0x010000) {
554
+			$output = sprintf("%c%c%c%c%s", $type, 0x82, $length / 0x0100, $length % 0x0100, $string);
555
+		} else {
556
+			$output = NULL;
557
+		}
558
+		return($output);
559
+	}
560
+
561
+	/* Modulus and Exponent must already be base64 decoded */
562
+
563
+	static function convertRSA($modulus, $exponent) {
564
+		/* make an ASN publicKeyInfo */
565
+		$exponentEncoding = XMLSecurityKey::makeAsnSegment(0x02, $exponent);
566
+		$modulusEncoding = XMLSecurityKey::makeAsnSegment(0x02, $modulus);
567
+		$sequenceEncoding = XMLSecurityKey:: makeAsnSegment(0x30, $modulusEncoding . $exponentEncoding);
568
+		$bitstringEncoding = XMLSecurityKey::makeAsnSegment(0x03, $sequenceEncoding);
569
+		$rsaAlgorithmIdentifier = pack("H*", "300D06092A864886F70D0101010500");
570
+		$publicKeyInfo = XMLSecurityKey::makeAsnSegment(0x30, $rsaAlgorithmIdentifier . $bitstringEncoding);
571
+
572
+		/* encode the publicKeyInfo in base64 and add PEM brackets */
573
+		$publicKeyInfoBase64 = base64_encode($publicKeyInfo);
574
+		$encoding = "-----BEGIN PUBLIC KEY-----\n";
575
+		$offset = 0;
576
+		while ($segment = substr($publicKeyInfoBase64, $offset, 64)) {
577
+			$encoding = $encoding . $segment . "\n";
578
+			$offset += 64;
579
+		}
580
+		return $encoding . "-----END PUBLIC KEY-----\n";
581
+	}
582
+
583
+	public function serializeKey($parent) {
584
+
585
+	}
586
+
587
+	/**
588
+	 * Retrieve the X509 certificate this key represents.
589
+	 *
590
+	 * Will return the X509 certificate in PEM-format if this key represents
591
+	 * an X509 certificate.
592
+	 *
593
+	 * @return  The X509 certificate or NULL if this key doesn't represent an X509-certificate.
594
+	 */
595
+	public function getX509Certificate() {
596
+		return $this->x509Certificate;
597
+	}
598
+
599
+	/* Get the thumbprint of this X509 certificate.
600 600
      *
601 601
      * Returns:
602 602
      *  The thumbprint as a lowercase 40-character hexadecimal number, or NULL
603 603
      *  if this isn't a X509 certificate.
604 604
      */
605 605
 
606
-    public function getX509Thumbprint() {
607
-        return $this->X509Thumbprint;
608
-    }
609
-
610
-    /**
611
-     * Create key from an EncryptedKey-element.
612
-     *
613
-     * @param DOMElement $element  The EncryptedKey-element.
614
-     * @return XMLSecurityKey  The new key.
615
-     */
616
-    public static function fromEncryptedKeyElement(DOMElement $element) {
617
-
618
-        $objenc = new XMLSecEnc();
619
-        $objenc->setNode($element);
620
-        if (!$objKey = $objenc->locateKey()) {
621
-            throw new Exception("Unable to locate algorithm for this Encrypted Key");
622
-        }
623
-        $objKey->isEncrypted = TRUE;
624
-        $objKey->encryptedCtx = $objenc;
625
-        XMLSecEnc::staticLocateKeyInfo($objKey, $element);
626
-        return $objKey;
627
-    }
606
+	public function getX509Thumbprint() {
607
+		return $this->X509Thumbprint;
608
+	}
609
+
610
+	/**
611
+	 * Create key from an EncryptedKey-element.
612
+	 *
613
+	 * @param DOMElement $element  The EncryptedKey-element.
614
+	 * @return XMLSecurityKey  The new key.
615
+	 */
616
+	public static function fromEncryptedKeyElement(DOMElement $element) {
617
+
618
+		$objenc = new XMLSecEnc();
619
+		$objenc->setNode($element);
620
+		if (!$objKey = $objenc->locateKey()) {
621
+			throw new Exception("Unable to locate algorithm for this Encrypted Key");
622
+		}
623
+		$objKey->isEncrypted = TRUE;
624
+		$objKey->encryptedCtx = $objenc;
625
+		XMLSecEnc::staticLocateKeyInfo($objKey, $element);
626
+		return $objKey;
627
+	}
628 628
 
629 629
 }
630 630
 
631 631
 class XMLSecurityDSig {
632
-    const XMLDSIGNS = 'http://www.w3.org/2000/09/xmldsig#';
633
-    const SHA1 = 'http://www.w3.org/2000/09/xmldsig#sha1';
634
-    const SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256';
635
-    const SHA512 = 'http://www.w3.org/2001/04/xmlenc#sha512';
636
-    const RIPEMD160 = 'http://www.w3.org/2001/04/xmlenc#ripemd160';
637
-
638
-    const C14N = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
639
-    const C14N_COMMENTS = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments';
640
-    const EXC_C14N = 'http://www.w3.org/2001/10/xml-exc-c14n#';
641
-    const EXC_C14N_COMMENTS = 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments';
642
-
643
-    const template = '<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
632
+	const XMLDSIGNS = 'http://www.w3.org/2000/09/xmldsig#';
633
+	const SHA1 = 'http://www.w3.org/2000/09/xmldsig#sha1';
634
+	const SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256';
635
+	const SHA512 = 'http://www.w3.org/2001/04/xmlenc#sha512';
636
+	const RIPEMD160 = 'http://www.w3.org/2001/04/xmlenc#ripemd160';
637
+
638
+	const C14N = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
639
+	const C14N_COMMENTS = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments';
640
+	const EXC_C14N = 'http://www.w3.org/2001/10/xml-exc-c14n#';
641
+	const EXC_C14N_COMMENTS = 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments';
642
+
643
+	const template = '<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
644 644
   <SignedInfo>
645 645
     <SignatureMethod />
646 646
   </SignedInfo>
647 647
 </Signature>';
648 648
 
649
-    public $sigNode = NULL;
650
-    public $idKeys = array();
651
-    public $idNS = array();
652
-    private $signedInfo = NULL;
653
-    private $xPathCtx = NULL;
654
-    private $canonicalMethod = NULL;
655
-    private $prefix = NULL;
656
-    private $searchpfx = 'secdsig';
657
-
658
-    /* This variable contains an associative array of validated nodes. */
659
-    private $validatedNodes = NULL;
660
-
661
-    public function __construct() {
662
-        $sigdoc = new DOMDocument();
663
-        $sigdoc->loadXML(XMLSecurityDSig::template);
664
-        $this->sigNode = $sigdoc->documentElement;
665
-    }
666
-
667
-    private function resetXPathObj() {
668
-        $this->xPathCtx = NULL;
669
-    }
670
-
671
-    private function getXPathObj() {
672
-        if (empty($this->xPathCtx) && !empty($this->sigNode)) {
673
-            $xpath = new DOMXPath($this->sigNode->ownerDocument);
674
-            $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
675
-            $this->xPathCtx = $xpath;
676
-        }
677
-        return $this->xPathCtx;
678
-    }
679
-
680
-    static function generate_GUID($prefix='pfx') {
681
-        $uuid = md5(uniqid(rand(), true));
682
-        $guid = $prefix . substr($uuid, 0, 8) . "-" .
683
-                substr($uuid, 8, 4) . "-" .
684
-                substr($uuid, 12, 4) . "-" .
685
-                substr($uuid, 16, 4) . "-" .
686
-                substr($uuid, 20, 12);
687
-        return $guid;
688
-    }
689
-
690
-    public function locateSignature($objDoc) {
691
-        if ($objDoc instanceof DOMDocument) {
692
-            $doc = $objDoc;
693
-        } else {
694
-            $doc = $objDoc->ownerDocument;
695
-        }
696
-        if ($doc) {
697
-            $xpath = new DOMXPath($doc);
698
-            $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
699
-            $query = ".//secdsig:Signature";
700
-            $nodeset = $xpath->query($query, $objDoc);
701
-            $this->sigNode = $nodeset->item(0);
702
-            return $this->sigNode;
703
-        }
704
-        return NULL;
705
-    }
706
-
707
-    public function createNewSignNode($name, $value=NULL) {
708
-        $doc = $this->sigNode->ownerDocument;
709
-        if ($this->prefix != null) {
710
-            $name = $this->prefix . ':' . $name;
711
-        }
712
-        if (!is_null($value)) {
713
-            $node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $name, $value);
714
-        } else {
715
-            $node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $name);
716
-        }
717
-        return $node;
718
-    }
719
-
720
-    public function setCanonicalMethod($method) {
721
-        switch ($method) {
722
-            case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
723
-            case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
724
-            case 'http://www.w3.org/2001/10/xml-exc-c14n#':
725
-            case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
726
-                $this->canonicalMethod = $method;
727
-                break;
728
-            default:
729
-                throw new Exception('Invalid Canonical Method');
730
-        }
731
-        if ($xpath = $this->getXPathObj()) {
732
-            $query = './' . $this->searchpfx . ':SignedInfo';
733
-            $nodeset = $xpath->query($query, $this->sigNode);
734
-            if ($sinfo = $nodeset->item(0)) {
735
-                $query = './' . $this->searchpfx . 'CanonicalizationMethod';
736
-                $nodeset = $xpath->query($query, $sinfo);
737
-                if (!($canonNode = $nodeset->item(0))) {
738
-                    $canonNode = $this->createNewSignNode('CanonicalizationMethod');
739
-                    $sinfo->insertBefore($canonNode, $sinfo->firstChild);
740
-                }
741
-                $canonNode->setAttribute('Algorithm', $this->canonicalMethod);
742
-            }
743
-        }
744
-    }
745
-
746
-    private function canonicalizeData($node, $canonicalmethod, $arXPath=NULL, $prefixList=NULL) {
747
-        $exclusive = FALSE;
748
-        $withComments = FALSE;
749
-        switch ($canonicalmethod) {
750
-            case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
751
-                $exclusive = FALSE;
752
-                $withComments = FALSE;
753
-                break;
754
-            case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
755
-                $withComments = TRUE;
756
-                break;
757
-            case 'http://www.w3.org/2001/10/xml-exc-c14n#':
758
-                $exclusive = TRUE;
759
-                break;
760
-            case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
761
-                $exclusive = TRUE;
762
-                $withComments = TRUE;
763
-                break;
764
-        }
765
-        /* Support PHP versions < 5.2 not containing C14N methods in DOM extension */
766
-        $php_version = explode('.', PHP_VERSION);
767
-        if (($php_version[0] < 5) || ($php_version[0] == 5 && $php_version[1] < 2)) {
768
-            if (!is_null($arXPath)) {
769
-                throw new Exception("PHP 5.2.0 or higher is required to perform XPath Transformations");
770
-            }
771
-            return C14NGeneral($node, $exclusive, $withComments);
772
-        }
773
-        return $node->C14N($exclusive, $withComments, $arXPath, $prefixList);
774
-    }
775
-
776
-    public function canonicalizeSignedInfo() {
777
-
778
-        $doc = $this->sigNode->ownerDocument;
779
-        $canonicalmethod = NULL;
780
-        if ($doc) {
781
-            $xpath = $this->getXPathObj();
782
-            $query = "./secdsig:SignedInfo";
783
-            $nodeset = $xpath->query($query, $this->sigNode);
784
-            if ($signInfoNode = $nodeset->item(0)) {
785
-                $query = "./secdsig:CanonicalizationMethod";
786
-                $nodeset = $xpath->query($query, $signInfoNode);
787
-                if ($canonNode = $nodeset->item(0)) {
788
-                    $canonicalmethod = $canonNode->getAttribute('Algorithm');
789
-                }
790
-                $this->signedInfo = $this->canonicalizeData($signInfoNode, $canonicalmethod);
791
-                return $this->signedInfo;
792
-            }
793
-        }
794
-        return NULL;
795
-    }
796
-
797
-    public function calculateDigest($digestAlgorithm, $data) {
798
-        switch ($digestAlgorithm) {
799
-            case XMLSecurityDSig::SHA1:
800
-                $alg = 'sha1';
801
-                break;
802
-            case XMLSecurityDSig::SHA256:
803
-                $alg = 'sha256';
804
-                break;
805
-            case XMLSecurityDSig::SHA512:
806
-                $alg = 'sha512';
807
-                break;
808
-            case XMLSecurityDSig::RIPEMD160:
809
-                $alg = 'ripemd160';
810
-                break;
811
-            default:
812
-                throw new Exception("Cannot validate digest: Unsupported Algorith <$digestAlgorithm>");
813
-        }
814
-        if (function_exists('hash')) {
815
-            return base64_encode(hash($alg, $data, TRUE));
816
-        } elseif (function_exists('mhash')) {
817
-            $alg = "MHASH_" . strtoupper($alg);
818
-            return base64_encode(mhash(constant($alg), $data));
819
-        } elseif ($alg === 'sha1') {
820
-            return base64_encode(sha1($data, TRUE));
821
-        } else {
822
-            throw new Exception('xmlseclibs is unable to calculate a digest. Maybe you need the mhash library?');
823
-        }
824
-    }
825
-
826
-    public function validateDigest($refNode, $data) {
827
-        $xpath = new DOMXPath($refNode->ownerDocument);
828
-        $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
829
-        $query = 'string(./secdsig:DigestMethod/@Algorithm)';
830
-        $digestAlgorithm = $xpath->evaluate($query, $refNode);
831
-        $digValue = $this->calculateDigest($digestAlgorithm, $data);
832
-        $query = 'string(./secdsig:DigestValue)';
833
-        $digestValue = $xpath->evaluate($query, $refNode);
834
-        return ($digValue == $digestValue);
835
-    }
836
-
837
-    public function processTransforms($refNode, $objData, $includeCommentNodes = TRUE) {
838
-        $data = $objData;
839
-        $xpath = new DOMXPath($refNode->ownerDocument);
840
-        $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
841
-        $query = './secdsig:Transforms/secdsig:Transform';
842
-        $nodelist = $xpath->query($query, $refNode);
843
-        $canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
844
-        $arXPath = NULL;
845
-        $prefixList = NULL;
846
-        foreach ($nodelist AS $transform) {
847
-            $algorithm = $transform->getAttribute("Algorithm");
848
-            switch ($algorithm) {
849
-                case 'http://www.w3.org/2001/10/xml-exc-c14n#':
850
-                case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
851
-
852
-                    if (!$includeCommentNodes) {
853
-                        /* We remove comment nodes by forcing it to use a canonicalization
649
+	public $sigNode = NULL;
650
+	public $idKeys = array();
651
+	public $idNS = array();
652
+	private $signedInfo = NULL;
653
+	private $xPathCtx = NULL;
654
+	private $canonicalMethod = NULL;
655
+	private $prefix = NULL;
656
+	private $searchpfx = 'secdsig';
657
+
658
+	/* This variable contains an associative array of validated nodes. */
659
+	private $validatedNodes = NULL;
660
+
661
+	public function __construct() {
662
+		$sigdoc = new DOMDocument();
663
+		$sigdoc->loadXML(XMLSecurityDSig::template);
664
+		$this->sigNode = $sigdoc->documentElement;
665
+	}
666
+
667
+	private function resetXPathObj() {
668
+		$this->xPathCtx = NULL;
669
+	}
670
+
671
+	private function getXPathObj() {
672
+		if (empty($this->xPathCtx) && !empty($this->sigNode)) {
673
+			$xpath = new DOMXPath($this->sigNode->ownerDocument);
674
+			$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
675
+			$this->xPathCtx = $xpath;
676
+		}
677
+		return $this->xPathCtx;
678
+	}
679
+
680
+	static function generate_GUID($prefix='pfx') {
681
+		$uuid = md5(uniqid(rand(), true));
682
+		$guid = $prefix . substr($uuid, 0, 8) . "-" .
683
+				substr($uuid, 8, 4) . "-" .
684
+				substr($uuid, 12, 4) . "-" .
685
+				substr($uuid, 16, 4) . "-" .
686
+				substr($uuid, 20, 12);
687
+		return $guid;
688
+	}
689
+
690
+	public function locateSignature($objDoc) {
691
+		if ($objDoc instanceof DOMDocument) {
692
+			$doc = $objDoc;
693
+		} else {
694
+			$doc = $objDoc->ownerDocument;
695
+		}
696
+		if ($doc) {
697
+			$xpath = new DOMXPath($doc);
698
+			$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
699
+			$query = ".//secdsig:Signature";
700
+			$nodeset = $xpath->query($query, $objDoc);
701
+			$this->sigNode = $nodeset->item(0);
702
+			return $this->sigNode;
703
+		}
704
+		return NULL;
705
+	}
706
+
707
+	public function createNewSignNode($name, $value=NULL) {
708
+		$doc = $this->sigNode->ownerDocument;
709
+		if ($this->prefix != null) {
710
+			$name = $this->prefix . ':' . $name;
711
+		}
712
+		if (!is_null($value)) {
713
+			$node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $name, $value);
714
+		} else {
715
+			$node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $name);
716
+		}
717
+		return $node;
718
+	}
719
+
720
+	public function setCanonicalMethod($method) {
721
+		switch ($method) {
722
+			case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
723
+			case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
724
+			case 'http://www.w3.org/2001/10/xml-exc-c14n#':
725
+			case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
726
+				$this->canonicalMethod = $method;
727
+				break;
728
+			default:
729
+				throw new Exception('Invalid Canonical Method');
730
+		}
731
+		if ($xpath = $this->getXPathObj()) {
732
+			$query = './' . $this->searchpfx . ':SignedInfo';
733
+			$nodeset = $xpath->query($query, $this->sigNode);
734
+			if ($sinfo = $nodeset->item(0)) {
735
+				$query = './' . $this->searchpfx . 'CanonicalizationMethod';
736
+				$nodeset = $xpath->query($query, $sinfo);
737
+				if (!($canonNode = $nodeset->item(0))) {
738
+					$canonNode = $this->createNewSignNode('CanonicalizationMethod');
739
+					$sinfo->insertBefore($canonNode, $sinfo->firstChild);
740
+				}
741
+				$canonNode->setAttribute('Algorithm', $this->canonicalMethod);
742
+			}
743
+		}
744
+	}
745
+
746
+	private function canonicalizeData($node, $canonicalmethod, $arXPath=NULL, $prefixList=NULL) {
747
+		$exclusive = FALSE;
748
+		$withComments = FALSE;
749
+		switch ($canonicalmethod) {
750
+			case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
751
+				$exclusive = FALSE;
752
+				$withComments = FALSE;
753
+				break;
754
+			case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
755
+				$withComments = TRUE;
756
+				break;
757
+			case 'http://www.w3.org/2001/10/xml-exc-c14n#':
758
+				$exclusive = TRUE;
759
+				break;
760
+			case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
761
+				$exclusive = TRUE;
762
+				$withComments = TRUE;
763
+				break;
764
+		}
765
+		/* Support PHP versions < 5.2 not containing C14N methods in DOM extension */
766
+		$php_version = explode('.', PHP_VERSION);
767
+		if (($php_version[0] < 5) || ($php_version[0] == 5 && $php_version[1] < 2)) {
768
+			if (!is_null($arXPath)) {
769
+				throw new Exception("PHP 5.2.0 or higher is required to perform XPath Transformations");
770
+			}
771
+			return C14NGeneral($node, $exclusive, $withComments);
772
+		}
773
+		return $node->C14N($exclusive, $withComments, $arXPath, $prefixList);
774
+	}
775
+
776
+	public function canonicalizeSignedInfo() {
777
+
778
+		$doc = $this->sigNode->ownerDocument;
779
+		$canonicalmethod = NULL;
780
+		if ($doc) {
781
+			$xpath = $this->getXPathObj();
782
+			$query = "./secdsig:SignedInfo";
783
+			$nodeset = $xpath->query($query, $this->sigNode);
784
+			if ($signInfoNode = $nodeset->item(0)) {
785
+				$query = "./secdsig:CanonicalizationMethod";
786
+				$nodeset = $xpath->query($query, $signInfoNode);
787
+				if ($canonNode = $nodeset->item(0)) {
788
+					$canonicalmethod = $canonNode->getAttribute('Algorithm');
789
+				}
790
+				$this->signedInfo = $this->canonicalizeData($signInfoNode, $canonicalmethod);
791
+				return $this->signedInfo;
792
+			}
793
+		}
794
+		return NULL;
795
+	}
796
+
797
+	public function calculateDigest($digestAlgorithm, $data) {
798
+		switch ($digestAlgorithm) {
799
+			case XMLSecurityDSig::SHA1:
800
+				$alg = 'sha1';
801
+				break;
802
+			case XMLSecurityDSig::SHA256:
803
+				$alg = 'sha256';
804
+				break;
805
+			case XMLSecurityDSig::SHA512:
806
+				$alg = 'sha512';
807
+				break;
808
+			case XMLSecurityDSig::RIPEMD160:
809
+				$alg = 'ripemd160';
810
+				break;
811
+			default:
812
+				throw new Exception("Cannot validate digest: Unsupported Algorith <$digestAlgorithm>");
813
+		}
814
+		if (function_exists('hash')) {
815
+			return base64_encode(hash($alg, $data, TRUE));
816
+		} elseif (function_exists('mhash')) {
817
+			$alg = "MHASH_" . strtoupper($alg);
818
+			return base64_encode(mhash(constant($alg), $data));
819
+		} elseif ($alg === 'sha1') {
820
+			return base64_encode(sha1($data, TRUE));
821
+		} else {
822
+			throw new Exception('xmlseclibs is unable to calculate a digest. Maybe you need the mhash library?');
823
+		}
824
+	}
825
+
826
+	public function validateDigest($refNode, $data) {
827
+		$xpath = new DOMXPath($refNode->ownerDocument);
828
+		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
829
+		$query = 'string(./secdsig:DigestMethod/@Algorithm)';
830
+		$digestAlgorithm = $xpath->evaluate($query, $refNode);
831
+		$digValue = $this->calculateDigest($digestAlgorithm, $data);
832
+		$query = 'string(./secdsig:DigestValue)';
833
+		$digestValue = $xpath->evaluate($query, $refNode);
834
+		return ($digValue == $digestValue);
835
+	}
836
+
837
+	public function processTransforms($refNode, $objData, $includeCommentNodes = TRUE) {
838
+		$data = $objData;
839
+		$xpath = new DOMXPath($refNode->ownerDocument);
840
+		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
841
+		$query = './secdsig:Transforms/secdsig:Transform';
842
+		$nodelist = $xpath->query($query, $refNode);
843
+		$canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
844
+		$arXPath = NULL;
845
+		$prefixList = NULL;
846
+		foreach ($nodelist AS $transform) {
847
+			$algorithm = $transform->getAttribute("Algorithm");
848
+			switch ($algorithm) {
849
+				case 'http://www.w3.org/2001/10/xml-exc-c14n#':
850
+				case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
851
+
852
+					if (!$includeCommentNodes) {
853
+						/* We remove comment nodes by forcing it to use a canonicalization
854 854
                          * without comments.
855 855
                          */
856
-                        $canonicalMethod = 'http://www.w3.org/2001/10/xml-exc-c14n#';
857
-                    } else {
858
-                        $canonicalMethod = $algorithm;
859
-                    }
860
-
861
-                    $node = $transform->firstChild;
862
-                    while ($node) {
863
-                        if ($node->localName == 'InclusiveNamespaces') {
864
-                            if ($pfx = $node->getAttribute('PrefixList')) {
865
-                                $arpfx = array();
866
-                                $pfxlist = explode(" ", $pfx);
867
-                                foreach ($pfxlist AS $pfx) {
868
-                                    $val = trim($pfx);
869
-                                    if (!empty($val)) {
870
-                                        $arpfx[] = $val;
871
-                                    }
872
-                                }
873
-                                if (count($arpfx) > 0) {
874
-                                    $prefixList = $arpfx;
875
-                                }
876
-                            }
877
-                            break;
878
-                        }
879
-                        $node = $node->nextSibling;
880
-                    }
881
-                    break;
882
-                case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
883
-                case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
884
-                    if (!$includeCommentNodes) {
885
-                        /* We remove comment nodes by forcing it to use a canonicalization
856
+						$canonicalMethod = 'http://www.w3.org/2001/10/xml-exc-c14n#';
857
+					} else {
858
+						$canonicalMethod = $algorithm;
859
+					}
860
+
861
+					$node = $transform->firstChild;
862
+					while ($node) {
863
+						if ($node->localName == 'InclusiveNamespaces') {
864
+							if ($pfx = $node->getAttribute('PrefixList')) {
865
+								$arpfx = array();
866
+								$pfxlist = explode(" ", $pfx);
867
+								foreach ($pfxlist AS $pfx) {
868
+									$val = trim($pfx);
869
+									if (!empty($val)) {
870
+										$arpfx[] = $val;
871
+									}
872
+								}
873
+								if (count($arpfx) > 0) {
874
+									$prefixList = $arpfx;
875
+								}
876
+							}
877
+							break;
878
+						}
879
+						$node = $node->nextSibling;
880
+					}
881
+					break;
882
+				case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
883
+				case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
884
+					if (!$includeCommentNodes) {
885
+						/* We remove comment nodes by forcing it to use a canonicalization
886 886
                          * without comments.
887 887
                          */
888
-                        $canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
889
-                    } else {
890
-                        $canonicalMethod = $algorithm;
891
-                    }
892
-
893
-                    break;
894
-                case 'http://www.w3.org/TR/1999/REC-xpath-19991116':
895
-                    $node = $transform->firstChild;
896
-                    while ($node) {
897
-                        if ($node->localName == 'XPath') {
898
-                            $arXPath = array();
899
-                            $arXPath['query'] = '(.//. | .//@* | .//namespace::*)[' . $node->nodeValue . ']';
900
-                            $arXpath['namespaces'] = array();
901
-                            $nslist = $xpath->query('./namespace::*', $node);
902
-                            foreach ($nslist AS $nsnode) {
903
-                                if ($nsnode->localName != "xml") {
904
-                                    $arXPath['namespaces'][$nsnode->localName] = $nsnode->nodeValue;
905
-                                }
906
-                            }
907
-                            break;
908
-                        }
909
-                        $node = $node->nextSibling;
910
-                    }
911
-                    break;
912
-            }
913
-        }
914
-        if ($data instanceof DOMNode) {
915
-            $data = $this->canonicalizeData($objData, $canonicalMethod, $arXPath, $prefixList);
916
-        }
917
-        return $data;
918
-    }
919
-
920
-    public function processRefNode($refNode) {
921
-        $dataObject = NULL;
922
-
923
-        /*
888
+						$canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
889
+					} else {
890
+						$canonicalMethod = $algorithm;
891
+					}
892
+
893
+					break;
894
+				case 'http://www.w3.org/TR/1999/REC-xpath-19991116':
895
+					$node = $transform->firstChild;
896
+					while ($node) {
897
+						if ($node->localName == 'XPath') {
898
+							$arXPath = array();
899
+							$arXPath['query'] = '(.//. | .//@* | .//namespace::*)[' . $node->nodeValue . ']';
900
+							$arXpath['namespaces'] = array();
901
+							$nslist = $xpath->query('./namespace::*', $node);
902
+							foreach ($nslist AS $nsnode) {
903
+								if ($nsnode->localName != "xml") {
904
+									$arXPath['namespaces'][$nsnode->localName] = $nsnode->nodeValue;
905
+								}
906
+							}
907
+							break;
908
+						}
909
+						$node = $node->nextSibling;
910
+					}
911
+					break;
912
+			}
913
+		}
914
+		if ($data instanceof DOMNode) {
915
+			$data = $this->canonicalizeData($objData, $canonicalMethod, $arXPath, $prefixList);
916
+		}
917
+		return $data;
918
+	}
919
+
920
+	public function processRefNode($refNode) {
921
+		$dataObject = NULL;
922
+
923
+		/*
924 924
          * Depending on the URI, we may not want to include comments in the result
925 925
          * See: http://www.w3.org/TR/xmldsig-core/#sec-ReferenceProcessingModel
926 926
          */
927
-        $includeCommentNodes = TRUE;
927
+		$includeCommentNodes = TRUE;
928 928
 
929
-        if ($uri = $refNode->getAttribute("URI")) {
930
-            $arUrl = parse_url($uri);
931
-            if (empty($arUrl['path'])) {
932
-                if ($identifier = $arUrl['fragment']) {
929
+		if ($uri = $refNode->getAttribute("URI")) {
930
+			$arUrl = parse_url($uri);
931
+			if (empty($arUrl['path'])) {
932
+				if ($identifier = $arUrl['fragment']) {
933 933
 
934
-                    /* This reference identifies a node with the given id by using
934
+					/* This reference identifies a node with the given id by using
935 935
                      * a URI on the form "#identifier". This should not include comments.
936 936
                      */
937
-                    $includeCommentNodes = FALSE;
938
-
939
-                    $xPath = new DOMXPath($refNode->ownerDocument);
940
-                    if ($this->idNS && is_array($this->idNS)) {
941
-                        foreach ($this->idNS AS $nspf => $ns) {
942
-                            $xPath->registerNamespace($nspf, $ns);
943
-                        }
944
-                    }
945
-                    $iDlist = '@Id="' . $identifier . '"';
946
-                    if (is_array($this->idKeys)) {
947
-                        foreach ($this->idKeys AS $idKey) {
948
-                            $iDlist .= " or @$idKey='$identifier'";
949
-                        }
950
-                    }
951
-                    $query = '//*[' . $iDlist . ']';
952
-                    $dataObject = $xPath->query($query)->item(0);
953
-                } else {
954
-                    $dataObject = $refNode->ownerDocument;
955
-                }
956
-            } else {
957
-                $dataObject = file_get_contents($arUrl);
958
-            }
959
-        } else {
960
-            /* This reference identifies the root node with an empty URI. This should
937
+					$includeCommentNodes = FALSE;
938
+
939
+					$xPath = new DOMXPath($refNode->ownerDocument);
940
+					if ($this->idNS && is_array($this->idNS)) {
941
+						foreach ($this->idNS AS $nspf => $ns) {
942
+							$xPath->registerNamespace($nspf, $ns);
943
+						}
944
+					}
945
+					$iDlist = '@Id="' . $identifier . '"';
946
+					if (is_array($this->idKeys)) {
947
+						foreach ($this->idKeys AS $idKey) {
948
+							$iDlist .= " or @$idKey='$identifier'";
949
+						}
950
+					}
951
+					$query = '//*[' . $iDlist . ']';
952
+					$dataObject = $xPath->query($query)->item(0);
953
+				} else {
954
+					$dataObject = $refNode->ownerDocument;
955
+				}
956
+			} else {
957
+				$dataObject = file_get_contents($arUrl);
958
+			}
959
+		} else {
960
+			/* This reference identifies the root node with an empty URI. This should
961 961
              * not include comments.
962 962
              */
963
-            $includeCommentNodes = FALSE;
964
-
965
-            $dataObject = $refNode->ownerDocument;
966
-        }
967
-        $data = $this->processTransforms($refNode, $dataObject, $includeCommentNodes);
968
-        if (!$this->validateDigest($refNode, $data)) {
969
-            return FALSE;
970
-        }
971
-
972
-        if ($dataObject instanceof DOMNode) {
973
-            /* Add this node to the list of validated nodes. */
974
-            if (!empty($identifier)) {
975
-                $this->validatedNodes[$identifier] = $dataObject;
976
-            } else {
977
-                $this->validatedNodes[] = $dataObject;
978
-            }
979
-        }
980
-
981
-        return TRUE;
982
-    }
983
-
984
-    public function getRefNodeID($refNode) {
985
-        if ($uri = $refNode->getAttribute("URI")) {
986
-            $arUrl = parse_url($uri);
987
-            if (empty($arUrl['path'])) {
988
-                if ($identifier = $arUrl['fragment']) {
989
-                    return $identifier;
990
-                }
991
-            }
992
-        }
993
-        return null;
994
-    }
995
-
996
-    public function getRefIDs() {
997
-        $refids = array();
998
-        $doc = $this->sigNode->ownerDocument;
999
-
1000
-        $xpath = $this->getXPathObj();
1001
-        $query = "./secdsig:SignedInfo/secdsig:Reference";
1002
-        $nodeset = $xpath->query($query, $this->sigNode);
1003
-        if ($nodeset->length == 0) {
1004
-            throw new Exception("Reference nodes not found");
1005
-        }
1006
-        foreach ($nodeset AS $refNode) {
1007
-            $refids[] = $this->getRefNodeID($refNode);
1008
-        }
1009
-        return $refids;
1010
-    }
1011
-
1012
-    public function validateReference() {
1013
-        $doc = $this->sigNode->ownerDocument;
1014
-        if (!$doc->isSameNode($this->sigNode)) {
1015
-            $this->sigNode->parentNode->removeChild($this->sigNode);
1016
-        }
1017
-        $xpath = $this->getXPathObj();
1018
-        $query = "./secdsig:SignedInfo/secdsig:Reference";
1019
-        $nodeset = $xpath->query($query, $this->sigNode);
1020
-        if ($nodeset->length == 0) {
1021
-            throw new Exception("Reference nodes not found");
1022
-        }
1023
-
1024
-        /* Initialize/reset the list of validated nodes. */
1025
-        $this->validatedNodes = array();
1026
-
1027
-        foreach ($nodeset AS $refNode) {
1028
-            if (!$this->processRefNode($refNode)) {
1029
-                /* Clear the list of validated nodes. */
1030
-                $this->validatedNodes = NULL;
1031
-                throw new Exception("Reference validation failed");
1032
-            }
1033
-        }
1034
-        return TRUE;
1035
-    }
1036
-
1037
-    private function addRefInternal($sinfoNode, $node, $algorithm, $arTransforms=NULL, $options=NULL) {
1038
-        $prefix = NULL;
1039
-        $prefix_ns = NULL;
1040
-        $id_name = 'Id';
1041
-        $overwrite_id = TRUE;
1042
-        $force_uri = FALSE;
1043
-
1044
-        if (is_array($options)) {
1045
-            $prefix = empty($options['prefix']) ? NULL : $options['prefix'];
1046
-            $prefix_ns = empty($options['prefix_ns']) ? NULL : $options['prefix_ns'];
1047
-            $id_name = empty($options['id_name']) ? 'Id' : $options['id_name'];
1048
-            $overwrite_id = !isset($options['overwrite']) ? TRUE : (bool) $options['overwrite'];
1049
-            $force_uri = !isset($options['force_uri']) ? FALSE : (bool) $options['force_uri'];
1050
-        }
1051
-
1052
-        $attname = $id_name;
1053
-        if (!empty($prefix)) {
1054
-            $attname = $prefix . ':' . $attname;
1055
-        }
1056
-
1057
-        $refNode = $this->createNewSignNode('Reference');
1058
-        $sinfoNode->appendChild($refNode);
1059
-
1060
-        if (!$node instanceof DOMDocument) {
1061
-            $uri = NULL;
1062
-            if (!$overwrite_id) {
1063
-                $uri = $node->getAttributeNS($prefix_ns, $attname);
1064
-            }
1065
-            if (empty($uri)) {
1066
-                $uri = XMLSecurityDSig::generate_GUID();
1067
-                $node->setAttributeNS($prefix_ns, $attname, $uri);
1068
-            }
1069
-            $refNode->setAttribute("URI", '#' . $uri);
1070
-        } elseif ($force_uri) {
1071
-            $refNode->setAttribute("URI", '');
1072
-        }
1073
-
1074
-        $transNodes = $this->createNewSignNode('Transforms');
1075
-        $refNode->appendChild($transNodes);
1076
-
1077
-        if (is_array($arTransforms)) {
1078
-            foreach ($arTransforms AS $transform) {
1079
-                $transNode = $this->createNewSignNode('Transform');
1080
-                $transNodes->appendChild($transNode);
1081
-                if (is_array($transform) &&
1082
-                        (!empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116'])) &&
1083
-                        (!empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['query']))) {
1084
-                    $transNode->setAttribute('Algorithm', 'http://www.w3.org/TR/1999/REC-xpath-19991116');
1085
-                    $XPathNode = $this->createNewSignNode('XPath', $transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['query']);
1086
-                    $transNode->appendChild($XPathNode);
1087
-                    if (!empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['namespaces'])) {
1088
-                        foreach ($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['namespaces'] AS $prefix => $namespace) {
1089
-                            $XPathNode->setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:$prefix", $namespace);
1090
-                        }
1091
-                    }
1092
-                } else {
1093
-                    $transNode->setAttribute('Algorithm', $transform);
1094
-                }
1095
-            }
1096
-        } elseif (!empty($this->canonicalMethod)) {
1097
-            $transNode = $this->createNewSignNode('Transform');
1098
-            $transNodes->appendChild($transNode);
1099
-            $transNode->setAttribute('Algorithm', $this->canonicalMethod);
1100
-        }
1101
-
1102
-        $canonicalData = $this->processTransforms($refNode, $node);
1103
-        $digValue = $this->calculateDigest($algorithm, $canonicalData);
1104
-
1105
-        $digestMethod = $this->createNewSignNode('DigestMethod');
1106
-        $refNode->appendChild($digestMethod);
1107
-        $digestMethod->setAttribute('Algorithm', $algorithm);
1108
-
1109
-        $digestValue = $this->createNewSignNode('DigestValue', $digValue);
1110
-        $refNode->appendChild($digestValue);
1111
-    }
1112
-
1113
-    public function addReference($node, $algorithm, $arTransforms=NULL, $options=NULL) {
1114
-        if ($xpath = $this->getXPathObj()) {
1115
-            $query = "./secdsig:SignedInfo";
1116
-            $nodeset = $xpath->query($query, $this->sigNode);
1117
-            if ($sInfo = $nodeset->item(0)) {
1118
-                $this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
1119
-            }
1120
-        }
1121
-    }
1122
-
1123
-    public function addReferenceList($arNodes, $algorithm, $arTransforms=NULL, $options=NULL) {
1124
-        if ($xpath = $this->getXPathObj()) {
1125
-            $query = "./secdsig:SignedInfo";
1126
-            $nodeset = $xpath->query($query, $this->sigNode);
1127
-            if ($sInfo = $nodeset->item(0)) {
1128
-                foreach ($arNodes AS $node) {
1129
-                    $this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
1130
-                }
1131
-            }
1132
-        }
1133
-    }
1134
-
1135
-    public function addObject($data, $mimetype=NULL, $encoding=NULL) {
1136
-        $objNode = $this->createNewSignNode('Object');
1137
-        $this->sigNode->appendChild($objNode);
1138
-        if (!empty($mimetype)) {
1139
-            $objNode->setAtribute('MimeType', $mimetype);
1140
-        }
1141
-        if (!empty($encoding)) {
1142
-            $objNode->setAttribute('Encoding', $encoding);
1143
-        }
1144
-
1145
-        if ($data instanceof DOMElement) {
1146
-            $newData = $this->sigNode->ownerDocument->importNode($data, TRUE);
1147
-        } else {
1148
-            $newData = $this->sigNode->ownerDocument->createTextNode($data);
1149
-        }
1150
-        $objNode->appendChild($newData);
1151
-
1152
-        return $objNode;
1153
-    }
1154
-
1155
-    public function locateKey($node=NULL) {
1156
-        if (empty($node)) {
1157
-            $node = $this->sigNode;
1158
-        }
1159
-        if (!$node instanceof DOMNode) {
1160
-            return NULL;
1161
-        }
1162
-        if ($doc = $node->ownerDocument) {
1163
-            $xpath = new DOMXPath($doc);
1164
-            $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1165
-            $query = "string(./secdsig:SignedInfo/secdsig:SignatureMethod/@Algorithm)";
1166
-            $algorithm = $xpath->evaluate($query, $node);
1167
-            if ($algorithm) {
1168
-                try {
1169
-                    $objKey = new XMLSecurityKey($algorithm, array('type' => 'public'));
1170
-                } catch (Exception $e) {
1171
-                    return NULL;
1172
-                }
1173
-                return $objKey;
1174
-            }
1175
-        }
1176
-        return NULL;
1177
-    }
1178
-
1179
-    public function verify($objKey) {
1180
-        $doc = $this->sigNode->ownerDocument;
1181
-        $xpath = new DOMXPath($doc);
1182
-        $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1183
-        $query = "string(./secdsig:SignatureValue)";
1184
-        $sigValue = $xpath->evaluate($query, $this->sigNode);
1185
-        if (empty($sigValue)) {
1186
-            throw new Exception("Unable to locate SignatureValue");
1187
-        }
1188
-        return $objKey->verifySignature($this->signedInfo, base64_decode($sigValue));
1189
-    }
1190
-
1191
-    public function signData($objKey, $data) {
1192
-        return $objKey->signData($data);
1193
-    }
1194
-
1195
-    public function sign($objKey, $appendToNode = NULL) {
1196
-        // If we have a parent node append it now so C14N properly works
1197
-        if ($appendToNode != NULL) {
1198
-            $this->resetXPathObj();
1199
-            $this->appendSignature($appendToNode);
1200
-            $this->sigNode = $appendToNode->lastChild;
1201
-        }
1202
-        if ($xpath = $this->getXPathObj()) {
1203
-            $query = "./secdsig:SignedInfo";
1204
-            $nodeset = $xpath->query($query, $this->sigNode);
1205
-            if ($sInfo = $nodeset->item(0)) {
1206
-                $query = "./secdsig:SignatureMethod";
1207
-                $nodeset = $xpath->query($query, $sInfo);
1208
-                $sMethod = $nodeset->item(0);
1209
-                $sMethod->setAttribute('Algorithm', $objKey->type);
1210
-                $data = $this->canonicalizeData($sInfo, $this->canonicalMethod);
1211
-                $sigValue = base64_encode($this->signData($objKey, $data));
1212
-                $sigValueNode = $this->createNewSignNode('SignatureValue', $sigValue);
1213
-                if ($infoSibling = $sInfo->nextSibling) {
1214
-                    $infoSibling->parentNode->insertBefore($sigValueNode, $infoSibling);
1215
-                } else {
1216
-                    $this->sigNode->appendChild($sigValueNode);
1217
-                }
1218
-            }
1219
-        }
1220
-    }
1221
-
1222
-    public function appendCert() {
1223
-
1224
-    }
1225
-
1226
-    public function appendKey($objKey, $parent=NULL) {
1227
-        $objKey->serializeKey($parent);
1228
-    }
1229
-
1230
-    /**
1231
-     * This function inserts the signature element.
1232
-     *
1233
-     * The signature element will be appended to the element, unless $beforeNode is specified. If $beforeNode
1234
-     * is specified, the signature element will be inserted as the last element before $beforeNode.
1235
-     *
1236
-     * @param $node  The node the signature element should be inserted into.
1237
-     * @param $beforeNode  The node the signature element should be located before.
1238
-     *
1239
-     * @return DOMNode The signature element node
1240
-     */
1241
-    public function insertSignature($node, $beforeNode = NULL) {
1242
-
1243
-        $document = $node->ownerDocument;
1244
-        $signatureElement = $document->importNode($this->sigNode, TRUE);
1245
-
1246
-        if ($beforeNode == NULL) {
1247
-            return $node->insertBefore($signatureElement);
1248
-        } else {
1249
-            return $node->insertBefore($signatureElement, $beforeNode);
1250
-        }
1251
-    }
1252
-
1253
-    public function appendSignature($parentNode, $insertBefore = FALSE) {
1254
-        $beforeNode = $insertBefore ? $parentNode->firstChild : NULL;
1255
-        return $this->insertSignature($parentNode, $beforeNode);
1256
-    }
1257
-
1258
-    static function get509XCert($cert, $isPEMFormat=TRUE) {
1259
-        $certs = XMLSecurityDSig::staticGet509XCerts($cert, $isPEMFormat);
1260
-        if (!empty($certs)) {
1261
-            return $certs[0];
1262
-        }
1263
-        return '';
1264
-    }
1265
-
1266
-    static function staticGet509XCerts($certs, $isPEMFormat=TRUE) {
1267
-        if ($isPEMFormat) {
1268
-            $data = '';
1269
-            $certlist = array();
1270
-            $arCert = explode("\n", $certs);
1271
-            $inData = FALSE;
1272
-            foreach ($arCert AS $curData) {
1273
-                if (!$inData) {
1274
-                    if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
1275
-                        $inData = TRUE;
1276
-                    }
1277
-                } else {
1278
-                    if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
1279
-                        $inData = FALSE;
1280
-                        $certlist[] = $data;
1281
-                        $data = '';
1282
-                        continue;
1283
-                    }
1284
-                    $data .= trim($curData);
1285
-                }
1286
-            }
1287
-            return $certlist;
1288
-        } else {
1289
-            return array($certs);
1290
-        }
1291
-    }
1292
-
1293
-    static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=TRUE, $isURL=False, $xpath=NULL) {
1294
-        if ($isURL) {
1295
-            $cert = file_get_contents($cert);
1296
-        }
1297
-        if (!$parentRef instanceof DOMElement) {
1298
-            throw new Exception('Invalid parent Node parameter');
1299
-        }
1300
-        $baseDoc = $parentRef->ownerDocument;
1301
-
1302
-        if (empty($xpath)) {
1303
-            $xpath = new DOMXPath($parentRef->ownerDocument);
1304
-            $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1305
-        }
1306
-
1307
-        $query = "./secdsig:KeyInfo";
1308
-        $nodeset = $xpath->query($query, $parentRef);
1309
-        $keyInfo = $nodeset->item(0);
1310
-        if (!$keyInfo) {
1311
-            $inserted = FALSE;
1312
-            $keyInfo = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:KeyInfo');
1313
-
1314
-            $query = "./secdsig:Object";
1315
-            $nodeset = $xpath->query($query, $parentRef);
1316
-            if ($sObject = $nodeset->item(0)) {
1317
-                $sObject->parentNode->insertBefore($keyInfo, $sObject);
1318
-                $inserted = TRUE;
1319
-            }
1320
-
1321
-            if (!$inserted) {
1322
-                $parentRef->appendChild($keyInfo);
1323
-            }
1324
-        }
1325
-
1326
-        // Add all certs if there are more than one
1327
-        $certs = XMLSecurityDSig::staticGet509XCerts($cert, $isPEMFormat);
1328
-
1329
-        // Atach X509 data node
1330
-        $x509DataNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Data');
1331
-        $keyInfo->appendChild($x509DataNode);
1332
-
1333
-        // Atach all certificate nodes
1334
-        foreach ($certs as $X509Cert) {
1335
-            $x509CertNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Certificate', $X509Cert);
1336
-            $x509DataNode->appendChild($x509CertNode);
1337
-        }
1338
-    }
1339
-
1340
-    public function add509Cert($cert, $isPEMFormat=TRUE, $isURL=False) {
1341
-        if ($xpath = $this->getXPathObj()) {
1342
-            self::staticAdd509Cert($this->sigNode, $cert, $isPEMFormat, $isURL, $xpath);
1343
-        }
1344
-    }
1345
-
1346
-    function addKeyInfoAndName($keyName, $xpath=NULL) {
1347
-
1348
-        $baseDoc = $this->sigNode->ownerDocument;
1349
-
1350
-        if (empty($xpath)) {
1351
-            $xpath = new DOMXPath($baseDoc);
1352
-            $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1353
-        }
1354
-
1355
-        $query = "./secdsig:KeyInfo";
1356
-        $nodeset = $xpath->query($query, $this->sigNode);
1357
-        $keyInfo = $nodeset->item(0);
1358
-        if (!$keyInfo) {
1359
-            $inserted = FALSE;
1360
-            $keyInfo = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'KeyInfo');
1361
-
1362
-            $query = "./secdsig:Object";
1363
-            $nodeset = $xpath->query($query, $this->sigNode);
1364
-            if ($sObject = $nodeset->item(0)) {
1365
-                $sObject->parentNode->insertBefore($keyInfo, $sObject);
1366
-                $inserted = TRUE;
1367
-            }
1368
-            if (!$inserted) {
1369
-                $this->sigNode->appendChild($keyInfo);
1370
-            }
1371
-        }
1372
-        $keyInfo->appendChild($baseDoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'KeyName', $keyName));
1373
-    }
1374
-
1375
-    /* This function retrieves an associative array of the validated nodes.
963
+			$includeCommentNodes = FALSE;
964
+
965
+			$dataObject = $refNode->ownerDocument;
966
+		}
967
+		$data = $this->processTransforms($refNode, $dataObject, $includeCommentNodes);
968
+		if (!$this->validateDigest($refNode, $data)) {
969
+			return FALSE;
970
+		}
971
+
972
+		if ($dataObject instanceof DOMNode) {
973
+			/* Add this node to the list of validated nodes. */
974
+			if (!empty($identifier)) {
975
+				$this->validatedNodes[$identifier] = $dataObject;
976
+			} else {
977
+				$this->validatedNodes[] = $dataObject;
978
+			}
979
+		}
980
+
981
+		return TRUE;
982
+	}
983
+
984
+	public function getRefNodeID($refNode) {
985
+		if ($uri = $refNode->getAttribute("URI")) {
986
+			$arUrl = parse_url($uri);
987
+			if (empty($arUrl['path'])) {
988
+				if ($identifier = $arUrl['fragment']) {
989
+					return $identifier;
990
+				}
991
+			}
992
+		}
993
+		return null;
994
+	}
995
+
996
+	public function getRefIDs() {
997
+		$refids = array();
998
+		$doc = $this->sigNode->ownerDocument;
999
+
1000
+		$xpath = $this->getXPathObj();
1001
+		$query = "./secdsig:SignedInfo/secdsig:Reference";
1002
+		$nodeset = $xpath->query($query, $this->sigNode);
1003
+		if ($nodeset->length == 0) {
1004
+			throw new Exception("Reference nodes not found");
1005
+		}
1006
+		foreach ($nodeset AS $refNode) {
1007
+			$refids[] = $this->getRefNodeID($refNode);
1008
+		}
1009
+		return $refids;
1010
+	}
1011
+
1012
+	public function validateReference() {
1013
+		$doc = $this->sigNode->ownerDocument;
1014
+		if (!$doc->isSameNode($this->sigNode)) {
1015
+			$this->sigNode->parentNode->removeChild($this->sigNode);
1016
+		}
1017
+		$xpath = $this->getXPathObj();
1018
+		$query = "./secdsig:SignedInfo/secdsig:Reference";
1019
+		$nodeset = $xpath->query($query, $this->sigNode);
1020
+		if ($nodeset->length == 0) {
1021
+			throw new Exception("Reference nodes not found");
1022
+		}
1023
+
1024
+		/* Initialize/reset the list of validated nodes. */
1025
+		$this->validatedNodes = array();
1026
+
1027
+		foreach ($nodeset AS $refNode) {
1028
+			if (!$this->processRefNode($refNode)) {
1029
+				/* Clear the list of validated nodes. */
1030
+				$this->validatedNodes = NULL;
1031
+				throw new Exception("Reference validation failed");
1032
+			}
1033
+		}
1034
+		return TRUE;
1035
+	}
1036
+
1037
+	private function addRefInternal($sinfoNode, $node, $algorithm, $arTransforms=NULL, $options=NULL) {
1038
+		$prefix = NULL;
1039
+		$prefix_ns = NULL;
1040
+		$id_name = 'Id';
1041
+		$overwrite_id = TRUE;
1042
+		$force_uri = FALSE;
1043
+
1044
+		if (is_array($options)) {
1045
+			$prefix = empty($options['prefix']) ? NULL : $options['prefix'];
1046
+			$prefix_ns = empty($options['prefix_ns']) ? NULL : $options['prefix_ns'];
1047
+			$id_name = empty($options['id_name']) ? 'Id' : $options['id_name'];
1048
+			$overwrite_id = !isset($options['overwrite']) ? TRUE : (bool) $options['overwrite'];
1049
+			$force_uri = !isset($options['force_uri']) ? FALSE : (bool) $options['force_uri'];
1050
+		}
1051
+
1052
+		$attname = $id_name;
1053
+		if (!empty($prefix)) {
1054
+			$attname = $prefix . ':' . $attname;
1055
+		}
1056
+
1057
+		$refNode = $this->createNewSignNode('Reference');
1058
+		$sinfoNode->appendChild($refNode);
1059
+
1060
+		if (!$node instanceof DOMDocument) {
1061
+			$uri = NULL;
1062
+			if (!$overwrite_id) {
1063
+				$uri = $node->getAttributeNS($prefix_ns, $attname);
1064
+			}
1065
+			if (empty($uri)) {
1066
+				$uri = XMLSecurityDSig::generate_GUID();
1067
+				$node->setAttributeNS($prefix_ns, $attname, $uri);
1068
+			}
1069
+			$refNode->setAttribute("URI", '#' . $uri);
1070
+		} elseif ($force_uri) {
1071
+			$refNode->setAttribute("URI", '');
1072
+		}
1073
+
1074
+		$transNodes = $this->createNewSignNode('Transforms');
1075
+		$refNode->appendChild($transNodes);
1076
+
1077
+		if (is_array($arTransforms)) {
1078
+			foreach ($arTransforms AS $transform) {
1079
+				$transNode = $this->createNewSignNode('Transform');
1080
+				$transNodes->appendChild($transNode);
1081
+				if (is_array($transform) &&
1082
+						(!empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116'])) &&
1083
+						(!empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['query']))) {
1084
+					$transNode->setAttribute('Algorithm', 'http://www.w3.org/TR/1999/REC-xpath-19991116');
1085
+					$XPathNode = $this->createNewSignNode('XPath', $transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['query']);
1086
+					$transNode->appendChild($XPathNode);
1087
+					if (!empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['namespaces'])) {
1088
+						foreach ($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['namespaces'] AS $prefix => $namespace) {
1089
+							$XPathNode->setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:$prefix", $namespace);
1090
+						}
1091
+					}
1092
+				} else {
1093
+					$transNode->setAttribute('Algorithm', $transform);
1094
+				}
1095
+			}
1096
+		} elseif (!empty($this->canonicalMethod)) {
1097
+			$transNode = $this->createNewSignNode('Transform');
1098
+			$transNodes->appendChild($transNode);
1099
+			$transNode->setAttribute('Algorithm', $this->canonicalMethod);
1100
+		}
1101
+
1102
+		$canonicalData = $this->processTransforms($refNode, $node);
1103
+		$digValue = $this->calculateDigest($algorithm, $canonicalData);
1104
+
1105
+		$digestMethod = $this->createNewSignNode('DigestMethod');
1106
+		$refNode->appendChild($digestMethod);
1107
+		$digestMethod->setAttribute('Algorithm', $algorithm);
1108
+
1109
+		$digestValue = $this->createNewSignNode('DigestValue', $digValue);
1110
+		$refNode->appendChild($digestValue);
1111
+	}
1112
+
1113
+	public function addReference($node, $algorithm, $arTransforms=NULL, $options=NULL) {
1114
+		if ($xpath = $this->getXPathObj()) {
1115
+			$query = "./secdsig:SignedInfo";
1116
+			$nodeset = $xpath->query($query, $this->sigNode);
1117
+			if ($sInfo = $nodeset->item(0)) {
1118
+				$this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
1119
+			}
1120
+		}
1121
+	}
1122
+
1123
+	public function addReferenceList($arNodes, $algorithm, $arTransforms=NULL, $options=NULL) {
1124
+		if ($xpath = $this->getXPathObj()) {
1125
+			$query = "./secdsig:SignedInfo";
1126
+			$nodeset = $xpath->query($query, $this->sigNode);
1127
+			if ($sInfo = $nodeset->item(0)) {
1128
+				foreach ($arNodes AS $node) {
1129
+					$this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
1130
+				}
1131
+			}
1132
+		}
1133
+	}
1134
+
1135
+	public function addObject($data, $mimetype=NULL, $encoding=NULL) {
1136
+		$objNode = $this->createNewSignNode('Object');
1137
+		$this->sigNode->appendChild($objNode);
1138
+		if (!empty($mimetype)) {
1139
+			$objNode->setAtribute('MimeType', $mimetype);
1140
+		}
1141
+		if (!empty($encoding)) {
1142
+			$objNode->setAttribute('Encoding', $encoding);
1143
+		}
1144
+
1145
+		if ($data instanceof DOMElement) {
1146
+			$newData = $this->sigNode->ownerDocument->importNode($data, TRUE);
1147
+		} else {
1148
+			$newData = $this->sigNode->ownerDocument->createTextNode($data);
1149
+		}
1150
+		$objNode->appendChild($newData);
1151
+
1152
+		return $objNode;
1153
+	}
1154
+
1155
+	public function locateKey($node=NULL) {
1156
+		if (empty($node)) {
1157
+			$node = $this->sigNode;
1158
+		}
1159
+		if (!$node instanceof DOMNode) {
1160
+			return NULL;
1161
+		}
1162
+		if ($doc = $node->ownerDocument) {
1163
+			$xpath = new DOMXPath($doc);
1164
+			$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1165
+			$query = "string(./secdsig:SignedInfo/secdsig:SignatureMethod/@Algorithm)";
1166
+			$algorithm = $xpath->evaluate($query, $node);
1167
+			if ($algorithm) {
1168
+				try {
1169
+					$objKey = new XMLSecurityKey($algorithm, array('type' => 'public'));
1170
+				} catch (Exception $e) {
1171
+					return NULL;
1172
+				}
1173
+				return $objKey;
1174
+			}
1175
+		}
1176
+		return NULL;
1177
+	}
1178
+
1179
+	public function verify($objKey) {
1180
+		$doc = $this->sigNode->ownerDocument;
1181
+		$xpath = new DOMXPath($doc);
1182
+		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1183
+		$query = "string(./secdsig:SignatureValue)";
1184
+		$sigValue = $xpath->evaluate($query, $this->sigNode);
1185
+		if (empty($sigValue)) {
1186
+			throw new Exception("Unable to locate SignatureValue");
1187
+		}
1188
+		return $objKey->verifySignature($this->signedInfo, base64_decode($sigValue));
1189
+	}
1190
+
1191
+	public function signData($objKey, $data) {
1192
+		return $objKey->signData($data);
1193
+	}
1194
+
1195
+	public function sign($objKey, $appendToNode = NULL) {
1196
+		// If we have a parent node append it now so C14N properly works
1197
+		if ($appendToNode != NULL) {
1198
+			$this->resetXPathObj();
1199
+			$this->appendSignature($appendToNode);
1200
+			$this->sigNode = $appendToNode->lastChild;
1201
+		}
1202
+		if ($xpath = $this->getXPathObj()) {
1203
+			$query = "./secdsig:SignedInfo";
1204
+			$nodeset = $xpath->query($query, $this->sigNode);
1205
+			if ($sInfo = $nodeset->item(0)) {
1206
+				$query = "./secdsig:SignatureMethod";
1207
+				$nodeset = $xpath->query($query, $sInfo);
1208
+				$sMethod = $nodeset->item(0);
1209
+				$sMethod->setAttribute('Algorithm', $objKey->type);
1210
+				$data = $this->canonicalizeData($sInfo, $this->canonicalMethod);
1211
+				$sigValue = base64_encode($this->signData($objKey, $data));
1212
+				$sigValueNode = $this->createNewSignNode('SignatureValue', $sigValue);
1213
+				if ($infoSibling = $sInfo->nextSibling) {
1214
+					$infoSibling->parentNode->insertBefore($sigValueNode, $infoSibling);
1215
+				} else {
1216
+					$this->sigNode->appendChild($sigValueNode);
1217
+				}
1218
+			}
1219
+		}
1220
+	}
1221
+
1222
+	public function appendCert() {
1223
+
1224
+	}
1225
+
1226
+	public function appendKey($objKey, $parent=NULL) {
1227
+		$objKey->serializeKey($parent);
1228
+	}
1229
+
1230
+	/**
1231
+	 * This function inserts the signature element.
1232
+	 *
1233
+	 * The signature element will be appended to the element, unless $beforeNode is specified. If $beforeNode
1234
+	 * is specified, the signature element will be inserted as the last element before $beforeNode.
1235
+	 *
1236
+	 * @param $node  The node the signature element should be inserted into.
1237
+	 * @param $beforeNode  The node the signature element should be located before.
1238
+	 *
1239
+	 * @return DOMNode The signature element node
1240
+	 */
1241
+	public function insertSignature($node, $beforeNode = NULL) {
1242
+
1243
+		$document = $node->ownerDocument;
1244
+		$signatureElement = $document->importNode($this->sigNode, TRUE);
1245
+
1246
+		if ($beforeNode == NULL) {
1247
+			return $node->insertBefore($signatureElement);
1248
+		} else {
1249
+			return $node->insertBefore($signatureElement, $beforeNode);
1250
+		}
1251
+	}
1252
+
1253
+	public function appendSignature($parentNode, $insertBefore = FALSE) {
1254
+		$beforeNode = $insertBefore ? $parentNode->firstChild : NULL;
1255
+		return $this->insertSignature($parentNode, $beforeNode);
1256
+	}
1257
+
1258
+	static function get509XCert($cert, $isPEMFormat=TRUE) {
1259
+		$certs = XMLSecurityDSig::staticGet509XCerts($cert, $isPEMFormat);
1260
+		if (!empty($certs)) {
1261
+			return $certs[0];
1262
+		}
1263
+		return '';
1264
+	}
1265
+
1266
+	static function staticGet509XCerts($certs, $isPEMFormat=TRUE) {
1267
+		if ($isPEMFormat) {
1268
+			$data = '';
1269
+			$certlist = array();
1270
+			$arCert = explode("\n", $certs);
1271
+			$inData = FALSE;
1272
+			foreach ($arCert AS $curData) {
1273
+				if (!$inData) {
1274
+					if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
1275
+						$inData = TRUE;
1276
+					}
1277
+				} else {
1278
+					if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
1279
+						$inData = FALSE;
1280
+						$certlist[] = $data;
1281
+						$data = '';
1282
+						continue;
1283
+					}
1284
+					$data .= trim($curData);
1285
+				}
1286
+			}
1287
+			return $certlist;
1288
+		} else {
1289
+			return array($certs);
1290
+		}
1291
+	}
1292
+
1293
+	static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=TRUE, $isURL=False, $xpath=NULL) {
1294
+		if ($isURL) {
1295
+			$cert = file_get_contents($cert);
1296
+		}
1297
+		if (!$parentRef instanceof DOMElement) {
1298
+			throw new Exception('Invalid parent Node parameter');
1299
+		}
1300
+		$baseDoc = $parentRef->ownerDocument;
1301
+
1302
+		if (empty($xpath)) {
1303
+			$xpath = new DOMXPath($parentRef->ownerDocument);
1304
+			$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1305
+		}
1306
+
1307
+		$query = "./secdsig:KeyInfo";
1308
+		$nodeset = $xpath->query($query, $parentRef);
1309
+		$keyInfo = $nodeset->item(0);
1310
+		if (!$keyInfo) {
1311
+			$inserted = FALSE;
1312
+			$keyInfo = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:KeyInfo');
1313
+
1314
+			$query = "./secdsig:Object";
1315
+			$nodeset = $xpath->query($query, $parentRef);
1316
+			if ($sObject = $nodeset->item(0)) {
1317
+				$sObject->parentNode->insertBefore($keyInfo, $sObject);
1318
+				$inserted = TRUE;
1319
+			}
1320
+
1321
+			if (!$inserted) {
1322
+				$parentRef->appendChild($keyInfo);
1323
+			}
1324
+		}
1325
+
1326
+		// Add all certs if there are more than one
1327
+		$certs = XMLSecurityDSig::staticGet509XCerts($cert, $isPEMFormat);
1328
+
1329
+		// Atach X509 data node
1330
+		$x509DataNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Data');
1331
+		$keyInfo->appendChild($x509DataNode);
1332
+
1333
+		// Atach all certificate nodes
1334
+		foreach ($certs as $X509Cert) {
1335
+			$x509CertNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Certificate', $X509Cert);
1336
+			$x509DataNode->appendChild($x509CertNode);
1337
+		}
1338
+	}
1339
+
1340
+	public function add509Cert($cert, $isPEMFormat=TRUE, $isURL=False) {
1341
+		if ($xpath = $this->getXPathObj()) {
1342
+			self::staticAdd509Cert($this->sigNode, $cert, $isPEMFormat, $isURL, $xpath);
1343
+		}
1344
+	}
1345
+
1346
+	function addKeyInfoAndName($keyName, $xpath=NULL) {
1347
+
1348
+		$baseDoc = $this->sigNode->ownerDocument;
1349
+
1350
+		if (empty($xpath)) {
1351
+			$xpath = new DOMXPath($baseDoc);
1352
+			$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1353
+		}
1354
+
1355
+		$query = "./secdsig:KeyInfo";
1356
+		$nodeset = $xpath->query($query, $this->sigNode);
1357
+		$keyInfo = $nodeset->item(0);
1358
+		if (!$keyInfo) {
1359
+			$inserted = FALSE;
1360
+			$keyInfo = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'KeyInfo');
1361
+
1362
+			$query = "./secdsig:Object";
1363
+			$nodeset = $xpath->query($query, $this->sigNode);
1364
+			if ($sObject = $nodeset->item(0)) {
1365
+				$sObject->parentNode->insertBefore($keyInfo, $sObject);
1366
+				$inserted = TRUE;
1367
+			}
1368
+			if (!$inserted) {
1369
+				$this->sigNode->appendChild($keyInfo);
1370
+			}
1371
+		}
1372
+		$keyInfo->appendChild($baseDoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'KeyName', $keyName));
1373
+	}
1374
+
1375
+	/* This function retrieves an associative array of the validated nodes.
1376 1376
      *
1377 1377
      * The array will contain the id of the referenced node as the key and the node itself
1378 1378
      * as the value.
@@ -1381,394 +1381,394 @@  discard block
 block discarded – undo
1381 1381
      *  An associative array of validated nodes or NULL if no nodes have been validated.
1382 1382
      */
1383 1383
 
1384
-    public function getValidatedNodes() {
1385
-        return $this->validatedNodes;
1386
-    }
1384
+	public function getValidatedNodes() {
1385
+		return $this->validatedNodes;
1386
+	}
1387 1387
 
1388 1388
 }
1389 1389
 
1390 1390
 class XMLSecEnc {
1391
-    const template = "<xenc:EncryptedData xmlns:xenc='http://www.w3.org/2001/04/xmlenc#'>
1391
+	const template = "<xenc:EncryptedData xmlns:xenc='http://www.w3.org/2001/04/xmlenc#'>
1392 1392
    <xenc:CipherData>
1393 1393
       <xenc:CipherValue></xenc:CipherValue>
1394 1394
    </xenc:CipherData>
1395 1395
 </xenc:EncryptedData>";
1396 1396
 
1397
-    const Element = 'http://www.w3.org/2001/04/xmlenc#Element';
1398
-    const Content = 'http://www.w3.org/2001/04/xmlenc#Content';
1399
-    const URI = 3;
1400
-    const XMLENCNS = 'http://www.w3.org/2001/04/xmlenc#';
1401
-
1402
-    private $encdoc = NULL;
1403
-    private $rawNode = NULL;
1404
-    public $type = NULL;
1405
-    public $encKey = NULL;
1406
-    private $references = array();
1407
-
1408
-    public function __construct() {
1409
-        $this->_resetTemplate();
1410
-    }
1411
-
1412
-    private function _resetTemplate() {
1413
-        $this->encdoc = new DOMDocument();
1414
-        $this->encdoc->loadXML(XMLSecEnc::template);
1415
-    }
1416
-
1417
-    public function addReference($name, $node, $type) {
1418
-        if (!$node instanceOf DOMNode) {
1419
-            throw new Exception('$node is not of type DOMNode');
1420
-        }
1421
-        $curencdoc = $this->encdoc;
1422
-        $this->_resetTemplate();
1423
-        $encdoc = $this->encdoc;
1424
-        $this->encdoc = $curencdoc;
1425
-        $refuri = XMLSecurityDSig::generate_GUID();
1426
-        $element = $encdoc->documentElement;
1427
-        $element->setAttribute("Id", $refuri);
1428
-        $this->references[$name] = array("node" => $node, "type" => $type, "encnode" => $encdoc, "refuri" => $refuri);
1429
-    }
1430
-
1431
-    public function setNode($node) {
1432
-        $this->rawNode = $node;
1433
-    }
1434
-
1435
-    public function encryptNode($objKey, $replace=TRUE) {
1436
-        $data = '';
1437
-        if (empty($this->rawNode)) {
1438
-            throw new Exception('Node to encrypt has not been set');
1439
-        }
1440
-        if (!$objKey instanceof XMLSecurityKey) {
1441
-            throw new Exception('Invalid Key');
1442
-        }
1443
-        $doc = $this->rawNode->ownerDocument;
1444
-        $xPath = new DOMXPath($this->encdoc);
1445
-        $objList = $xPath->query('/xenc:EncryptedData/xenc:CipherData/xenc:CipherValue');
1446
-        $cipherValue = $objList->item(0);
1447
-        if ($cipherValue == NULL) {
1448
-            throw new Exception('Error locating CipherValue element within template');
1449
-        }
1450
-        switch ($this->type) {
1451
-            case (XMLSecEnc::Element):
1452
-                $data = $doc->saveXML($this->rawNode);
1453
-                $this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Element);
1454
-                break;
1455
-            case (XMLSecEnc::Content):
1456
-                $children = $this->rawNode->childNodes;
1457
-                foreach ($children AS $child) {
1458
-                    $data .= $doc->saveXML($child);
1459
-                }
1460
-                $this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Content);
1461
-                break;
1462
-            default:
1463
-                throw new Exception('Type is currently not supported');
1464
-                return;
1465
-        }
1466
-
1467
-        $encMethod = $this->encdoc->documentElement->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
1468
-        $encMethod->setAttribute('Algorithm', $objKey->getAlgorith());
1469
-        $cipherValue->parentNode->parentNode->insertBefore($encMethod, $cipherValue->parentNode->parentNode->firstChild);
1470
-
1471
-        $strEncrypt = base64_encode($objKey->encryptData($data));
1472
-        $value = $this->encdoc->createTextNode($strEncrypt);
1473
-        $cipherValue->appendChild($value);
1474
-
1475
-        if ($replace) {
1476
-            switch ($this->type) {
1477
-                case (XMLSecEnc::Element):
1478
-                    if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
1479
-                        return $this->encdoc;
1480
-                    }
1481
-                    $importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE);
1482
-                    $this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
1483
-                    return $importEnc;
1484
-                    break;
1485
-                case (XMLSecEnc::Content):
1486
-                    $importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE);
1487
-                    while ($this->rawNode->firstChild) {
1488
-                        $this->rawNode->removeChild($this->rawNode->firstChild);
1489
-                    }
1490
-                    $this->rawNode->appendChild($importEnc);
1491
-                    return $importEnc;
1492
-                    break;
1493
-            }
1494
-        }
1495
-    }
1496
-
1497
-    public function encryptReferences($objKey) {
1498
-        $curRawNode = $this->rawNode;
1499
-        $curType = $this->type;
1500
-        foreach ($this->references AS $name => $reference) {
1501
-            $this->encdoc = $reference["encnode"];
1502
-            $this->rawNode = $reference["node"];
1503
-            $this->type = $reference["type"];
1504
-            try {
1505
-                $encNode = $this->encryptNode($objKey);
1506
-                $this->references[$name]["encnode"] = $encNode;
1507
-            } catch (Exception $e) {
1508
-                $this->rawNode = $curRawNode;
1509
-                $this->type = $curType;
1510
-                throw $e;
1511
-            }
1512
-        }
1513
-        $this->rawNode = $curRawNode;
1514
-        $this->type = $curType;
1515
-    }
1516
-
1517
-    /**
1518
-     * Retrieve the CipherValue text from this encrypted node.
1519
-     *
1520
-     * @return string|NULL  The Ciphervalue text, or NULL if no CipherValue is found.
1521
-     */
1522
-    public function getCipherValue() {
1523
-        if (empty($this->rawNode)) {
1524
-            throw new Exception('Node to decrypt has not been set');
1525
-        }
1526
-
1527
-        $doc = $this->rawNode->ownerDocument;
1528
-        $xPath = new DOMXPath($doc);
1529
-        $xPath->registerNamespace('xmlencr', XMLSecEnc::XMLENCNS);
1530
-        /* Only handles embedded content right now and not a reference */
1531
-        $query = "./xmlencr:CipherData/xmlencr:CipherValue";
1532
-        $nodeset = $xPath->query($query, $this->rawNode);
1533
-        $node = $nodeset->item(0);
1534
-
1535
-        if (!$node) {
1536
-            return NULL;
1537
-        }
1538
-
1539
-        return base64_decode($node->nodeValue);
1540
-    }
1541
-
1542
-    /**
1543
-     * Decrypt this encrypted node.
1544
-     *
1545
-     * The behaviour of this function depends on the value of $replace.
1546
-     * If $replace is FALSE, we will return the decrypted data as a string.
1547
-     * If $replace is TRUE, we will insert the decrypted element(s) into the
1548
-     * document, and return the decrypted element(s).
1549
-     *
1550
-     * @params XMLSecurityKey $objKey  The decryption key that should be used when decrypting the node.
1551
-     * @params boolean $replace  Whether we should replace the encrypted node in the XML document with the decrypted data. The default is TRUE.
1552
-     * @return string|DOMElement  The decrypted data.
1553
-     */
1554
-    public function decryptNode($objKey, $replace=TRUE) {
1555
-        if (!$objKey instanceof XMLSecurityKey) {
1556
-            throw new Exception('Invalid Key');
1557
-        }
1558
-
1559
-        $encryptedData = $this->getCipherValue();
1560
-        if ($encryptedData) {
1561
-            $decrypted = $objKey->decryptData($encryptedData);
1562
-            if ($replace) {
1563
-                switch ($this->type) {
1564
-                    case (XMLSecEnc::Element):
1565
-                        $newdoc = new DOMDocument();
1566
-                        $newdoc->loadXML($decrypted);
1567
-                        if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
1568
-                            return $newdoc;
1569
-                        }
1570
-                        $importEnc = $this->rawNode->ownerDocument->importNode($newdoc->documentElement, TRUE);
1571
-                        $this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
1572
-                        return $importEnc;
1573
-                        break;
1574
-                    case (XMLSecEnc::Content):
1575
-                        if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
1576
-                            $doc = $this->rawNode;
1577
-                        } else {
1578
-                            $doc = $this->rawNode->ownerDocument;
1579
-                        }
1580
-                        $newFrag = $doc->createDocumentFragment();
1581
-                        $newFrag->appendXML($decrypted);
1582
-                        $parent = $this->rawNode->parentNode;
1583
-                        $parent->replaceChild($newFrag, $this->rawNode);
1584
-                        return $parent;
1585
-                        break;
1586
-                    default:
1587
-                        return $decrypted;
1588
-                }
1589
-            } else {
1590
-                return $decrypted;
1591
-            }
1592
-        } else {
1593
-            throw new Exception("Cannot locate encrypted data");
1594
-        }
1595
-    }
1596
-
1597
-    public function encryptKey($srcKey, $rawKey, $append=TRUE) {
1598
-        if ((!$srcKey instanceof XMLSecurityKey) || (!$rawKey instanceof XMLSecurityKey)) {
1599
-            throw new Exception('Invalid Key');
1600
-        }
1601
-        $strEncKey = base64_encode($srcKey->encryptData($rawKey->key));
1602
-        $root = $this->encdoc->documentElement;
1603
-        $encKey = $this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptedKey');
1604
-        if ($append) {
1605
-            $keyInfo = $root->insertBefore($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'), $root->firstChild);
1606
-            $keyInfo->appendChild($encKey);
1607
-        } else {
1608
-            $this->encKey = $encKey;
1609
-        }
1610
-        $encMethod = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
1611
-        $encMethod->setAttribute('Algorithm', $srcKey->getAlgorith());
1612
-        if (!empty($srcKey->name)) {
1613
-            $keyInfo = $encKey->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'));
1614
-            $keyInfo->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyName', $srcKey->name));
1615
-        }
1616
-        $cipherData = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherData'));
1617
-        $cipherData->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherValue', $strEncKey));
1618
-        if (is_array($this->references) && count($this->references) > 0) {
1619
-            $refList = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:ReferenceList'));
1620
-            foreach ($this->references AS $name => $reference) {
1621
-                $refuri = $reference["refuri"];
1622
-                $dataRef = $refList->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:DataReference'));
1623
-                $dataRef->setAttribute("URI", '#' . $refuri);
1624
-            }
1625
-        }
1626
-        return;
1627
-    }
1628
-
1629
-    public function decryptKey($encKey) {
1630
-        if (!$encKey->isEncrypted) {
1631
-            throw new Exception("Key is not Encrypted");
1632
-        }
1633
-        if (empty($encKey->key)) {
1634
-            throw new Exception("Key is missing data to perform the decryption");
1635
-        }
1636
-        return $this->decryptNode($encKey, FALSE);
1637
-    }
1638
-
1639
-    public function locateEncryptedData($element) {
1640
-        if ($element instanceof DOMDocument) {
1641
-            $doc = $element;
1642
-        } else {
1643
-            $doc = $element->ownerDocument;
1644
-        }
1645
-        if ($doc) {
1646
-            $xpath = new DOMXPath($doc);
1647
-            $query = "//*[local-name()='EncryptedData' and namespace-uri()='" . XMLSecEnc::XMLENCNS . "']";
1648
-            $nodeset = $xpath->query($query);
1649
-            return $nodeset->item(0);
1650
-        }
1651
-        return NULL;
1652
-    }
1653
-
1654
-    public function locateKey($node=NULL) {
1655
-        if (empty($node)) {
1656
-            $node = $this->rawNode;
1657
-        }
1658
-        if (!$node instanceof DOMNode) {
1659
-            return NULL;
1660
-        }
1661
-        if ($doc = $node->ownerDocument) {
1662
-            $xpath = new DOMXPath($doc);
1663
-            $xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
1664
-            $query = ".//xmlsecenc:EncryptionMethod";
1665
-            $nodeset = $xpath->query($query, $node);
1666
-            if ($encmeth = $nodeset->item(0)) {
1667
-                $attrAlgorithm = $encmeth->getAttribute("Algorithm");
1668
-                try {
1669
-                    $objKey = new XMLSecurityKey($attrAlgorithm, array('type' => 'private'));
1670
-                } catch (Exception $e) {
1671
-                    return NULL;
1672
-                }
1673
-                return $objKey;
1674
-            }
1675
-        }
1676
-        return NULL;
1677
-    }
1678
-
1679
-    static function staticLocateKeyInfo($objBaseKey=NULL, $node=NULL) {
1680
-        if (empty($node) || (!$node instanceof DOMNode)) {
1681
-            return NULL;
1682
-        }
1683
-        $doc = $node->ownerDocument;
1684
-        if (!$doc) {
1685
-            return NULL;
1686
-        }
1687
-
1688
-        $xpath = new DOMXPath($doc);
1689
-        $xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
1690
-        $xpath->registerNamespace('xmlsecdsig', XMLSecurityDSig::XMLDSIGNS);
1691
-        $query = "./xmlsecdsig:KeyInfo";
1692
-        $nodeset = $xpath->query($query, $node);
1693
-        $encmeth = $nodeset->item(0);
1694
-        if (!$encmeth) {
1695
-            /* No KeyInfo in EncryptedData / EncryptedKey. */
1696
-            return $objBaseKey;
1697
-        }
1698
-
1699
-        foreach ($encmeth->childNodes AS $child) {
1700
-            switch ($child->localName) {
1701
-                case 'KeyName':
1702
-                    if (!empty($objBaseKey)) {
1703
-                        $objBaseKey->name = $child->nodeValue;
1704
-                    }
1705
-                    break;
1706
-                case 'KeyValue':
1707
-                    foreach ($child->childNodes AS $keyval) {
1708
-                        switch ($keyval->localName) {
1709
-                            case 'DSAKeyValue':
1710
-                                throw new Exception("DSAKeyValue currently not supported");
1711
-                                break;
1712
-                            case 'RSAKeyValue':
1713
-                                $modulus = NULL;
1714
-                                $exponent = NULL;
1715
-                                if ($modulusNode = $keyval->getElementsByTagName('Modulus')->item(0)) {
1716
-                                    $modulus = base64_decode($modulusNode->nodeValue);
1717
-                                }
1718
-                                if ($exponentNode = $keyval->getElementsByTagName('Exponent')->item(0)) {
1719
-                                    $exponent = base64_decode($exponentNode->nodeValue);
1720
-                                }
1721
-                                if (empty($modulus) || empty($exponent)) {
1722
-                                    throw new Exception("Missing Modulus or Exponent");
1723
-                                }
1724
-                                $publicKey = XMLSecurityKey::convertRSA($modulus, $exponent);
1725
-                                $objBaseKey->loadKey($publicKey);
1726
-                                break;
1727
-                        }
1728
-                    }
1729
-                    break;
1730
-                case 'RetrievalMethod':
1731
-                    $type = $child->getAttribute('Type');
1732
-                    if ($type !== 'http://www.w3.org/2001/04/xmlenc#EncryptedKey') {
1733
-                        /* Unsupported key type. */
1734
-                        break;
1735
-                    }
1736
-                    $uri = $child->getAttribute('URI');
1737
-                    if ($uri[0] !== '#') {
1738
-                        /* URI not a reference - unsupported. */
1739
-                        break;
1740
-                    }
1741
-                    $id = substr($uri, 1);
1742
-
1743
-                    $query = "//xmlsecenc:EncryptedKey[@Id='$id']";
1744
-                    $keyElement = $xpath->query($query)->item(0);
1745
-                    if (!$keyElement) {
1746
-                        throw new Exception("Unable to locate EncryptedKey with @Id='$id'.");
1747
-                    }
1748
-
1749
-                    return XMLSecurityKey::fromEncryptedKeyElement($keyElement);
1750
-                case 'EncryptedKey':
1751
-                    return XMLSecurityKey::fromEncryptedKeyElement($child);
1752
-                case 'X509Data':
1753
-                    if ($x509certNodes = $child->getElementsByTagName('X509Certificate')) {
1754
-                        if ($x509certNodes->length > 0) {
1755
-                            $x509cert = $x509certNodes->item(0)->textContent;
1756
-                            $x509cert = str_replace(array("\r", "\n"), "", $x509cert);
1757
-                            $x509cert = "-----BEGIN CERTIFICATE-----\n" . chunk_split($x509cert, 64, "\n") . "-----END CERTIFICATE-----\n";
1758
-                            $objBaseKey->loadKey($x509cert, FALSE, TRUE);
1759
-                        }
1760
-                    }
1761
-                    break;
1762
-            }
1763
-        }
1764
-        return $objBaseKey;
1765
-    }
1766
-
1767
-    public function locateKeyInfo($objBaseKey=NULL, $node=NULL) {
1768
-        if (empty($node)) {
1769
-            $node = $this->rawNode;
1770
-        }
1771
-        return XMLSecEnc::staticLocateKeyInfo($objBaseKey, $node);
1772
-    }
1397
+	const Element = 'http://www.w3.org/2001/04/xmlenc#Element';
1398
+	const Content = 'http://www.w3.org/2001/04/xmlenc#Content';
1399
+	const URI = 3;
1400
+	const XMLENCNS = 'http://www.w3.org/2001/04/xmlenc#';
1401
+
1402
+	private $encdoc = NULL;
1403
+	private $rawNode = NULL;
1404
+	public $type = NULL;
1405
+	public $encKey = NULL;
1406
+	private $references = array();
1407
+
1408
+	public function __construct() {
1409
+		$this->_resetTemplate();
1410
+	}
1411
+
1412
+	private function _resetTemplate() {
1413
+		$this->encdoc = new DOMDocument();
1414
+		$this->encdoc->loadXML(XMLSecEnc::template);
1415
+	}
1416
+
1417
+	public function addReference($name, $node, $type) {
1418
+		if (!$node instanceOf DOMNode) {
1419
+			throw new Exception('$node is not of type DOMNode');
1420
+		}
1421
+		$curencdoc = $this->encdoc;
1422
+		$this->_resetTemplate();
1423
+		$encdoc = $this->encdoc;
1424
+		$this->encdoc = $curencdoc;
1425
+		$refuri = XMLSecurityDSig::generate_GUID();
1426
+		$element = $encdoc->documentElement;
1427
+		$element->setAttribute("Id", $refuri);
1428
+		$this->references[$name] = array("node" => $node, "type" => $type, "encnode" => $encdoc, "refuri" => $refuri);
1429
+	}
1430
+
1431
+	public function setNode($node) {
1432
+		$this->rawNode = $node;
1433
+	}
1434
+
1435
+	public function encryptNode($objKey, $replace=TRUE) {
1436
+		$data = '';
1437
+		if (empty($this->rawNode)) {
1438
+			throw new Exception('Node to encrypt has not been set');
1439
+		}
1440
+		if (!$objKey instanceof XMLSecurityKey) {
1441
+			throw new Exception('Invalid Key');
1442
+		}
1443
+		$doc = $this->rawNode->ownerDocument;
1444
+		$xPath = new DOMXPath($this->encdoc);
1445
+		$objList = $xPath->query('/xenc:EncryptedData/xenc:CipherData/xenc:CipherValue');
1446
+		$cipherValue = $objList->item(0);
1447
+		if ($cipherValue == NULL) {
1448
+			throw new Exception('Error locating CipherValue element within template');
1449
+		}
1450
+		switch ($this->type) {
1451
+			case (XMLSecEnc::Element):
1452
+				$data = $doc->saveXML($this->rawNode);
1453
+				$this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Element);
1454
+				break;
1455
+			case (XMLSecEnc::Content):
1456
+				$children = $this->rawNode->childNodes;
1457
+				foreach ($children AS $child) {
1458
+					$data .= $doc->saveXML($child);
1459
+				}
1460
+				$this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Content);
1461
+				break;
1462
+			default:
1463
+				throw new Exception('Type is currently not supported');
1464
+				return;
1465
+		}
1466
+
1467
+		$encMethod = $this->encdoc->documentElement->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
1468
+		$encMethod->setAttribute('Algorithm', $objKey->getAlgorith());
1469
+		$cipherValue->parentNode->parentNode->insertBefore($encMethod, $cipherValue->parentNode->parentNode->firstChild);
1470
+
1471
+		$strEncrypt = base64_encode($objKey->encryptData($data));
1472
+		$value = $this->encdoc->createTextNode($strEncrypt);
1473
+		$cipherValue->appendChild($value);
1474
+
1475
+		if ($replace) {
1476
+			switch ($this->type) {
1477
+				case (XMLSecEnc::Element):
1478
+					if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
1479
+						return $this->encdoc;
1480
+					}
1481
+					$importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE);
1482
+					$this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
1483
+					return $importEnc;
1484
+					break;
1485
+				case (XMLSecEnc::Content):
1486
+					$importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE);
1487
+					while ($this->rawNode->firstChild) {
1488
+						$this->rawNode->removeChild($this->rawNode->firstChild);
1489
+					}
1490
+					$this->rawNode->appendChild($importEnc);
1491
+					return $importEnc;
1492
+					break;
1493
+			}
1494
+		}
1495
+	}
1496
+
1497
+	public function encryptReferences($objKey) {
1498
+		$curRawNode = $this->rawNode;
1499
+		$curType = $this->type;
1500
+		foreach ($this->references AS $name => $reference) {
1501
+			$this->encdoc = $reference["encnode"];
1502
+			$this->rawNode = $reference["node"];
1503
+			$this->type = $reference["type"];
1504
+			try {
1505
+				$encNode = $this->encryptNode($objKey);
1506
+				$this->references[$name]["encnode"] = $encNode;
1507
+			} catch (Exception $e) {
1508
+				$this->rawNode = $curRawNode;
1509
+				$this->type = $curType;
1510
+				throw $e;
1511
+			}
1512
+		}
1513
+		$this->rawNode = $curRawNode;
1514
+		$this->type = $curType;
1515
+	}
1516
+
1517
+	/**
1518
+	 * Retrieve the CipherValue text from this encrypted node.
1519
+	 *
1520
+	 * @return string|NULL  The Ciphervalue text, or NULL if no CipherValue is found.
1521
+	 */
1522
+	public function getCipherValue() {
1523
+		if (empty($this->rawNode)) {
1524
+			throw new Exception('Node to decrypt has not been set');
1525
+		}
1526
+
1527
+		$doc = $this->rawNode->ownerDocument;
1528
+		$xPath = new DOMXPath($doc);
1529
+		$xPath->registerNamespace('xmlencr', XMLSecEnc::XMLENCNS);
1530
+		/* Only handles embedded content right now and not a reference */
1531
+		$query = "./xmlencr:CipherData/xmlencr:CipherValue";
1532
+		$nodeset = $xPath->query($query, $this->rawNode);
1533
+		$node = $nodeset->item(0);
1534
+
1535
+		if (!$node) {
1536
+			return NULL;
1537
+		}
1538
+
1539
+		return base64_decode($node->nodeValue);
1540
+	}
1541
+
1542
+	/**
1543
+	 * Decrypt this encrypted node.
1544
+	 *
1545
+	 * The behaviour of this function depends on the value of $replace.
1546
+	 * If $replace is FALSE, we will return the decrypted data as a string.
1547
+	 * If $replace is TRUE, we will insert the decrypted element(s) into the
1548
+	 * document, and return the decrypted element(s).
1549
+	 *
1550
+	 * @params XMLSecurityKey $objKey  The decryption key that should be used when decrypting the node.
1551
+	 * @params boolean $replace  Whether we should replace the encrypted node in the XML document with the decrypted data. The default is TRUE.
1552
+	 * @return string|DOMElement  The decrypted data.
1553
+	 */
1554
+	public function decryptNode($objKey, $replace=TRUE) {
1555
+		if (!$objKey instanceof XMLSecurityKey) {
1556
+			throw new Exception('Invalid Key');
1557
+		}
1558
+
1559
+		$encryptedData = $this->getCipherValue();
1560
+		if ($encryptedData) {
1561
+			$decrypted = $objKey->decryptData($encryptedData);
1562
+			if ($replace) {
1563
+				switch ($this->type) {
1564
+					case (XMLSecEnc::Element):
1565
+						$newdoc = new DOMDocument();
1566
+						$newdoc->loadXML($decrypted);
1567
+						if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
1568
+							return $newdoc;
1569
+						}
1570
+						$importEnc = $this->rawNode->ownerDocument->importNode($newdoc->documentElement, TRUE);
1571
+						$this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
1572
+						return $importEnc;
1573
+						break;
1574
+					case (XMLSecEnc::Content):
1575
+						if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
1576
+							$doc = $this->rawNode;
1577
+						} else {
1578
+							$doc = $this->rawNode->ownerDocument;
1579
+						}
1580
+						$newFrag = $doc->createDocumentFragment();
1581
+						$newFrag->appendXML($decrypted);
1582
+						$parent = $this->rawNode->parentNode;
1583
+						$parent->replaceChild($newFrag, $this->rawNode);
1584
+						return $parent;
1585
+						break;
1586
+					default:
1587
+						return $decrypted;
1588
+				}
1589
+			} else {
1590
+				return $decrypted;
1591
+			}
1592
+		} else {
1593
+			throw new Exception("Cannot locate encrypted data");
1594
+		}
1595
+	}
1596
+
1597
+	public function encryptKey($srcKey, $rawKey, $append=TRUE) {
1598
+		if ((!$srcKey instanceof XMLSecurityKey) || (!$rawKey instanceof XMLSecurityKey)) {
1599
+			throw new Exception('Invalid Key');
1600
+		}
1601
+		$strEncKey = base64_encode($srcKey->encryptData($rawKey->key));
1602
+		$root = $this->encdoc->documentElement;
1603
+		$encKey = $this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptedKey');
1604
+		if ($append) {
1605
+			$keyInfo = $root->insertBefore($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'), $root->firstChild);
1606
+			$keyInfo->appendChild($encKey);
1607
+		} else {
1608
+			$this->encKey = $encKey;
1609
+		}
1610
+		$encMethod = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
1611
+		$encMethod->setAttribute('Algorithm', $srcKey->getAlgorith());
1612
+		if (!empty($srcKey->name)) {
1613
+			$keyInfo = $encKey->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'));
1614
+			$keyInfo->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyName', $srcKey->name));
1615
+		}
1616
+		$cipherData = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherData'));
1617
+		$cipherData->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherValue', $strEncKey));
1618
+		if (is_array($this->references) && count($this->references) > 0) {
1619
+			$refList = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:ReferenceList'));
1620
+			foreach ($this->references AS $name => $reference) {
1621
+				$refuri = $reference["refuri"];
1622
+				$dataRef = $refList->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:DataReference'));
1623
+				$dataRef->setAttribute("URI", '#' . $refuri);
1624
+			}
1625
+		}
1626
+		return;
1627
+	}
1628
+
1629
+	public function decryptKey($encKey) {
1630
+		if (!$encKey->isEncrypted) {
1631
+			throw new Exception("Key is not Encrypted");
1632
+		}
1633
+		if (empty($encKey->key)) {
1634
+			throw new Exception("Key is missing data to perform the decryption");
1635
+		}
1636
+		return $this->decryptNode($encKey, FALSE);
1637
+	}
1638
+
1639
+	public function locateEncryptedData($element) {
1640
+		if ($element instanceof DOMDocument) {
1641
+			$doc = $element;
1642
+		} else {
1643
+			$doc = $element->ownerDocument;
1644
+		}
1645
+		if ($doc) {
1646
+			$xpath = new DOMXPath($doc);
1647
+			$query = "//*[local-name()='EncryptedData' and namespace-uri()='" . XMLSecEnc::XMLENCNS . "']";
1648
+			$nodeset = $xpath->query($query);
1649
+			return $nodeset->item(0);
1650
+		}
1651
+		return NULL;
1652
+	}
1653
+
1654
+	public function locateKey($node=NULL) {
1655
+		if (empty($node)) {
1656
+			$node = $this->rawNode;
1657
+		}
1658
+		if (!$node instanceof DOMNode) {
1659
+			return NULL;
1660
+		}
1661
+		if ($doc = $node->ownerDocument) {
1662
+			$xpath = new DOMXPath($doc);
1663
+			$xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
1664
+			$query = ".//xmlsecenc:EncryptionMethod";
1665
+			$nodeset = $xpath->query($query, $node);
1666
+			if ($encmeth = $nodeset->item(0)) {
1667
+				$attrAlgorithm = $encmeth->getAttribute("Algorithm");
1668
+				try {
1669
+					$objKey = new XMLSecurityKey($attrAlgorithm, array('type' => 'private'));
1670
+				} catch (Exception $e) {
1671
+					return NULL;
1672
+				}
1673
+				return $objKey;
1674
+			}
1675
+		}
1676
+		return NULL;
1677
+	}
1678
+
1679
+	static function staticLocateKeyInfo($objBaseKey=NULL, $node=NULL) {
1680
+		if (empty($node) || (!$node instanceof DOMNode)) {
1681
+			return NULL;
1682
+		}
1683
+		$doc = $node->ownerDocument;
1684
+		if (!$doc) {
1685
+			return NULL;
1686
+		}
1687
+
1688
+		$xpath = new DOMXPath($doc);
1689
+		$xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
1690
+		$xpath->registerNamespace('xmlsecdsig', XMLSecurityDSig::XMLDSIGNS);
1691
+		$query = "./xmlsecdsig:KeyInfo";
1692
+		$nodeset = $xpath->query($query, $node);
1693
+		$encmeth = $nodeset->item(0);
1694
+		if (!$encmeth) {
1695
+			/* No KeyInfo in EncryptedData / EncryptedKey. */
1696
+			return $objBaseKey;
1697
+		}
1698
+
1699
+		foreach ($encmeth->childNodes AS $child) {
1700
+			switch ($child->localName) {
1701
+				case 'KeyName':
1702
+					if (!empty($objBaseKey)) {
1703
+						$objBaseKey->name = $child->nodeValue;
1704
+					}
1705
+					break;
1706
+				case 'KeyValue':
1707
+					foreach ($child->childNodes AS $keyval) {
1708
+						switch ($keyval->localName) {
1709
+							case 'DSAKeyValue':
1710
+								throw new Exception("DSAKeyValue currently not supported");
1711
+								break;
1712
+							case 'RSAKeyValue':
1713
+								$modulus = NULL;
1714
+								$exponent = NULL;
1715
+								if ($modulusNode = $keyval->getElementsByTagName('Modulus')->item(0)) {
1716
+									$modulus = base64_decode($modulusNode->nodeValue);
1717
+								}
1718
+								if ($exponentNode = $keyval->getElementsByTagName('Exponent')->item(0)) {
1719
+									$exponent = base64_decode($exponentNode->nodeValue);
1720
+								}
1721
+								if (empty($modulus) || empty($exponent)) {
1722
+									throw new Exception("Missing Modulus or Exponent");
1723
+								}
1724
+								$publicKey = XMLSecurityKey::convertRSA($modulus, $exponent);
1725
+								$objBaseKey->loadKey($publicKey);
1726
+								break;
1727
+						}
1728
+					}
1729
+					break;
1730
+				case 'RetrievalMethod':
1731
+					$type = $child->getAttribute('Type');
1732
+					if ($type !== 'http://www.w3.org/2001/04/xmlenc#EncryptedKey') {
1733
+						/* Unsupported key type. */
1734
+						break;
1735
+					}
1736
+					$uri = $child->getAttribute('URI');
1737
+					if ($uri[0] !== '#') {
1738
+						/* URI not a reference - unsupported. */
1739
+						break;
1740
+					}
1741
+					$id = substr($uri, 1);
1742
+
1743
+					$query = "//xmlsecenc:EncryptedKey[@Id='$id']";
1744
+					$keyElement = $xpath->query($query)->item(0);
1745
+					if (!$keyElement) {
1746
+						throw new Exception("Unable to locate EncryptedKey with @Id='$id'.");
1747
+					}
1748
+
1749
+					return XMLSecurityKey::fromEncryptedKeyElement($keyElement);
1750
+				case 'EncryptedKey':
1751
+					return XMLSecurityKey::fromEncryptedKeyElement($child);
1752
+				case 'X509Data':
1753
+					if ($x509certNodes = $child->getElementsByTagName('X509Certificate')) {
1754
+						if ($x509certNodes->length > 0) {
1755
+							$x509cert = $x509certNodes->item(0)->textContent;
1756
+							$x509cert = str_replace(array("\r", "\n"), "", $x509cert);
1757
+							$x509cert = "-----BEGIN CERTIFICATE-----\n" . chunk_split($x509cert, 64, "\n") . "-----END CERTIFICATE-----\n";
1758
+							$objBaseKey->loadKey($x509cert, FALSE, TRUE);
1759
+						}
1760
+					}
1761
+					break;
1762
+			}
1763
+		}
1764
+		return $objBaseKey;
1765
+	}
1766
+
1767
+	public function locateKeyInfo($objBaseKey=NULL, $node=NULL) {
1768
+		if (empty($node)) {
1769
+			$node = $this->rawNode;
1770
+		}
1771
+		return XMLSecEnc::staticLocateKeyInfo($objBaseKey, $node);
1772
+	}
1773 1773
 
1774 1774
 }
Please login to merge, or discard this patch.
includes/xmlseclibs/xmlseclibs-ing.php 1 patch
Indentation   +1687 added lines, -1687 removed lines patch added patch discarded remove patch
@@ -47,101 +47,101 @@  discard block
 block discarded – undo
47 47
 
48 48
 /* helper function */
49 49
 function sortAndAddAttrs($element, $arAtts) {
50
-    $newAtts = array();
51
-    foreach ($arAtts AS $attnode) {
52
-        $newAtts[$attnode->nodeName] = $attnode;
53
-    }
54
-    ksort($newAtts);
55
-    foreach ($newAtts as $attnode) {
56
-        $element->setAttribute($attnode->nodeName, $attnode->nodeValue);
57
-    }
50
+	$newAtts = array();
51
+	foreach ($arAtts AS $attnode) {
52
+		$newAtts[$attnode->nodeName] = $attnode;
53
+	}
54
+	ksort($newAtts);
55
+	foreach ($newAtts as $attnode) {
56
+		$element->setAttribute($attnode->nodeName, $attnode->nodeValue);
57
+	}
58 58
 }
59 59
 
60 60
 /* helper function */
61 61
 
62 62
 function canonical($tree, $element, $withcomments) {
63
-    if ($tree->nodeType != XML_DOCUMENT_NODE) {
64
-        $dom = $tree->ownerDocument;
65
-    } else {
66
-        $dom = $tree;
67
-    }
68
-    if ($element->nodeType != XML_ELEMENT_NODE) {
69
-        if ($element->nodeType == XML_DOCUMENT_NODE) {
70
-            foreach ($element->childNodes AS $node) {
71
-                canonical($dom, $node, $withcomments);
72
-            }
73
-            return;
74
-        }
75
-        if ($element->nodeType == XML_COMMENT_NODE && !$withcomments) {
76
-            return;
77
-        }
78
-        $tree->appendChild($dom->importNode($element, TRUE));
79
-        return;
80
-    }
81
-    $arNS = array();
82
-    if ($element->namespaceURI != "") {
83
-        if ($element->prefix == "") {
84
-            $elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName);
85
-        } else {
86
-            $prefix = $tree->lookupPrefix($element->namespaceURI);
87
-            if ($prefix == $element->prefix) {
88
-                $elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName);
89
-            } else {
90
-                $elCopy = $dom->createElement($element->nodeName);
91
-                $arNS[$element->namespaceURI] = $element->prefix;
92
-            }
93
-        }
94
-    } else {
95
-        $elCopy = $dom->createElement($element->nodeName);
96
-    }
97
-    $tree->appendChild($elCopy);
98
-
99
-    /* Create DOMXPath based on original document */
100
-    $xPath = new DOMXPath($element->ownerDocument);
101
-
102
-    /* Get namespaced attributes */
103
-    $arAtts = $xPath->query('attribute::*[namespace-uri(.) != ""]', $element);
104
-
105
-    /* Create an array with namespace URIs as keys, and sort them */
106
-    foreach ($arAtts AS $attnode) {
107
-        if (array_key_exists($attnode->namespaceURI, $arNS) &&
108
-            ($arNS[$attnode->namespaceURI] == $attnode->prefix)) {
109
-            continue;
110
-        }
111
-        $prefix = $tree->lookupPrefix($attnode->namespaceURI);
112
-        if ($prefix != $attnode->prefix) {
113
-            $arNS[$attnode->namespaceURI] = $attnode->prefix;
114
-        } else {
115
-            $arNS[$attnode->namespaceURI] = NULL;
116
-        }
117
-    }
118
-    if (count($arNS) > 0) {
119
-        asort($arNS);
120
-    }
121
-
122
-    /* Add namespace nodes */
123
-    foreach ($arNS AS $namespaceURI => $prefix) {
124
-        if ($prefix != NULL) {
125
-            $elCopy->setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:" . $prefix, $namespaceURI);
126
-        }
127
-    }
128
-    if (count($arNS) > 0) {
129
-        ksort($arNS);
130
-    }
131
-
132
-    /* Get attributes not in a namespace, and then sort and add them */
133
-    $arAtts = $xPath->query('attribute::*[namespace-uri(.) = ""]', $element);
134
-    sortAndAddAttrs($elCopy, $arAtts);
135
-
136
-    /* Loop through the URIs, and then sort and add attributes within that namespace */
137
-    foreach ($arNS as $nsURI => $prefix) {
138
-        $arAtts = $xPath->query('attribute::*[namespace-uri(.) = "' . $nsURI . '"]', $element);
139
-        sortAndAddAttrs($elCopy, $arAtts);
140
-    }
141
-
142
-    foreach ($element->childNodes AS $node) {
143
-        canonical($elCopy, $node, $withcomments);
144
-    }
63
+	if ($tree->nodeType != XML_DOCUMENT_NODE) {
64
+		$dom = $tree->ownerDocument;
65
+	} else {
66
+		$dom = $tree;
67
+	}
68
+	if ($element->nodeType != XML_ELEMENT_NODE) {
69
+		if ($element->nodeType == XML_DOCUMENT_NODE) {
70
+			foreach ($element->childNodes AS $node) {
71
+				canonical($dom, $node, $withcomments);
72
+			}
73
+			return;
74
+		}
75
+		if ($element->nodeType == XML_COMMENT_NODE && !$withcomments) {
76
+			return;
77
+		}
78
+		$tree->appendChild($dom->importNode($element, TRUE));
79
+		return;
80
+	}
81
+	$arNS = array();
82
+	if ($element->namespaceURI != "") {
83
+		if ($element->prefix == "") {
84
+			$elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName);
85
+		} else {
86
+			$prefix = $tree->lookupPrefix($element->namespaceURI);
87
+			if ($prefix == $element->prefix) {
88
+				$elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName);
89
+			} else {
90
+				$elCopy = $dom->createElement($element->nodeName);
91
+				$arNS[$element->namespaceURI] = $element->prefix;
92
+			}
93
+		}
94
+	} else {
95
+		$elCopy = $dom->createElement($element->nodeName);
96
+	}
97
+	$tree->appendChild($elCopy);
98
+
99
+	/* Create DOMXPath based on original document */
100
+	$xPath = new DOMXPath($element->ownerDocument);
101
+
102
+	/* Get namespaced attributes */
103
+	$arAtts = $xPath->query('attribute::*[namespace-uri(.) != ""]', $element);
104
+
105
+	/* Create an array with namespace URIs as keys, and sort them */
106
+	foreach ($arAtts AS $attnode) {
107
+		if (array_key_exists($attnode->namespaceURI, $arNS) &&
108
+			($arNS[$attnode->namespaceURI] == $attnode->prefix)) {
109
+			continue;
110
+		}
111
+		$prefix = $tree->lookupPrefix($attnode->namespaceURI);
112
+		if ($prefix != $attnode->prefix) {
113
+			$arNS[$attnode->namespaceURI] = $attnode->prefix;
114
+		} else {
115
+			$arNS[$attnode->namespaceURI] = NULL;
116
+		}
117
+	}
118
+	if (count($arNS) > 0) {
119
+		asort($arNS);
120
+	}
121
+
122
+	/* Add namespace nodes */
123
+	foreach ($arNS AS $namespaceURI => $prefix) {
124
+		if ($prefix != NULL) {
125
+			$elCopy->setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:" . $prefix, $namespaceURI);
126
+		}
127
+	}
128
+	if (count($arNS) > 0) {
129
+		ksort($arNS);
130
+	}
131
+
132
+	/* Get attributes not in a namespace, and then sort and add them */
133
+	$arAtts = $xPath->query('attribute::*[namespace-uri(.) = ""]', $element);
134
+	sortAndAddAttrs($elCopy, $arAtts);
135
+
136
+	/* Loop through the URIs, and then sort and add attributes within that namespace */
137
+	foreach ($arNS as $nsURI => $prefix) {
138
+		$arAtts = $xPath->query('attribute::*[namespace-uri(.) = "' . $nsURI . '"]', $element);
139
+		sortAndAddAttrs($elCopy, $arAtts);
140
+	}
141
+
142
+	foreach ($element->childNodes AS $node) {
143
+		canonical($elCopy, $node, $withcomments);
144
+	}
145 145
 }
146 146
 
147 147
 /*
@@ -151,1256 +151,1256 @@  discard block
 block discarded – undo
151 151
  */
152 152
 
153 153
 function C14NGeneral($element, $exclusive=FALSE, $withcomments=FALSE) {
154
-    /* IF PHP 5.2+ then use built in canonical functionality */
155
-    $php_version = explode('.', PHP_VERSION);
156
-    if (($php_version[0] > 5) || ($php_version[0] == 5 && $php_version[1] >= 2)) {
157
-        return $element->C14N($exclusive, $withcomments);
158
-    }
159
-
160
-    /* Must be element or document */
161
-    if (!$element instanceof DOMElement && !$element instanceof DOMDocument) {
162
-        return NULL;
163
-    }
164
-    /* Currently only exclusive XML is supported */
165
-    if ($exclusive == FALSE) {
166
-        throw new Exception("Only exclusive canonicalization is supported in this version of PHP");
167
-    }
168
-
169
-    $copyDoc = new DOMDocument();
170
-    canonical($copyDoc, $element, $withcomments);
171
-    return $copyDoc->saveXML($copyDoc->documentElement, LIBXML_NOEMPTYTAG);
154
+	/* IF PHP 5.2+ then use built in canonical functionality */
155
+	$php_version = explode('.', PHP_VERSION);
156
+	if (($php_version[0] > 5) || ($php_version[0] == 5 && $php_version[1] >= 2)) {
157
+		return $element->C14N($exclusive, $withcomments);
158
+	}
159
+
160
+	/* Must be element or document */
161
+	if (!$element instanceof DOMElement && !$element instanceof DOMDocument) {
162
+		return NULL;
163
+	}
164
+	/* Currently only exclusive XML is supported */
165
+	if ($exclusive == FALSE) {
166
+		throw new Exception("Only exclusive canonicalization is supported in this version of PHP");
167
+	}
168
+
169
+	$copyDoc = new DOMDocument();
170
+	canonical($copyDoc, $element, $withcomments);
171
+	return $copyDoc->saveXML($copyDoc->documentElement, LIBXML_NOEMPTYTAG);
172 172
 }
173 173
 
174 174
 class XMLSecurityKey {
175
-    const TRIPLEDES_CBC = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
176
-    const AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
177
-    const AES192_CBC = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
178
-    const AES256_CBC = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
179
-    const RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
180
-    const RSA_OAEP_MGF1P = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
181
-    const DSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1';
182
-    const RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
183
-    const RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
184
-
185
-    private $cryptParams = array();
186
-    public $type = 0;
187
-    public $key = NULL;
188
-    public $passphrase = "";
189
-    public $iv = NULL;
190
-    public $name = NULL;
191
-    public $keyChain = NULL;
192
-    public $isEncrypted = FALSE;
193
-    public $encryptedCtx = NULL;
194
-    public $guid = NULL;
195
-
196
-    /**
197
-     * This variable contains the certificate as a string if this key represents an X509-certificate.
198
-     * If this key doesn't represent a certificate, this will be NULL.
199
-     */
200
-    private $x509Certificate = NULL;
201
-
202
-    /* This variable contains the certificate thunbprint if we have loaded an X509-certificate. */
203
-    private $X509Thumbprint = NULL;
204
-
205
-    public function __construct($type, $params=NULL) {
206
-        srand();
207
-        switch ($type) {
208
-            case (XMLSecurityKey::TRIPLEDES_CBC):
209
-                $this->cryptParams['library'] = 'mcrypt';
210
-                $this->cryptParams['cipher'] = MCRYPT_TRIPLEDES;
211
-                $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
212
-                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
213
-                $this->cryptParams['keysize'] = 24;
214
-                break;
215
-            case (XMLSecurityKey::AES128_CBC):
216
-                $this->cryptParams['library'] = 'mcrypt';
217
-                $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
218
-                $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
219
-                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
220
-                $this->cryptParams['keysize'] = 16;
221
-                break;
222
-            case (XMLSecurityKey::AES192_CBC):
223
-                $this->cryptParams['library'] = 'mcrypt';
224
-                $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
225
-                $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
226
-                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
227
-                $this->cryptParams['keysize'] = 24;
228
-                break;
229
-            case (XMLSecurityKey::AES256_CBC):
230
-                $this->cryptParams['library'] = 'mcrypt';
231
-                $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
232
-                $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
233
-                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
234
-                $this->cryptParams['keysize'] = 32;
235
-                break;
236
-            case (XMLSecurityKey::RSA_1_5):
237
-                $this->cryptParams['library'] = 'openssl';
238
-                $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
239
-                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
240
-                if (is_array($params) && !empty($params['type'])) {
241
-                    if ($params['type'] == 'public' || $params['type'] == 'private') {
242
-                        $this->cryptParams['type'] = $params['type'];
243
-                        break;
244
-                    }
245
-                }
246
-                throw new Exception('Certificate "type" (private/public) must be passed via parameters');
247
-                return;
248
-            case (XMLSecurityKey::RSA_OAEP_MGF1P):
249
-                $this->cryptParams['library'] = 'openssl';
250
-                $this->cryptParams['padding'] = OPENSSL_PKCS1_OAEP_PADDING;
251
-                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
252
-                $this->cryptParams['hash'] = NULL;
253
-                if (is_array($params) && !empty($params['type'])) {
254
-                    if ($params['type'] == 'public' || $params['type'] == 'private') {
255
-                        $this->cryptParams['type'] = $params['type'];
256
-                        break;
257
-                    }
258
-                }
259
-                throw new Exception('Certificate "type" (private/public) must be passed via parameters');
260
-                return;
261
-            case (XMLSecurityKey::RSA_SHA1):
262
-                $this->cryptParams['library'] = 'openssl';
263
-                $this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
264
-                $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
265
-                if (is_array($params) && !empty($params['type'])) {
266
-                    if ($params['type'] == 'public' || $params['type'] == 'private') {
267
-                        $this->cryptParams['type'] = $params['type'];
268
-                        break;
269
-                    }
270
-                }
271
-                throw new Exception('Certificate "type" (private/public) must be passed via parameters');
272
-                break;
273
-            case (XMLSecurityKey::RSA_SHA256):
274
-                $this->cryptParams['library'] = 'openssl';
275
-                $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
276
-                $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
277
-                $this->cryptParams['digest'] = 'SHA256';
278
-                if (is_array($params) && !empty($params['type'])) {
279
-                    if ($params['type'] == 'public' || $params['type'] == 'private') {
280
-                        $this->cryptParams['type'] = $params['type'];
281
-                        break;
282
-                    }
283
-                }
284
-                throw new Exception('Certificate "type" (private/public) must be passed via parameters');
285
-                break;
286
-            default:
287
-                throw new Exception('Invalid Key Type');
288
-                return;
289
-        }
290
-        $this->type = $type;
291
-    }
292
-
293
-    /**
294
-     * Retrieve the key size for the symmetric encryption algorithm..
295
-     *
296
-     * If the key size is unknown, or this isn't a symmetric encryption algorithm,
297
-     * NULL is returned.
298
-     *
299
-     * @return int|NULL  The number of bytes in the key.
300
-     */
301
-    public function getSymmetricKeySize() {
302
-        if (!isset($this->cryptParams['keysize'])) {
303
-            return NULL;
304
-        }
305
-        return $this->cryptParams['keysize'];
306
-    }
307
-
308
-    public function generateSessionKey() {
309
-        if (!isset($this->cryptParams['keysize'])) {
310
-            throw new Exception('Unknown key size for type "' . $this->type . '".');
311
-        }
312
-        $keysize = $this->cryptParams['keysize'];
313
-
314
-        if (function_exists('openssl_random_pseudo_bytes')) {
315
-            /* We have PHP >= 5.3 - use openssl to generate session key. */
316
-            $key = openssl_random_pseudo_bytes($keysize);
317
-        } else {
318
-            /* Generating random key using iv generation routines */
319
-            $key = mcrypt_create_iv($keysize, MCRYPT_RAND);
320
-        }
321
-
322
-        if ($this->type === XMLSecurityKey::TRIPLEDES_CBC) {
323
-            /* Make sure that the generated key has the proper parity bits set.
175
+	const TRIPLEDES_CBC = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
176
+	const AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
177
+	const AES192_CBC = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
178
+	const AES256_CBC = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
179
+	const RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
180
+	const RSA_OAEP_MGF1P = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
181
+	const DSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1';
182
+	const RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
183
+	const RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
184
+
185
+	private $cryptParams = array();
186
+	public $type = 0;
187
+	public $key = NULL;
188
+	public $passphrase = "";
189
+	public $iv = NULL;
190
+	public $name = NULL;
191
+	public $keyChain = NULL;
192
+	public $isEncrypted = FALSE;
193
+	public $encryptedCtx = NULL;
194
+	public $guid = NULL;
195
+
196
+	/**
197
+	 * This variable contains the certificate as a string if this key represents an X509-certificate.
198
+	 * If this key doesn't represent a certificate, this will be NULL.
199
+	 */
200
+	private $x509Certificate = NULL;
201
+
202
+	/* This variable contains the certificate thunbprint if we have loaded an X509-certificate. */
203
+	private $X509Thumbprint = NULL;
204
+
205
+	public function __construct($type, $params=NULL) {
206
+		srand();
207
+		switch ($type) {
208
+			case (XMLSecurityKey::TRIPLEDES_CBC):
209
+				$this->cryptParams['library'] = 'mcrypt';
210
+				$this->cryptParams['cipher'] = MCRYPT_TRIPLEDES;
211
+				$this->cryptParams['mode'] = MCRYPT_MODE_CBC;
212
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
213
+				$this->cryptParams['keysize'] = 24;
214
+				break;
215
+			case (XMLSecurityKey::AES128_CBC):
216
+				$this->cryptParams['library'] = 'mcrypt';
217
+				$this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
218
+				$this->cryptParams['mode'] = MCRYPT_MODE_CBC;
219
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
220
+				$this->cryptParams['keysize'] = 16;
221
+				break;
222
+			case (XMLSecurityKey::AES192_CBC):
223
+				$this->cryptParams['library'] = 'mcrypt';
224
+				$this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
225
+				$this->cryptParams['mode'] = MCRYPT_MODE_CBC;
226
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
227
+				$this->cryptParams['keysize'] = 24;
228
+				break;
229
+			case (XMLSecurityKey::AES256_CBC):
230
+				$this->cryptParams['library'] = 'mcrypt';
231
+				$this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
232
+				$this->cryptParams['mode'] = MCRYPT_MODE_CBC;
233
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
234
+				$this->cryptParams['keysize'] = 32;
235
+				break;
236
+			case (XMLSecurityKey::RSA_1_5):
237
+				$this->cryptParams['library'] = 'openssl';
238
+				$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
239
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
240
+				if (is_array($params) && !empty($params['type'])) {
241
+					if ($params['type'] == 'public' || $params['type'] == 'private') {
242
+						$this->cryptParams['type'] = $params['type'];
243
+						break;
244
+					}
245
+				}
246
+				throw new Exception('Certificate "type" (private/public) must be passed via parameters');
247
+				return;
248
+			case (XMLSecurityKey::RSA_OAEP_MGF1P):
249
+				$this->cryptParams['library'] = 'openssl';
250
+				$this->cryptParams['padding'] = OPENSSL_PKCS1_OAEP_PADDING;
251
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
252
+				$this->cryptParams['hash'] = NULL;
253
+				if (is_array($params) && !empty($params['type'])) {
254
+					if ($params['type'] == 'public' || $params['type'] == 'private') {
255
+						$this->cryptParams['type'] = $params['type'];
256
+						break;
257
+					}
258
+				}
259
+				throw new Exception('Certificate "type" (private/public) must be passed via parameters');
260
+				return;
261
+			case (XMLSecurityKey::RSA_SHA1):
262
+				$this->cryptParams['library'] = 'openssl';
263
+				$this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
264
+				$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
265
+				if (is_array($params) && !empty($params['type'])) {
266
+					if ($params['type'] == 'public' || $params['type'] == 'private') {
267
+						$this->cryptParams['type'] = $params['type'];
268
+						break;
269
+					}
270
+				}
271
+				throw new Exception('Certificate "type" (private/public) must be passed via parameters');
272
+				break;
273
+			case (XMLSecurityKey::RSA_SHA256):
274
+				$this->cryptParams['library'] = 'openssl';
275
+				$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
276
+				$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
277
+				$this->cryptParams['digest'] = 'SHA256';
278
+				if (is_array($params) && !empty($params['type'])) {
279
+					if ($params['type'] == 'public' || $params['type'] == 'private') {
280
+						$this->cryptParams['type'] = $params['type'];
281
+						break;
282
+					}
283
+				}
284
+				throw new Exception('Certificate "type" (private/public) must be passed via parameters');
285
+				break;
286
+			default:
287
+				throw new Exception('Invalid Key Type');
288
+				return;
289
+		}
290
+		$this->type = $type;
291
+	}
292
+
293
+	/**
294
+	 * Retrieve the key size for the symmetric encryption algorithm..
295
+	 *
296
+	 * If the key size is unknown, or this isn't a symmetric encryption algorithm,
297
+	 * NULL is returned.
298
+	 *
299
+	 * @return int|NULL  The number of bytes in the key.
300
+	 */
301
+	public function getSymmetricKeySize() {
302
+		if (!isset($this->cryptParams['keysize'])) {
303
+			return NULL;
304
+		}
305
+		return $this->cryptParams['keysize'];
306
+	}
307
+
308
+	public function generateSessionKey() {
309
+		if (!isset($this->cryptParams['keysize'])) {
310
+			throw new Exception('Unknown key size for type "' . $this->type . '".');
311
+		}
312
+		$keysize = $this->cryptParams['keysize'];
313
+
314
+		if (function_exists('openssl_random_pseudo_bytes')) {
315
+			/* We have PHP >= 5.3 - use openssl to generate session key. */
316
+			$key = openssl_random_pseudo_bytes($keysize);
317
+		} else {
318
+			/* Generating random key using iv generation routines */
319
+			$key = mcrypt_create_iv($keysize, MCRYPT_RAND);
320
+		}
321
+
322
+		if ($this->type === XMLSecurityKey::TRIPLEDES_CBC) {
323
+			/* Make sure that the generated key has the proper parity bits set.
324 324
              * Mcrypt doesn't care about the parity bits, but others may care.
325 325
              */
326
-            for ($i = 0; $i < strlen($key); $i++) {
327
-                $byte = ord($key[$i]) & 0xfe;
328
-                $parity = 1;
329
-                for ($j = 1; $j < 8; $j++) {
330
-                    $parity ^= ($byte >> $j) & 1;
331
-                }
332
-                $byte |= $parity;
333
-                $key[$i] = chr($byte);
334
-            }
335
-        }
336
-
337
-        $this->key = $key;
338
-        return $key;
339
-    }
340
-
341
-    public static function getRawThumbprint($cert) {
342
-
343
-        $arCert = explode("\n", $cert);
344
-        $data = '';
345
-        $inData = FALSE;
346
-
347
-        foreach ($arCert AS $curData) {
348
-            if (!$inData) {
349
-                if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
350
-                    $inData = TRUE;
351
-                }
352
-            } else {
353
-                if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
354
-                    $inData = FALSE;
355
-                    break;
356
-                }
357
-                $data .= trim($curData);
358
-            }
359
-        }
360
-
361
-        if (!empty($data)) {
362
-            return strtolower(sha1(base64_decode($data)));
363
-        }
364
-
365
-        return NULL;
366
-    }
367
-
368
-    public function loadKey($key, $isFile=FALSE, $isCert = FALSE) {
369
-        if ($isFile) {
370
-            $this->key = file_get_contents($key);
371
-        } else {
372
-            $this->key = $key;
373
-        }
374
-        if ($isCert) {
375
-            $this->key = openssl_x509_read($this->key);
376
-            openssl_x509_export($this->key, $str_cert);
377
-            $this->x509Certificate = $str_cert;
378
-            $this->key = $str_cert;
379
-        } else {
380
-            $this->x509Certificate = NULL;
381
-        }
382
-        if ($this->cryptParams['library'] == 'openssl') {
383
-            if ($this->cryptParams['type'] == 'public') {
384
-                if ($isCert) {
385
-                    /* Load the thumbprint if this is an X509 certificate. */
386
-                    $this->X509Thumbprint = self::getRawThumbprint($this->key);
387
-                }
388
-                $this->key = openssl_get_publickey($this->key);
389
-            } else {
390
-                $this->key = openssl_get_privatekey($this->key, $this->passphrase);
391
-            }
392
-        } else if ($this->cryptParams['cipher'] == MCRYPT_RIJNDAEL_128) {
393
-            /* Check key length */
394
-            switch ($this->type) {
395
-                case (XMLSecurityKey::AES256_CBC):
396
-                    if (strlen($this->key) < 25) {
397
-                        throw new Exception('Key must contain at least 25 characters for this cipher');
398
-                    }
399
-                    break;
400
-                case (XMLSecurityKey::AES192_CBC):
401
-                    if (strlen($this->key) < 17) {
402
-                        throw new Exception('Key must contain at least 17 characters for this cipher');
403
-                    }
404
-                    break;
405
-            }
406
-        }
407
-    }
408
-
409
-    private function encryptMcrypt($data) {
410
-        $td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
411
-        $this->iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
412
-        mcrypt_generic_init($td, $this->key, $this->iv);
413
-        if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) {
414
-            $bs = mcrypt_enc_get_block_size($td);
415
-            for ($datalen0 = $datalen = strlen($data); (($datalen % $bs) != ($bs - 1)); $datalen++)
416
-                $data.=chr(rand(1, 127));
417
-            $data.=chr($datalen - $datalen0 + 1);
418
-        }
419
-        $encrypted_data = $this->iv . mcrypt_generic($td, $data);
420
-        mcrypt_generic_deinit($td);
421
-        mcrypt_module_close($td);
422
-        return $encrypted_data;
423
-    }
424
-
425
-    private function decryptMcrypt($data) {
426
-        $td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
427
-        $iv_length = mcrypt_enc_get_iv_size($td);
428
-
429
-        $this->iv = substr($data, 0, $iv_length);
430
-        $data = substr($data, $iv_length);
431
-
432
-        mcrypt_generic_init($td, $this->key, $this->iv);
433
-        $decrypted_data = mdecrypt_generic($td, $data);
434
-        mcrypt_generic_deinit($td);
435
-        mcrypt_module_close($td);
436
-        if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) {
437
-            $dataLen = strlen($decrypted_data);
438
-            $paddingLength = substr($decrypted_data, $dataLen - 1, 1);
439
-            $decrypted_data = substr($decrypted_data, 0, $dataLen - ord($paddingLength));
440
-        }
441
-        return $decrypted_data;
442
-    }
443
-
444
-    private function encryptOpenSSL($data) {
445
-        if ($this->cryptParams['type'] == 'public') {
446
-            if (!openssl_public_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
447
-                throw new Exception('Failure encrypting Data');
448
-                return;
449
-            }
450
-        } else {
451
-            if (!openssl_private_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
452
-                throw new Exception('Failure encrypting Data');
453
-                return;
454
-            }
455
-        }
456
-        return $encrypted_data;
457
-    }
458
-
459
-    private function decryptOpenSSL($data) {
460
-        if ($this->cryptParams['type'] == 'public') {
461
-            if (!openssl_public_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
462
-                throw new Exception('Failure decrypting Data');
463
-                return;
464
-            }
465
-        } else {
466
-            if (!openssl_private_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
467
-                throw new Exception('Failure decrypting Data');
468
-                return;
469
-            }
470
-        }
471
-        return $decrypted;
472
-    }
473
-
474
-    function custom_openssl_sign($data, &$signature, $priv_key_id, $signature_alg = 'sha256WithRSAEncryption') {
475
-        $pinfo = openssl_pkey_get_details($priv_key_id);
476
-        $hash = hash('sha256', $data);
477
-        $t = '3031300d060960864801650304020105000420'; # sha256
478
-        $t .= $hash;
479
-        $pslen = $pinfo['bits']/8 - (strlen($t)/2 + 3);
480
-
481
-        $eb = '0001' . str_repeat('FF', $pslen) . '00' . $t;
482
-        $eb = pack('H*', $eb);
483
-
484
-        return openssl_private_encrypt($eb, $signature, $priv_key_id, OPENSSL_NO_PADDING);
485
-    }
486
-
487
-    function custom_openssl_verify ($data, &$signature, $priv_key_id, $signature_alg = 'sha256WithRSAEncryption') {
488
-        $pinfo = openssl_pkey_get_details($priv_key_id);
489
-        $hash = hash('sha256', $data);
490
-        $t = '3031300d060960864801650304020105000420'; # sha256
491
-        $t .= $hash;
492
-        $pslen = $pinfo['bits']/8 - (strlen($t)/2 + 3);
493
-
494
-        $eb = '0001' . str_repeat('FF', $pslen) . '00' . $t;
495
-        $eb = pack('H*', $eb);
496
-
497
-        return openssl_public_decrypt($eb, $signature, $priv_key_id, OPENSSL_NO_PADDING);
498
-    }
499
-
500
-    private function signOpenSSL($data) {
501
-        $algo = OPENSSL_ALGO_SHA1;
502
-        if (!empty($this->cryptParams['digest'])) {
503
-            $algo = $this->cryptParams['digest'];
504
-        }
505
-        $signature = '';
506
-
507
-        if (!$this->custom_openssl_sign($data, $signature, $this->key)) {
508
-            throw new Exception('Failure Signing Data: ' . openssl_error_string() . ' - ' . $algo);
509
-            return;
510
-        }
511
-        return $signature;
512
-    }
513
-
514
-    private function verifyOpenSSL($data, $signature) {
515
-        $algo = OPENSSL_ALGO_SHA1;
516
-        if (!empty($this->cryptParams['digest'])) {
517
-            $algo = $this->cryptParams['digest'];
518
-        }
519
-        return $this->custom_openssl_verify($data, $signature, $this->key);
520
-    }
521
-
522
-    public function encryptData($data) {
523
-        switch ($this->cryptParams['library']) {
524
-            case 'mcrypt':
525
-                return $this->encryptMcrypt($data);
526
-                break;
527
-            case 'openssl':
528
-                return $this->encryptOpenSSL($data);
529
-                break;
530
-        }
531
-    }
532
-
533
-    public function decryptData($data) {
534
-        switch ($this->cryptParams['library']) {
535
-            case 'mcrypt':
536
-                return $this->decryptMcrypt($data);
537
-                break;
538
-            case 'openssl':
539
-                return $this->decryptOpenSSL($data);
540
-                break;
541
-        }
542
-    }
543
-
544
-    public function signData($data) {
545
-        switch ($this->cryptParams['library']) {
546
-            case 'openssl':
547
-                return $this->signOpenSSL($data);
548
-                break;
549
-        }
550
-    }
551
-
552
-    public function verifySignature($data, $signature) {
553
-        switch ($this->cryptParams['library']) {
554
-            case 'openssl':
555
-                return $this->verifyOpenSSL($data, $signature);
556
-                break;
557
-        }
558
-    }
559
-
560
-    public function getAlgorith() {
561
-        return $this->cryptParams['method'];
562
-    }
563
-
564
-    static function makeAsnSegment($type, $string) {
565
-        switch ($type) {
566
-            case 0x02:
567
-                if (ord($string) > 0x7f)
568
-                    $string = chr(0) . $string;
569
-                break;
570
-            case 0x03:
571
-                $string = chr(0) . $string;
572
-                break;
573
-        }
574
-
575
-        $length = strlen($string);
576
-
577
-        if ($length < 128) {
578
-            $output = sprintf("%c%c%s", $type, $length, $string);
579
-        } else if ($length < 0x0100) {
580
-            $output = sprintf("%c%c%c%s", $type, 0x81, $length, $string);
581
-        } else if ($length < 0x010000) {
582
-            $output = sprintf("%c%c%c%c%s", $type, 0x82, $length / 0x0100, $length % 0x0100, $string);
583
-        } else {
584
-            $output = NULL;
585
-        }
586
-        return($output);
587
-    }
588
-
589
-    /* Modulus and Exponent must already be base64 decoded */
590
-
591
-    static function convertRSA($modulus, $exponent) {
592
-        /* make an ASN publicKeyInfo */
593
-        $exponentEncoding = XMLSecurityKey::makeAsnSegment(0x02, $exponent);
594
-        $modulusEncoding = XMLSecurityKey::makeAsnSegment(0x02, $modulus);
595
-        $sequenceEncoding = XMLSecurityKey:: makeAsnSegment(0x30, $modulusEncoding . $exponentEncoding);
596
-        $bitstringEncoding = XMLSecurityKey::makeAsnSegment(0x03, $sequenceEncoding);
597
-        $rsaAlgorithmIdentifier = pack("H*", "300D06092A864886F70D0101010500");
598
-        $publicKeyInfo = XMLSecurityKey::makeAsnSegment(0x30, $rsaAlgorithmIdentifier . $bitstringEncoding);
599
-
600
-        /* encode the publicKeyInfo in base64 and add PEM brackets */
601
-        $publicKeyInfoBase64 = base64_encode($publicKeyInfo);
602
-        $encoding = "-----BEGIN PUBLIC KEY-----\n";
603
-        $offset = 0;
604
-        while ($segment = substr($publicKeyInfoBase64, $offset, 64)) {
605
-            $encoding = $encoding . $segment . "\n";
606
-            $offset += 64;
607
-        }
608
-        return $encoding . "-----END PUBLIC KEY-----\n";
609
-    }
610
-
611
-    public function serializeKey($parent) {
612
-
613
-    }
614
-
615
-    /**
616
-     * Retrieve the X509 certificate this key represents.
617
-     *
618
-     * Will return the X509 certificate in PEM-format if this key represents
619
-     * an X509 certificate.
620
-     *
621
-     * @return  The X509 certificate or NULL if this key doesn't represent an X509-certificate.
622
-     */
623
-    public function getX509Certificate() {
624
-        return $this->x509Certificate;
625
-    }
626
-
627
-    /* Get the thumbprint of this X509 certificate.
326
+			for ($i = 0; $i < strlen($key); $i++) {
327
+				$byte = ord($key[$i]) & 0xfe;
328
+				$parity = 1;
329
+				for ($j = 1; $j < 8; $j++) {
330
+					$parity ^= ($byte >> $j) & 1;
331
+				}
332
+				$byte |= $parity;
333
+				$key[$i] = chr($byte);
334
+			}
335
+		}
336
+
337
+		$this->key = $key;
338
+		return $key;
339
+	}
340
+
341
+	public static function getRawThumbprint($cert) {
342
+
343
+		$arCert = explode("\n", $cert);
344
+		$data = '';
345
+		$inData = FALSE;
346
+
347
+		foreach ($arCert AS $curData) {
348
+			if (!$inData) {
349
+				if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
350
+					$inData = TRUE;
351
+				}
352
+			} else {
353
+				if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
354
+					$inData = FALSE;
355
+					break;
356
+				}
357
+				$data .= trim($curData);
358
+			}
359
+		}
360
+
361
+		if (!empty($data)) {
362
+			return strtolower(sha1(base64_decode($data)));
363
+		}
364
+
365
+		return NULL;
366
+	}
367
+
368
+	public function loadKey($key, $isFile=FALSE, $isCert = FALSE) {
369
+		if ($isFile) {
370
+			$this->key = file_get_contents($key);
371
+		} else {
372
+			$this->key = $key;
373
+		}
374
+		if ($isCert) {
375
+			$this->key = openssl_x509_read($this->key);
376
+			openssl_x509_export($this->key, $str_cert);
377
+			$this->x509Certificate = $str_cert;
378
+			$this->key = $str_cert;
379
+		} else {
380
+			$this->x509Certificate = NULL;
381
+		}
382
+		if ($this->cryptParams['library'] == 'openssl') {
383
+			if ($this->cryptParams['type'] == 'public') {
384
+				if ($isCert) {
385
+					/* Load the thumbprint if this is an X509 certificate. */
386
+					$this->X509Thumbprint = self::getRawThumbprint($this->key);
387
+				}
388
+				$this->key = openssl_get_publickey($this->key);
389
+			} else {
390
+				$this->key = openssl_get_privatekey($this->key, $this->passphrase);
391
+			}
392
+		} else if ($this->cryptParams['cipher'] == MCRYPT_RIJNDAEL_128) {
393
+			/* Check key length */
394
+			switch ($this->type) {
395
+				case (XMLSecurityKey::AES256_CBC):
396
+					if (strlen($this->key) < 25) {
397
+						throw new Exception('Key must contain at least 25 characters for this cipher');
398
+					}
399
+					break;
400
+				case (XMLSecurityKey::AES192_CBC):
401
+					if (strlen($this->key) < 17) {
402
+						throw new Exception('Key must contain at least 17 characters for this cipher');
403
+					}
404
+					break;
405
+			}
406
+		}
407
+	}
408
+
409
+	private function encryptMcrypt($data) {
410
+		$td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
411
+		$this->iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
412
+		mcrypt_generic_init($td, $this->key, $this->iv);
413
+		if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) {
414
+			$bs = mcrypt_enc_get_block_size($td);
415
+			for ($datalen0 = $datalen = strlen($data); (($datalen % $bs) != ($bs - 1)); $datalen++)
416
+				$data.=chr(rand(1, 127));
417
+			$data.=chr($datalen - $datalen0 + 1);
418
+		}
419
+		$encrypted_data = $this->iv . mcrypt_generic($td, $data);
420
+		mcrypt_generic_deinit($td);
421
+		mcrypt_module_close($td);
422
+		return $encrypted_data;
423
+	}
424
+
425
+	private function decryptMcrypt($data) {
426
+		$td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
427
+		$iv_length = mcrypt_enc_get_iv_size($td);
428
+
429
+		$this->iv = substr($data, 0, $iv_length);
430
+		$data = substr($data, $iv_length);
431
+
432
+		mcrypt_generic_init($td, $this->key, $this->iv);
433
+		$decrypted_data = mdecrypt_generic($td, $data);
434
+		mcrypt_generic_deinit($td);
435
+		mcrypt_module_close($td);
436
+		if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) {
437
+			$dataLen = strlen($decrypted_data);
438
+			$paddingLength = substr($decrypted_data, $dataLen - 1, 1);
439
+			$decrypted_data = substr($decrypted_data, 0, $dataLen - ord($paddingLength));
440
+		}
441
+		return $decrypted_data;
442
+	}
443
+
444
+	private function encryptOpenSSL($data) {
445
+		if ($this->cryptParams['type'] == 'public') {
446
+			if (!openssl_public_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
447
+				throw new Exception('Failure encrypting Data');
448
+				return;
449
+			}
450
+		} else {
451
+			if (!openssl_private_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
452
+				throw new Exception('Failure encrypting Data');
453
+				return;
454
+			}
455
+		}
456
+		return $encrypted_data;
457
+	}
458
+
459
+	private function decryptOpenSSL($data) {
460
+		if ($this->cryptParams['type'] == 'public') {
461
+			if (!openssl_public_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
462
+				throw new Exception('Failure decrypting Data');
463
+				return;
464
+			}
465
+		} else {
466
+			if (!openssl_private_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
467
+				throw new Exception('Failure decrypting Data');
468
+				return;
469
+			}
470
+		}
471
+		return $decrypted;
472
+	}
473
+
474
+	function custom_openssl_sign($data, &$signature, $priv_key_id, $signature_alg = 'sha256WithRSAEncryption') {
475
+		$pinfo = openssl_pkey_get_details($priv_key_id);
476
+		$hash = hash('sha256', $data);
477
+		$t = '3031300d060960864801650304020105000420'; # sha256
478
+		$t .= $hash;
479
+		$pslen = $pinfo['bits']/8 - (strlen($t)/2 + 3);
480
+
481
+		$eb = '0001' . str_repeat('FF', $pslen) . '00' . $t;
482
+		$eb = pack('H*', $eb);
483
+
484
+		return openssl_private_encrypt($eb, $signature, $priv_key_id, OPENSSL_NO_PADDING);
485
+	}
486
+
487
+	function custom_openssl_verify ($data, &$signature, $priv_key_id, $signature_alg = 'sha256WithRSAEncryption') {
488
+		$pinfo = openssl_pkey_get_details($priv_key_id);
489
+		$hash = hash('sha256', $data);
490
+		$t = '3031300d060960864801650304020105000420'; # sha256
491
+		$t .= $hash;
492
+		$pslen = $pinfo['bits']/8 - (strlen($t)/2 + 3);
493
+
494
+		$eb = '0001' . str_repeat('FF', $pslen) . '00' . $t;
495
+		$eb = pack('H*', $eb);
496
+
497
+		return openssl_public_decrypt($eb, $signature, $priv_key_id, OPENSSL_NO_PADDING);
498
+	}
499
+
500
+	private function signOpenSSL($data) {
501
+		$algo = OPENSSL_ALGO_SHA1;
502
+		if (!empty($this->cryptParams['digest'])) {
503
+			$algo = $this->cryptParams['digest'];
504
+		}
505
+		$signature = '';
506
+
507
+		if (!$this->custom_openssl_sign($data, $signature, $this->key)) {
508
+			throw new Exception('Failure Signing Data: ' . openssl_error_string() . ' - ' . $algo);
509
+			return;
510
+		}
511
+		return $signature;
512
+	}
513
+
514
+	private function verifyOpenSSL($data, $signature) {
515
+		$algo = OPENSSL_ALGO_SHA1;
516
+		if (!empty($this->cryptParams['digest'])) {
517
+			$algo = $this->cryptParams['digest'];
518
+		}
519
+		return $this->custom_openssl_verify($data, $signature, $this->key);
520
+	}
521
+
522
+	public function encryptData($data) {
523
+		switch ($this->cryptParams['library']) {
524
+			case 'mcrypt':
525
+				return $this->encryptMcrypt($data);
526
+				break;
527
+			case 'openssl':
528
+				return $this->encryptOpenSSL($data);
529
+				break;
530
+		}
531
+	}
532
+
533
+	public function decryptData($data) {
534
+		switch ($this->cryptParams['library']) {
535
+			case 'mcrypt':
536
+				return $this->decryptMcrypt($data);
537
+				break;
538
+			case 'openssl':
539
+				return $this->decryptOpenSSL($data);
540
+				break;
541
+		}
542
+	}
543
+
544
+	public function signData($data) {
545
+		switch ($this->cryptParams['library']) {
546
+			case 'openssl':
547
+				return $this->signOpenSSL($data);
548
+				break;
549
+		}
550
+	}
551
+
552
+	public function verifySignature($data, $signature) {
553
+		switch ($this->cryptParams['library']) {
554
+			case 'openssl':
555
+				return $this->verifyOpenSSL($data, $signature);
556
+				break;
557
+		}
558
+	}
559
+
560
+	public function getAlgorith() {
561
+		return $this->cryptParams['method'];
562
+	}
563
+
564
+	static function makeAsnSegment($type, $string) {
565
+		switch ($type) {
566
+			case 0x02:
567
+				if (ord($string) > 0x7f)
568
+					$string = chr(0) . $string;
569
+				break;
570
+			case 0x03:
571
+				$string = chr(0) . $string;
572
+				break;
573
+		}
574
+
575
+		$length = strlen($string);
576
+
577
+		if ($length < 128) {
578
+			$output = sprintf("%c%c%s", $type, $length, $string);
579
+		} else if ($length < 0x0100) {
580
+			$output = sprintf("%c%c%c%s", $type, 0x81, $length, $string);
581
+		} else if ($length < 0x010000) {
582
+			$output = sprintf("%c%c%c%c%s", $type, 0x82, $length / 0x0100, $length % 0x0100, $string);
583
+		} else {
584
+			$output = NULL;
585
+		}
586
+		return($output);
587
+	}
588
+
589
+	/* Modulus and Exponent must already be base64 decoded */
590
+
591
+	static function convertRSA($modulus, $exponent) {
592
+		/* make an ASN publicKeyInfo */
593
+		$exponentEncoding = XMLSecurityKey::makeAsnSegment(0x02, $exponent);
594
+		$modulusEncoding = XMLSecurityKey::makeAsnSegment(0x02, $modulus);
595
+		$sequenceEncoding = XMLSecurityKey:: makeAsnSegment(0x30, $modulusEncoding . $exponentEncoding);
596
+		$bitstringEncoding = XMLSecurityKey::makeAsnSegment(0x03, $sequenceEncoding);
597
+		$rsaAlgorithmIdentifier = pack("H*", "300D06092A864886F70D0101010500");
598
+		$publicKeyInfo = XMLSecurityKey::makeAsnSegment(0x30, $rsaAlgorithmIdentifier . $bitstringEncoding);
599
+
600
+		/* encode the publicKeyInfo in base64 and add PEM brackets */
601
+		$publicKeyInfoBase64 = base64_encode($publicKeyInfo);
602
+		$encoding = "-----BEGIN PUBLIC KEY-----\n";
603
+		$offset = 0;
604
+		while ($segment = substr($publicKeyInfoBase64, $offset, 64)) {
605
+			$encoding = $encoding . $segment . "\n";
606
+			$offset += 64;
607
+		}
608
+		return $encoding . "-----END PUBLIC KEY-----\n";
609
+	}
610
+
611
+	public function serializeKey($parent) {
612
+
613
+	}
614
+
615
+	/**
616
+	 * Retrieve the X509 certificate this key represents.
617
+	 *
618
+	 * Will return the X509 certificate in PEM-format if this key represents
619
+	 * an X509 certificate.
620
+	 *
621
+	 * @return  The X509 certificate or NULL if this key doesn't represent an X509-certificate.
622
+	 */
623
+	public function getX509Certificate() {
624
+		return $this->x509Certificate;
625
+	}
626
+
627
+	/* Get the thumbprint of this X509 certificate.
628 628
      *
629 629
      * Returns:
630 630
      *  The thumbprint as a lowercase 40-character hexadecimal number, or NULL
631 631
      *  if this isn't a X509 certificate.
632 632
      */
633 633
 
634
-    public function getX509Thumbprint() {
635
-        return $this->X509Thumbprint;
636
-    }
637
-
638
-    /**
639
-     * Create key from an EncryptedKey-element.
640
-     *
641
-     * @param DOMElement $element  The EncryptedKey-element.
642
-     * @return XMLSecurityKey  The new key.
643
-     */
644
-    public static function fromEncryptedKeyElement(DOMElement $element) {
645
-
646
-        $objenc = new XMLSecEnc();
647
-        $objenc->setNode($element);
648
-        if (!$objKey = $objenc->locateKey()) {
649
-            throw new Exception("Unable to locate algorithm for this Encrypted Key");
650
-        }
651
-        $objKey->isEncrypted = TRUE;
652
-        $objKey->encryptedCtx = $objenc;
653
-        XMLSecEnc::staticLocateKeyInfo($objKey, $element);
654
-        return $objKey;
655
-    }
634
+	public function getX509Thumbprint() {
635
+		return $this->X509Thumbprint;
636
+	}
637
+
638
+	/**
639
+	 * Create key from an EncryptedKey-element.
640
+	 *
641
+	 * @param DOMElement $element  The EncryptedKey-element.
642
+	 * @return XMLSecurityKey  The new key.
643
+	 */
644
+	public static function fromEncryptedKeyElement(DOMElement $element) {
645
+
646
+		$objenc = new XMLSecEnc();
647
+		$objenc->setNode($element);
648
+		if (!$objKey = $objenc->locateKey()) {
649
+			throw new Exception("Unable to locate algorithm for this Encrypted Key");
650
+		}
651
+		$objKey->isEncrypted = TRUE;
652
+		$objKey->encryptedCtx = $objenc;
653
+		XMLSecEnc::staticLocateKeyInfo($objKey, $element);
654
+		return $objKey;
655
+	}
656 656
 
657 657
 }
658 658
 
659 659
 class XMLSecurityDSig {
660
-    const XMLDSIGNS = 'http://www.w3.org/2000/09/xmldsig#';
661
-    const SHA1 = 'http://www.w3.org/2000/09/xmldsig#sha1';
662
-    const SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256';
663
-    const SHA512 = 'http://www.w3.org/2001/04/xmlenc#sha512';
664
-    const RIPEMD160 = 'http://www.w3.org/2001/04/xmlenc#ripemd160';
665
-
666
-    const C14N = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
667
-    const C14N_COMMENTS = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments';
668
-    const EXC_C14N = 'http://www.w3.org/2001/10/xml-exc-c14n#';
669
-    const EXC_C14N_COMMENTS = 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments';
670
-
671
-    const template = '<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
660
+	const XMLDSIGNS = 'http://www.w3.org/2000/09/xmldsig#';
661
+	const SHA1 = 'http://www.w3.org/2000/09/xmldsig#sha1';
662
+	const SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256';
663
+	const SHA512 = 'http://www.w3.org/2001/04/xmlenc#sha512';
664
+	const RIPEMD160 = 'http://www.w3.org/2001/04/xmlenc#ripemd160';
665
+
666
+	const C14N = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
667
+	const C14N_COMMENTS = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments';
668
+	const EXC_C14N = 'http://www.w3.org/2001/10/xml-exc-c14n#';
669
+	const EXC_C14N_COMMENTS = 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments';
670
+
671
+	const template = '<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
672 672
   <SignedInfo>
673 673
     <SignatureMethod />
674 674
   </SignedInfo>
675 675
 </Signature>';
676 676
 
677
-    public $sigNode = NULL;
678
-    public $idKeys = array();
679
-    public $idNS = array();
680
-    private $signedInfo = NULL;
681
-    private $xPathCtx = NULL;
682
-    private $canonicalMethod = NULL;
683
-    private $prefix = NULL;
684
-    private $searchpfx = 'secdsig';
685
-
686
-    /* This variable contains an associative array of validated nodes. */
687
-    private $validatedNodes = NULL;
688
-
689
-    public function __construct() {
690
-        $sigdoc = new DOMDocument();
691
-        $sigdoc->loadXML(XMLSecurityDSig::template);
692
-        $this->sigNode = $sigdoc->documentElement;
693
-    }
694
-
695
-    private function resetXPathObj() {
696
-        $this->xPathCtx = NULL;
697
-    }
698
-
699
-    private function getXPathObj() {
700
-        if (empty($this->xPathCtx) && !empty($this->sigNode)) {
701
-            $xpath = new DOMXPath($this->sigNode->ownerDocument);
702
-            $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
703
-            $this->xPathCtx = $xpath;
704
-        }
705
-        return $this->xPathCtx;
706
-    }
707
-
708
-    static function generate_GUID($prefix='pfx') {
709
-        $uuid = md5(uniqid(rand(), true));
710
-        $guid = $prefix . substr($uuid, 0, 8) . "-" .
711
-            substr($uuid, 8, 4) . "-" .
712
-            substr($uuid, 12, 4) . "-" .
713
-            substr($uuid, 16, 4) . "-" .
714
-            substr($uuid, 20, 12);
715
-        return $guid;
716
-    }
717
-
718
-    public function locateSignature($objDoc) {
719
-        if ($objDoc instanceof DOMDocument) {
720
-            $doc = $objDoc;
721
-        } else {
722
-            $doc = $objDoc->ownerDocument;
723
-        }
724
-        if ($doc) {
725
-            $xpath = new DOMXPath($doc);
726
-            $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
727
-            $query = ".//secdsig:Signature";
728
-            $nodeset = $xpath->query($query, $objDoc);
729
-            $this->sigNode = $nodeset->item(0);
730
-            return $this->sigNode;
731
-        }
732
-        return NULL;
733
-    }
734
-
735
-    public function createNewSignNode($name, $value=NULL) {
736
-        $doc = $this->sigNode->ownerDocument;
737
-        if ($this->prefix != null) {
738
-            $name = $this->prefix . ':' . $name;
739
-        }
740
-        if (!is_null($value)) {
741
-            $node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $name, $value);
742
-        } else {
743
-            $node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $name);
744
-        }
745
-        return $node;
746
-    }
747
-
748
-    public function setCanonicalMethod($method) {
749
-        switch ($method) {
750
-            case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
751
-            case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
752
-            case 'http://www.w3.org/2001/10/xml-exc-c14n#':
753
-            case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
754
-                $this->canonicalMethod = $method;
755
-                break;
756
-            default:
757
-                throw new Exception('Invalid Canonical Method');
758
-        }
759
-        if ($xpath = $this->getXPathObj()) {
760
-            $query = './' . $this->searchpfx . ':SignedInfo';
761
-            $nodeset = $xpath->query($query, $this->sigNode);
762
-            if ($sinfo = $nodeset->item(0)) {
763
-                $query = './' . $this->searchpfx . 'CanonicalizationMethod';
764
-                $nodeset = $xpath->query($query, $sinfo);
765
-                if (!($canonNode = $nodeset->item(0))) {
766
-                    $canonNode = $this->createNewSignNode('CanonicalizationMethod');
767
-                    $sinfo->insertBefore($canonNode, $sinfo->firstChild);
768
-                }
769
-                $canonNode->setAttribute('Algorithm', $this->canonicalMethod);
770
-            }
771
-        }
772
-    }
773
-
774
-    private function canonicalizeData($node, $canonicalmethod, $arXPath=NULL, $prefixList=NULL) {
775
-        $exclusive = FALSE;
776
-        $withComments = FALSE;
777
-        switch ($canonicalmethod) {
778
-            case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
779
-                $exclusive = FALSE;
780
-                $withComments = FALSE;
781
-                break;
782
-            case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
783
-                $withComments = TRUE;
784
-                break;
785
-            case 'http://www.w3.org/2001/10/xml-exc-c14n#':
786
-                $exclusive = TRUE;
787
-                break;
788
-            case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
789
-                $exclusive = TRUE;
790
-                $withComments = TRUE;
791
-                break;
792
-        }
793
-        /* Support PHP versions < 5.2 not containing C14N methods in DOM extension */
794
-        $php_version = explode('.', PHP_VERSION);
795
-        if (($php_version[0] < 5) || ($php_version[0] == 5 && $php_version[1] < 2)) {
796
-            if (!is_null($arXPath)) {
797
-                throw new Exception("PHP 5.2.0 or higher is required to perform XPath Transformations");
798
-            }
799
-            return C14NGeneral($node, $exclusive, $withComments);
800
-        }
801
-        return $node->C14N($exclusive, $withComments, $arXPath, $prefixList);
802
-    }
803
-
804
-    public function canonicalizeSignedInfo() {
805
-
806
-        $doc = $this->sigNode->ownerDocument;
807
-        $canonicalmethod = NULL;
808
-        if ($doc) {
809
-            $xpath = $this->getXPathObj();
810
-            $query = "./secdsig:SignedInfo";
811
-            $nodeset = $xpath->query($query, $this->sigNode);
812
-            if ($signInfoNode = $nodeset->item(0)) {
813
-                $query = "./secdsig:CanonicalizationMethod";
814
-                $nodeset = $xpath->query($query, $signInfoNode);
815
-                if ($canonNode = $nodeset->item(0)) {
816
-                    $canonicalmethod = $canonNode->getAttribute('Algorithm');
817
-                }
818
-                $this->signedInfo = $this->canonicalizeData($signInfoNode, $canonicalmethod);
819
-                return $this->signedInfo;
820
-            }
821
-        }
822
-        return NULL;
823
-    }
824
-
825
-    public function calculateDigest($digestAlgorithm, $data) {
826
-        switch ($digestAlgorithm) {
827
-            case XMLSecurityDSig::SHA1:
828
-                $alg = 'sha1';
829
-                break;
830
-            case XMLSecurityDSig::SHA256:
831
-                $alg = 'sha256';
832
-                break;
833
-            case XMLSecurityDSig::SHA512:
834
-                $alg = 'sha512';
835
-                break;
836
-            case XMLSecurityDSig::RIPEMD160:
837
-                $alg = 'ripemd160';
838
-                break;
839
-            default:
840
-                throw new Exception("Cannot validate digest: Unsupported Algorith <$digestAlgorithm>");
841
-        }
842
-        if (function_exists('hash')) {
843
-            return base64_encode(hash($alg, $data, TRUE));
844
-        } elseif (function_exists('mhash')) {
845
-            $alg = "MHASH_" . strtoupper($alg);
846
-            return base64_encode(mhash(constant($alg), $data));
847
-        } elseif ($alg === 'sha1') {
848
-            return base64_encode(sha1($data, TRUE));
849
-        } else {
850
-            throw new Exception('xmlseclibs is unable to calculate a digest. Maybe you need the mhash library?');
851
-        }
852
-    }
853
-
854
-    public function validateDigest($refNode, $data) {
855
-        $xpath = new DOMXPath($refNode->ownerDocument);
856
-        $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
857
-        $query = 'string(./secdsig:DigestMethod/@Algorithm)';
858
-        $digestAlgorithm = $xpath->evaluate($query, $refNode);
859
-        $digValue = $this->calculateDigest($digestAlgorithm, $data);
860
-        $query = 'string(./secdsig:DigestValue)';
861
-        $digestValue = $xpath->evaluate($query, $refNode);
862
-        return ($digValue == $digestValue);
863
-    }
864
-
865
-    public function processTransforms($refNode, $objData, $includeCommentNodes = TRUE) {
866
-        $data = $objData;
867
-        $xpath = new DOMXPath($refNode->ownerDocument);
868
-        $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
869
-        $query = './secdsig:Transforms/secdsig:Transform';
870
-        $nodelist = $xpath->query($query, $refNode);
871
-        $canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
872
-        $arXPath = NULL;
873
-        $prefixList = NULL;
874
-        foreach ($nodelist AS $transform) {
875
-            $algorithm = $transform->getAttribute("Algorithm");
876
-            switch ($algorithm) {
877
-                case 'http://www.w3.org/2001/10/xml-exc-c14n#':
878
-                case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
879
-
880
-                    if (!$includeCommentNodes) {
881
-                        /* We remove comment nodes by forcing it to use a canonicalization
677
+	public $sigNode = NULL;
678
+	public $idKeys = array();
679
+	public $idNS = array();
680
+	private $signedInfo = NULL;
681
+	private $xPathCtx = NULL;
682
+	private $canonicalMethod = NULL;
683
+	private $prefix = NULL;
684
+	private $searchpfx = 'secdsig';
685
+
686
+	/* This variable contains an associative array of validated nodes. */
687
+	private $validatedNodes = NULL;
688
+
689
+	public function __construct() {
690
+		$sigdoc = new DOMDocument();
691
+		$sigdoc->loadXML(XMLSecurityDSig::template);
692
+		$this->sigNode = $sigdoc->documentElement;
693
+	}
694
+
695
+	private function resetXPathObj() {
696
+		$this->xPathCtx = NULL;
697
+	}
698
+
699
+	private function getXPathObj() {
700
+		if (empty($this->xPathCtx) && !empty($this->sigNode)) {
701
+			$xpath = new DOMXPath($this->sigNode->ownerDocument);
702
+			$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
703
+			$this->xPathCtx = $xpath;
704
+		}
705
+		return $this->xPathCtx;
706
+	}
707
+
708
+	static function generate_GUID($prefix='pfx') {
709
+		$uuid = md5(uniqid(rand(), true));
710
+		$guid = $prefix . substr($uuid, 0, 8) . "-" .
711
+			substr($uuid, 8, 4) . "-" .
712
+			substr($uuid, 12, 4) . "-" .
713
+			substr($uuid, 16, 4) . "-" .
714
+			substr($uuid, 20, 12);
715
+		return $guid;
716
+	}
717
+
718
+	public function locateSignature($objDoc) {
719
+		if ($objDoc instanceof DOMDocument) {
720
+			$doc = $objDoc;
721
+		} else {
722
+			$doc = $objDoc->ownerDocument;
723
+		}
724
+		if ($doc) {
725
+			$xpath = new DOMXPath($doc);
726
+			$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
727
+			$query = ".//secdsig:Signature";
728
+			$nodeset = $xpath->query($query, $objDoc);
729
+			$this->sigNode = $nodeset->item(0);
730
+			return $this->sigNode;
731
+		}
732
+		return NULL;
733
+	}
734
+
735
+	public function createNewSignNode($name, $value=NULL) {
736
+		$doc = $this->sigNode->ownerDocument;
737
+		if ($this->prefix != null) {
738
+			$name = $this->prefix . ':' . $name;
739
+		}
740
+		if (!is_null($value)) {
741
+			$node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $name, $value);
742
+		} else {
743
+			$node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $name);
744
+		}
745
+		return $node;
746
+	}
747
+
748
+	public function setCanonicalMethod($method) {
749
+		switch ($method) {
750
+			case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
751
+			case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
752
+			case 'http://www.w3.org/2001/10/xml-exc-c14n#':
753
+			case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
754
+				$this->canonicalMethod = $method;
755
+				break;
756
+			default:
757
+				throw new Exception('Invalid Canonical Method');
758
+		}
759
+		if ($xpath = $this->getXPathObj()) {
760
+			$query = './' . $this->searchpfx . ':SignedInfo';
761
+			$nodeset = $xpath->query($query, $this->sigNode);
762
+			if ($sinfo = $nodeset->item(0)) {
763
+				$query = './' . $this->searchpfx . 'CanonicalizationMethod';
764
+				$nodeset = $xpath->query($query, $sinfo);
765
+				if (!($canonNode = $nodeset->item(0))) {
766
+					$canonNode = $this->createNewSignNode('CanonicalizationMethod');
767
+					$sinfo->insertBefore($canonNode, $sinfo->firstChild);
768
+				}
769
+				$canonNode->setAttribute('Algorithm', $this->canonicalMethod);
770
+			}
771
+		}
772
+	}
773
+
774
+	private function canonicalizeData($node, $canonicalmethod, $arXPath=NULL, $prefixList=NULL) {
775
+		$exclusive = FALSE;
776
+		$withComments = FALSE;
777
+		switch ($canonicalmethod) {
778
+			case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
779
+				$exclusive = FALSE;
780
+				$withComments = FALSE;
781
+				break;
782
+			case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
783
+				$withComments = TRUE;
784
+				break;
785
+			case 'http://www.w3.org/2001/10/xml-exc-c14n#':
786
+				$exclusive = TRUE;
787
+				break;
788
+			case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
789
+				$exclusive = TRUE;
790
+				$withComments = TRUE;
791
+				break;
792
+		}
793
+		/* Support PHP versions < 5.2 not containing C14N methods in DOM extension */
794
+		$php_version = explode('.', PHP_VERSION);
795
+		if (($php_version[0] < 5) || ($php_version[0] == 5 && $php_version[1] < 2)) {
796
+			if (!is_null($arXPath)) {
797
+				throw new Exception("PHP 5.2.0 or higher is required to perform XPath Transformations");
798
+			}
799
+			return C14NGeneral($node, $exclusive, $withComments);
800
+		}
801
+		return $node->C14N($exclusive, $withComments, $arXPath, $prefixList);
802
+	}
803
+
804
+	public function canonicalizeSignedInfo() {
805
+
806
+		$doc = $this->sigNode->ownerDocument;
807
+		$canonicalmethod = NULL;
808
+		if ($doc) {
809
+			$xpath = $this->getXPathObj();
810
+			$query = "./secdsig:SignedInfo";
811
+			$nodeset = $xpath->query($query, $this->sigNode);
812
+			if ($signInfoNode = $nodeset->item(0)) {
813
+				$query = "./secdsig:CanonicalizationMethod";
814
+				$nodeset = $xpath->query($query, $signInfoNode);
815
+				if ($canonNode = $nodeset->item(0)) {
816
+					$canonicalmethod = $canonNode->getAttribute('Algorithm');
817
+				}
818
+				$this->signedInfo = $this->canonicalizeData($signInfoNode, $canonicalmethod);
819
+				return $this->signedInfo;
820
+			}
821
+		}
822
+		return NULL;
823
+	}
824
+
825
+	public function calculateDigest($digestAlgorithm, $data) {
826
+		switch ($digestAlgorithm) {
827
+			case XMLSecurityDSig::SHA1:
828
+				$alg = 'sha1';
829
+				break;
830
+			case XMLSecurityDSig::SHA256:
831
+				$alg = 'sha256';
832
+				break;
833
+			case XMLSecurityDSig::SHA512:
834
+				$alg = 'sha512';
835
+				break;
836
+			case XMLSecurityDSig::RIPEMD160:
837
+				$alg = 'ripemd160';
838
+				break;
839
+			default:
840
+				throw new Exception("Cannot validate digest: Unsupported Algorith <$digestAlgorithm>");
841
+		}
842
+		if (function_exists('hash')) {
843
+			return base64_encode(hash($alg, $data, TRUE));
844
+		} elseif (function_exists('mhash')) {
845
+			$alg = "MHASH_" . strtoupper($alg);
846
+			return base64_encode(mhash(constant($alg), $data));
847
+		} elseif ($alg === 'sha1') {
848
+			return base64_encode(sha1($data, TRUE));
849
+		} else {
850
+			throw new Exception('xmlseclibs is unable to calculate a digest. Maybe you need the mhash library?');
851
+		}
852
+	}
853
+
854
+	public function validateDigest($refNode, $data) {
855
+		$xpath = new DOMXPath($refNode->ownerDocument);
856
+		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
857
+		$query = 'string(./secdsig:DigestMethod/@Algorithm)';
858
+		$digestAlgorithm = $xpath->evaluate($query, $refNode);
859
+		$digValue = $this->calculateDigest($digestAlgorithm, $data);
860
+		$query = 'string(./secdsig:DigestValue)';
861
+		$digestValue = $xpath->evaluate($query, $refNode);
862
+		return ($digValue == $digestValue);
863
+	}
864
+
865
+	public function processTransforms($refNode, $objData, $includeCommentNodes = TRUE) {
866
+		$data = $objData;
867
+		$xpath = new DOMXPath($refNode->ownerDocument);
868
+		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
869
+		$query = './secdsig:Transforms/secdsig:Transform';
870
+		$nodelist = $xpath->query($query, $refNode);
871
+		$canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
872
+		$arXPath = NULL;
873
+		$prefixList = NULL;
874
+		foreach ($nodelist AS $transform) {
875
+			$algorithm = $transform->getAttribute("Algorithm");
876
+			switch ($algorithm) {
877
+				case 'http://www.w3.org/2001/10/xml-exc-c14n#':
878
+				case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
879
+
880
+					if (!$includeCommentNodes) {
881
+						/* We remove comment nodes by forcing it to use a canonicalization
882 882
                          * without comments.
883 883
                          */
884
-                        $canonicalMethod = 'http://www.w3.org/2001/10/xml-exc-c14n#';
885
-                    } else {
886
-                        $canonicalMethod = $algorithm;
887
-                    }
888
-
889
-                    $node = $transform->firstChild;
890
-                    while ($node) {
891
-                        if ($node->localName == 'InclusiveNamespaces') {
892
-                            if ($pfx = $node->getAttribute('PrefixList')) {
893
-                                $arpfx = array();
894
-                                $pfxlist = explode(" ", $pfx);
895
-                                foreach ($pfxlist AS $pfx) {
896
-                                    $val = trim($pfx);
897
-                                    if (!empty($val)) {
898
-                                        $arpfx[] = $val;
899
-                                    }
900
-                                }
901
-                                if (count($arpfx) > 0) {
902
-                                    $prefixList = $arpfx;
903
-                                }
904
-                            }
905
-                            break;
906
-                        }
907
-                        $node = $node->nextSibling;
908
-                    }
909
-                    break;
910
-                case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
911
-                case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
912
-                    if (!$includeCommentNodes) {
913
-                        /* We remove comment nodes by forcing it to use a canonicalization
884
+						$canonicalMethod = 'http://www.w3.org/2001/10/xml-exc-c14n#';
885
+					} else {
886
+						$canonicalMethod = $algorithm;
887
+					}
888
+
889
+					$node = $transform->firstChild;
890
+					while ($node) {
891
+						if ($node->localName == 'InclusiveNamespaces') {
892
+							if ($pfx = $node->getAttribute('PrefixList')) {
893
+								$arpfx = array();
894
+								$pfxlist = explode(" ", $pfx);
895
+								foreach ($pfxlist AS $pfx) {
896
+									$val = trim($pfx);
897
+									if (!empty($val)) {
898
+										$arpfx[] = $val;
899
+									}
900
+								}
901
+								if (count($arpfx) > 0) {
902
+									$prefixList = $arpfx;
903
+								}
904
+							}
905
+							break;
906
+						}
907
+						$node = $node->nextSibling;
908
+					}
909
+					break;
910
+				case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
911
+				case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
912
+					if (!$includeCommentNodes) {
913
+						/* We remove comment nodes by forcing it to use a canonicalization
914 914
                          * without comments.
915 915
                          */
916
-                        $canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
917
-                    } else {
918
-                        $canonicalMethod = $algorithm;
919
-                    }
920
-
921
-                    break;
922
-                case 'http://www.w3.org/TR/1999/REC-xpath-19991116':
923
-                    $node = $transform->firstChild;
924
-                    while ($node) {
925
-                        if ($node->localName == 'XPath') {
926
-                            $arXPath = array();
927
-                            $arXPath['query'] = '(.//. | .//@* | .//namespace::*)[' . $node->nodeValue . ']';
928
-                            $arXpath['namespaces'] = array();
929
-                            $nslist = $xpath->query('./namespace::*', $node);
930
-                            foreach ($nslist AS $nsnode) {
931
-                                if ($nsnode->localName != "xml") {
932
-                                    $arXPath['namespaces'][$nsnode->localName] = $nsnode->nodeValue;
933
-                                }
934
-                            }
935
-                            break;
936
-                        }
937
-                        $node = $node->nextSibling;
938
-                    }
939
-                    break;
940
-            }
941
-        }
942
-        if ($data instanceof DOMNode) {
943
-            $data = $this->canonicalizeData($objData, $canonicalMethod, $arXPath, $prefixList);
944
-        }
945
-        return $data;
946
-    }
947
-
948
-    public function processRefNode($refNode) {
949
-        $dataObject = NULL;
950
-
951
-        /*
916
+						$canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
917
+					} else {
918
+						$canonicalMethod = $algorithm;
919
+					}
920
+
921
+					break;
922
+				case 'http://www.w3.org/TR/1999/REC-xpath-19991116':
923
+					$node = $transform->firstChild;
924
+					while ($node) {
925
+						if ($node->localName == 'XPath') {
926
+							$arXPath = array();
927
+							$arXPath['query'] = '(.//. | .//@* | .//namespace::*)[' . $node->nodeValue . ']';
928
+							$arXpath['namespaces'] = array();
929
+							$nslist = $xpath->query('./namespace::*', $node);
930
+							foreach ($nslist AS $nsnode) {
931
+								if ($nsnode->localName != "xml") {
932
+									$arXPath['namespaces'][$nsnode->localName] = $nsnode->nodeValue;
933
+								}
934
+							}
935
+							break;
936
+						}
937
+						$node = $node->nextSibling;
938
+					}
939
+					break;
940
+			}
941
+		}
942
+		if ($data instanceof DOMNode) {
943
+			$data = $this->canonicalizeData($objData, $canonicalMethod, $arXPath, $prefixList);
944
+		}
945
+		return $data;
946
+	}
947
+
948
+	public function processRefNode($refNode) {
949
+		$dataObject = NULL;
950
+
951
+		/*
952 952
          * Depending on the URI, we may not want to include comments in the result
953 953
          * See: http://www.w3.org/TR/xmldsig-core/#sec-ReferenceProcessingModel
954 954
          */
955
-        $includeCommentNodes = TRUE;
955
+		$includeCommentNodes = TRUE;
956 956
 
957
-        if ($uri = $refNode->getAttribute("URI")) {
958
-            $arUrl = parse_url($uri);
959
-            if (empty($arUrl['path'])) {
960
-                if ($identifier = $arUrl['fragment']) {
957
+		if ($uri = $refNode->getAttribute("URI")) {
958
+			$arUrl = parse_url($uri);
959
+			if (empty($arUrl['path'])) {
960
+				if ($identifier = $arUrl['fragment']) {
961 961
 
962
-                    /* This reference identifies a node with the given id by using
962
+					/* This reference identifies a node with the given id by using
963 963
                      * a URI on the form "#identifier". This should not include comments.
964 964
                      */
965
-                    $includeCommentNodes = FALSE;
966
-
967
-                    $xPath = new DOMXPath($refNode->ownerDocument);
968
-                    if ($this->idNS && is_array($this->idNS)) {
969
-                        foreach ($this->idNS AS $nspf => $ns) {
970
-                            $xPath->registerNamespace($nspf, $ns);
971
-                        }
972
-                    }
973
-                    $iDlist = '@Id="' . $identifier . '"';
974
-                    if (is_array($this->idKeys)) {
975
-                        foreach ($this->idKeys AS $idKey) {
976
-                            $iDlist .= " or @$idKey='$identifier'";
977
-                        }
978
-                    }
979
-                    $query = '//*[' . $iDlist . ']';
980
-                    $dataObject = $xPath->query($query)->item(0);
981
-                } else {
982
-                    $dataObject = $refNode->ownerDocument;
983
-                }
984
-            } else {
985
-                $dataObject = file_get_contents($arUrl);
986
-            }
987
-        } else {
988
-            /* This reference identifies the root node with an empty URI. This should
965
+					$includeCommentNodes = FALSE;
966
+
967
+					$xPath = new DOMXPath($refNode->ownerDocument);
968
+					if ($this->idNS && is_array($this->idNS)) {
969
+						foreach ($this->idNS AS $nspf => $ns) {
970
+							$xPath->registerNamespace($nspf, $ns);
971
+						}
972
+					}
973
+					$iDlist = '@Id="' . $identifier . '"';
974
+					if (is_array($this->idKeys)) {
975
+						foreach ($this->idKeys AS $idKey) {
976
+							$iDlist .= " or @$idKey='$identifier'";
977
+						}
978
+					}
979
+					$query = '//*[' . $iDlist . ']';
980
+					$dataObject = $xPath->query($query)->item(0);
981
+				} else {
982
+					$dataObject = $refNode->ownerDocument;
983
+				}
984
+			} else {
985
+				$dataObject = file_get_contents($arUrl);
986
+			}
987
+		} else {
988
+			/* This reference identifies the root node with an empty URI. This should
989 989
              * not include comments.
990 990
              */
991
-            $includeCommentNodes = FALSE;
992
-
993
-            $dataObject = $refNode->ownerDocument;
994
-        }
995
-        $data = $this->processTransforms($refNode, $dataObject, $includeCommentNodes);
996
-        if (!$this->validateDigest($refNode, $data)) {
997
-            return FALSE;
998
-        }
999
-
1000
-        if ($dataObject instanceof DOMNode) {
1001
-            /* Add this node to the list of validated nodes. */
1002
-            if (!empty($identifier)) {
1003
-                $this->validatedNodes[$identifier] = $dataObject;
1004
-            } else {
1005
-                $this->validatedNodes[] = $dataObject;
1006
-            }
1007
-        }
1008
-
1009
-        return TRUE;
1010
-    }
1011
-
1012
-    public function getRefNodeID($refNode) {
1013
-        if ($uri = $refNode->getAttribute("URI")) {
1014
-            $arUrl = parse_url($uri);
1015
-            if (empty($arUrl['path'])) {
1016
-                if ($identifier = $arUrl['fragment']) {
1017
-                    return $identifier;
1018
-                }
1019
-            }
1020
-        }
1021
-        return null;
1022
-    }
1023
-
1024
-    public function getRefIDs() {
1025
-        $refids = array();
1026
-        $doc = $this->sigNode->ownerDocument;
1027
-
1028
-        $xpath = $this->getXPathObj();
1029
-        $query = "./secdsig:SignedInfo/secdsig:Reference";
1030
-        $nodeset = $xpath->query($query, $this->sigNode);
1031
-        if ($nodeset->length == 0) {
1032
-            throw new Exception("Reference nodes not found");
1033
-        }
1034
-        foreach ($nodeset AS $refNode) {
1035
-            $refids[] = $this->getRefNodeID($refNode);
1036
-        }
1037
-        return $refids;
1038
-    }
1039
-
1040
-    public function validateReference() {
1041
-        $doc = $this->sigNode->ownerDocument;
1042
-        if (!$doc->isSameNode($this->sigNode)) {
1043
-            $this->sigNode->parentNode->removeChild($this->sigNode);
1044
-        }
1045
-        $xpath = $this->getXPathObj();
1046
-        $query = "./secdsig:SignedInfo/secdsig:Reference";
1047
-        $nodeset = $xpath->query($query, $this->sigNode);
1048
-        if ($nodeset->length == 0) {
1049
-            throw new Exception("Reference nodes not found");
1050
-        }
1051
-
1052
-        /* Initialize/reset the list of validated nodes. */
1053
-        $this->validatedNodes = array();
1054
-
1055
-        foreach ($nodeset AS $refNode) {
1056
-            if (!$this->processRefNode($refNode)) {
1057
-                /* Clear the list of validated nodes. */
1058
-                $this->validatedNodes = NULL;
1059
-                throw new Exception("Reference validation failed");
1060
-            }
1061
-        }
1062
-        return TRUE;
1063
-    }
1064
-
1065
-    private function addRefInternal($sinfoNode, $node, $algorithm, $arTransforms=NULL, $options=NULL) {
1066
-        $prefix = NULL;
1067
-        $prefix_ns = NULL;
1068
-        $id_name = 'Id';
1069
-        $overwrite_id = TRUE;
1070
-        $force_uri = FALSE;
1071
-
1072
-        if (is_array($options)) {
1073
-            $prefix = empty($options['prefix']) ? NULL : $options['prefix'];
1074
-            $prefix_ns = empty($options['prefix_ns']) ? NULL : $options['prefix_ns'];
1075
-            $id_name = empty($options['id_name']) ? 'Id' : $options['id_name'];
1076
-            $overwrite_id = !isset($options['overwrite']) ? TRUE : (bool) $options['overwrite'];
1077
-            $force_uri = !isset($options['force_uri']) ? FALSE : (bool) $options['force_uri'];
1078
-        }
1079
-
1080
-        $attname = $id_name;
1081
-        if (!empty($prefix)) {
1082
-            $attname = $prefix . ':' . $attname;
1083
-        }
1084
-
1085
-        $refNode = $this->createNewSignNode('Reference');
1086
-        $sinfoNode->appendChild($refNode);
1087
-
1088
-        if (!$node instanceof DOMDocument) {
1089
-            $uri = NULL;
1090
-            if (!$overwrite_id) {
1091
-                $uri = $node->getAttributeNS($prefix_ns, $attname);
1092
-            }
1093
-            if (empty($uri)) {
1094
-                $uri = XMLSecurityDSig::generate_GUID();
1095
-                $node->setAttributeNS($prefix_ns, $attname, $uri);
1096
-            }
1097
-            $refNode->setAttribute("URI", '#' . $uri);
1098
-        } elseif ($force_uri) {
1099
-            $refNode->setAttribute("URI", '');
1100
-        }
1101
-
1102
-        $transNodes = $this->createNewSignNode('Transforms');
1103
-        $refNode->appendChild($transNodes);
1104
-
1105
-        if (is_array($arTransforms)) {
1106
-            foreach ($arTransforms AS $transform) {
1107
-                $transNode = $this->createNewSignNode('Transform');
1108
-                $transNodes->appendChild($transNode);
1109
-                if (is_array($transform) &&
1110
-                    (!empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116'])) &&
1111
-                    (!empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['query']))) {
1112
-                    $transNode->setAttribute('Algorithm', 'http://www.w3.org/TR/1999/REC-xpath-19991116');
1113
-                    $XPathNode = $this->createNewSignNode('XPath', $transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['query']);
1114
-                    $transNode->appendChild($XPathNode);
1115
-                    if (!empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['namespaces'])) {
1116
-                        foreach ($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['namespaces'] AS $prefix => $namespace) {
1117
-                            $XPathNode->setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:$prefix", $namespace);
1118
-                        }
1119
-                    }
1120
-                } else {
1121
-                    $transNode->setAttribute('Algorithm', $transform);
1122
-                }
1123
-            }
1124
-        } elseif (!empty($this->canonicalMethod)) {
1125
-            $transNode = $this->createNewSignNode('Transform');
1126
-            $transNodes->appendChild($transNode);
1127
-            $transNode->setAttribute('Algorithm', $this->canonicalMethod);
1128
-        }
1129
-
1130
-        $canonicalData = $this->processTransforms($refNode, $node);
1131
-        $digValue = $this->calculateDigest($algorithm, $canonicalData);
1132
-
1133
-        $digestMethod = $this->createNewSignNode('DigestMethod');
1134
-        $refNode->appendChild($digestMethod);
1135
-        $digestMethod->setAttribute('Algorithm', $algorithm);
1136
-
1137
-        $digestValue = $this->createNewSignNode('DigestValue', $digValue);
1138
-        $refNode->appendChild($digestValue);
1139
-    }
1140
-
1141
-    public function addReference($node, $algorithm, $arTransforms=NULL, $options=NULL) {
1142
-        if ($xpath = $this->getXPathObj()) {
1143
-            $query = "./secdsig:SignedInfo";
1144
-            $nodeset = $xpath->query($query, $this->sigNode);
1145
-            if ($sInfo = $nodeset->item(0)) {
1146
-                $this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
1147
-            }
1148
-        }
1149
-    }
1150
-
1151
-    public function addReferenceList($arNodes, $algorithm, $arTransforms=NULL, $options=NULL) {
1152
-        if ($xpath = $this->getXPathObj()) {
1153
-            $query = "./secdsig:SignedInfo";
1154
-            $nodeset = $xpath->query($query, $this->sigNode);
1155
-            if ($sInfo = $nodeset->item(0)) {
1156
-                foreach ($arNodes AS $node) {
1157
-                    $this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
1158
-                }
1159
-            }
1160
-        }
1161
-    }
1162
-
1163
-    public function addObject($data, $mimetype=NULL, $encoding=NULL) {
1164
-        $objNode = $this->createNewSignNode('Object');
1165
-        $this->sigNode->appendChild($objNode);
1166
-        if (!empty($mimetype)) {
1167
-            $objNode->setAtribute('MimeType', $mimetype);
1168
-        }
1169
-        if (!empty($encoding)) {
1170
-            $objNode->setAttribute('Encoding', $encoding);
1171
-        }
1172
-
1173
-        if ($data instanceof DOMElement) {
1174
-            $newData = $this->sigNode->ownerDocument->importNode($data, TRUE);
1175
-        } else {
1176
-            $newData = $this->sigNode->ownerDocument->createTextNode($data);
1177
-        }
1178
-        $objNode->appendChild($newData);
1179
-
1180
-        return $objNode;
1181
-    }
1182
-
1183
-    public function locateKey($node=NULL) {
1184
-        if (empty($node)) {
1185
-            $node = $this->sigNode;
1186
-        }
1187
-        if (!$node instanceof DOMNode) {
1188
-            return NULL;
1189
-        }
1190
-        if ($doc = $node->ownerDocument) {
1191
-            $xpath = new DOMXPath($doc);
1192
-            $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1193
-            $query = "string(./secdsig:SignedInfo/secdsig:SignatureMethod/@Algorithm)";
1194
-            $algorithm = $xpath->evaluate($query, $node);
1195
-            if ($algorithm) {
1196
-                try {
1197
-                    $objKey = new XMLSecurityKey($algorithm, array('type' => 'public'));
1198
-                } catch (Exception $e) {
1199
-                    return NULL;
1200
-                }
1201
-                return $objKey;
1202
-            }
1203
-        }
1204
-        return NULL;
1205
-    }
1206
-
1207
-    public function verify($objKey) {
1208
-        $doc = $this->sigNode->ownerDocument;
1209
-        $xpath = new DOMXPath($doc);
1210
-        $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1211
-        $query = "string(./secdsig:SignatureValue)";
1212
-        $sigValue = $xpath->evaluate($query, $this->sigNode);
1213
-        if (empty($sigValue)) {
1214
-            throw new Exception("Unable to locate SignatureValue");
1215
-        }
1216
-        return $objKey->verifySignature($this->signedInfo, base64_decode($sigValue));
1217
-    }
1218
-
1219
-    public function signData($objKey, $data) {
1220
-        return $objKey->signData($data);
1221
-    }
1222
-
1223
-    public function sign($objKey, $appendToNode = NULL) {
1224
-        // If we have a parent node append it now so C14N properly works
1225
-        if ($appendToNode != NULL) {
1226
-            $this->resetXPathObj();
1227
-            $this->appendSignature($appendToNode);
1228
-            $this->sigNode = $appendToNode->lastChild;
1229
-        }
1230
-        if ($xpath = $this->getXPathObj()) {
1231
-            $query = "./secdsig:SignedInfo";
1232
-            $nodeset = $xpath->query($query, $this->sigNode);
1233
-            if ($sInfo = $nodeset->item(0)) {
1234
-                $query = "./secdsig:SignatureMethod";
1235
-                $nodeset = $xpath->query($query, $sInfo);
1236
-                $sMethod = $nodeset->item(0);
1237
-                $sMethod->setAttribute('Algorithm', $objKey->type);
1238
-                $data = $this->canonicalizeData($sInfo, $this->canonicalMethod);
1239
-                $sigValue = base64_encode($this->signData($objKey, $data));
1240
-                $sigValueNode = $this->createNewSignNode('SignatureValue', $sigValue);
1241
-                if ($infoSibling = $sInfo->nextSibling) {
1242
-                    $infoSibling->parentNode->insertBefore($sigValueNode, $infoSibling);
1243
-                } else {
1244
-                    $this->sigNode->appendChild($sigValueNode);
1245
-                }
1246
-            }
1247
-        }
1248
-    }
1249
-
1250
-    public function appendCert() {
1251
-
1252
-    }
1253
-
1254
-    public function appendKey($objKey, $parent=NULL) {
1255
-        $objKey->serializeKey($parent);
1256
-    }
1257
-
1258
-    /**
1259
-     * This function inserts the signature element.
1260
-     *
1261
-     * The signature element will be appended to the element, unless $beforeNode is specified. If $beforeNode
1262
-     * is specified, the signature element will be inserted as the last element before $beforeNode.
1263
-     *
1264
-     * @param $node  The node the signature element should be inserted into.
1265
-     * @param $beforeNode  The node the signature element should be located before.
1266
-     *
1267
-     * @return DOMNode The signature element node
1268
-     */
1269
-    public function insertSignature($node, $beforeNode = NULL) {
1270
-
1271
-        $document = $node->ownerDocument;
1272
-        $signatureElement = $document->importNode($this->sigNode, TRUE);
1273
-
1274
-        if ($beforeNode == NULL) {
1275
-            return $node->insertBefore($signatureElement);
1276
-        } else {
1277
-            return $node->insertBefore($signatureElement, $beforeNode);
1278
-        }
1279
-    }
1280
-
1281
-    public function appendSignature($parentNode, $insertBefore = FALSE) {
1282
-        $beforeNode = $insertBefore ? $parentNode->firstChild : NULL;
1283
-        return $this->insertSignature($parentNode, $beforeNode);
1284
-    }
1285
-
1286
-    static function get509XCert($cert, $isPEMFormat=TRUE) {
1287
-        $certs = XMLSecurityDSig::staticGet509XCerts($cert, $isPEMFormat);
1288
-        if (!empty($certs)) {
1289
-            return $certs[0];
1290
-        }
1291
-        return '';
1292
-    }
1293
-
1294
-    static function staticGet509XCerts($certs, $isPEMFormat=TRUE) {
1295
-        if ($isPEMFormat) {
1296
-            $data = '';
1297
-            $certlist = array();
1298
-            $arCert = explode("\n", $certs);
1299
-            $inData = FALSE;
1300
-            foreach ($arCert AS $curData) {
1301
-                if (!$inData) {
1302
-                    if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
1303
-                        $inData = TRUE;
1304
-                    }
1305
-                } else {
1306
-                    if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
1307
-                        $inData = FALSE;
1308
-                        $certlist[] = $data;
1309
-                        $data = '';
1310
-                        continue;
1311
-                    }
1312
-                    $data .= trim($curData);
1313
-                }
1314
-            }
1315
-            return $certlist;
1316
-        } else {
1317
-            return array($certs);
1318
-        }
1319
-    }
1320
-
1321
-    static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=TRUE, $isURL=False, $xpath=NULL) {
1322
-        if ($isURL) {
1323
-            $cert = file_get_contents($cert);
1324
-        }
1325
-        if (!$parentRef instanceof DOMElement) {
1326
-            throw new Exception('Invalid parent Node parameter');
1327
-        }
1328
-        $baseDoc = $parentRef->ownerDocument;
1329
-
1330
-        if (empty($xpath)) {
1331
-            $xpath = new DOMXPath($parentRef->ownerDocument);
1332
-            $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1333
-        }
1334
-
1335
-        $query = "./secdsig:KeyInfo";
1336
-        $nodeset = $xpath->query($query, $parentRef);
1337
-        $keyInfo = $nodeset->item(0);
1338
-        if (!$keyInfo) {
1339
-            $inserted = FALSE;
1340
-            $keyInfo = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:KeyInfo');
1341
-
1342
-            $query = "./secdsig:Object";
1343
-            $nodeset = $xpath->query($query, $parentRef);
1344
-            if ($sObject = $nodeset->item(0)) {
1345
-                $sObject->parentNode->insertBefore($keyInfo, $sObject);
1346
-                $inserted = TRUE;
1347
-            }
1348
-
1349
-            if (!$inserted) {
1350
-                $parentRef->appendChild($keyInfo);
1351
-            }
1352
-        }
1353
-
1354
-        // Add all certs if there are more than one
1355
-        $certs = XMLSecurityDSig::staticGet509XCerts($cert, $isPEMFormat);
1356
-
1357
-        // Atach X509 data node
1358
-        $x509DataNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Data');
1359
-        $keyInfo->appendChild($x509DataNode);
1360
-
1361
-        // Atach all certificate nodes
1362
-        foreach ($certs as $X509Cert) {
1363
-            $x509CertNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Certificate', $X509Cert);
1364
-            $x509DataNode->appendChild($x509CertNode);
1365
-        }
1366
-    }
1367
-
1368
-    public function add509Cert($cert, $isPEMFormat=TRUE, $isURL=False) {
1369
-        if ($xpath = $this->getXPathObj()) {
1370
-            self::staticAdd509Cert($this->sigNode, $cert, $isPEMFormat, $isURL, $xpath);
1371
-        }
1372
-    }
1373
-
1374
-    function addKeyInfoAndName($keyName, $xpath=NULL) {
1375
-
1376
-        $baseDoc = $this->sigNode->ownerDocument;
1377
-
1378
-        if (empty($xpath)) {
1379
-            $xpath = new DOMXPath($baseDoc);
1380
-            $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1381
-        }
1382
-
1383
-        $query = "./secdsig:KeyInfo";
1384
-        $nodeset = $xpath->query($query, $this->sigNode);
1385
-        $keyInfo = $nodeset->item(0);
1386
-        if (!$keyInfo) {
1387
-            $inserted = FALSE;
1388
-            $keyInfo = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'KeyInfo');
1389
-
1390
-            $query = "./secdsig:Object";
1391
-            $nodeset = $xpath->query($query, $this->sigNode);
1392
-            if ($sObject = $nodeset->item(0)) {
1393
-                $sObject->parentNode->insertBefore($keyInfo, $sObject);
1394
-                $inserted = TRUE;
1395
-            }
1396
-            if (!$inserted) {
1397
-                $this->sigNode->appendChild($keyInfo);
1398
-            }
1399
-        }
1400
-        $keyInfo->appendChild($baseDoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'KeyName', $keyName));
1401
-    }
1402
-
1403
-    /* This function retrieves an associative array of the validated nodes.
991
+			$includeCommentNodes = FALSE;
992
+
993
+			$dataObject = $refNode->ownerDocument;
994
+		}
995
+		$data = $this->processTransforms($refNode, $dataObject, $includeCommentNodes);
996
+		if (!$this->validateDigest($refNode, $data)) {
997
+			return FALSE;
998
+		}
999
+
1000
+		if ($dataObject instanceof DOMNode) {
1001
+			/* Add this node to the list of validated nodes. */
1002
+			if (!empty($identifier)) {
1003
+				$this->validatedNodes[$identifier] = $dataObject;
1004
+			} else {
1005
+				$this->validatedNodes[] = $dataObject;
1006
+			}
1007
+		}
1008
+
1009
+		return TRUE;
1010
+	}
1011
+
1012
+	public function getRefNodeID($refNode) {
1013
+		if ($uri = $refNode->getAttribute("URI")) {
1014
+			$arUrl = parse_url($uri);
1015
+			if (empty($arUrl['path'])) {
1016
+				if ($identifier = $arUrl['fragment']) {
1017
+					return $identifier;
1018
+				}
1019
+			}
1020
+		}
1021
+		return null;
1022
+	}
1023
+
1024
+	public function getRefIDs() {
1025
+		$refids = array();
1026
+		$doc = $this->sigNode->ownerDocument;
1027
+
1028
+		$xpath = $this->getXPathObj();
1029
+		$query = "./secdsig:SignedInfo/secdsig:Reference";
1030
+		$nodeset = $xpath->query($query, $this->sigNode);
1031
+		if ($nodeset->length == 0) {
1032
+			throw new Exception("Reference nodes not found");
1033
+		}
1034
+		foreach ($nodeset AS $refNode) {
1035
+			$refids[] = $this->getRefNodeID($refNode);
1036
+		}
1037
+		return $refids;
1038
+	}
1039
+
1040
+	public function validateReference() {
1041
+		$doc = $this->sigNode->ownerDocument;
1042
+		if (!$doc->isSameNode($this->sigNode)) {
1043
+			$this->sigNode->parentNode->removeChild($this->sigNode);
1044
+		}
1045
+		$xpath = $this->getXPathObj();
1046
+		$query = "./secdsig:SignedInfo/secdsig:Reference";
1047
+		$nodeset = $xpath->query($query, $this->sigNode);
1048
+		if ($nodeset->length == 0) {
1049
+			throw new Exception("Reference nodes not found");
1050
+		}
1051
+
1052
+		/* Initialize/reset the list of validated nodes. */
1053
+		$this->validatedNodes = array();
1054
+
1055
+		foreach ($nodeset AS $refNode) {
1056
+			if (!$this->processRefNode($refNode)) {
1057
+				/* Clear the list of validated nodes. */
1058
+				$this->validatedNodes = NULL;
1059
+				throw new Exception("Reference validation failed");
1060
+			}
1061
+		}
1062
+		return TRUE;
1063
+	}
1064
+
1065
+	private function addRefInternal($sinfoNode, $node, $algorithm, $arTransforms=NULL, $options=NULL) {
1066
+		$prefix = NULL;
1067
+		$prefix_ns = NULL;
1068
+		$id_name = 'Id';
1069
+		$overwrite_id = TRUE;
1070
+		$force_uri = FALSE;
1071
+
1072
+		if (is_array($options)) {
1073
+			$prefix = empty($options['prefix']) ? NULL : $options['prefix'];
1074
+			$prefix_ns = empty($options['prefix_ns']) ? NULL : $options['prefix_ns'];
1075
+			$id_name = empty($options['id_name']) ? 'Id' : $options['id_name'];
1076
+			$overwrite_id = !isset($options['overwrite']) ? TRUE : (bool) $options['overwrite'];
1077
+			$force_uri = !isset($options['force_uri']) ? FALSE : (bool) $options['force_uri'];
1078
+		}
1079
+
1080
+		$attname = $id_name;
1081
+		if (!empty($prefix)) {
1082
+			$attname = $prefix . ':' . $attname;
1083
+		}
1084
+
1085
+		$refNode = $this->createNewSignNode('Reference');
1086
+		$sinfoNode->appendChild($refNode);
1087
+
1088
+		if (!$node instanceof DOMDocument) {
1089
+			$uri = NULL;
1090
+			if (!$overwrite_id) {
1091
+				$uri = $node->getAttributeNS($prefix_ns, $attname);
1092
+			}
1093
+			if (empty($uri)) {
1094
+				$uri = XMLSecurityDSig::generate_GUID();
1095
+				$node->setAttributeNS($prefix_ns, $attname, $uri);
1096
+			}
1097
+			$refNode->setAttribute("URI", '#' . $uri);
1098
+		} elseif ($force_uri) {
1099
+			$refNode->setAttribute("URI", '');
1100
+		}
1101
+
1102
+		$transNodes = $this->createNewSignNode('Transforms');
1103
+		$refNode->appendChild($transNodes);
1104
+
1105
+		if (is_array($arTransforms)) {
1106
+			foreach ($arTransforms AS $transform) {
1107
+				$transNode = $this->createNewSignNode('Transform');
1108
+				$transNodes->appendChild($transNode);
1109
+				if (is_array($transform) &&
1110
+					(!empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116'])) &&
1111
+					(!empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['query']))) {
1112
+					$transNode->setAttribute('Algorithm', 'http://www.w3.org/TR/1999/REC-xpath-19991116');
1113
+					$XPathNode = $this->createNewSignNode('XPath', $transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['query']);
1114
+					$transNode->appendChild($XPathNode);
1115
+					if (!empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['namespaces'])) {
1116
+						foreach ($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['namespaces'] AS $prefix => $namespace) {
1117
+							$XPathNode->setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:$prefix", $namespace);
1118
+						}
1119
+					}
1120
+				} else {
1121
+					$transNode->setAttribute('Algorithm', $transform);
1122
+				}
1123
+			}
1124
+		} elseif (!empty($this->canonicalMethod)) {
1125
+			$transNode = $this->createNewSignNode('Transform');
1126
+			$transNodes->appendChild($transNode);
1127
+			$transNode->setAttribute('Algorithm', $this->canonicalMethod);
1128
+		}
1129
+
1130
+		$canonicalData = $this->processTransforms($refNode, $node);
1131
+		$digValue = $this->calculateDigest($algorithm, $canonicalData);
1132
+
1133
+		$digestMethod = $this->createNewSignNode('DigestMethod');
1134
+		$refNode->appendChild($digestMethod);
1135
+		$digestMethod->setAttribute('Algorithm', $algorithm);
1136
+
1137
+		$digestValue = $this->createNewSignNode('DigestValue', $digValue);
1138
+		$refNode->appendChild($digestValue);
1139
+	}
1140
+
1141
+	public function addReference($node, $algorithm, $arTransforms=NULL, $options=NULL) {
1142
+		if ($xpath = $this->getXPathObj()) {
1143
+			$query = "./secdsig:SignedInfo";
1144
+			$nodeset = $xpath->query($query, $this->sigNode);
1145
+			if ($sInfo = $nodeset->item(0)) {
1146
+				$this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
1147
+			}
1148
+		}
1149
+	}
1150
+
1151
+	public function addReferenceList($arNodes, $algorithm, $arTransforms=NULL, $options=NULL) {
1152
+		if ($xpath = $this->getXPathObj()) {
1153
+			$query = "./secdsig:SignedInfo";
1154
+			$nodeset = $xpath->query($query, $this->sigNode);
1155
+			if ($sInfo = $nodeset->item(0)) {
1156
+				foreach ($arNodes AS $node) {
1157
+					$this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
1158
+				}
1159
+			}
1160
+		}
1161
+	}
1162
+
1163
+	public function addObject($data, $mimetype=NULL, $encoding=NULL) {
1164
+		$objNode = $this->createNewSignNode('Object');
1165
+		$this->sigNode->appendChild($objNode);
1166
+		if (!empty($mimetype)) {
1167
+			$objNode->setAtribute('MimeType', $mimetype);
1168
+		}
1169
+		if (!empty($encoding)) {
1170
+			$objNode->setAttribute('Encoding', $encoding);
1171
+		}
1172
+
1173
+		if ($data instanceof DOMElement) {
1174
+			$newData = $this->sigNode->ownerDocument->importNode($data, TRUE);
1175
+		} else {
1176
+			$newData = $this->sigNode->ownerDocument->createTextNode($data);
1177
+		}
1178
+		$objNode->appendChild($newData);
1179
+
1180
+		return $objNode;
1181
+	}
1182
+
1183
+	public function locateKey($node=NULL) {
1184
+		if (empty($node)) {
1185
+			$node = $this->sigNode;
1186
+		}
1187
+		if (!$node instanceof DOMNode) {
1188
+			return NULL;
1189
+		}
1190
+		if ($doc = $node->ownerDocument) {
1191
+			$xpath = new DOMXPath($doc);
1192
+			$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1193
+			$query = "string(./secdsig:SignedInfo/secdsig:SignatureMethod/@Algorithm)";
1194
+			$algorithm = $xpath->evaluate($query, $node);
1195
+			if ($algorithm) {
1196
+				try {
1197
+					$objKey = new XMLSecurityKey($algorithm, array('type' => 'public'));
1198
+				} catch (Exception $e) {
1199
+					return NULL;
1200
+				}
1201
+				return $objKey;
1202
+			}
1203
+		}
1204
+		return NULL;
1205
+	}
1206
+
1207
+	public function verify($objKey) {
1208
+		$doc = $this->sigNode->ownerDocument;
1209
+		$xpath = new DOMXPath($doc);
1210
+		$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1211
+		$query = "string(./secdsig:SignatureValue)";
1212
+		$sigValue = $xpath->evaluate($query, $this->sigNode);
1213
+		if (empty($sigValue)) {
1214
+			throw new Exception("Unable to locate SignatureValue");
1215
+		}
1216
+		return $objKey->verifySignature($this->signedInfo, base64_decode($sigValue));
1217
+	}
1218
+
1219
+	public function signData($objKey, $data) {
1220
+		return $objKey->signData($data);
1221
+	}
1222
+
1223
+	public function sign($objKey, $appendToNode = NULL) {
1224
+		// If we have a parent node append it now so C14N properly works
1225
+		if ($appendToNode != NULL) {
1226
+			$this->resetXPathObj();
1227
+			$this->appendSignature($appendToNode);
1228
+			$this->sigNode = $appendToNode->lastChild;
1229
+		}
1230
+		if ($xpath = $this->getXPathObj()) {
1231
+			$query = "./secdsig:SignedInfo";
1232
+			$nodeset = $xpath->query($query, $this->sigNode);
1233
+			if ($sInfo = $nodeset->item(0)) {
1234
+				$query = "./secdsig:SignatureMethod";
1235
+				$nodeset = $xpath->query($query, $sInfo);
1236
+				$sMethod = $nodeset->item(0);
1237
+				$sMethod->setAttribute('Algorithm', $objKey->type);
1238
+				$data = $this->canonicalizeData($sInfo, $this->canonicalMethod);
1239
+				$sigValue = base64_encode($this->signData($objKey, $data));
1240
+				$sigValueNode = $this->createNewSignNode('SignatureValue', $sigValue);
1241
+				if ($infoSibling = $sInfo->nextSibling) {
1242
+					$infoSibling->parentNode->insertBefore($sigValueNode, $infoSibling);
1243
+				} else {
1244
+					$this->sigNode->appendChild($sigValueNode);
1245
+				}
1246
+			}
1247
+		}
1248
+	}
1249
+
1250
+	public function appendCert() {
1251
+
1252
+	}
1253
+
1254
+	public function appendKey($objKey, $parent=NULL) {
1255
+		$objKey->serializeKey($parent);
1256
+	}
1257
+
1258
+	/**
1259
+	 * This function inserts the signature element.
1260
+	 *
1261
+	 * The signature element will be appended to the element, unless $beforeNode is specified. If $beforeNode
1262
+	 * is specified, the signature element will be inserted as the last element before $beforeNode.
1263
+	 *
1264
+	 * @param $node  The node the signature element should be inserted into.
1265
+	 * @param $beforeNode  The node the signature element should be located before.
1266
+	 *
1267
+	 * @return DOMNode The signature element node
1268
+	 */
1269
+	public function insertSignature($node, $beforeNode = NULL) {
1270
+
1271
+		$document = $node->ownerDocument;
1272
+		$signatureElement = $document->importNode($this->sigNode, TRUE);
1273
+
1274
+		if ($beforeNode == NULL) {
1275
+			return $node->insertBefore($signatureElement);
1276
+		} else {
1277
+			return $node->insertBefore($signatureElement, $beforeNode);
1278
+		}
1279
+	}
1280
+
1281
+	public function appendSignature($parentNode, $insertBefore = FALSE) {
1282
+		$beforeNode = $insertBefore ? $parentNode->firstChild : NULL;
1283
+		return $this->insertSignature($parentNode, $beforeNode);
1284
+	}
1285
+
1286
+	static function get509XCert($cert, $isPEMFormat=TRUE) {
1287
+		$certs = XMLSecurityDSig::staticGet509XCerts($cert, $isPEMFormat);
1288
+		if (!empty($certs)) {
1289
+			return $certs[0];
1290
+		}
1291
+		return '';
1292
+	}
1293
+
1294
+	static function staticGet509XCerts($certs, $isPEMFormat=TRUE) {
1295
+		if ($isPEMFormat) {
1296
+			$data = '';
1297
+			$certlist = array();
1298
+			$arCert = explode("\n", $certs);
1299
+			$inData = FALSE;
1300
+			foreach ($arCert AS $curData) {
1301
+				if (!$inData) {
1302
+					if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
1303
+						$inData = TRUE;
1304
+					}
1305
+				} else {
1306
+					if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
1307
+						$inData = FALSE;
1308
+						$certlist[] = $data;
1309
+						$data = '';
1310
+						continue;
1311
+					}
1312
+					$data .= trim($curData);
1313
+				}
1314
+			}
1315
+			return $certlist;
1316
+		} else {
1317
+			return array($certs);
1318
+		}
1319
+	}
1320
+
1321
+	static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=TRUE, $isURL=False, $xpath=NULL) {
1322
+		if ($isURL) {
1323
+			$cert = file_get_contents($cert);
1324
+		}
1325
+		if (!$parentRef instanceof DOMElement) {
1326
+			throw new Exception('Invalid parent Node parameter');
1327
+		}
1328
+		$baseDoc = $parentRef->ownerDocument;
1329
+
1330
+		if (empty($xpath)) {
1331
+			$xpath = new DOMXPath($parentRef->ownerDocument);
1332
+			$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1333
+		}
1334
+
1335
+		$query = "./secdsig:KeyInfo";
1336
+		$nodeset = $xpath->query($query, $parentRef);
1337
+		$keyInfo = $nodeset->item(0);
1338
+		if (!$keyInfo) {
1339
+			$inserted = FALSE;
1340
+			$keyInfo = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:KeyInfo');
1341
+
1342
+			$query = "./secdsig:Object";
1343
+			$nodeset = $xpath->query($query, $parentRef);
1344
+			if ($sObject = $nodeset->item(0)) {
1345
+				$sObject->parentNode->insertBefore($keyInfo, $sObject);
1346
+				$inserted = TRUE;
1347
+			}
1348
+
1349
+			if (!$inserted) {
1350
+				$parentRef->appendChild($keyInfo);
1351
+			}
1352
+		}
1353
+
1354
+		// Add all certs if there are more than one
1355
+		$certs = XMLSecurityDSig::staticGet509XCerts($cert, $isPEMFormat);
1356
+
1357
+		// Atach X509 data node
1358
+		$x509DataNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Data');
1359
+		$keyInfo->appendChild($x509DataNode);
1360
+
1361
+		// Atach all certificate nodes
1362
+		foreach ($certs as $X509Cert) {
1363
+			$x509CertNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Certificate', $X509Cert);
1364
+			$x509DataNode->appendChild($x509CertNode);
1365
+		}
1366
+	}
1367
+
1368
+	public function add509Cert($cert, $isPEMFormat=TRUE, $isURL=False) {
1369
+		if ($xpath = $this->getXPathObj()) {
1370
+			self::staticAdd509Cert($this->sigNode, $cert, $isPEMFormat, $isURL, $xpath);
1371
+		}
1372
+	}
1373
+
1374
+	function addKeyInfoAndName($keyName, $xpath=NULL) {
1375
+
1376
+		$baseDoc = $this->sigNode->ownerDocument;
1377
+
1378
+		if (empty($xpath)) {
1379
+			$xpath = new DOMXPath($baseDoc);
1380
+			$xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1381
+		}
1382
+
1383
+		$query = "./secdsig:KeyInfo";
1384
+		$nodeset = $xpath->query($query, $this->sigNode);
1385
+		$keyInfo = $nodeset->item(0);
1386
+		if (!$keyInfo) {
1387
+			$inserted = FALSE;
1388
+			$keyInfo = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'KeyInfo');
1389
+
1390
+			$query = "./secdsig:Object";
1391
+			$nodeset = $xpath->query($query, $this->sigNode);
1392
+			if ($sObject = $nodeset->item(0)) {
1393
+				$sObject->parentNode->insertBefore($keyInfo, $sObject);
1394
+				$inserted = TRUE;
1395
+			}
1396
+			if (!$inserted) {
1397
+				$this->sigNode->appendChild($keyInfo);
1398
+			}
1399
+		}
1400
+		$keyInfo->appendChild($baseDoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'KeyName', $keyName));
1401
+	}
1402
+
1403
+	/* This function retrieves an associative array of the validated nodes.
1404 1404
      *
1405 1405
      * The array will contain the id of the referenced node as the key and the node itself
1406 1406
      * as the value.
@@ -1409,395 +1409,395 @@  discard block
 block discarded – undo
1409 1409
      *  An associative array of validated nodes or NULL if no nodes have been validated.
1410 1410
      */
1411 1411
 
1412
-    public function getValidatedNodes() {
1413
-        return $this->validatedNodes;
1414
-    }
1412
+	public function getValidatedNodes() {
1413
+		return $this->validatedNodes;
1414
+	}
1415 1415
 
1416 1416
 }
1417 1417
 
1418 1418
 class XMLSecEnc {
1419
-    const template = "<xenc:EncryptedData xmlns:xenc='http://www.w3.org/2001/04/xmlenc#'>
1419
+	const template = "<xenc:EncryptedData xmlns:xenc='http://www.w3.org/2001/04/xmlenc#'>
1420 1420
    <xenc:CipherData>
1421 1421
       <xenc:CipherValue></xenc:CipherValue>
1422 1422
    </xenc:CipherData>
1423 1423
 </xenc:EncryptedData>";
1424 1424
 
1425
-    const Element = 'http://www.w3.org/2001/04/xmlenc#Element';
1426
-    const Content = 'http://www.w3.org/2001/04/xmlenc#Content';
1427
-    const URI = 3;
1428
-    const XMLENCNS = 'http://www.w3.org/2001/04/xmlenc#';
1429
-
1430
-    private $encdoc = NULL;
1431
-    private $rawNode = NULL;
1432
-    public $type = NULL;
1433
-    public $encKey = NULL;
1434
-    private $references = array();
1435
-
1436
-    public function __construct() {
1437
-        $this->_resetTemplate();
1438
-    }
1439
-
1440
-    private function _resetTemplate() {
1441
-        $this->encdoc = new DOMDocument();
1442
-        $this->encdoc->loadXML(XMLSecEnc::template);
1443
-    }
1444
-
1445
-    public function addReference($name, $node, $type) {
1446
-        if (!$node instanceOf DOMNode) {
1447
-            throw new Exception('$node is not of type DOMNode');
1448
-        }
1449
-        $curencdoc = $this->encdoc;
1450
-        $this->_resetTemplate();
1451
-        $encdoc = $this->encdoc;
1452
-        $this->encdoc = $curencdoc;
1453
-        $refuri = XMLSecurityDSig::generate_GUID();
1454
-        $element = $encdoc->documentElement;
1455
-        $element->setAttribute("Id", $refuri);
1456
-        $this->references[$name] = array("node" => $node, "type" => $type, "encnode" => $encdoc, "refuri" => $refuri);
1457
-    }
1458
-
1459
-    public function setNode($node) {
1460
-        $this->rawNode = $node;
1461
-    }
1462
-
1463
-    public function encryptNode($objKey, $replace=TRUE) {
1464
-        $data = '';
1465
-        if (empty($this->rawNode)) {
1466
-            throw new Exception('Node to encrypt has not been set');
1467
-        }
1468
-        if (!$objKey instanceof XMLSecurityKey) {
1469
-            throw new Exception('Invalid Key');
1470
-        }
1471
-        $doc = $this->rawNode->ownerDocument;
1472
-        $xPath = new DOMXPath($this->encdoc);
1473
-        $objList = $xPath->query('/xenc:EncryptedData/xenc:CipherData/xenc:CipherValue');
1474
-        $cipherValue = $objList->item(0);
1475
-        if ($cipherValue == NULL) {
1476
-            throw new Exception('Error locating CipherValue element within template');
1477
-        }
1478
-        switch ($this->type) {
1479
-            case (XMLSecEnc::Element):
1480
-                $data = $doc->saveXML($this->rawNode);
1481
-                $this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Element);
1482
-                break;
1483
-            case (XMLSecEnc::Content):
1484
-                $children = $this->rawNode->childNodes;
1485
-                foreach ($children AS $child) {
1486
-                    $data .= $doc->saveXML($child);
1487
-                }
1488
-                $this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Content);
1489
-                break;
1490
-            default:
1491
-                throw new Exception('Type is currently not supported');
1492
-                return;
1493
-        }
1494
-
1495
-        $encMethod = $this->encdoc->documentElement->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
1496
-        $encMethod->setAttribute('Algorithm', $objKey->getAlgorith());
1497
-        $cipherValue->parentNode->parentNode->insertBefore($encMethod, $cipherValue->parentNode->parentNode->firstChild);
1498
-
1499
-        $strEncrypt = base64_encode($objKey->encryptData($data));
1500
-        $value = $this->encdoc->createTextNode($strEncrypt);
1501
-        $cipherValue->appendChild($value);
1502
-
1503
-        if ($replace) {
1504
-            switch ($this->type) {
1505
-                case (XMLSecEnc::Element):
1506
-                    if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
1507
-                        return $this->encdoc;
1508
-                    }
1509
-                    $importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE);
1510
-                    $this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
1511
-                    return $importEnc;
1512
-                    break;
1513
-                case (XMLSecEnc::Content):
1514
-                    $importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE);
1515
-                    while ($this->rawNode->firstChild) {
1516
-                        $this->rawNode->removeChild($this->rawNode->firstChild);
1517
-                    }
1518
-                    $this->rawNode->appendChild($importEnc);
1519
-                    return $importEnc;
1520
-                    break;
1521
-            }
1522
-        }
1523
-    }
1524
-
1525
-    public function encryptReferences($objKey) {
1526
-        $curRawNode = $this->rawNode;
1527
-        $curType = $this->type;
1528
-        foreach ($this->references AS $name => $reference) {
1529
-            $this->encdoc = $reference["encnode"];
1530
-            $this->rawNode = $reference["node"];
1531
-            $this->type = $reference["type"];
1532
-            try {
1533
-                $encNode = $this->encryptNode($objKey);
1534
-                $this->references[$name]["encnode"] = $encNode;
1535
-            } catch (Exception $e) {
1536
-                $this->rawNode = $curRawNode;
1537
-                $this->type = $curType;
1538
-                throw $e;
1539
-            }
1540
-        }
1541
-        $this->rawNode = $curRawNode;
1542
-        $this->type = $curType;
1543
-    }
1544
-
1545
-    /**
1546
-     * Retrieve the CipherValue text from this encrypted node.
1547
-     *
1548
-     * @return string|NULL  The Ciphervalue text, or NULL if no CipherValue is found.
1549
-     */
1550
-    public function getCipherValue() {
1551
-        if (empty($this->rawNode)) {
1552
-            throw new Exception('Node to decrypt has not been set');
1553
-        }
1554
-
1555
-        $doc = $this->rawNode->ownerDocument;
1556
-        $xPath = new DOMXPath($doc);
1557
-        $xPath->registerNamespace('xmlencr', XMLSecEnc::XMLENCNS);
1558
-        /* Only handles embedded content right now and not a reference */
1559
-        $query = "./xmlencr:CipherData/xmlencr:CipherValue";
1560
-        $nodeset = $xPath->query($query, $this->rawNode);
1561
-        $node = $nodeset->item(0);
1562
-
1563
-        if (!$node) {
1564
-            return NULL;
1565
-        }
1566
-
1567
-        return base64_decode($node->nodeValue);
1568
-    }
1569
-
1570
-    /**
1571
-     * Decrypt this encrypted node.
1572
-     *
1573
-     * The behaviour of this function depends on the value of $replace.
1574
-     * If $replace is FALSE, we will return the decrypted data as a string.
1575
-     * If $replace is TRUE, we will insert the decrypted element(s) into the
1576
-     * document, and return the decrypted element(s).
1577
-     *
1578
-     * @params XMLSecurityKey $objKey  The decryption key that should be used when decrypting the node.
1579
-     * @params boolean $replace  Whether we should replace the encrypted node in the XML document with the decrypted data. The default is TRUE.
1580
-     * @return string|DOMElement  The decrypted data.
1581
-     */
1582
-    public function decryptNode($objKey, $replace=TRUE) {
1583
-        if (!$objKey instanceof XMLSecurityKey) {
1584
-            throw new Exception('Invalid Key');
1585
-        }
1586
-
1587
-        $encryptedData = $this->getCipherValue();
1588
-        if ($encryptedData) {
1589
-            $decrypted = $objKey->decryptData($encryptedData);
1590
-            if ($replace) {
1591
-                switch ($this->type) {
1592
-                    case (XMLSecEnc::Element):
1593
-                        $newdoc = new DOMDocument();
1594
-                        $newdoc->loadXML($decrypted);
1595
-                        if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
1596
-                            return $newdoc;
1597
-                        }
1598
-                        $importEnc = $this->rawNode->ownerDocument->importNode($newdoc->documentElement, TRUE);
1599
-                        $this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
1600
-                        return $importEnc;
1601
-                        break;
1602
-                    case (XMLSecEnc::Content):
1603
-                        if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
1604
-                            $doc = $this->rawNode;
1605
-                        } else {
1606
-                            $doc = $this->rawNode->ownerDocument;
1607
-                        }
1608
-                        $newFrag = $doc->createDocumentFragment();
1609
-                        $newFrag->appendXML($decrypted);
1610
-                        $parent = $this->rawNode->parentNode;
1611
-                        $parent->replaceChild($newFrag, $this->rawNode);
1612
-                        return $parent;
1613
-                        break;
1614
-                    default:
1615
-                        return $decrypted;
1616
-                }
1617
-            } else {
1618
-                return $decrypted;
1619
-            }
1620
-        } else {
1621
-            throw new Exception("Cannot locate encrypted data");
1622
-        }
1623
-    }
1624
-
1625
-    public function encryptKey($srcKey, $rawKey, $append=TRUE) {
1626
-        if ((!$srcKey instanceof XMLSecurityKey) || (!$rawKey instanceof XMLSecurityKey)) {
1627
-            throw new Exception('Invalid Key');
1628
-        }
1629
-        $strEncKey = base64_encode($srcKey->encryptData($rawKey->key));
1630
-        $root = $this->encdoc->documentElement;
1631
-        $encKey = $this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptedKey');
1632
-        if ($append) {
1633
-            $keyInfo = $root->insertBefore($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'), $root->firstChild);
1634
-            $keyInfo->appendChild($encKey);
1635
-        } else {
1636
-            $this->encKey = $encKey;
1637
-        }
1638
-        $encMethod = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
1639
-        $encMethod->setAttribute('Algorithm', $srcKey->getAlgorith());
1640
-        if (!empty($srcKey->name)) {
1641
-            $keyInfo = $encKey->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'));
1642
-            $keyInfo->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyName', $srcKey->name));
1643
-        }
1644
-        $cipherData = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherData'));
1645
-        $cipherData->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherValue', $strEncKey));
1646
-        if (is_array($this->references) && count($this->references) > 0) {
1647
-            $refList = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:ReferenceList'));
1648
-            foreach ($this->references AS $name => $reference) {
1649
-                $refuri = $reference["refuri"];
1650
-                $dataRef = $refList->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:DataReference'));
1651
-                $dataRef->setAttribute("URI", '#' . $refuri);
1652
-            }
1653
-        }
1654
-        return;
1655
-    }
1656
-
1657
-    public function decryptKey($encKey) {
1658
-        if (!$encKey->isEncrypted) {
1659
-            throw new Exception("Key is not Encrypted");
1660
-        }
1661
-        if (empty($encKey->key)) {
1662
-            throw new Exception("Key is missing data to perform the decryption");
1663
-        }
1664
-        return $this->decryptNode($encKey, FALSE);
1665
-    }
1666
-
1667
-    public function locateEncryptedData($element) {
1668
-        if ($element instanceof DOMDocument) {
1669
-            $doc = $element;
1670
-        } else {
1671
-            $doc = $element->ownerDocument;
1672
-        }
1673
-        if ($doc) {
1674
-            $xpath = new DOMXPath($doc);
1675
-            $query = "//*[local-name()='EncryptedData' and namespace-uri()='" . XMLSecEnc::XMLENCNS . "']";
1676
-            $nodeset = $xpath->query($query);
1677
-            return $nodeset->item(0);
1678
-        }
1679
-        return NULL;
1680
-    }
1681
-
1682
-    public function locateKey($node=NULL) {
1683
-        if (empty($node)) {
1684
-            $node = $this->rawNode;
1685
-        }
1686
-        if (!$node instanceof DOMNode) {
1687
-            return NULL;
1688
-        }
1689
-        if ($doc = $node->ownerDocument) {
1690
-            $xpath = new DOMXPath($doc);
1691
-            $xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
1692
-            $query = ".//xmlsecenc:EncryptionMethod";
1693
-            $nodeset = $xpath->query($query, $node);
1694
-            if ($encmeth = $nodeset->item(0)) {
1695
-                $attrAlgorithm = $encmeth->getAttribute("Algorithm");
1696
-                try {
1697
-                    $objKey = new XMLSecurityKey($attrAlgorithm, array('type' => 'private'));
1698
-                } catch (Exception $e) {
1699
-                    return NULL;
1700
-                }
1701
-                return $objKey;
1702
-            }
1703
-        }
1704
-        return NULL;
1705
-    }
1706
-
1707
-    static function staticLocateKeyInfo($objBaseKey=NULL, $node=NULL) {
1708
-        if (empty($node) || (!$node instanceof DOMNode)) {
1709
-            return NULL;
1710
-        }
1711
-        $doc = $node->ownerDocument;
1712
-        if (!$doc) {
1713
-            return NULL;
1714
-        }
1715
-
1716
-        $xpath = new DOMXPath($doc);
1717
-        $xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
1718
-        $xpath->registerNamespace('xmlsecdsig', XMLSecurityDSig::XMLDSIGNS);
1719
-        $query = "./xmlsecdsig:KeyInfo";
1720
-        $nodeset = $xpath->query($query, $node);
1721
-        $encmeth = $nodeset->item(0);
1722
-        if (!$encmeth) {
1723
-            /* No KeyInfo in EncryptedData / EncryptedKey. */
1724
-            return $objBaseKey;
1725
-        }
1726
-
1727
-        foreach ($encmeth->childNodes AS $child) {
1728
-            switch ($child->localName) {
1729
-                case 'KeyName':
1730
-                    if (!empty($objBaseKey)) {
1731
-                        $objBaseKey->name = $child->nodeValue;
1732
-                    }
1733
-                    break;
1734
-                case 'KeyValue':
1735
-                    foreach ($child->childNodes AS $keyval) {
1736
-                        switch ($keyval->localName) {
1737
-                            case 'DSAKeyValue':
1738
-                                throw new Exception("DSAKeyValue currently not supported");
1739
-                                break;
1740
-                            case 'RSAKeyValue':
1741
-                                $modulus = NULL;
1742
-                                $exponent = NULL;
1743
-                                if ($modulusNode = $keyval->getElementsByTagName('Modulus')->item(0)) {
1744
-                                    $modulus = base64_decode($modulusNode->nodeValue);
1745
-                                }
1746
-                                if ($exponentNode = $keyval->getElementsByTagName('Exponent')->item(0)) {
1747
-                                    $exponent = base64_decode($exponentNode->nodeValue);
1748
-                                }
1749
-                                if (empty($modulus) || empty($exponent)) {
1750
-                                    throw new Exception("Missing Modulus or Exponent");
1751
-                                }
1752
-                                $publicKey = XMLSecurityKey::convertRSA($modulus, $exponent);
1753
-                                $objBaseKey->loadKey($publicKey);
1754
-                                break;
1755
-                        }
1756
-                    }
1757
-                    break;
1758
-                case 'RetrievalMethod':
1759
-                    $type = $child->getAttribute('Type');
1760
-                    if ($type !== 'http://www.w3.org/2001/04/xmlenc#EncryptedKey') {
1761
-                        /* Unsupported key type. */
1762
-                        break;
1763
-                    }
1764
-                    $uri = $child->getAttribute('URI');
1765
-                    if ($uri[0] !== '#') {
1766
-                        /* URI not a reference - unsupported. */
1767
-                        break;
1768
-                    }
1769
-                    $id = substr($uri, 1);
1770
-
1771
-                    $query = "//xmlsecenc:EncryptedKey[@Id='$id']";
1772
-                    $keyElement = $xpath->query($query)->item(0);
1773
-                    if (!$keyElement) {
1774
-                        throw new Exception("Unable to locate EncryptedKey with @Id='$id'.");
1775
-                    }
1776
-
1777
-                    return XMLSecurityKey::fromEncryptedKeyElement($keyElement);
1778
-                case 'EncryptedKey':
1779
-                    return XMLSecurityKey::fromEncryptedKeyElement($child);
1780
-                case 'X509Data':
1781
-                    if ($x509certNodes = $child->getElementsByTagName('X509Certificate')) {
1782
-                        if ($x509certNodes->length > 0) {
1783
-                            $x509cert = $x509certNodes->item(0)->textContent;
1784
-                            $x509cert = str_replace(array("\r", "\n"), "", $x509cert);
1785
-                            $x509cert = "-----BEGIN CERTIFICATE-----\n" . chunk_split($x509cert, 64, "\n") . "-----END CERTIFICATE-----\n";
1786
-                            $objBaseKey->loadKey($x509cert, FALSE, TRUE);
1787
-                        }
1788
-                    }
1789
-                    break;
1790
-            }
1791
-        }
1792
-        return $objBaseKey;
1793
-    }
1794
-
1795
-    public function locateKeyInfo($objBaseKey=NULL, $node=NULL) {
1796
-        if (empty($node)) {
1797
-            $node = $this->rawNode;
1798
-        }
1799
-        return XMLSecEnc::staticLocateKeyInfo($objBaseKey, $node);
1800
-    }
1425
+	const Element = 'http://www.w3.org/2001/04/xmlenc#Element';
1426
+	const Content = 'http://www.w3.org/2001/04/xmlenc#Content';
1427
+	const URI = 3;
1428
+	const XMLENCNS = 'http://www.w3.org/2001/04/xmlenc#';
1429
+
1430
+	private $encdoc = NULL;
1431
+	private $rawNode = NULL;
1432
+	public $type = NULL;
1433
+	public $encKey = NULL;
1434
+	private $references = array();
1435
+
1436
+	public function __construct() {
1437
+		$this->_resetTemplate();
1438
+	}
1439
+
1440
+	private function _resetTemplate() {
1441
+		$this->encdoc = new DOMDocument();
1442
+		$this->encdoc->loadXML(XMLSecEnc::template);
1443
+	}
1444
+
1445
+	public function addReference($name, $node, $type) {
1446
+		if (!$node instanceOf DOMNode) {
1447
+			throw new Exception('$node is not of type DOMNode');
1448
+		}
1449
+		$curencdoc = $this->encdoc;
1450
+		$this->_resetTemplate();
1451
+		$encdoc = $this->encdoc;
1452
+		$this->encdoc = $curencdoc;
1453
+		$refuri = XMLSecurityDSig::generate_GUID();
1454
+		$element = $encdoc->documentElement;
1455
+		$element->setAttribute("Id", $refuri);
1456
+		$this->references[$name] = array("node" => $node, "type" => $type, "encnode" => $encdoc, "refuri" => $refuri);
1457
+	}
1458
+
1459
+	public function setNode($node) {
1460
+		$this->rawNode = $node;
1461
+	}
1462
+
1463
+	public function encryptNode($objKey, $replace=TRUE) {
1464
+		$data = '';
1465
+		if (empty($this->rawNode)) {
1466
+			throw new Exception('Node to encrypt has not been set');
1467
+		}
1468
+		if (!$objKey instanceof XMLSecurityKey) {
1469
+			throw new Exception('Invalid Key');
1470
+		}
1471
+		$doc = $this->rawNode->ownerDocument;
1472
+		$xPath = new DOMXPath($this->encdoc);
1473
+		$objList = $xPath->query('/xenc:EncryptedData/xenc:CipherData/xenc:CipherValue');
1474
+		$cipherValue = $objList->item(0);
1475
+		if ($cipherValue == NULL) {
1476
+			throw new Exception('Error locating CipherValue element within template');
1477
+		}
1478
+		switch ($this->type) {
1479
+			case (XMLSecEnc::Element):
1480
+				$data = $doc->saveXML($this->rawNode);
1481
+				$this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Element);
1482
+				break;
1483
+			case (XMLSecEnc::Content):
1484
+				$children = $this->rawNode->childNodes;
1485
+				foreach ($children AS $child) {
1486
+					$data .= $doc->saveXML($child);
1487
+				}
1488
+				$this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Content);
1489
+				break;
1490
+			default:
1491
+				throw new Exception('Type is currently not supported');
1492
+				return;
1493
+		}
1494
+
1495
+		$encMethod = $this->encdoc->documentElement->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
1496
+		$encMethod->setAttribute('Algorithm', $objKey->getAlgorith());
1497
+		$cipherValue->parentNode->parentNode->insertBefore($encMethod, $cipherValue->parentNode->parentNode->firstChild);
1498
+
1499
+		$strEncrypt = base64_encode($objKey->encryptData($data));
1500
+		$value = $this->encdoc->createTextNode($strEncrypt);
1501
+		$cipherValue->appendChild($value);
1502
+
1503
+		if ($replace) {
1504
+			switch ($this->type) {
1505
+				case (XMLSecEnc::Element):
1506
+					if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
1507
+						return $this->encdoc;
1508
+					}
1509
+					$importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE);
1510
+					$this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
1511
+					return $importEnc;
1512
+					break;
1513
+				case (XMLSecEnc::Content):
1514
+					$importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE);
1515
+					while ($this->rawNode->firstChild) {
1516
+						$this->rawNode->removeChild($this->rawNode->firstChild);
1517
+					}
1518
+					$this->rawNode->appendChild($importEnc);
1519
+					return $importEnc;
1520
+					break;
1521
+			}
1522
+		}
1523
+	}
1524
+
1525
+	public function encryptReferences($objKey) {
1526
+		$curRawNode = $this->rawNode;
1527
+		$curType = $this->type;
1528
+		foreach ($this->references AS $name => $reference) {
1529
+			$this->encdoc = $reference["encnode"];
1530
+			$this->rawNode = $reference["node"];
1531
+			$this->type = $reference["type"];
1532
+			try {
1533
+				$encNode = $this->encryptNode($objKey);
1534
+				$this->references[$name]["encnode"] = $encNode;
1535
+			} catch (Exception $e) {
1536
+				$this->rawNode = $curRawNode;
1537
+				$this->type = $curType;
1538
+				throw $e;
1539
+			}
1540
+		}
1541
+		$this->rawNode = $curRawNode;
1542
+		$this->type = $curType;
1543
+	}
1544
+
1545
+	/**
1546
+	 * Retrieve the CipherValue text from this encrypted node.
1547
+	 *
1548
+	 * @return string|NULL  The Ciphervalue text, or NULL if no CipherValue is found.
1549
+	 */
1550
+	public function getCipherValue() {
1551
+		if (empty($this->rawNode)) {
1552
+			throw new Exception('Node to decrypt has not been set');
1553
+		}
1554
+
1555
+		$doc = $this->rawNode->ownerDocument;
1556
+		$xPath = new DOMXPath($doc);
1557
+		$xPath->registerNamespace('xmlencr', XMLSecEnc::XMLENCNS);
1558
+		/* Only handles embedded content right now and not a reference */
1559
+		$query = "./xmlencr:CipherData/xmlencr:CipherValue";
1560
+		$nodeset = $xPath->query($query, $this->rawNode);
1561
+		$node = $nodeset->item(0);
1562
+
1563
+		if (!$node) {
1564
+			return NULL;
1565
+		}
1566
+
1567
+		return base64_decode($node->nodeValue);
1568
+	}
1569
+
1570
+	/**
1571
+	 * Decrypt this encrypted node.
1572
+	 *
1573
+	 * The behaviour of this function depends on the value of $replace.
1574
+	 * If $replace is FALSE, we will return the decrypted data as a string.
1575
+	 * If $replace is TRUE, we will insert the decrypted element(s) into the
1576
+	 * document, and return the decrypted element(s).
1577
+	 *
1578
+	 * @params XMLSecurityKey $objKey  The decryption key that should be used when decrypting the node.
1579
+	 * @params boolean $replace  Whether we should replace the encrypted node in the XML document with the decrypted data. The default is TRUE.
1580
+	 * @return string|DOMElement  The decrypted data.
1581
+	 */
1582
+	public function decryptNode($objKey, $replace=TRUE) {
1583
+		if (!$objKey instanceof XMLSecurityKey) {
1584
+			throw new Exception('Invalid Key');
1585
+		}
1586
+
1587
+		$encryptedData = $this->getCipherValue();
1588
+		if ($encryptedData) {
1589
+			$decrypted = $objKey->decryptData($encryptedData);
1590
+			if ($replace) {
1591
+				switch ($this->type) {
1592
+					case (XMLSecEnc::Element):
1593
+						$newdoc = new DOMDocument();
1594
+						$newdoc->loadXML($decrypted);
1595
+						if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
1596
+							return $newdoc;
1597
+						}
1598
+						$importEnc = $this->rawNode->ownerDocument->importNode($newdoc->documentElement, TRUE);
1599
+						$this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
1600
+						return $importEnc;
1601
+						break;
1602
+					case (XMLSecEnc::Content):
1603
+						if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
1604
+							$doc = $this->rawNode;
1605
+						} else {
1606
+							$doc = $this->rawNode->ownerDocument;
1607
+						}
1608
+						$newFrag = $doc->createDocumentFragment();
1609
+						$newFrag->appendXML($decrypted);
1610
+						$parent = $this->rawNode->parentNode;
1611
+						$parent->replaceChild($newFrag, $this->rawNode);
1612
+						return $parent;
1613
+						break;
1614
+					default:
1615
+						return $decrypted;
1616
+				}
1617
+			} else {
1618
+				return $decrypted;
1619
+			}
1620
+		} else {
1621
+			throw new Exception("Cannot locate encrypted data");
1622
+		}
1623
+	}
1624
+
1625
+	public function encryptKey($srcKey, $rawKey, $append=TRUE) {
1626
+		if ((!$srcKey instanceof XMLSecurityKey) || (!$rawKey instanceof XMLSecurityKey)) {
1627
+			throw new Exception('Invalid Key');
1628
+		}
1629
+		$strEncKey = base64_encode($srcKey->encryptData($rawKey->key));
1630
+		$root = $this->encdoc->documentElement;
1631
+		$encKey = $this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptedKey');
1632
+		if ($append) {
1633
+			$keyInfo = $root->insertBefore($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'), $root->firstChild);
1634
+			$keyInfo->appendChild($encKey);
1635
+		} else {
1636
+			$this->encKey = $encKey;
1637
+		}
1638
+		$encMethod = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
1639
+		$encMethod->setAttribute('Algorithm', $srcKey->getAlgorith());
1640
+		if (!empty($srcKey->name)) {
1641
+			$keyInfo = $encKey->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'));
1642
+			$keyInfo->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyName', $srcKey->name));
1643
+		}
1644
+		$cipherData = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherData'));
1645
+		$cipherData->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherValue', $strEncKey));
1646
+		if (is_array($this->references) && count($this->references) > 0) {
1647
+			$refList = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:ReferenceList'));
1648
+			foreach ($this->references AS $name => $reference) {
1649
+				$refuri = $reference["refuri"];
1650
+				$dataRef = $refList->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:DataReference'));
1651
+				$dataRef->setAttribute("URI", '#' . $refuri);
1652
+			}
1653
+		}
1654
+		return;
1655
+	}
1656
+
1657
+	public function decryptKey($encKey) {
1658
+		if (!$encKey->isEncrypted) {
1659
+			throw new Exception("Key is not Encrypted");
1660
+		}
1661
+		if (empty($encKey->key)) {
1662
+			throw new Exception("Key is missing data to perform the decryption");
1663
+		}
1664
+		return $this->decryptNode($encKey, FALSE);
1665
+	}
1666
+
1667
+	public function locateEncryptedData($element) {
1668
+		if ($element instanceof DOMDocument) {
1669
+			$doc = $element;
1670
+		} else {
1671
+			$doc = $element->ownerDocument;
1672
+		}
1673
+		if ($doc) {
1674
+			$xpath = new DOMXPath($doc);
1675
+			$query = "//*[local-name()='EncryptedData' and namespace-uri()='" . XMLSecEnc::XMLENCNS . "']";
1676
+			$nodeset = $xpath->query($query);
1677
+			return $nodeset->item(0);
1678
+		}
1679
+		return NULL;
1680
+	}
1681
+
1682
+	public function locateKey($node=NULL) {
1683
+		if (empty($node)) {
1684
+			$node = $this->rawNode;
1685
+		}
1686
+		if (!$node instanceof DOMNode) {
1687
+			return NULL;
1688
+		}
1689
+		if ($doc = $node->ownerDocument) {
1690
+			$xpath = new DOMXPath($doc);
1691
+			$xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
1692
+			$query = ".//xmlsecenc:EncryptionMethod";
1693
+			$nodeset = $xpath->query($query, $node);
1694
+			if ($encmeth = $nodeset->item(0)) {
1695
+				$attrAlgorithm = $encmeth->getAttribute("Algorithm");
1696
+				try {
1697
+					$objKey = new XMLSecurityKey($attrAlgorithm, array('type' => 'private'));
1698
+				} catch (Exception $e) {
1699
+					return NULL;
1700
+				}
1701
+				return $objKey;
1702
+			}
1703
+		}
1704
+		return NULL;
1705
+	}
1706
+
1707
+	static function staticLocateKeyInfo($objBaseKey=NULL, $node=NULL) {
1708
+		if (empty($node) || (!$node instanceof DOMNode)) {
1709
+			return NULL;
1710
+		}
1711
+		$doc = $node->ownerDocument;
1712
+		if (!$doc) {
1713
+			return NULL;
1714
+		}
1715
+
1716
+		$xpath = new DOMXPath($doc);
1717
+		$xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
1718
+		$xpath->registerNamespace('xmlsecdsig', XMLSecurityDSig::XMLDSIGNS);
1719
+		$query = "./xmlsecdsig:KeyInfo";
1720
+		$nodeset = $xpath->query($query, $node);
1721
+		$encmeth = $nodeset->item(0);
1722
+		if (!$encmeth) {
1723
+			/* No KeyInfo in EncryptedData / EncryptedKey. */
1724
+			return $objBaseKey;
1725
+		}
1726
+
1727
+		foreach ($encmeth->childNodes AS $child) {
1728
+			switch ($child->localName) {
1729
+				case 'KeyName':
1730
+					if (!empty($objBaseKey)) {
1731
+						$objBaseKey->name = $child->nodeValue;
1732
+					}
1733
+					break;
1734
+				case 'KeyValue':
1735
+					foreach ($child->childNodes AS $keyval) {
1736
+						switch ($keyval->localName) {
1737
+							case 'DSAKeyValue':
1738
+								throw new Exception("DSAKeyValue currently not supported");
1739
+								break;
1740
+							case 'RSAKeyValue':
1741
+								$modulus = NULL;
1742
+								$exponent = NULL;
1743
+								if ($modulusNode = $keyval->getElementsByTagName('Modulus')->item(0)) {
1744
+									$modulus = base64_decode($modulusNode->nodeValue);
1745
+								}
1746
+								if ($exponentNode = $keyval->getElementsByTagName('Exponent')->item(0)) {
1747
+									$exponent = base64_decode($exponentNode->nodeValue);
1748
+								}
1749
+								if (empty($modulus) || empty($exponent)) {
1750
+									throw new Exception("Missing Modulus or Exponent");
1751
+								}
1752
+								$publicKey = XMLSecurityKey::convertRSA($modulus, $exponent);
1753
+								$objBaseKey->loadKey($publicKey);
1754
+								break;
1755
+						}
1756
+					}
1757
+					break;
1758
+				case 'RetrievalMethod':
1759
+					$type = $child->getAttribute('Type');
1760
+					if ($type !== 'http://www.w3.org/2001/04/xmlenc#EncryptedKey') {
1761
+						/* Unsupported key type. */
1762
+						break;
1763
+					}
1764
+					$uri = $child->getAttribute('URI');
1765
+					if ($uri[0] !== '#') {
1766
+						/* URI not a reference - unsupported. */
1767
+						break;
1768
+					}
1769
+					$id = substr($uri, 1);
1770
+
1771
+					$query = "//xmlsecenc:EncryptedKey[@Id='$id']";
1772
+					$keyElement = $xpath->query($query)->item(0);
1773
+					if (!$keyElement) {
1774
+						throw new Exception("Unable to locate EncryptedKey with @Id='$id'.");
1775
+					}
1776
+
1777
+					return XMLSecurityKey::fromEncryptedKeyElement($keyElement);
1778
+				case 'EncryptedKey':
1779
+					return XMLSecurityKey::fromEncryptedKeyElement($child);
1780
+				case 'X509Data':
1781
+					if ($x509certNodes = $child->getElementsByTagName('X509Certificate')) {
1782
+						if ($x509certNodes->length > 0) {
1783
+							$x509cert = $x509certNodes->item(0)->textContent;
1784
+							$x509cert = str_replace(array("\r", "\n"), "", $x509cert);
1785
+							$x509cert = "-----BEGIN CERTIFICATE-----\n" . chunk_split($x509cert, 64, "\n") . "-----END CERTIFICATE-----\n";
1786
+							$objBaseKey->loadKey($x509cert, FALSE, TRUE);
1787
+						}
1788
+					}
1789
+					break;
1790
+			}
1791
+		}
1792
+		return $objBaseKey;
1793
+	}
1794
+
1795
+	public function locateKeyInfo($objBaseKey=NULL, $node=NULL) {
1796
+		if (empty($node)) {
1797
+			$node = $this->rawNode;
1798
+		}
1799
+		return XMLSecEnc::staticLocateKeyInfo($objBaseKey, $node);
1800
+	}
1801 1801
 
1802 1802
 
1803 1803
 }
Please login to merge, or discard this patch.