From 912b6d2562cffbfbd4c7aaeeab198ff1e4653190 Mon Sep 17 00:00:00 2001 From: Ivan Novak Date: Mon, 26 Jun 2023 23:48:27 +0200 Subject: [PATCH 1/7] add all options to SignedXmlOptions, move idMode into the options, fix types --- README.md | 54 ++++++++++++++++++++++++++++------------------- index.d.ts | 35 ++++++++++++++++-------------- index.js | 2 ++ lib/signed-xml.js | 54 ++++++++++++++++++++++++++++++----------------- 4 files changed, 88 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 56cc6fc2..289baab3 100644 --- a/README.md +++ b/README.md @@ -75,9 +75,8 @@ var SignedXml = require("xml-crypto").SignedXml, var xml = "" + "" + "Harry Potter" + "" + ""; -var sig = new SignedXml(); +var sig = new SignedXml({ privateKey: fs.readFileSync("client.pem") }); sig.addReference("//*[local-name(.)='book']"); -sig.privateKey = fs.readFileSync("client.pem"); sig.computeSignature(xml); fs.writeFileSync("signed.xml", sig.getSignedXml()); ``` @@ -139,8 +138,7 @@ var signature = select( doc, "//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']" )[0]; -var sig = new SignedXml(); -sig.publicCert = new FileKeyInfo("client_public.pem"); +var sig = new SignedXml({ publicCert: fs.readFileSync("client_public.pem") }); sig.loadSignature(signature); var res = sig.checkSignature(xml); if (!res) console.log(sig.validationErrors); @@ -173,9 +171,11 @@ which makes XML developers confused and then leads to incorrect implementation f If you keep failing verification, it is worth trying to guess such a hidden transform and specify it to the option as below: ```javascript -var option = { implicitTransforms: ["http://www.w3.org/TR/2001/REC-xml-c14n-20010315"] }; -var sig = new SignedXml(null, option); -sig.publicCert = new FileKeyInfo("client_public.pem"); +var options = { + implicitTransforms: ["http://www.w3.org/TR/2001/REC-xml-c14n-20010315"], + publicCert: fs.readFileSync("client_public.pem"), +}; +var sig = new SignedXml(options); sig.loadSignature(signature); var res = sig.checkSignature(xml); ``` @@ -196,9 +196,19 @@ See [xpath.js](https://github.com/yaronn/xpath.js) for usage. Note that this is ### SignedXml -The `SignedXml` constructor provides an abstraction for sign and verify xml documents. The object is constructed using `new SignedXml([idMode])` where: +The `SignedXml` constructor provides an abstraction for sign and verify xml documents. The object is constructed using `new SignedXml(options?: SignedXmlOptions)` where the possible options are: -- `idMode` - if the value of `"wssecurity"` is passed it will create/validate id's with the ws-security namespace. +- `idMode` - default `null` - if the value of `wssecurity` is passed it will create/validate id's with the ws-security namespace. +- `idAttribute` - string - default `Id` or `ID` or `id` - the name of the attribute that contains the id of the element +- `privateKey` - string or Buffer - default `null` - the private key to use for signing +- `publicCert` - string or Buffer - default `null` - the public certificate to use for verifying +- `signatureAlgorithm` - string - default `http://www.w3.org/2000/09/xmldsig#rsa-sha1` - the signature algorithm to use +- `canonicalizationAlgorithm` - string - default `http://www.w3.org/TR/2001/REC-xml-c14n-20010315` - the canonicalization algorithm to use +- `inclusiveNamespacesPrefixList` - string - default `null` - a list of namespace prefixes to include during canonicalization +- `implicitTransforms` - string[] - default `[]` - a list of implicit transforms to use during verification +- `keyInfoAttributes` - object - default `{}` - a hash of attributes and values `attrName: value` to add to the KeyInfo node +- `getKeyInfoContent` - function - default `SignedXml.geTKeyInfoContent` - a function that returns the content of the KeyInfo node +- `getCertFromKeyInfo` - function - default `SignedXml.getCertFromKeyInfo` - a function that returns the certificate from the KeyInfo node #### API @@ -325,19 +335,22 @@ Now do the signing. Note how we configure the signature to use the above algorit ```javascript function signXml(xml, xpath, key, dest) { - var sig = new SignedXml(); + var options = { + publicCert: fs.readFileSync("my_public_cert.pem", "latin1"), + privateKey: fs.readFileSync(key), + /*configure the signature object to use the custom algorithms*/ + signatureAlgorithm: "http://mySignatureAlgorithm", + canonicalizationAlgorithm: "http://MyCanonicalization", + }; + + var sig = new SignedXml(options); - /*configure the signature object to use the custom algorithms*/ - sig.signatureAlgorithm = "http://mySignatureAlgorithm"; - sig.publicCert = fs.readFileSync("my_public_cert.pem", "latin1"); - sig.canonicalizationAlgorithm = "http://MyCanonicalization"; sig.addReference( "//*[local-name(.)='x']", ["http://MyTransformation"], "http://myDigestAlgorithm" ); - sig.privateKey = fs.readFileSync(key); sig.addReference(xpath); sig.computeSignature(xml); fs.writeFileSync(dest, sig.getSignedXml()); @@ -369,9 +382,8 @@ function AsyncSignatureAlgorithm() { }; } -SignedXml.SignatureAlgorithms["http://asyncSignatureAlgorithm"] = AsyncSignatureAlgorithm; -var sig = new SignedXml(); -sig.signatureAlgorithm = "http://asyncSignatureAlgorithm"; +var sig = new SignedXml({ signatureAlgorithm: "http://asyncSignatureAlgorithm" }); +sig.SignatureAlgorithms["http://asyncSignatureAlgorithm"] = AsyncSignatureAlgorithm; sig.computeSignature(xml, opts, function (err) { var signedResponse = sig.getSignedXml(); }); @@ -421,9 +433,8 @@ var SignedXml = require("xml-crypto").SignedXml, var xml = "" + "" + "Harry Potter" + "" + ""; -var sig = new SignedXml(); +var sig = new SignedXml({ privateKey: fs.readFileSync("client.pem") }); sig.addReference("//*[local-name(.)='book']"); -sig.privateKey = fs.readFileSync("client.pem"); sig.computeSignature(xml, { prefix: "ds", }); @@ -445,9 +456,8 @@ var SignedXml = require("xml-crypto").SignedXml, var xml = "" + "" + "Harry Potter" + "" + ""; -var sig = new SignedXml(); +var sig = new SignedXml({ privateKey: fs.readFileSync("client.pem") }); sig.addReference("//*[local-name(.)='book']"); -sig.privateKey = fs.readFileSync("client.pem"); sig.computeSignature(xml, { location: { reference: "//*[local-name(.)='book']", action: "after" }, //This will place the signature after the book element }); diff --git a/index.d.ts b/index.d.ts index f777353c..dfc0126b 100644 --- a/index.d.ts +++ b/index.d.ts @@ -36,11 +36,17 @@ type SignatureAlgorithmType = * Options for the SignedXml constructor. */ type SignedXmlOptions = { - canonicalizationAlgorithm?: TransformAlgorithmType; - inclusiveNamespacesPrefixList?: string; + idMode?: "wssecurity"; idAttribute?: string; - implicitTransforms?: ReadonlyArray; + privateKey?: crypto.KeyLike; + publicCert?: crypto.KeyLike; signatureAlgorithm?: SignatureAlgorithmType; + canonicalizationAlgorithm?: CanonicalizationAlgorithmType; + inclusiveNamespacesPrefixList?: string; + implicitTransforms?: ReadonlyArray; + keyInfoAttributes?: { [attrName: string]: string }; + getKeyInfoContent?(args?: GetKeyInfoContentArgs): string | null; + getCertFromKeyInfo?(keyInfo: string): string | null; }; type CanonicalizationOrTransformationAlgorithmProcessOptions = { @@ -186,8 +192,6 @@ export class SignedXml { canonicalizationAlgorithm: TransformAlgorithmType; // It specifies a list of namespace prefixes that should be considered "inclusive" during the canonicalization process. inclusiveNamespacesPrefixList: string; - // The structure for managing keys and KeyInfo section in XML data. See {@link KeyInfoProvider} - keyInfoProvider: KeyInfoProvider; // Specifies the data to be signed within an XML document. See {@link Reference} references: Reference[]; // One of the supported signature algorithms. See {@link SignatureAlgorithmType} @@ -200,10 +204,9 @@ export class SignedXml { /** * The SignedXml constructor provides an abstraction for sign and verify xml documents. The object is constructed using - * @param idMode if the value of "wssecurity" is passed it will create/validate id's with the ws-security namespace. - * @param options {@link SignedXmlOptions + * @param options {@link SignedXmlOptions} */ - constructor(idMode?: "wssecurity" | null, options?: SignedXmlOptions); + constructor(options?: SignedXmlOptions); /** * Due to key-confusion issues, it's risky to have both hmac @@ -344,17 +347,17 @@ export class SignedXml { getCertFromKeyInfo(keyInfo: string): string | null; } -export class Utils { +export declare module utils { /** * @param pem The PEM-encoded base64 certificate to strip headers from */ - static pemToDer(pem: string): string; + export function pemToDer(pem: string): string; /** * @param der The DER-encoded base64 certificate to add PEM headers too * @param pemLabel The label of the header and footer to add */ - static derToPem( + export function derToPem( der: string, pemLabel: ["CERTIFICATE" | "PRIVATE KEY" | "RSA PUBLIC KEY"] ): string; @@ -373,12 +376,12 @@ export class Utils { * - normalize line length to maximum of 64 characters * - ensure that 'preeb' has line ending '\n' * - * With couple of notes: + * With a couple of notes: * - 'eol' is normalized to '\n' * * @param pem The PEM string to normalize to RFC7468 'stricttextualmsg' definition */ - static normalizePem(pem: string): string; + export function normalizePem(pem: string): string; /** * PEM format has wide range of usages, but this library @@ -393,9 +396,9 @@ export class Utils { * - 'preeb' and 'posteb' lines are limited to 64 characters, but * should not cause any issues in context of PKIX, PKCS and CMS. */ - PEM_FORMAT_REGEX: RegExp; - EXTRACT_X509_CERTS: RegExp; - BASE64_REGEX: RegExp; + export const EXTRACT_X509_CERTS: RegExp; + export const PEM_FORMAT_REGEX: RegExp; + export const BASE64_REGEX: RegExp; } /** diff --git a/index.js b/index.js index a1e65d5d..9142ad42 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,8 @@ const select = require("xpath").select; +const utils = require("./lib/utils"); module.exports = require("./lib/signed-xml"); module.exports.xpath = function (node, xpath) { return select(xpath, node); }; +module.exports.utils = utils; diff --git a/lib/signed-xml.js b/lib/signed-xml.js index 9e2ed485..da2949c6 100644 --- a/lib/signed-xml.js +++ b/lib/signed-xml.js @@ -11,18 +11,42 @@ const signatureAlgorithms = require("./signature-algorithms"); * @type {import ("../index.d.ts").SignedXml} */ class SignedXml { - constructor(idMode, options = {}) { - this.options = options; - this.idMode = idMode; + /** @param {import("../index.d.ts").SignedXmlOptions} [options={}] */ + constructor(options = {}) { + const { + idMode, + idAttribute, + privateKey, + publicCert, + signatureAlgorithm, + canonicalizationAlgorithm, + inclusiveNamespacesPrefixList, + implicitTransforms, + keyInfoAttributes, + getKeyInfoContent, + getCertFromKeyInfo, + } = options; + + // Options + this.idMode = idMode || null; + this.idAttributes = ["Id", "ID", "id"]; + if (idAttribute) { + this.idAttributes.unshift(idAttribute); + } + this.privateKey = privateKey || null; + this.publicCert = publicCert || null; + this.signatureAlgorithm = signatureAlgorithm || "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; + this.canonicalizationAlgorithm = + canonicalizationAlgorithm || "http://www.w3.org/2001/10/xml-exc-c14n#"; + this.inclusiveNamespacesPrefixList = inclusiveNamespacesPrefixList || ""; + this.implicitTransforms = implicitTransforms || []; + this.keyInfoAttributes = keyInfoAttributes || {}; + this.getKeyInfoContent = getKeyInfoContent || SignedXml.getKeyInfoContent; + this.getCertFromKeyInfo = getCertFromKeyInfo || SignedXml.getCertFromKeyInfo; + + // Internal state this.references = []; this.id = 0; - this.privateKey = null; - this.publicCert = null; - this.signatureAlgorithm = - this.options.signatureAlgorithm || "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; - this.canonicalizationAlgorithm = - this.options.canonicalizationAlgorithm || "http://www.w3.org/2001/10/xml-exc-c14n#"; - this.inclusiveNamespacesPrefixList = this.options.inclusiveNamespacesPrefixList || ""; this.signedXml = ""; this.signatureXml = ""; this.signatureNode = null; @@ -30,14 +54,6 @@ class SignedXml { this.originalXmlWithIds = ""; this.validationErrors = []; this.keyInfo = null; - this.idAttributes = ["Id", "ID", "id"]; - if (this.options.idAttribute) { - this.idAttributes.unshift(this.options.idAttribute); - } - this.implicitTransforms = this.options.implicitTransforms || []; - this.getKeyInfoContent = SignedXml.getKeyInfoContent; - this.getCertFromKeyInfo = SignedXml.getCertFromKeyInfo; - this.keyInfoAttributes = {}; this.CanonicalizationAlgorithms = { "http://www.w3.org/TR/2001/REC-xml-c14n-20010315": c14n.C14nCanonicalization, @@ -65,7 +81,7 @@ class SignedXml { } /** - * Due to key-confusion issues, its risky to have both hmac + * Due to key-confusion issues, it's risky to have both hmac * and digital signature algos enabled at the same time. * This enables HMAC and disables other signing algos. */ From 81c4bc4a6e93e2a1040ca2c69af78f797e804dad Mon Sep 17 00:00:00 2001 From: Ivan Novak Date: Mon, 26 Jun 2023 23:55:54 +0200 Subject: [PATCH 2/7] fix tests --- test/signature-unit-tests.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/signature-unit-tests.js b/test/signature-unit-tests.js index 738e6fdf..971cf89c 100644 --- a/test/signature-unit-tests.js +++ b/test/signature-unit-tests.js @@ -13,7 +13,7 @@ describe("Signature unit tests", function () { doc )[0]; - const sig = new SignedXml(mode); + const sig = new SignedXml({ idMode: mode }); sig.publicCert = fs.readFileSync("./test/static/client_public.pem"); sig.loadSignature(node); try { @@ -92,7 +92,7 @@ describe("Signature unit tests", function () { ""; - const sig = new SignedXml(mode); + const sig = new SignedXml({ idMode: mode }); sig.privateKey = fs.readFileSync("./test/static/client.pem"); sig.addReference("//*[local-name(.)='x']"); sig.computeSignature(xml); @@ -112,7 +112,7 @@ describe("Signature unit tests", function () { function verifyAddsId(mode, nsMode) { const xml = ''; - const sig = new SignedXml(mode); + const sig = new SignedXml({ idMode: mode }); sig.privateKey = fs.readFileSync("./test/static/client.pem"); sig.addReference("//*[local-name(.)='x']"); @@ -177,7 +177,7 @@ describe("Signature unit tests", function () { function verifyReferenceNS() { const xml = 'xml-cryptogithub'; - const sig = new SignedXml("wssecurity"); + const sig = new SignedXml({ idMode: "wssecurity" }); sig.privateKey = fs.readFileSync("./test/static/client.pem"); @@ -922,7 +922,7 @@ describe("Signature unit tests", function () { it("creates InclusiveNamespaces element inside CanonicalizationMethod when inclusiveNamespacesPrefixList is set on SignedXml options", function () { const xml = ""; - const sig = new SignedXml(null, { inclusiveNamespacesPrefixList: "prefix1 prefix2" }); + const sig = new SignedXml({ inclusiveNamespacesPrefixList: "prefix1 prefix2" }); sig.privateKey = fs.readFileSync("./test/static/client.pem"); sig.publicCert = null; @@ -955,7 +955,7 @@ describe("Signature unit tests", function () { it("does not create InclusiveNamespaces element inside CanonicalizationMethod when inclusiveNamespacesPrefixList is not set on SignedXml options", function () { const xml = ""; - const sig = new SignedXml(null); // Omit inclusiveNamespacesPrefixList property + const sig = new SignedXml(); // Omit inclusiveNamespacesPrefixList property sig.privateKey = fs.readFileSync("./test/static/client.pem"); sig.publicCert = null; From 51bcab591ea61c358f3ce1ab62c6761271324dff Mon Sep 17 00:00:00 2001 From: Ivan Novak Date: Tue, 27 Jun 2023 17:00:57 +0200 Subject: [PATCH 3/7] update readme --- README.md | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 289baab3..bff92502 100644 --- a/README.md +++ b/README.md @@ -61,11 +61,12 @@ _Signature Algorithm:_ RSA-SHA1 http://www.w3.org/2000/09/xmldsig#rsa-sha1 ## Signing Xml documents -When signing a xml document you can specify the following properties on a `SignedXml` instance to customize the signature process: +When signing a xml document you can pass the following options to the `SignedXml` constructor to customize the signature process: -- `sign.privateKey` - **[required]** a `Buffer` or pem encoded `String` containing your private key -- `sign.signatureAlgorithm` - **[optional]** one of the supported [signature algorithms](#signature-algorithms). Ex: `sign.signatureAlgorithm = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"` -- `sign.canonicalizationAlgorithm` - **[optional]** one of the supported [canonicalization algorithms](#canonicalization-and-transformation-algorithms). Ex: `sign.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#WithComments"` +- `privateKey` - **[required]** a `Buffer` or pem encoded `String` containing your private key +- `publicCert` - **[optional]** a `Buffer` or pem encoded `String` containing your public key +- `signatureAlgorithm` - **[optional]** one of the supported [signature algorithms](#signature-algorithms). Ex: `sign.signatureAlgorithm = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"` +- `canonicalizationAlgorithm` - **[optional]** one of the supported [canonicalization algorithms](#canonicalization-and-transformation-algorithms). Ex: `sign.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#WithComments"` Use this code: @@ -107,20 +108,22 @@ The result will be: Note: -To generate a `` element in the signature you must provide a key info implementation, see [customizing algorithms](#customizing-algorithms) for an example. +If you set the `publicCert` property, a `` element with the public certificate will be generated in the signature. +To customize this see [customizing algorithms](#customizing-algorithms) for an example. ## Verifying Xml documents -When verifying a xml document you must specify the following properties on a ``SignedXml` instance: +When verifying a xml document you can pass the following options to the `SignedXml` constructor to customize the verify process: -- `sign.publicCert` - **[optional]** your certificate as a string, a string of multiple certs in PEM format, or a Buffer, see [customizing algorithms](#customizing-algorithms) for an implementation example +- `publicCert` - **[optional]** your certificate as a string, a string of multiple certs in PEM format, or a Buffer +- `privateKey` - **[optional]** your private key as a string or a Buffer - used for verifying symmetrical signatures (HMAC) -The certificate that will be used to check the signature will first be determined by calling `.getCertFromKeyInfo()`, which function you can customize as you see fit. If that returns `null`, then `.publicCert` is used. If that is `null`, then `.privateKey` is used (for symmetrical signing applications). +The certificate that will be used to check the signature will first be determined by calling `.getCertFromKeyInfo()`, which function you can customize as you see fit. If that returns `null`, then `publicCert` is used. If that is `null`, then `privateKey` is used (for symmetrical signing applications). -You can use any dom parser you want in your code (or none, depending on your usage). This sample uses [xmldom](https://github.com/jindw/xmldom) so you should install it first: +You can use any dom parser you want in your code (or none, depending on your usage). This sample uses [xmldom](https://github.com/jindw/xmldom), so you should install it first: ```shell -npm install xmldom +npm install @xmldom/xmldom ``` Example: @@ -144,7 +147,7 @@ var res = sig.checkSignature(xml); if (!res) console.log(sig.validationErrors); ``` -if the verification process fails `sig.validationErrors` will have the errors. +If the verification process fails `sig.validationErrors` will contain the errors. In order to protect from some attacks we must check the content we want to use is the one that has been signed: @@ -366,7 +369,7 @@ You can always look at the actual code as a sample. ## Asynchronous signing and verification -If the private key is not stored locally and you wish to use a signing server or Hardware Security Module (HSM) to sign documents you can create a custom signing algorithm that uses an asynchronous callback. +If the private key is not stored locally, and you wish to use a signing server or Hardware Security Module (HSM) to sign documents you can create a custom signing algorithm that uses an asynchronous callback. ```javascript function AsyncSignatureAlgorithm() { @@ -467,8 +470,9 @@ sig.computeSignature(xml, { ## Development -The test framework is [nodeunit](https://github.com/caolan/nodeunit). To run tests use: +The testing framework we use is [Mocha](https://github.com/mochajs/mocha) with [Chai](https://github.com/chaijs/chai) as the assertion framework. +To run tests use: ```shell npm test ``` From 79438e4df385539f7e7b1572b6c84416599d3e14 Mon Sep 17 00:00:00 2001 From: Ivan Novak Date: Tue, 27 Jun 2023 17:04:19 +0200 Subject: [PATCH 4/7] update types --- index.d.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/index.d.ts b/index.d.ts index dfc0126b..31544e1f 100644 --- a/index.d.ts +++ b/index.d.ts @@ -100,22 +100,22 @@ export interface Reference { isEmptyUri?: boolean; } -/** Implement this to create a new CanonicalizationAlgorithm */ -export class CanonicalizationOrTransformationAlgorithm { +/** Implement this to create a new CanonicalizationOrTransformationAlgorithm */ +export interface CanonicalizationOrTransformationAlgorithm { process(node: Node, options: CanonicalizationOrTransformationAlgorithmProcessOptions): string; getAlgorithmName(): CanonicalizationAlgorithmType; } /** Implement this to create a new HashAlgorithm */ -export class HashAlgorithm { +export interface HashAlgorithm { getAlgorithmName(): HashAlgorithmType; getHash(xml: string): string; } /** Implement this to create a new SignatureAlgorithm */ -export class SignatureAlgorithm { +export interface SignatureAlgorithm { /** * Sign the given string using the given key */ @@ -141,7 +141,7 @@ export class SignatureAlgorithm { } /** Implement this to create a new TransformAlgorithm */ -export class TransformAlgorithm { +export interface TransformAlgorithm { getAlgorithmName(): TransformAlgorithmType; process(node: Node): string; From 6ac908bd41f675c509aa87fc0d8120be6636c5d1 Mon Sep 17 00:00:00 2001 From: Ivan Novak Date: Tue, 27 Jun 2023 17:10:19 +0200 Subject: [PATCH 5/7] lint --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index bff92502..b738f8db 100644 --- a/README.md +++ b/README.md @@ -473,6 +473,7 @@ sig.computeSignature(xml, { The testing framework we use is [Mocha](https://github.com/mochajs/mocha) with [Chai](https://github.com/chaijs/chai) as the assertion framework. To run tests use: + ```shell npm test ``` From 2c6f7ecfdd93012d6db8b189579ac7b5cafd8eb3 Mon Sep 17 00:00:00 2001 From: Ivan Novak Date: Tue, 27 Jun 2023 17:13:58 +0200 Subject: [PATCH 6/7] update xmldom link --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b738f8db..13dc1769 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,7 @@ When verifying a xml document you can pass the following options to the `SignedX The certificate that will be used to check the signature will first be determined by calling `.getCertFromKeyInfo()`, which function you can customize as you see fit. If that returns `null`, then `publicCert` is used. If that is `null`, then `privateKey` is used (for symmetrical signing applications). -You can use any dom parser you want in your code (or none, depending on your usage). This sample uses [xmldom](https://github.com/jindw/xmldom), so you should install it first: +You can use any dom parser you want in your code (or none, depending on your usage). This sample uses [xmldom](https://github.com/xmldom/xmldom), so you should install it first: ```shell npm install @xmldom/xmldom @@ -237,7 +237,7 @@ To sign xml documents: To verify xml documents: - `loadSignature(signatureXml)` - loads the signature where: - - `signatureXml` - a string or node object (like an [xml-dom](https://github.com/jindw/xmldom) node) containing the xml representation of the signature + - `signatureXml` - a string or node object (like an [xmldom](https://github.com/xmldom/xmldom) node) containing the xml representation of the signature - `checkSignature(xml)` - validates the given xml document and returns true if the validation was successful, `sig.validationErrors` will have the validation errors if any, where: - `xml` - a string containing a xml document From 8bbb630b3ea088e5580bb2c1e311b900501b0076 Mon Sep 17 00:00:00 2001 From: shunkica Date: Wed, 28 Jun 2023 07:08:55 +0200 Subject: [PATCH 7/7] Update README.md Co-authored-by: Chris Barth --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 13dc1769..09dfe1b3 100644 --- a/README.md +++ b/README.md @@ -369,7 +369,7 @@ You can always look at the actual code as a sample. ## Asynchronous signing and verification -If the private key is not stored locally, and you wish to use a signing server or Hardware Security Module (HSM) to sign documents you can create a custom signing algorithm that uses an asynchronous callback. +If the private key is not stored locally, and you wish to use a signing server or Hardware Security Module (HSM) to sign documents, you can create a custom signing algorithm that uses an asynchronous callback. ```javascript function AsyncSignatureAlgorithm() {