37
37
* @author Robert Richards <[email protected] >
38
38
* @copyright 2007-2019 Robert Richards <[email protected] >
39
39
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
40
- * @version 3.0.4 modified
40
+ * @version 3.1.2 modified
41
41
*/
42
42
43
43
class XMLSecurityKey {
@@ -198,21 +198,21 @@ public function getSymmetricKeySize() {
198
198
}
199
199
return $ this ->cryptParams ['keysize ' ];
200
200
}
201
-
201
+
202
202
public function generateSessionKey () {
203
203
if (!isset ($ this ->cryptParams ['keysize ' ])) {
204
204
throw new Exception ('Unknown key size for type " ' . $ this ->type . '". ' );
205
205
}
206
206
$ keysize = $ this ->cryptParams ['keysize ' ];
207
-
207
+
208
208
if (function_exists ('openssl_random_pseudo_bytes ' )) {
209
209
/* We have PHP >= 5.3 - use openssl to generate session key. */
210
210
$ key = openssl_random_pseudo_bytes ($ keysize );
211
211
} else {
212
212
/* Generating random key using iv generation routines */
213
213
$ key = mcrypt_create_iv ($ keysize , MCRYPT_RAND );
214
214
}
215
-
215
+
216
216
if ($ this ->type === XMLSecurityKey::TRIPLEDES_CBC ) {
217
217
/* Make sure that the generated key has the proper parity bits set.
218
218
* Mcrypt doesn't care about the parity bits, but others may care.
@@ -227,7 +227,7 @@ public function generateSessionKey() {
227
227
$ key [$ i ] = chr ($ byte );
228
228
}
229
229
}
230
-
230
+
231
231
$ this ->key = $ key ;
232
232
return $ key ;
233
233
}
@@ -281,6 +281,10 @@ public function loadKey($key, $isFile=false, $isCert = false) {
281
281
$ this ->key = openssl_get_publickey ($ this ->key );
282
282
} else {
283
283
$ this ->key = openssl_get_privatekey ($ this ->key , $ this ->passphrase );
284
+
285
+ if ($ this ->key === false ) {
286
+ throw new Exception ('Unable to extract private key (invalid key or passphrase): ' . openssl_error_string ());
287
+ }
284
288
}
285
289
} else if (isset ($ this ->cryptParams ['cipher ' ]) && $ this ->cryptParams ['cipher ' ] == MCRYPT_RIJNDAEL_128 ) {
286
290
/* Check key length */
@@ -469,7 +473,7 @@ static function convertRSA($modulus, $exponent) {
469
473
public function serializeKey ($ parent ) {
470
474
471
475
}
472
-
476
+
473
477
474
478
475
479
/**
@@ -557,7 +561,7 @@ public function __construct() {
557
561
private function resetXPathObj () {
558
562
$ this ->xPathCtx = null ;
559
563
}
560
-
564
+
561
565
private function getXPathObj () {
562
566
if (empty ($ this ->xPathCtx ) && ! empty ($ this ->sigNode )) {
563
567
$ xpath = new DOMXPath ($ this ->sigNode ->ownerDocument );
@@ -654,7 +658,7 @@ private function canonicalizeData($node, $canonicalmethod, $arXPath=null, $prefi
654
658
$ withComments = true ;
655
659
break ;
656
660
}
657
-
661
+
658
662
if (is_null ($ arXPath ) && ($ node instanceof DOMNode) && ($ node ->ownerDocument !== null ) && $ node ->isSameNode ($ node ->ownerDocument ->documentElement )) {
659
663
/* Check for any PI or comments as they would have been excluded */
660
664
$ element = $ node ;
@@ -668,7 +672,7 @@ private function canonicalizeData($node, $canonicalmethod, $arXPath=null, $prefi
668
672
$ node = $ node ->ownerDocument ;
669
673
}
670
674
}
671
-
675
+
672
676
return $ node ->C14N ($ exclusive , $ withComments , $ arXPath , $ prefixList );
673
677
}
674
678
@@ -686,10 +690,22 @@ public function canonicalizeSignedInfo() {
686
690
if ($ signInfoNode = $ nodeset ->item (0 )) {
687
691
$ query = "./secdsig:CanonicalizationMethod " ;
688
692
$ nodeset = $ xpath ->query ($ query , $ signInfoNode );
693
+ $ prefixList = null ;
689
694
if ($ canonNode = $ nodeset ->item (0 )) {
690
695
$ canonicalmethod = $ canonNode ->getAttribute ('Algorithm ' );
696
+ foreach ($ canonNode ->childNodes as $ node )
697
+ {
698
+ if ($ node ->localName == 'InclusiveNamespaces ' ) {
699
+ if ($ pfx = $ node ->getAttribute ('PrefixList ' )) {
700
+ $ arpfx = array_filter (explode (' ' , $ pfx ));
701
+ if (count ($ arpfx ) > 0 ) {
702
+ $ prefixList = array_merge ($ prefixList ? $ prefixList : array (), $ arpfx );
703
+ }
704
+ }
705
+ }
706
+ }
691
707
}
692
- $ this ->signedInfo = $ this ->canonicalizeData ($ signInfoNode , $ canonicalmethod );
708
+ $ this ->signedInfo = $ this ->canonicalizeData ($ signInfoNode , $ canonicalmethod, null , $ prefixList );
693
709
return $ this ->signedInfo ;
694
710
}
695
711
}
@@ -918,10 +934,10 @@ public function validateReference() {
918
934
if ($ nodeset ->length == 0 ) {
919
935
throw new Exception ("Reference nodes not found " );
920
936
}
921
-
937
+
922
938
/* Initialize/reset the list of validated nodes. */
923
939
$ this ->validatedNodes = array ();
924
-
940
+
925
941
foreach ($ nodeset AS $ refNode ) {
926
942
if (! $ this ->processRefNode ($ refNode )) {
927
943
/* Clear the list of validated nodes. */
@@ -976,8 +992,8 @@ private function addRefInternal($sinfoNode, $node, $algorithm, $arTransforms=nul
976
992
foreach ($ arTransforms AS $ transform ) {
977
993
$ transNode = $ this ->createNewSignNode ('Transform ' );
978
994
$ transNodes ->appendChild ($ transNode );
979
- if (is_array ($ transform ) &&
980
- (! empty ($ transform ['http://www.w3.org/TR/1999/REC-xpath-19991116 ' ])) &&
995
+ if (is_array ($ transform ) &&
996
+ (! empty ($ transform ['http://www.w3.org/TR/1999/REC-xpath-19991116 ' ])) &&
981
997
(! empty ($ transform ['http://www.w3.org/TR/1999/REC-xpath-19991116 ' ]['query ' ]))) {
982
998
$ transNode ->setAttribute ('Algorithm ' , 'http://www.w3.org/TR/1999/REC-xpath-19991116 ' );
983
999
$ XPathNode = $ this ->createNewSignNode ('XPath ' , $ transform ['http://www.w3.org/TR/1999/REC-xpath-19991116 ' ]['query ' ]);
@@ -1134,7 +1150,7 @@ public function appendKey($objKey, $parent=null) {
1134
1150
*
1135
1151
* @param $node The node the signature element should be inserted into.
1136
1152
* @param $beforeNode The node the signature element should be located before.
1137
- *
1153
+ *
1138
1154
* @return DOMNode The signature element node
1139
1155
*/
1140
1156
public function insertSignature ($ node , $ beforeNode = null ) {
@@ -1196,9 +1212,9 @@ static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=true, $isURL=fa
1196
1212
if (! $ parentRef instanceof DOMElement) {
1197
1213
throw new Exception ('Invalid parent Node parameter ' );
1198
1214
}
1199
-
1215
+
1200
1216
list ($ parentRef , $ keyInfo ) = self ::auxKeyInfo ($ parentRef , $ xpath );
1201
-
1217
+
1202
1218
// Add all certs if there are more than one
1203
1219
$ certs = XMLSecurityDSig::staticGet509XCerts ($ cert , $ isPEMFormat );
1204
1220
@@ -1217,7 +1233,7 @@ static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=true, $isURL=fa
1217
1233
$ subjectName = true ;
1218
1234
}
1219
1235
}
1220
-
1236
+
1221
1237
// Attach all certificate nodes and any additional data
1222
1238
foreach ($ certs as $ X509Cert ){
1223
1239
if ($ issuerSerial || $ subjectName ) {
@@ -1236,7 +1252,7 @@ static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=true, $isURL=fa
1236
1252
}
1237
1253
$ subjectNameValue = implode (', ' , $ parts );
1238
1254
} else {
1239
- $ subjectNameValue = $ certData ['issuer ' ];
1255
+ $ subjectNameValue = $ certData ['subject ' ];
1240
1256
}
1241
1257
$ x509SubjectNode = $ baseDoc ->createElementNS (XMLSecurityDSig::XMLDSIGNS , 'ds:X509SubjectName ' , $ subjectNameValue );
1242
1258
$ x509DataNode ->appendChild ($ x509SubjectNode );
@@ -1251,17 +1267,17 @@ static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=true, $isURL=fa
1251
1267
} else {
1252
1268
$ issuerName = $ certData ['issuer ' ];
1253
1269
}
1254
-
1270
+
1255
1271
$ x509IssuerNode = $ baseDoc ->createElementNS (XMLSecurityDSig::XMLDSIGNS , 'ds:X509IssuerSerial ' );
1256
1272
$ x509DataNode ->appendChild ($ x509IssuerNode );
1257
-
1273
+
1258
1274
$ x509Node = $ baseDoc ->createElementNS (XMLSecurityDSig::XMLDSIGNS , 'ds:X509IssuerName ' , $ issuerName );
1259
1275
$ x509IssuerNode ->appendChild ($ x509Node );
1260
1276
$ x509Node = $ baseDoc ->createElementNS (XMLSecurityDSig::XMLDSIGNS , 'ds:X509SerialNumber ' , $ certData ['serialNumber ' ]);
1261
1277
$ x509IssuerNode ->appendChild ($ x509Node );
1262
1278
}
1263
1279
}
1264
-
1280
+
1265
1281
}
1266
1282
$ x509CertNode = $ baseDoc ->createElementNS (XMLSecurityDSig::XMLDSIGNS , 'ds:X509Certificate ' , $ X509Cert );
1267
1283
$ x509DataNode ->appendChild ($ x509CertNode );
@@ -1273,14 +1289,14 @@ public function add509Cert($cert, $isPEMFormat=true, $isURL=false, $options=null
1273
1289
self ::staticAdd509Cert ($ this ->sigNode , $ cert , $ isPEMFormat , $ isURL , $ xpath , $ options );
1274
1290
}
1275
1291
}
1276
-
1292
+
1277
1293
/**
1278
1294
* This function appends a node to the KeyInfo.
1279
1295
*
1280
1296
* The KeyInfo element will be created if one does not exist in the document.
1281
1297
*
1282
1298
* @param DOMNode $node The node to append to the KeyInfo.
1283
- *
1299
+ *
1284
1300
* @return DOMNode The KeyInfo element node
1285
1301
*/
1286
1302
public function appendToKeyInfo ($ node ) {
@@ -1289,20 +1305,20 @@ public function appendToKeyInfo($node) {
1289
1305
$ xpath = $ this ->getXPathObj ();
1290
1306
1291
1307
list ($ parentRef , $ keyInfo ) = self ::auxKeyInfo ($ parentRef , $ xpath );
1292
-
1308
+
1293
1309
$ keyInfo ->appendChild ($ node );
1294
-
1310
+
1295
1311
return $ keyInfo ;
1296
1312
}
1297
-
1313
+
1298
1314
static function auxKeyInfo ($ parentRef , $ xpath =null )
1299
1315
{
1300
1316
$ baseDoc = $ parentRef ->ownerDocument ;
1301
1317
if (empty ($ xpath )) {
1302
1318
$ xpath = new DOMXPath ($ parentRef ->ownerDocument );
1303
1319
$ xpath ->registerNamespace ('secdsig ' , XMLSecurityDSig::XMLDSIGNS );
1304
1320
}
1305
-
1321
+
1306
1322
$ query = "./secdsig:KeyInfo " ;
1307
1323
$ nodeset = $ xpath ->query ($ query , $ parentRef );
1308
1324
$ keyInfo = $ nodeset ->item (0 );
@@ -1507,7 +1523,7 @@ public function getCipherValue() {
1507
1523
* @params XMLSecurityKey $objKey The decryption key that should be used when decrypting the node.
1508
1524
* @params boolean $replace Whether we should replace the encrypted node in the XML document with the decrypted data. The default is true.
1509
1525
* @return string|DOMElement The decrypted data.
1510
- */
1526
+ */
1511
1527
public function decryptNode ($ objKey , $ replace =true ) {
1512
1528
if (! $ objKey instanceof XMLSecurityKey) {
1513
1529
throw new Exception ('Invalid Key ' );
@@ -1707,7 +1723,7 @@ static function staticLocateKeyInfo($objBaseKey=null, $node=null) {
1707
1723
if ($ x509certNodes = $ child ->getElementsByTagName ('X509Certificate ' )) {
1708
1724
if ($ x509certNodes ->length > 0 ) {
1709
1725
$ x509cert = $ x509certNodes ->item (0 )->textContent ;
1710
- $ x509cert = str_replace (array ("\r" , "\n" , " " ), "" , $ x509cert );
1726
+ $ x509cert = str_replace (array ("\r" , "\n" , " " , "\t" ), "" , $ x509cert );
1711
1727
$ x509cert = "-----BEGIN CERTIFICATE----- \n" .chunk_split ($ x509cert , 64 , "\n" )."-----END CERTIFICATE----- \n" ;
1712
1728
$ objBaseKey ->loadKey ($ x509cert , false , true );
1713
1729
}
0 commit comments