Skip to content

Add support for inserting and signing Object elements inside the Signature #506

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

shunkica
Copy link
Contributor

@shunkica shunkica commented Jun 20, 2025

Added support for custom <Object> elements within the <Signature> element via a new

getObjectContent?(): Array<{ content: string; attributes?: ObjectAttributes; }> | null method.

This is specified in xmldsig-core1/#sec-Object

Modified the signature creation process to sign and reference these internal objects.

These changes are also a step towards XAdES support.

@shunkica
Copy link
Contributor Author

@cjbarth I am happy with this PR. Let me know if you need any changes for this to be merged.

@shunkica
Copy link
Contributor Author

I have added the option to specify custom Id and Type attributes on references via the addReference method, as specified in xmldsig-core1/#sec-Reference

This is required to allow XAdES implementations because the Reference must contain Type="http://uri.etsi.org/01903#SignedProperties"

@srd90 srd90 mentioned this pull request Jul 2, 2025
@@ -164,6 +176,7 @@ export class SignedXml {
this.keyInfoAttributes = keyInfoAttributes ?? this.keyInfoAttributes;
this.getKeyInfoContent = getKeyInfoContent ?? this.getKeyInfoContent;
this.getCertFromKeyInfo = getCertFromKeyInfo ?? SignedXml.noop;
this.getObjectContent = getObjectContent ?? this.getObjectContent;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just have this return SignedXml.noop instead of the custom this.getObjectContent?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. Looking at the property initializers and the constructor these are also redundant:

  getKeyInfoContent = SignedXml.getKeyInfoContent;
  getCertFromKeyInfo = SignedXml.getCertFromKeyInfo;
  getObjectContent = SignedXml.getObjectContent;

Since they get overwritten in the constructor anyway.

Could probably be something like getKeyInfoContent: (args?: GetKeyInfoContentArgs) => string | null; etc.

const objectNodesWithNull = xpath.select("//*[local-name(.)='Object']", docWithNull);

if (Array.isArray(objectNodesWithNull)) {
expect(objectNodesWithNull.length).to.equal(0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is your test, why would you put an if/else around expect() Don't you know what is coming back?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The result comes from a third party library and the return type is Array<Node> | Node | string | number | boolean | null but yes it could be whittled down.

const objectNodesWithEmpty = xpath.select("//*[local-name(.)='Object']", docWithEmpty);

if (Array.isArray(objectNodesWithEmpty)) {
expect(objectNodesWithEmpty.length).to.equal(0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as before; I wouldn't expect an if/else around an expect() in a test.

@@ -58,6 +73,7 @@ export interface SignedXmlOptions {
keyInfoAttributes?: Record<string, string>;
getKeyInfoContent?(args?: GetKeyInfoContentArgs): string | null;
getCertFromKeyInfo?(keyInfo?: Node | null): string | null;
getObjectContent?(): Array<{ content: string; attributes?: ObjectAttributes }> | null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why make this a function? Why not just an Array?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not strictly necessary but at the time I thought it was more in line with the current code since it provides more flexibility and allows for dynamic generation of objects at signature time.

@cjbarth
Copy link
Contributor

cjbarth commented Jul 8, 2025

@imedacf, does this PR address your issue? Would you like to review this code?

@shunkica , are you using these features in a production system already, perhaps with your own fork?

@shunkica
Copy link
Contributor Author

shunkica commented Jul 8, 2025

@imedacf, does this PR address your issue? Would you like to review this code?

@shunkica , are you using these features in a production system already, perhaps with your own fork?

Not using them as of yet but I plan on it in the coming months as things develop here with some legislature changes.

Co-authored-by: Chris Barth <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants