@@ -229,6 +229,288 @@ describe("Object support in XML signatures", function () {
229229 expect ( isValid ) . to . be . true ;
230230 } ) ;
231231
232+ it ( "should sign Object with SHA256 digest algorithm" , function ( ) {
233+ // Create a simple XML document to sign
234+ const xml = '<root><x xmlns="ns"></x><y attr="value"></y><z><w></w></z></root>' ;
235+
236+ // Create a SignedXml instance with custom getObjectContent
237+ const sig = new SignedXml ( {
238+ getObjectContent : ( ) => [
239+ {
240+ content : "<Data>Test data for SHA256 digest</Data>" ,
241+ attributes : {
242+ Id : "object1" ,
243+ MimeType : "text/xml" ,
244+ } ,
245+ } ,
246+ ] ,
247+ } ) ;
248+
249+ // Set up the signature
250+ sig . privateKey = fs . readFileSync ( "./test/static/client.pem" ) ;
251+
252+ // Add a reference to the document element
253+ sig . addReference ( {
254+ xpath : "//*[local-name(.)='x']" ,
255+ digestAlgorithm : "http://www.w3.org/2001/04/xmlenc#sha256" ,
256+ transforms : [ "http://www.w3.org/2001/10/xml-exc-c14n#" ] ,
257+ } ) ;
258+
259+ // Add a reference to the Object element with SHA256
260+ sig . addReference ( {
261+ xpath : "//*[@Id='object1']" ,
262+ digestAlgorithm : "http://www.w3.org/2001/04/xmlenc#sha256" ,
263+ transforms : [ "http://www.w3.org/2001/10/xml-exc-c14n#" ] ,
264+ isSignatureReference : true ,
265+ } ) ;
266+
267+ // Set required algorithms
268+ sig . canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#" ;
269+ sig . signatureAlgorithm = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" ;
270+
271+ // Compute the signature
272+ sig . computeSignature ( xml ) ;
273+
274+ // Get the signed XML
275+ const signedXml = sig . getSignedXml ( ) ;
276+
277+ // Parse the signed XML
278+ const doc = new xmldom . DOMParser ( ) . parseFromString ( signedXml ) ;
279+
280+ // Verify that the ds:Object element exists
281+ const objectNodes = xpath . select ( "//*[local-name(.)='Object']" , doc ) ;
282+ isDomNode . assertIsArrayOfNodes ( objectNodes ) ;
283+ expect ( objectNodes . length ) . to . equal ( 1 ) ;
284+
285+ // Verify that there are two Reference elements
286+ const referenceNodes = xpath . select ( "//*[local-name(.)='Reference']" , doc ) ;
287+ isDomNode . assertIsArrayOfNodes ( referenceNodes ) ;
288+ expect ( referenceNodes . length ) . to . equal ( 2 ) ;
289+
290+ // Verify that the references use SHA256
291+ const digestMethodNodes = xpath . select ( "//*[local-name(.)='DigestMethod']" , doc ) ;
292+ isDomNode . assertIsArrayOfNodes ( digestMethodNodes ) ;
293+
294+ for ( const digestMethod of digestMethodNodes ) {
295+ isDomNode . assertIsElementNode ( digestMethod ) ;
296+ expect ( digestMethod . getAttribute ( "Algorithm" ) ) . to . equal (
297+ "http://www.w3.org/2001/04/xmlenc#sha256" ,
298+ ) ;
299+ }
300+
301+ // Verify that the signature method is RSA-SHA256
302+ const signatureMethod = xpath . select1 ( "//*[local-name(.)='SignatureMethod']" , doc ) ;
303+ isDomNode . assertIsElementNode ( signatureMethod ) ;
304+ expect ( signatureMethod . getAttribute ( "Algorithm" ) ) . to . equal (
305+ "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" ,
306+ ) ;
307+
308+ // Verify that the signature is still valid
309+ const verifier = new SignedXml ( ) ;
310+ verifier . publicCert = fs . readFileSync ( "./test/static/client_public.pem" ) ;
311+
312+ // First load the signature
313+ const signatureNode = xpath . select1 (
314+ "//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']" ,
315+ doc ,
316+ ) ;
317+ isDomNode . assertIsNodeLike ( signatureNode ) ;
318+ verifier . loadSignature ( signatureNode ) ;
319+
320+ // Then check the signature
321+ const isValid = verifier . checkSignature ( signedXml ) ;
322+ expect ( isValid ) . to . be . true ;
323+ } ) ;
324+
325+ it ( "should sign Object with SHA512 digest algorithm and RSA-SHA512 signature" , function ( ) {
326+ // Create a simple XML document to sign
327+ const xml = '<root><x xmlns="ns"></x><y attr="value"></y><z><w></w></z></root>' ;
328+
329+ // Create a SignedXml instance with custom getObjectContent
330+ const sig = new SignedXml ( {
331+ getObjectContent : ( ) => [
332+ {
333+ content : "<Data>Test data for SHA512 digest</Data>" ,
334+ attributes : {
335+ Id : "object1" ,
336+ MimeType : "text/xml" ,
337+ } ,
338+ } ,
339+ ] ,
340+ } ) ;
341+
342+ // Set up the signature
343+ sig . privateKey = fs . readFileSync ( "./test/static/client.pem" ) ;
344+
345+ // Add a reference to the document element
346+ sig . addReference ( {
347+ xpath : "//*[local-name(.)='x']" ,
348+ digestAlgorithm : "http://www.w3.org/2001/04/xmlenc#sha512" ,
349+ transforms : [ "http://www.w3.org/2001/10/xml-exc-c14n#" ] ,
350+ } ) ;
351+
352+ // Add a reference to the Object element with SHA512
353+ sig . addReference ( {
354+ xpath : "//*[@Id='object1']" ,
355+ digestAlgorithm : "http://www.w3.org/2001/04/xmlenc#sha512" ,
356+ transforms : [ "http://www.w3.org/2001/10/xml-exc-c14n#" ] ,
357+ isSignatureReference : true ,
358+ } ) ;
359+
360+ // Set required algorithms
361+ sig . canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#" ;
362+ sig . signatureAlgorithm = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512" ;
363+
364+ // Compute the signature
365+ sig . computeSignature ( xml ) ;
366+
367+ // Get the signed XML
368+ const signedXml = sig . getSignedXml ( ) ;
369+
370+ // Parse the signed XML
371+ const doc = new xmldom . DOMParser ( ) . parseFromString ( signedXml ) ;
372+
373+ // Verify that the ds:Object element exists
374+ const objectNodes = xpath . select ( "//*[local-name(.)='Object']" , doc ) ;
375+ isDomNode . assertIsArrayOfNodes ( objectNodes ) ;
376+ expect ( objectNodes . length ) . to . equal ( 1 ) ;
377+
378+ // Verify that there are two Reference elements
379+ const referenceNodes = xpath . select ( "//*[local-name(.)='Reference']" , doc ) ;
380+ isDomNode . assertIsArrayOfNodes ( referenceNodes ) ;
381+ expect ( referenceNodes . length ) . to . equal ( 2 ) ;
382+
383+ // Verify that the references use SHA512
384+ const digestMethodNodes = xpath . select ( "//*[local-name(.)='DigestMethod']" , doc ) ;
385+ isDomNode . assertIsArrayOfNodes ( digestMethodNodes ) ;
386+
387+ for ( const digestMethod of digestMethodNodes ) {
388+ isDomNode . assertIsElementNode ( digestMethod ) ;
389+ expect ( digestMethod . getAttribute ( "Algorithm" ) ) . to . equal (
390+ "http://www.w3.org/2001/04/xmlenc#sha512" ,
391+ ) ;
392+ }
393+
394+ // Verify that the signature method is RSA-SHA512
395+ const signatureMethod = xpath . select1 ( "//*[local-name(.)='SignatureMethod']" , doc ) ;
396+ isDomNode . assertIsElementNode ( signatureMethod ) ;
397+ expect ( signatureMethod . getAttribute ( "Algorithm" ) ) . to . equal (
398+ "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512" ,
399+ ) ;
400+
401+ // Verify that the signature is still valid
402+ const verifier = new SignedXml ( ) ;
403+ verifier . publicCert = fs . readFileSync ( "./test/static/client_public.pem" ) ;
404+
405+ // First load the signature
406+ const signatureNode = xpath . select1 (
407+ "//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']" ,
408+ doc ,
409+ ) ;
410+ isDomNode . assertIsNodeLike ( signatureNode ) ;
411+ verifier . loadSignature ( signatureNode ) ;
412+
413+ // Then check the signature
414+ const isValid = verifier . checkSignature ( signedXml ) ;
415+ expect ( isValid ) . to . be . true ;
416+ } ) ;
417+
418+ it ( "should sign Object with C14N canonicalization algorithm" , function ( ) {
419+ // Create a simple XML document to sign
420+ const xml = '<root><x xmlns="ns"></x><y attr="value"></y><z><w></w></z></root>' ;
421+
422+ // Create a SignedXml instance with custom getObjectContent
423+ const sig = new SignedXml ( {
424+ getObjectContent : ( ) => [
425+ {
426+ content : "<Data>Test data for C14N canonicalization</Data>" ,
427+ attributes : {
428+ Id : "object1" ,
429+ MimeType : "text/xml" ,
430+ } ,
431+ } ,
432+ ] ,
433+ } ) ;
434+
435+ // Set up the signature
436+ sig . privateKey = fs . readFileSync ( "./test/static/client.pem" ) ;
437+
438+ // Add a reference to the document element
439+ sig . addReference ( {
440+ xpath : "//*[local-name(.)='x']" ,
441+ digestAlgorithm : "http://www.w3.org/2000/09/xmldsig#sha1" ,
442+ transforms : [ "http://www.w3.org/TR/2001/REC-xml-c14n-20010315" ] ,
443+ } ) ;
444+
445+ // Add a reference to the Object element
446+ sig . addReference ( {
447+ xpath : "//*[@Id='object1']" ,
448+ digestAlgorithm : "http://www.w3.org/2000/09/xmldsig#sha1" ,
449+ transforms : [ "http://www.w3.org/TR/2001/REC-xml-c14n-20010315" ] ,
450+ isSignatureReference : true ,
451+ } ) ;
452+
453+ // Set required algorithms
454+ sig . canonicalizationAlgorithm = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315" ;
455+ sig . signatureAlgorithm = "http://www.w3.org/2000/09/xmldsig#rsa-sha1" ;
456+
457+ // Compute the signature
458+ sig . computeSignature ( xml ) ;
459+
460+ // Get the signed XML
461+ const signedXml = sig . getSignedXml ( ) ;
462+
463+ // Parse the signed XML
464+ const doc = new xmldom . DOMParser ( ) . parseFromString ( signedXml ) ;
465+
466+ // Verify that the ds:Object element exists
467+ const objectNodes = xpath . select ( "//*[local-name(.)='Object']" , doc ) ;
468+ isDomNode . assertIsArrayOfNodes ( objectNodes ) ;
469+ expect ( objectNodes . length ) . to . equal ( 1 ) ;
470+
471+ // Verify that there are two Reference elements
472+ const referenceNodes = xpath . select ( "//*[local-name(.)='Reference']" , doc ) ;
473+ isDomNode . assertIsArrayOfNodes ( referenceNodes ) ;
474+ expect ( referenceNodes . length ) . to . equal ( 2 ) ;
475+
476+ // Verify that the transforms use C14N
477+ const transforms = xpath . select (
478+ "//*[local-name(.)='Reference']/*[local-name(.)='Transforms']/*[local-name(.)='Transform']" ,
479+ doc ,
480+ ) ;
481+ isDomNode . assertIsArrayOfNodes ( transforms ) ;
482+
483+ for ( const transform of transforms ) {
484+ isDomNode . assertIsElementNode ( transform ) ;
485+ expect ( transform . getAttribute ( "Algorithm" ) ) . to . equal (
486+ "http://www.w3.org/TR/2001/REC-xml-c14n-20010315" ,
487+ ) ;
488+ }
489+
490+ // Verify that the CanonicalizationMethod is C14N
491+ const canonMethod = xpath . select1 ( "//*[local-name(.)='CanonicalizationMethod']" , doc ) ;
492+ isDomNode . assertIsElementNode ( canonMethod ) ;
493+ expect ( canonMethod . getAttribute ( "Algorithm" ) ) . to . equal (
494+ "http://www.w3.org/TR/2001/REC-xml-c14n-20010315" ,
495+ ) ;
496+
497+ // Verify that the signature is still valid
498+ const verifier = new SignedXml ( ) ;
499+ verifier . publicCert = fs . readFileSync ( "./test/static/client_public.pem" ) ;
500+
501+ // First load the signature
502+ const signatureNode = xpath . select1 (
503+ "//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']" ,
504+ doc ,
505+ ) ;
506+ isDomNode . assertIsNodeLike ( signatureNode ) ;
507+ verifier . loadSignature ( signatureNode ) ;
508+
509+ // Then check the signature
510+ const isValid = verifier . checkSignature ( signedXml ) ;
511+ expect ( isValid ) . to . be . true ;
512+ } ) ;
513+
232514 it ( "should add a reference to an Object element" , function ( ) {
233515 // Create a simple XML document to sign
234516 const xml = '<root><x xmlns="ns"></x><y attr="value"></y><z><w></w></z></root>' ;
@@ -259,7 +541,6 @@ describe("Object support in XML signatures", function () {
259541 // Add a reference to the Object element by its ID
260542 sig . addReference ( {
261543 xpath : "//*[@Id='object1']" ,
262- uri : "#object1" ,
263544 digestAlgorithm : "http://www.w3.org/2000/09/xmldsig#sha1" ,
264545 transforms : [ "http://www.w3.org/2001/10/xml-exc-c14n#" ] ,
265546 isSignatureReference : true ,
@@ -347,7 +628,7 @@ describe("Object support in XML signatures", function () {
347628
348629 // Add a reference to the Object element by its ID only, marking it as a signature reference
349630 sig . addReference ( {
350- uri : "# object1" ,
631+ xpath : "//*[@Id=' object1'] " ,
351632 digestAlgorithm : "http://www.w3.org/2000/09/xmldsig#sha1" ,
352633 transforms : [ "http://www.w3.org/2001/10/xml-exc-c14n#" ] ,
353634 isSignatureReference : true ,
0 commit comments