@@ -72,7 +72,7 @@ export class SignedXml {
7272 * Contains the references that were signed.
7373 * @see {@link Reference }
7474 */
75- private references : ( Reference & { wasProcessed : boolean } ) [ ] = [ ] ;
75+ private references : Reference [ ] = [ ] ;
7676
7777 /**
7878 * Contains the canonicalized XML of the references that were validly signed.
@@ -833,7 +833,6 @@ export class SignedXml {
833833 isEmptyUri,
834834 id,
835835 type,
836- wasProcessed : false ,
837836 getValidatedNode : ( ) => {
838837 throw new Error (
839838 "Reference has not been validated yet; Did you call `sig.checkSignature()`?" ,
@@ -1182,7 +1181,6 @@ export class SignedXml {
11821181 `<${ prefix } DigestValue>${ digestAlgorithm . getHash ( canonXml ) } </${ prefix } DigestValue>` +
11831182 `</${ prefix } Reference>` ;
11841183 }
1185- ref . wasProcessed = true ;
11861184 }
11871185
11881186 return res ;
@@ -1328,9 +1326,8 @@ export class SignedXml {
13281326 * This is called after the initial signature has been created to handle references to signature elements
13291327 */
13301328 private processSignatureReferences ( doc : Document , signatureElem : Element , prefix ?: string ) {
1331- // Get unprocessed references
1332- const unprocessedReferences = this . references . filter ( ( ref ) => ! ref . wasProcessed ) ;
1333- if ( unprocessedReferences . length === 0 ) {
1329+ const pendingRefs = this . references ;
1330+ if ( ! utils . isArrayHasLength ( pendingRefs ) ) {
13341331 return ;
13351332 }
13361333
@@ -1352,7 +1349,7 @@ export class SignedXml {
13521349 const signatureDoc = signatureElem . ownerDocument ;
13531350
13541351 // Process each unprocessed reference
1355- for ( const ref of unprocessedReferences ) {
1352+ for ( const ref of pendingRefs ) {
13561353 const nodes = xpath . selectWithResolver ( ref . xpath ?? "" , doc , this . namespaceResolver ) ;
13571354
13581355 if ( ! utils . isArrayHasLength ( nodes ) ) {
@@ -1374,19 +1371,28 @@ export class SignedXml {
13741371 ) ;
13751372 }
13761373
1377- // Create the reference element directly using DOM methods to avoid namespace issues
1378- const referenceElem = signatureDoc . createElementNS (
1379- signatureNamespace ,
1380- `${ prefix } Reference` ,
1381- ) ;
1374+ // Compute the target URI we intend to add
1375+ let targetUri : string ;
13821376 if ( ref . isEmptyUri ) {
1383- referenceElem . setAttribute ( "URI" , "" ) ;
1377+ targetUri = "" ;
13841378 } else {
13851379 const id = this . ensureHasId ( node ) ;
13861380 ref . uri = id ;
1387- referenceElem . setAttribute ( "URI" , `#${ id } ` ) ;
1381+ targetUri = `#${ id } ` ;
1382+ }
1383+
1384+ // Skip if a Reference with this URI already exists
1385+ if ( utils . hasReferenceWithUri ( signedInfoNode , targetUri , signatureNamespace ) ) {
1386+ continue ;
13881387 }
13891388
1389+ // Create the reference element directly using DOM methods to avoid namespace issues
1390+ const referenceElem = signatureDoc . createElementNS (
1391+ signatureNamespace ,
1392+ `${ prefix } Reference` ,
1393+ ) ;
1394+ referenceElem . setAttribute ( "URI" , targetUri ) ;
1395+
13901396 if ( ref . id ) {
13911397 referenceElem . setAttribute ( "Id" , ref . id ) ;
13921398 }
@@ -1448,7 +1454,6 @@ export class SignedXml {
14481454 // Append the reference element to SignedInfo
14491455 signedInfoNode . appendChild ( referenceElem ) ;
14501456 }
1451- ref . wasProcessed = true ;
14521457 }
14531458 }
14541459
0 commit comments