@@ -357,35 +357,63 @@ SignedXml.prototype.checkSignature = function(xml) {
357
357
return true
358
358
}
359
359
360
- SignedXml . prototype . validateSignatureValue = function ( doc ) {
360
+ SignedXml . prototype . getCanonSignedInfoXml = function ( doc ) {
361
361
var signedInfo = utils . findChilds ( this . signatureNode , "SignedInfo" )
362
362
if ( signedInfo . length == 0 ) throw new Error ( "could not find SignedInfo element in the message" )
363
363
364
364
if ( this . canonicalizationAlgorithm === "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
365
365
|| this . canonicalizationAlgorithm === "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" )
366
366
{
367
367
if ( ! doc || typeof ( doc ) !== "object" ) {
368
- throw new Error ( "When canonicalization method is non-exclusive, whole xml dom must be provided as an argument" ) ;
368
+ throw new Error (
369
+ "When canonicalization method is non-exclusive, whole xml dom must be provided as an argument"
370
+ ) ;
369
371
}
370
372
}
371
373
372
374
/**
373
- * Search for ancestor namespaces before validating signature .
375
+ * Search for ancestor namespaces before canonicalization .
374
376
*/
375
377
var ancestorNamespaces = [ ] ;
376
378
ancestorNamespaces = findAncestorNs ( doc , "//*[local-name()='SignedInfo']" ) ;
377
379
378
380
var c14nOptions = {
379
381
ancestorNamespaces : ancestorNamespaces
380
382
} ;
381
- var signedInfoCanon = this . getCanonXml ( [ this . canonicalizationAlgorithm ] , signedInfo [ 0 ] , c14nOptions )
383
+ return this . getCanonXml ( [ this . canonicalizationAlgorithm ] , signedInfo [ 0 ] , c14nOptions )
384
+ }
385
+
386
+ SignedXml . prototype . getCanonReferenceXml = function ( doc , ref , node ) {
387
+ /**
388
+ * Search for ancestor namespaces before canonicalization.
389
+ */
390
+ if ( Array . isArray ( ref . transforms ) ) {
391
+ ref . ancestorNamespaces = findAncestorNs ( doc , ref . xpath )
392
+ }
393
+
394
+ var c14nOptions = {
395
+ inclusiveNamespacesPrefixList : ref . inclusiveNamespacesPrefixList ,
396
+ ancestorNamespaces : ref . ancestorNamespaces
397
+ }
398
+
399
+ return this . getCanonXml ( ref . transforms , node , c14nOptions )
400
+ }
401
+
402
+ SignedXml . prototype . validateSignatureValue = function ( doc ) {
403
+ var signedInfoCanon = this . getCanonSignedInfoXml ( doc )
382
404
var signer = this . findSignatureAlgorithm ( this . signatureAlgorithm )
383
405
var res = signer . verifySignature ( signedInfoCanon , this . signingKey , this . signatureValue )
384
406
if ( ! res ) this . validationErrors . push ( "invalid signature: the signature value " +
385
407
this . signatureValue + " is incorrect" )
386
408
return res
387
409
}
388
410
411
+ SignedXml . prototype . calculateSignatureValue = function ( doc ) {
412
+ var signedInfoCanon = this . getCanonSignedInfoXml ( doc )
413
+ var signer = this . findSignatureAlgorithm ( this . signatureAlgorithm )
414
+ this . signatureValue = signer . getSignature ( signedInfoCanon , this . signingKey )
415
+ }
416
+
389
417
SignedXml . prototype . findSignatureAlgorithm = function ( name ) {
390
418
var algo = SignedXml . SignatureAlgorithms [ name ]
391
419
if ( algo ) return new algo ( )
@@ -413,7 +441,6 @@ SignedXml.prototype.validateReferences = function(doc) {
413
441
414
442
var uri = ref . uri [ 0 ] == "#" ? ref . uri . substring ( 1 ) : ref . uri
415
443
var elem = [ ] ;
416
- var elemXpath ;
417
444
418
445
if ( uri == "" ) {
419
446
elem = xpath . select ( "//*" , doc )
@@ -423,6 +450,7 @@ SignedXml.prototype.validateReferences = function(doc) {
423
450
throw new Error ( "Cannot validate a uri with quotes inside it" ) ;
424
451
}
425
452
else {
453
+ var elemXpath ;
426
454
var num_elements_for_id = 0 ;
427
455
for ( var index in this . idAttributes ) {
428
456
if ( ! this . idAttributes . hasOwnProperty ( index ) ) continue ;
@@ -439,6 +467,8 @@ SignedXml.prototype.validateReferences = function(doc) {
439
467
'same value for the ID / Id / Id attributes, in order to prevent ' +
440
468
'signature wrapping attack.' ) ;
441
469
}
470
+
471
+ ref . xpath = elemXpath ;
442
472
}
443
473
444
474
if ( elem . length == 0 ) {
@@ -447,19 +477,7 @@ SignedXml.prototype.validateReferences = function(doc) {
447
477
return false
448
478
}
449
479
450
- /**
451
- * Search for ancestor namespaces before validating references.
452
- */
453
- if ( Array . isArray ( ref . transforms ) ) {
454
- ref . ancestorNamespaces = findAncestorNs ( doc , elemXpath ) ;
455
- }
456
-
457
- var c14nOptions = {
458
- inclusiveNamespacesPrefixList : ref . inclusiveNamespacesPrefixList ,
459
- ancestorNamespaces : ref . ancestorNamespaces
460
- } ;
461
-
462
- var canonXml = this . getCanonXml ( ref . transforms , elem [ 0 ] , c14nOptions ) ;
480
+ var canonXml = this . getCanonReferenceXml ( doc , ref , elem [ 0 ] )
463
481
464
482
var hash = this . findHashAlgorithm ( ref . digestAlgorithm )
465
483
var digest = hash . getHash ( canonXml )
@@ -679,13 +697,11 @@ SignedXml.prototype.computeSignature = function(xml, opts) {
679
697
// add the xml namespace attribute
680
698
signatureAttrs . push ( xmlNsAttr + "=\"http://www.w3.org/2000/09/xmldsig#\"" ) ;
681
699
682
- this . signatureXml = "<" + currentPrefix + "Signature " + signatureAttrs . join ( " " ) + ">"
700
+ var signatureXml = "<" + currentPrefix + "Signature " + signatureAttrs . join ( " " ) + ">"
683
701
684
- var signedInfo = this . createSignedInfo ( doc , prefix ) ;
685
- this . signatureXml += signedInfo ;
686
- this . signatureXml += this . createSignature ( signedInfo , prefix ) ;
687
- this . signatureXml += this . getKeyInfo ( prefix )
688
- this . signatureXml += "</" + currentPrefix + "Signature>"
702
+ signatureXml += this . createSignedInfo ( doc , prefix ) ;
703
+ signatureXml += this . getKeyInfo ( prefix )
704
+ signatureXml += "</" + currentPrefix + "Signature>"
689
705
690
706
this . originalXmlWithIds = doc . toString ( )
691
707
@@ -696,7 +712,7 @@ SignedXml.prototype.computeSignature = function(xml, opts) {
696
712
697
713
// A trick to remove the namespaces that already exist in the xml
698
714
// This only works if the prefix and namespace match with those in te xml
699
- var dummySignatureWrapper = "<Dummy " + existingPrefixesString + ">" + this . signatureXml + "</Dummy>"
715
+ var dummySignatureWrapper = "<Dummy " + existingPrefixesString + ">" + signatureXml + "</Dummy>"
700
716
var xml = new Dom ( ) . parseFromString ( dummySignatureWrapper )
701
717
var signatureDoc = xml . documentElement . firstChild ;
702
718
@@ -718,6 +734,16 @@ SignedXml.prototype.computeSignature = function(xml, opts) {
718
734
referenceNode . parentNode . insertBefore ( signatureDoc , referenceNode . nextSibling ) ;
719
735
}
720
736
737
+ this . signatureNode = signatureDoc
738
+ this . calculateSignatureValue ( doc )
739
+
740
+ var signedInfoNode = utils . findChilds ( this . signatureNode , "SignedInfo" )
741
+ if ( signedInfoNode . length == 0 ) throw new Error ( "could not find SignedInfo element in the message" )
742
+
743
+ signedInfoNode = signedInfoNode [ 0 ] ;
744
+ signatureDoc . insertBefore ( this . createSignature ( prefix ) , signedInfoNode . nextSibling )
745
+
746
+ this . signatureXml = signatureDoc . toString ( )
721
747
this . signedXml = doc . toString ( )
722
748
}
723
749
@@ -778,7 +804,7 @@ SignedXml.prototype.createReferences = function(doc, prefix) {
778
804
res += "<" + prefix + "Transform Algorithm=\"" + transform . getAlgorithmName ( ) + "\" />"
779
805
}
780
806
781
- var canonXml = this . getCanonXml ( ref . transforms , node )
807
+ var canonXml = this . getCanonReferenceXml ( doc , ref , node )
782
808
783
809
var digestAlgorithm = this . findHashAlgorithm ( ref . digestAlgorithm )
784
810
res += "</" + prefix + "Transforms>" +
@@ -880,7 +906,7 @@ SignedXml.prototype.createSignedInfo = function(doc, prefix) {
880
906
* Create the Signature element
881
907
*
882
908
*/
883
- SignedXml . prototype . createSignature = function ( signedInfo , prefix ) {
909
+ SignedXml . prototype . createSignature = function ( prefix ) {
884
910
var xmlNsAttr = 'xmlns'
885
911
886
912
if ( prefix ) {
@@ -890,20 +916,15 @@ SignedXml.prototype.createSignature = function(signedInfo, prefix) {
890
916
prefix = '' ;
891
917
}
892
918
919
+ var signatureValueXml = "<" + prefix + "SignatureValue>" + this . signatureValue + "</" + prefix + "SignatureValue>"
893
920
//the canonicalization requires to get a valid xml node.
894
921
//we need to wrap the info in a dummy signature since it contains the default namespace.
895
922
var dummySignatureWrapper = "<" + prefix + "Signature " + xmlNsAttr + "=\"http://www.w3.org/2000/09/xmldsig#\">" +
896
- signedInfo +
897
- "</" + prefix + "Signature>"
923
+ signatureValueXml +
924
+ "</" + prefix + "Signature>"
898
925
899
- var xml = new Dom ( ) . parseFromString ( dummySignatureWrapper )
900
- //get the signedInfo
901
- var node = xml . documentElement . firstChild ;
902
- var canAlgorithm = new this . findCanonicalizationAlgorithm ( this . canonicalizationAlgorithm )
903
- var canonizedSignedInfo = canAlgorithm . process ( node )
904
- var signatureAlgorithm = this . findSignatureAlgorithm ( this . signatureAlgorithm )
905
- this . signatureValue = signatureAlgorithm . getSignature ( canonizedSignedInfo , this . signingKey )
906
- return "<" + prefix + "SignatureValue>" + this . signatureValue + "</" + prefix + "SignatureValue>"
926
+ var doc = new Dom ( ) . parseFromString ( dummySignatureWrapper )
927
+ return doc . documentElement . firstChild ;
907
928
}
908
929
909
930
@@ -917,4 +938,4 @@ SignedXml.prototype.getOriginalXmlWithIds = function() {
917
938
918
939
SignedXml . prototype . getSignedXml = function ( ) {
919
940
return this . signedXml
920
- }
941
+ }
0 commit comments