@@ -587,6 +587,7 @@ public function processTransforms($refNode, $objData, $includeCommentNodes = tru
587587 $ arXPath = null ;
588588 $ prefixList = null ;
589589 $ xpathTransformCount = 0 ;
590+ $ enveloped = false ;
590591 foreach ($ nodelist AS $ transform ) {
591592 $ algorithm = $ transform ->getAttribute ("Algorithm " );
592593 switch ($ algorithm ) {
@@ -637,29 +638,7 @@ public function processTransforms($refNode, $objData, $includeCommentNodes = tru
637638
638639 break ;
639640 case self ::ENVELOPED :
640- /*
641- * Enveloped-signature: remove the Signature from the nodeset.
642- * validateReference() strips sigNode from the document when any
643- * Reference declares this transform; when signing, the Signature
644- * is typically not yet attached. If it is still a proper descendant
645- * of the data node, detach it here so C14N matches verification.
646- */
647- if ($ data instanceof DOMNode) {
648- $ sig = $ this ->sigNode ;
649- if ($ sig instanceof DOMNode && $ sig ->parentNode !== null ) {
650- $ ancestor = $ data instanceof DOMDocument ? $ data ->documentElement : $ data ;
651- if ($ ancestor !== null && ! $ sig ->isSameNode ($ ancestor )) {
652- $ walk = $ sig ->parentNode ;
653- while ($ walk !== null ) {
654- if ($ walk ->isSameNode ($ ancestor )) {
655- $ sig ->parentNode ->removeChild ($ sig );
656- break ;
657- }
658- $ walk = $ walk ->parentNode ;
659- }
660- }
661- }
662- }
641+ $ enveloped = true ;
663642 break ;
664643 case 'http://www.w3.org/TR/1999/REC-xpath-19991116 ' :
665644 /*
@@ -709,7 +688,42 @@ public function processTransforms($refNode, $objData, $includeCommentNodes = tru
709688 }
710689 }
711690 if ($ data instanceof DOMNode) {
712- $ data = $ this ->canonicalizeData ($ objData , $ canonicalMethod , $ arXPath , $ prefixList );
691+ $ sig = null ;
692+ $ sigParent = null ;
693+ $ sigNextSibling = null ;
694+
695+ /*
696+ * Temporarily detach an enveloped Signature for canonicalization,
697+ * then restore it so validation does not mutate the caller's DOM.
698+ */
699+ if ($ enveloped ) {
700+ $ candidate = $ this ->sigNode ;
701+ $ ancestor = $ data instanceof DOMDocument ? $ data ->documentElement : $ data ;
702+ if ($ candidate instanceof DOMNode
703+ && $ candidate ->parentNode !== null
704+ && $ ancestor !== null
705+ && ! $ candidate ->isSameNode ($ ancestor )) {
706+ $ walk = $ candidate ->parentNode ;
707+ while ($ walk !== null ) {
708+ if ($ walk ->isSameNode ($ ancestor )) {
709+ $ sig = $ candidate ;
710+ $ sigParent = $ sig ->parentNode ;
711+ $ sigNextSibling = $ sig ->nextSibling ;
712+ $ sigParent ->removeChild ($ sig );
713+ break ;
714+ }
715+ $ walk = $ walk ->parentNode ;
716+ }
717+ }
718+ }
719+
720+ try {
721+ $ data = $ this ->canonicalizeData ($ objData , $ canonicalMethod , $ arXPath , $ prefixList );
722+ } finally {
723+ if ($ sig !== null && $ sig ->parentNode === null ) {
724+ $ sigParent ->insertBefore ($ sig , $ sigNextSibling );
725+ }
726+ }
713727 }
714728 return $ data ;
715729 }
0 commit comments