3737 * @author Robert Richards <rrichards@cdatazone.org>
3838 * @copyright 2007-2019 Robert Richards <rrichards@cdatazone.org>
3939 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
40- * @version 3.0.4 modified
40+ * @version 3.1.2 modified
4141 */
4242
4343class XMLSecurityKey {
@@ -198,21 +198,21 @@ public function getSymmetricKeySize() {
198198 }
199199 return $ this ->cryptParams ['keysize ' ];
200200 }
201-
201+
202202 public function generateSessionKey () {
203203 if (!isset ($ this ->cryptParams ['keysize ' ])) {
204204 throw new Exception ('Unknown key size for type " ' . $ this ->type . '". ' );
205205 }
206206 $ keysize = $ this ->cryptParams ['keysize ' ];
207-
207+
208208 if (function_exists ('openssl_random_pseudo_bytes ' )) {
209209 /* We have PHP >= 5.3 - use openssl to generate session key. */
210210 $ key = openssl_random_pseudo_bytes ($ keysize );
211211 } else {
212212 /* Generating random key using iv generation routines */
213213 $ key = mcrypt_create_iv ($ keysize , MCRYPT_RAND );
214214 }
215-
215+
216216 if ($ this ->type === XMLSecurityKey::TRIPLEDES_CBC ) {
217217 /* Make sure that the generated key has the proper parity bits set.
218218 * Mcrypt doesn't care about the parity bits, but others may care.
@@ -227,7 +227,7 @@ public function generateSessionKey() {
227227 $ key [$ i ] = chr ($ byte );
228228 }
229229 }
230-
230+
231231 $ this ->key = $ key ;
232232 return $ key ;
233233 }
@@ -281,6 +281,10 @@ public function loadKey($key, $isFile=false, $isCert = false) {
281281 $ this ->key = openssl_get_publickey ($ this ->key );
282282 } else {
283283 $ 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+ }
284288 }
285289 } else if (isset ($ this ->cryptParams ['cipher ' ]) && $ this ->cryptParams ['cipher ' ] == MCRYPT_RIJNDAEL_128 ) {
286290 /* Check key length */
@@ -469,7 +473,7 @@ static function convertRSA($modulus, $exponent) {
469473 public function serializeKey ($ parent ) {
470474
471475 }
472-
476+
473477
474478
475479 /**
@@ -557,7 +561,7 @@ public function __construct() {
557561 private function resetXPathObj () {
558562 $ this ->xPathCtx = null ;
559563 }
560-
564+
561565 private function getXPathObj () {
562566 if (empty ($ this ->xPathCtx ) && ! empty ($ this ->sigNode )) {
563567 $ xpath = new DOMXPath ($ this ->sigNode ->ownerDocument );
@@ -654,7 +658,7 @@ private function canonicalizeData($node, $canonicalmethod, $arXPath=null, $prefi
654658 $ withComments = true ;
655659 break ;
656660 }
657-
661+
658662 if (is_null ($ arXPath ) && ($ node instanceof DOMNode) && ($ node ->ownerDocument !== null ) && $ node ->isSameNode ($ node ->ownerDocument ->documentElement )) {
659663 /* Check for any PI or comments as they would have been excluded */
660664 $ element = $ node ;
@@ -668,7 +672,7 @@ private function canonicalizeData($node, $canonicalmethod, $arXPath=null, $prefi
668672 $ node = $ node ->ownerDocument ;
669673 }
670674 }
671-
675+
672676 return $ node ->C14N ($ exclusive , $ withComments , $ arXPath , $ prefixList );
673677 }
674678
@@ -686,10 +690,22 @@ public function canonicalizeSignedInfo() {
686690 if ($ signInfoNode = $ nodeset ->item (0 )) {
687691 $ query = "./secdsig:CanonicalizationMethod " ;
688692 $ nodeset = $ xpath ->query ($ query , $ signInfoNode );
693+ $ prefixList = null ;
689694 if ($ canonNode = $ nodeset ->item (0 )) {
690695 $ 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+ }
691707 }
692- $ this ->signedInfo = $ this ->canonicalizeData ($ signInfoNode , $ canonicalmethod );
708+ $ this ->signedInfo = $ this ->canonicalizeData ($ signInfoNode , $ canonicalmethod, null , $ prefixList );
693709 return $ this ->signedInfo ;
694710 }
695711 }
@@ -918,10 +934,10 @@ public function validateReference() {
918934 if ($ nodeset ->length == 0 ) {
919935 throw new Exception ("Reference nodes not found " );
920936 }
921-
937+
922938 /* Initialize/reset the list of validated nodes. */
923939 $ this ->validatedNodes = array ();
924-
940+
925941 foreach ($ nodeset AS $ refNode ) {
926942 if (! $ this ->processRefNode ($ refNode )) {
927943 /* Clear the list of validated nodes. */
@@ -976,8 +992,8 @@ private function addRefInternal($sinfoNode, $node, $algorithm, $arTransforms=nul
976992 foreach ($ arTransforms AS $ transform ) {
977993 $ transNode = $ this ->createNewSignNode ('Transform ' );
978994 $ 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 ' ])) &&
981997 (! empty ($ transform ['http://www.w3.org/TR/1999/REC-xpath-19991116 ' ]['query ' ]))) {
982998 $ transNode ->setAttribute ('Algorithm ' , 'http://www.w3.org/TR/1999/REC-xpath-19991116 ' );
983999 $ 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) {
11341150 *
11351151 * @param $node The node the signature element should be inserted into.
11361152 * @param $beforeNode The node the signature element should be located before.
1137- *
1153+ *
11381154 * @return DOMNode The signature element node
11391155 */
11401156 public function insertSignature ($ node , $ beforeNode = null ) {
@@ -1196,9 +1212,9 @@ static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=true, $isURL=fa
11961212 if (! $ parentRef instanceof DOMElement) {
11971213 throw new Exception ('Invalid parent Node parameter ' );
11981214 }
1199-
1215+
12001216 list ($ parentRef , $ keyInfo ) = self ::auxKeyInfo ($ parentRef , $ xpath );
1201-
1217+
12021218 // Add all certs if there are more than one
12031219 $ certs = XMLSecurityDSig::staticGet509XCerts ($ cert , $ isPEMFormat );
12041220
@@ -1217,7 +1233,7 @@ static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=true, $isURL=fa
12171233 $ subjectName = true ;
12181234 }
12191235 }
1220-
1236+
12211237 // Attach all certificate nodes and any additional data
12221238 foreach ($ certs as $ X509Cert ){
12231239 if ($ issuerSerial || $ subjectName ) {
@@ -1236,7 +1252,7 @@ static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=true, $isURL=fa
12361252 }
12371253 $ subjectNameValue = implode (', ' , $ parts );
12381254 } else {
1239- $ subjectNameValue = $ certData ['issuer ' ];
1255+ $ subjectNameValue = $ certData ['subject ' ];
12401256 }
12411257 $ x509SubjectNode = $ baseDoc ->createElementNS (XMLSecurityDSig::XMLDSIGNS , 'ds:X509SubjectName ' , $ subjectNameValue );
12421258 $ x509DataNode ->appendChild ($ x509SubjectNode );
@@ -1251,17 +1267,17 @@ static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=true, $isURL=fa
12511267 } else {
12521268 $ issuerName = $ certData ['issuer ' ];
12531269 }
1254-
1270+
12551271 $ x509IssuerNode = $ baseDoc ->createElementNS (XMLSecurityDSig::XMLDSIGNS , 'ds:X509IssuerSerial ' );
12561272 $ x509DataNode ->appendChild ($ x509IssuerNode );
1257-
1273+
12581274 $ x509Node = $ baseDoc ->createElementNS (XMLSecurityDSig::XMLDSIGNS , 'ds:X509IssuerName ' , $ issuerName );
12591275 $ x509IssuerNode ->appendChild ($ x509Node );
12601276 $ x509Node = $ baseDoc ->createElementNS (XMLSecurityDSig::XMLDSIGNS , 'ds:X509SerialNumber ' , $ certData ['serialNumber ' ]);
12611277 $ x509IssuerNode ->appendChild ($ x509Node );
12621278 }
12631279 }
1264-
1280+
12651281 }
12661282 $ x509CertNode = $ baseDoc ->createElementNS (XMLSecurityDSig::XMLDSIGNS , 'ds:X509Certificate ' , $ X509Cert );
12671283 $ x509DataNode ->appendChild ($ x509CertNode );
@@ -1273,14 +1289,14 @@ public function add509Cert($cert, $isPEMFormat=true, $isURL=false, $options=null
12731289 self ::staticAdd509Cert ($ this ->sigNode , $ cert , $ isPEMFormat , $ isURL , $ xpath , $ options );
12741290 }
12751291 }
1276-
1292+
12771293 /**
12781294 * This function appends a node to the KeyInfo.
12791295 *
12801296 * The KeyInfo element will be created if one does not exist in the document.
12811297 *
12821298 * @param DOMNode $node The node to append to the KeyInfo.
1283- *
1299+ *
12841300 * @return DOMNode The KeyInfo element node
12851301 */
12861302 public function appendToKeyInfo ($ node ) {
@@ -1289,20 +1305,20 @@ public function appendToKeyInfo($node) {
12891305 $ xpath = $ this ->getXPathObj ();
12901306
12911307 list ($ parentRef , $ keyInfo ) = self ::auxKeyInfo ($ parentRef , $ xpath );
1292-
1308+
12931309 $ keyInfo ->appendChild ($ node );
1294-
1310+
12951311 return $ keyInfo ;
12961312 }
1297-
1313+
12981314 static function auxKeyInfo ($ parentRef , $ xpath =null )
12991315 {
13001316 $ baseDoc = $ parentRef ->ownerDocument ;
13011317 if (empty ($ xpath )) {
13021318 $ xpath = new DOMXPath ($ parentRef ->ownerDocument );
13031319 $ xpath ->registerNamespace ('secdsig ' , XMLSecurityDSig::XMLDSIGNS );
13041320 }
1305-
1321+
13061322 $ query = "./secdsig:KeyInfo " ;
13071323 $ nodeset = $ xpath ->query ($ query , $ parentRef );
13081324 $ keyInfo = $ nodeset ->item (0 );
@@ -1507,7 +1523,7 @@ public function getCipherValue() {
15071523 * @params XMLSecurityKey $objKey The decryption key that should be used when decrypting the node.
15081524 * @params boolean $replace Whether we should replace the encrypted node in the XML document with the decrypted data. The default is true.
15091525 * @return string|DOMElement The decrypted data.
1510- */
1526+ */
15111527 public function decryptNode ($ objKey , $ replace =true ) {
15121528 if (! $ objKey instanceof XMLSecurityKey) {
15131529 throw new Exception ('Invalid Key ' );
@@ -1707,7 +1723,7 @@ static function staticLocateKeyInfo($objBaseKey=null, $node=null) {
17071723 if ($ x509certNodes = $ child ->getElementsByTagName ('X509Certificate ' )) {
17081724 if ($ x509certNodes ->length > 0 ) {
17091725 $ x509cert = $ x509certNodes ->item (0 )->textContent ;
1710- $ x509cert = str_replace (array ("\r" , "\n" , " " ), "" , $ x509cert );
1726+ $ x509cert = str_replace (array ("\r" , "\n" , " " , "\t" ), "" , $ x509cert );
17111727 $ x509cert = "-----BEGIN CERTIFICATE----- \n" .chunk_split ($ x509cert , 64 , "\n" )."-----END CERTIFICATE----- \n" ;
17121728 $ objBaseKey ->loadKey ($ x509cert , false , true );
17131729 }
0 commit comments