Repository: PeculiarVentures/xadesjs Branch: master Commit: f36e52582964 Files: 56 Total size: 223.7 KB Directory structure: gitextract_0mi2stbx/ ├── .github/ │ └── workflows/ │ └── ci.yml ├── .gitignore ├── .npmignore ├── LICENSE.md ├── README.md ├── eslint.config.mjs ├── examples/ │ └── html/ │ ├── sign.html │ ├── src/ │ │ ├── helper.js │ │ └── main.js │ └── verify.html ├── package.json ├── rollup.config.js ├── src/ │ ├── dateformat.ts │ ├── index.ts │ ├── signed_xml.ts │ └── xml/ │ ├── any.ts │ ├── certificate_values.ts │ ├── commitment_type_indication.ts │ ├── complete_certificate_refs.ts │ ├── complete_revocation_refs.ts │ ├── converter.ts │ ├── counter_signature.ts │ ├── data_object.ts │ ├── data_object_format.ts │ ├── date_time.ts │ ├── encapsulated_pki_data.ts │ ├── generic_time_stamp.ts │ ├── index.ts │ ├── object_identifier.ts │ ├── other_time_stamp.ts │ ├── qualifying_properties.ts │ ├── qualifying_properties_reference.ts │ ├── revocation_values.ts │ ├── signature_policy_identifier.ts │ ├── signature_product_place.ts │ ├── signed_data_object_properties.ts │ ├── signed_properties.ts │ ├── signed_signature_properties.ts │ ├── signer_role.ts │ ├── signing_certificate.ts │ ├── signing_certificate_v2.ts │ ├── unsigned_data_object_property.ts │ ├── unsigned_properties.ts │ ├── unsigned_signature_properties.ts │ ├── xades.xsd │ ├── xades_time_stamp.ts │ ├── xml.ts │ └── xml_base.ts ├── test/ │ ├── signed_xml/ │ │ └── signing.ts │ ├── vectors/ │ │ └── reading.ts │ └── xml/ │ ├── date_time.ts │ ├── encapsulated_pki_data.ts │ ├── generic_time_stamp.ts │ └── object_identifier.ts ├── tsconfig.json └── tsconfig.types.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/ci.yml ================================================ name: CI on: push: branches: - master pull_request: branches: - master jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22 cache: 'npm' - name: Install dependencies run: npm ci - name: Lint run: npm run lint - name: Coverage run: npm run coverage - name: Coveralls uses: coverallsapp/github-action@v2 ================================================ FILE: .gitignore ================================================ .vscode/ .nyc_output/ coverage/ node_modules/ build/ **/*.map *.log # MAC OS .DS_Store ================================================ FILE: .npmignore ================================================ .vscode/ .github/ .nyc_output/ coverage/ node_modules/ test/ examples/ src/ **/*.map *.log rollup.*.js ts*.json ================================================ FILE: LICENSE.md ================================================ The MIT License (MIT) Copyright (c) 2015 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # XAdESjs [![license](https://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://raw.githubusercontent.com/PeculiarVentures/xadesjs/master/LICENSE.md) [![GitHub Actions](https://github.com/PeculiarVentures/xadesjs/workflows/CI/badge.svg)](https://github.com/PeculiarVentures/xadesjs/actions) [![Coverage Status](https://coveralls.io/repos/github/PeculiarVentures/xadesjs/badge.svg?branch=master)](https://coveralls.io/github/PeculiarVentures/xadesjs?branch=master) [![npm version](https://badge.fury.io/js/xadesjs.svg)](https://badge.fury.io/js/xadesjs) [![NPM](https://nodei.co/npm/xadesjs.png)](https://nodei.co/npm/xadesjs/) ## Notice: Repository Archived This repository is no longer maintained. Its functionality has been merged into the [xmldsigjs](https://github.com/PeculiarVentures/xmldsigjs) monorepo, and is now part of it. For future development and updates, please use [xmldsigjs](https://github.com/PeculiarVentures/xmldsigjs). ## Introduction [XAdES](https://en.wikipedia.org/wiki/XAdES) is short for "XML Advanced Electronic Signatures", it is a superset of XMLDSIG. This library aims to provide an implementation of XAdES in Typescript/Javascript that is built on [XMLDSIGjs](https://github.com/PeculiarVentures/xmldsigjs). Since it is based on [XMLDSIGjs](https://github.com/PeculiarVentures/xmldsigjs) and that library uses Web Crypto for cryptographic operations it can be used both in browsers and in Node.js (when used with a polyfill like [webcrypto](https://github.com/PeculiarVentures/webcrypto), [node-webcrypto-ossl](https://github.com/PeculiarVentures/node-webcrypto-ossl) or [node-webcrypto-p11](https://github.com/PeculiarVentures/node-webcrypto-p11)). There are seven different profiles of XAdES, they are: - Basic Electronic Signature (XAdES-BES) - XAdES with Timestamp (XAdES-T) - XAdES with Complete Validation Data (XAdES-C) - XAdES with Extended Validation Data (XAdES-X) - XAdES with Extended Long Term Validation Data (XAdES-X-L) - XAdES with Archiving Validation Data (XAdES-A) - XAdES with Explicit policy electronic signatures (XAdES-EPES) They differ slightly based on what is included in the signature: | | Provides Digital Signature | Includes Cryptographic Timestamp | Includes Revocation References | Includes Revocation Data | Allows Secure Timestamp Countersignature | |------------|----------------------------|----------------------------------|--------------------------------|--------------------------|------------------------------------------| | **XAdES-BES** | **Yes** | **No** | **No** | **No** | **No** | | XAdES-EPES | Yes | No | No | No | No | | XAdES-T | Yes | Yes | No | No | No | | XAdES-C | Yes | Yes | Yes | No | No | | XAdES-X | Yes | Yes | Yes | No | No | | XAdES-X-L | Yes | Yes | Yes | Yes | No | | XAdES-A | Yes | Yes | Yes | Yes | Yes | - Only XAdES-BES (in *BOLD*) is fully supported by XAdESjs. For the other variants can be created, decoded and verified but the caller must do the construction and policy to ensure compliant messages on their own. ## INSTALLING ``` npm install xadesjs ``` The npm module has a `dist` folder with the following files: | Name | Size | Description | |-----------------|--------|------------------------------------------------| | index.js | 105 Kb | UMD module with external modules. Has comments | | xades.js | 803 Kb | UMD bundle module. Has comments | | xades.min.js | 296 Kb | minified UMD bundle module | There is also a `lib` folder with an ES2015 JS file which you can use with `rollup` bundler. ## COMPATABILITY ### CRYPTOGRAPHIC ALGORITHM SUPPORT | Name | SHA1 | SHA2-256 | SHA2-384 | SHA2-512 | |-------------------|------|----------|----------|----------| | RSASSA-PKCS1-v1_5 | X | X | X | X | | RSA-PSS | X | X | X | X | | ECDSA | X | X | X | X | | HMAC | X | X | X | X | ### CANONICALIZATION ALGORITHM SUPPORT - XmlDsigC14NTransform - XmlDsigC14NWithCommentsTransform - XmlDsigExcC14NTransform - XmlDsigExcC14NWithCommentsTransform - XmlDsigEnvelopedSignatureTransform - XmlDsigBase64Transform ### PLATFORM SUPPORT XAdESjs works with any browser that suppports Web Crypto. Since node does not have Web Crypto you will need a polyfill on this platform, for this reason the npm package includes [webcrypto](https://github.com/PeculiarVentures/webcrypto); browsers do not need this dependency and in those cases though it will be installed it will be ignored. If you need to use a Hardware Security Module we have also created a polyfill for Web Crypto that supports PKCS #11. Our polyfill for this is [node-webcrypto-p11](https://github.com/PeculiarVentures/node-webcrypto-p11). To use [node-webcrypto-ossl](https://github.com/PeculiarVentures/node-webcrypto-ossl) you need to specify you want to use it, that looks like this: ```javascript var xadesjs = require("./built/xades.js"); var { Crypto } = require("@peculiar/webcrypto"); xadesjs.Application.setEngine("NodeJS", new Crypto()); ``` The [node-webcrypto-p11](https://github.com/PeculiarVentures/node-webcrypto-p11) polyfill will work the same way. The only difference is that you have to specify the details about your PKCS #11 device when you instansiate it: ```javascript var xadesjs = require("./built/xades.js"); var WebCrypto = require("node-webcrypto-p11").WebCrypto; xadesjs.Application.setEngine("PKCS11", new WebCrypto({ library: "/path/to/pkcs11.so", name: "Name of PKCS11 lib", slot: 0, sessionFlags: 2 | 4, // RW_SESSION | SERIAL_SESSION pin: "token pin" })); ``` ## WARNING **Using XMLDSIG is a bit like running with scissors, that said it is needed for interoperability with a number of systems, for this reason, we have done this implementation.** ## Usage ### Sign ```typescript SignedXml.Sign(algorithm: Algorithm, key: CryptoKey, data: Document, options?: OptionsXAdES): PromiseLike; ``` __Parameters__ | Name | Description | |:--------------|:------------------------------------------------------------------------| | algorithm | Signing [Algorithm](https://www.w3.org/TR/WebCryptoAPI/#algorithms) | | key | Signing [Key](https://www.w3.org/TR/WebCryptoAPI/#cryptokey-interface) | | data | XML document which must be signed | | options | Additional options | #### Options ```typescript interface OptionsXAdES { /** * Public key for KeyInfo block */ keyValue?: CryptoKey; /** * List of X509 Certificates */ x509?: string[]; /** * List of Reference * Default is Reference with hash alg SHA-256 and exc-c14n transform */ references?: OptionsSignReference[]; // Signed signature properties signingCertificate?: string; signingTime?: OptionsSigningTime; policy?: OptionsPolicyId; productionPlace?: OptionsProductionPlace; signerRole?: OptionsSignerRole; } interface OptionsSignReference { /** * Id of Reference */ id?: string; uri?: string; /** * Hash algorithm */ hash: AlgorithmIdentifier; /** * List of transforms */ transforms?: OptionsSignTransform[]; } type OptionsSignTransform = "enveloped" | "c14n" | "exc-c14n" | "c14n-com" | "exc-c14n-com" | "base64"; interface OptionsSigningTime { value?: Date; format?: string; } interface OptionsSignerRole { claimed?: string[]; certified?: string[]; } interface OptionsProductionPlace { city?: string; state?: string; code?: string; country?: string; } interface OptionsPolicyId { } ``` ### Verify ```typescript Verify(key?: CryptoKey): PromiseLike; ``` __Parameters__ | Name | Description | |:--------------|:------------------------------------------------------------------------| | key | Verifying [Key](https://www.w3.org/TR/WebCryptoAPI/#cryptokey-interface). Optional. If key not set it looks for keys in KeyInfo element of Signature. | ## EXAMPLES ### Create XAdES-BES Signature #### In Node ```javascript var xadesjs = require("xadesjs"); var { Crypto } = require("@peculiar/webcrypto"); xadesjs.Application.setEngine("NodeJS", new Crypto()); // Generate RSA key pair var privateKey, publicKey; xadesjs.Application.crypto.subtle.generateKey( { name: "RSASSA-PKCS1-v1_5", modulusLength: 1024, //can be 1024, 2048, or 4096, publicExponent: new Uint8Array([1, 0, 1]), hash: { name: "SHA-1" }, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512" }, false, //whether the key is extractable (i.e. can be used in exportKey) ["sign", "verify"] //can be any combination of "sign" and "verify" ) .then(function (keyPair) { // Push ganerated keys to global variable privateKey = keyPair.privateKey; publicKey = keyPair.publicKey; // Call sign function var xmlString = '\n\t\n\tAlfonso Soriano\n\t2B\n\tNew York Yankees\n'; return SignXml(xmlString, keyPair, { name: "RSASSA-PKCS1-v1_5", hash: { name: "SHA-1" } }); }) .then(function (signedDocument) { console.log("Signed document:\n\n", signedDocument); }) .catch(function (e) { console.error(e); }); function SignXml(xmlString, keys, algorithm) { return Promise.resolve() .then(() => { var xmlDoc = xadesjs.Parse(xmlString); var signedXml = new xadesjs.SignedXml(); return signedXml.Sign( // Signing document algorithm, // algorithm keys.privateKey, // key xmlDoc, // document { // options keyValue: keys.publicKey, references: [ { hash: "SHA-256", transforms: ["enveloped"] } ], productionPlace: { country: "Country", state: "State", city: "City", code: "Code", }, signingCertificate: "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" }) }) .then(signature => signature.toString()); } ``` #### In the browser ```html XADESJS Signature Sample
``` ### Check XAdES-BES Signature #### In Node ```js var XAdES = require("xadesjs"); var { Crypto } = require("@peculiar/webcrypto"); XAdES.Application.setEngine("NodeJS", new Crypto()); var fs = require("fs"); var xmlString = fs.readFileSync("some.xml","utf8"); var signedDocument = XAdES.Parse(xmlString, "application/xml"); var xmlSignature = signedDocument.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature"); var signedXml = new xadesjs.SignedXml(signedDocument); signedXml.LoadXml(xmlSignature[0]); signedXml.Verify() .then(res => { console.log((res ? "Valid" : "Invalid") + " signature"); }) .catch(function (e) { console.error(e); }); ``` #### In the browser ```html XADESJS Signature Sample
``` ### XAdES-EPES signature ```js const fs = require("fs"); var { Crypto } = require("@peculiar/webcrypto"); const xadesjs = require("xadesjs"); const { XMLSerializer } = require("xmldom"); const crypto = new Crypto(); xadesjs.Application.setEngine("NodeJS", crypto); function preparePem(pem) { return pem // remove BEGIN/END .replace(/-----(BEGIN|END)[\w\d\s]+-----/g, "") // remove \r, \n .replace(/[\r\n]/g, ""); } function pem2der(pem) { pem = preparePem(pem); // convert base64 to ArrayBuffer return new Uint8Array(Buffer.from(pem, "base64")).buffer; } async function main() { const hash = "SHA-256" const alg = { name: "RSASSA-PKCS1-v1_5", hash, } // Read cert const certPem = fs.readFileSync("cert.pem", { encoding: "utf8" }); const certDer = pem2der(certPem); // Read key const keyPem = fs.readFileSync("key.pem", { encoding: "utf8" }); const keyDer = pem2der(keyPem); const key = await crypto.subtle.importKey("pkcs8", keyDer, alg, false, ["sign"]); // XAdES-EPES var xmlString = ``; var xml = xadesjs.Parse(xmlString); var xadesXml = new xadesjs.SignedXml(); const x509 = preparePem(certPem); const signature = await xadesXml.Sign( // Signing document alg, // algorithm key, // key xml, // document { // options references: [ { hash, transforms: ["c14n", "enveloped"] } ], policy: { hash, identifier: { qualifier: "OIDAsURI", value: "quilifier.uri", }, qualifiers: [ { noticeRef: { organization: "PeculiarVentures", noticeNumbers: [1, 2, 3, 4, 5] } } ] }, productionPlace: { country: "Russia", state: "Marij El", city: "Yoshkar-Ola", code: "424000", }, signingCertificate: x509 }); // append signature xml.documentElement.appendChild(signature.GetXml()); // serialize XML const oSerializer = new XMLSerializer(); const sXML = oSerializer.serializeToString(xml); console.log(sXML.toString()) } main() .catch((err) => { console.error(err); }); ``` ## TESTING ### In NodeJS: ``` npm test ``` ## THANKS AND ACKNOWLEDGEMENT This project takes inspiration (style, approach, design and code) from both the [Mono System.Security.Cryptography.Xml](https://github.com/mono/mono/tree/master/mcs/class/System.Security/System.Security.Cryptography.Xml) implementation as well as [xml-crypto](https://github.com/yaronn/xml-crypto). ## RELATED - [xmldsigjs](https://github.com/PeculiarVentures/xmldsigjs) - [Why XML Security is Broken](https://www.cs.auckland.ac.nz/~pgut001/pubs/xmlsec.txt) - [ETSI EN 319 132-1 - XML Advanced Electronic Signatures (XAdES)](http://www.etsi.org/deliver/etsi_en/319100_319199/31913201/01.01.00_30/en_31913201v010100v.pdf) - [ETSI EN 319 132-2 - XML Advanced Electronic Signatures (XAdES)](http://www.etsi.org/deliver/etsi_en/319100_319199/31913202/01.01.00_30/en_31913202v010100v.pdf) - [XML Signature Syntax and Processing](https://www.w3.org/TR/xmldsig-core/) - [XML Security Algorithm Cross-Reference](https://tools.ietf.org/html/rfc6931) - [XMLDSIG HTML Signing Profile](https://www.w3.org/2007/11/h6n/) - [Canonical XML](https://www.w3.org/TR/xml-c14n) - [Exclusive XML Canonicalization](https://www.w3.org/TR/xml-exc-c14n/) - [Internet X.509 Public Key Infrastructure Time-Stamp Protocol](https://www.ietf.org/rfc/rfc3161.txt) - [XAdESj](https://github.com/luisgoncalves/xades4j) - [PKIjs](pkijs.org) - [@peculiar/webcrypto](https://github.com/PeculiarVentures/webcrypto) - [node-webcrypto-ossl](https://github.com/PeculiarVentures/node-webcrypto-ossl) - [node-webcrypto-p11](https://github.com/PeculiarVentures/node-webcrypto-p11) ================================================ FILE: eslint.config.mjs ================================================ // eslint-disable-next-line import/no-unresolved import tseslint from 'typescript-eslint'; import baseConfig from '@peculiar/eslint-config-base'; export default tseslint.config([ ...baseConfig, { ignores: [ 'build/*', 'coverage/*', 'examples/*', ], }, { rules: { '@typescript-eslint/no-non-null-assertion': 'off', 'no-useless-escape': 'off', '@stylistic/max-len': 'off', }, files: [ 'test/**/*.ts', ], }, { rules: { '@typescript-eslint/naming-convention': 'off', '@typescript-eslint/no-explicit-any': 'off', }, }, ]); ================================================ FILE: examples/html/sign.html ================================================ XAdES

XAdES::Sign

Signing params

Select key algorithm


Iclude key vallue:

Select digest algorithm

Type of signature

Enveloped:

Select canon method

Set production place

Set xml

Result

================================================ FILE: examples/html/src/helper.js ================================================ var Browser = { IE: "Internet Explorer", Safari: "Safari", Edge: "Edge", Chrome: "Chrome", Firefox: "Firefox Mozilla", }; /** * Returns info about browser */ function BrowserInfo() { var res = { name: "", version: "" }; var userAgent = self.navigator.userAgent; var reg; if (reg = /edge\/([\d\.]+)/i.exec(userAgent)) { res.name = Browser.Edge; res.version = reg[1]; } else if (/msie/i.test(userAgent)) { res.name = Browser.IE; res.version = /msie ([\d\.]+)/i.exec(userAgent)[1]; } else if (/Trident/i.test(userAgent)) { res.name = Browser.IE; res.version = /rv:([\d\.]+)/i.exec(userAgent)[1]; } else if (/chrome/i.test(userAgent)) { res.name = Browser.Chrome; res.version = /chrome\/([\d\.]+)/i.exec(userAgent)[1]; } else if (/safari/i.test(userAgent)) { res.name = Browser.Safari; res.version = /([\d\.]+) safari/i.exec(userAgent)[1]; } else if (/firefox/i.test(userAgent)) { res.name = Browser.Firefox; res.version = /firefox\/([\d\.]+)/i.exec(userAgent)[1]; } return res; } stringToBuffer = function (text) { var res = new Uint8Array(text.length); for (var i = 0; i < text.length; i++) res[i] = text.charCodeAt(i); return res; }; buffer2string = function (buffer) { var res = ""; for (var i = 0; i < buffer.length; i++) res += String.fromCharCode(buffer[i]); return res; }; ================================================ FILE: examples/html/src/main.js ================================================ function getAlgorithm() { var $key = document.getElementById("key"); var alg = {}; switch ($key.value) { case "rsassa": alg = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256", modulusLength: 1024, publicExponent: new Uint8Array([1, 0, 1]), }; break; case "rsapss": alg = { name: "RSA-PSS", hash: "SHA-256", modulusLength: 1024, publicExponent: new Uint8Array([1, 0, 1]), saltLength: 32, }; break; case "ecdsa": alg = { name: "ECDSA", hash: "SHA-256", namedCurve: "P-256", }; break; } return alg; } function getHashAlgorithm() { return document.getElementById("digest").value; } function getCanonMethod() { return document.getElementById("canon").value; } function isEnveloped() { return document.getElementById("enveloped").checked; } function useKeyValue() { return document.getElementById("keyValue").checked; } function getXml() { return document.getElementById("xml").value; } function getProductionPlace() { var res = {}; ["country", "state", "city", "code"].forEach(function (item) { var $item = document.getElementById(item); if ($item && $item.value) res[item] = $item.value; }); return Object.keys(res).length ? res : null; } function generateKey(alg) { return crypto.subtle.generateKey(alg, false, ["sign", "verify"]) } function exportKey(key) { return crypto.subtle.exportKey("jwk", key) } function error(e) { alert(e.message); console.error(e); } function sign() { var transforms = []; if (isEnveloped()) transforms.push("enveloped"); transforms.push(getCanonMethod()); console.log(transforms); var alg = getAlgorithm(); var keys, signature, res = {}; Promise.resolve() .then(function () { return generateKey(alg); }) .then(function (ks) { keys = ks; return exportKey(ks.publicKey) }) .then(function (jwk) { res.jwk = jwk; }) .then(function () { signature = new XAdES.SignedXml(); return signature.Sign( // Signing document alg, // algorithm keys.privateKey, // key XAdES.Parse(getXml()), // document { // options keyValue: useKeyValue() ? keys.publicKey : void 0, references: [ { hash: getHashAlgorithm(), transforms: transforms } ], productionPlace: getProductionPlace(), signerRole: { claimed: ["BOSS"] } }); }) .then(function () { var sig = signature.toString() res.signature = sig; document.getElementById("jwk").value = JSON.stringify(res.jwk); document.getElementById("signature").value = res.signature; }) .catch(function (e) { console.error(e); }); } function verify() { var $xml = document.getElementById("xml"); var $info = document.getElementById("signature_info"); if (!$xml.value) return error(new Error("Unable to get XML")); var xml = XAdES.Parse($xml.value); var signature = new XAdES.SignedXml(xml); var xmlSignatures = XAdES.Select(xml, "//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']"); if (!(xmlSignatures && xmlSignatures.length)) return error("Cannot get XML signature from XML document"); signature.LoadXml(xmlSignatures[0]); signature.Verify() .then(function (res) { var info = []; info.push("Signature valid: " + res.toString()); info.push("================================="); var si = signature.XmlSignature.SignedInfo; info.push("Signature method: " + si.SignatureMethod.Algorithm); info.push("Canonicalization method: " + si.CanonicalizationMethod.Algorithm); info.push("References:"); si.References.ForEach(function (ref, index) { info.push(" Reference #" + (index + 1)); ref.Type && info.push(" Type: " + ref.Type); ref.Uri && info.push(" Uri: " + ref.Uri); info.push(" Digest method: " + ref.DigestMethod.Algorithm); ref.Transforms.ForEach(function (transform) { info.push(" Transform: " + transform.Algorithm); }); }); var ssp = signature.SignedProperties.SignedSignatureProperties; info.push("Signed signature properties:"); info.push(" Signing time: " + ssp.SigningTime.Value); if (ssp.SigningCertificate.Count) { info.push("Signing certificate:"); ssp.SigningCertificate.ForEach(function (cert) { info.push(" Issuer name: " + cert.IssuerSerial.X509IssuerName); info.push(" Serial number: " + cert.IssuerSerial.X509SerialNumber); info.push(" Digest method: " + cert.CertDigest.DigestMethod.Algorithm); info.push(" Digest: " + XAdES.Convert.ToHex(cert.CertDigest.DigestValue)); }); } if (ssp.SignatureProductionPlace.Element) { info.push(" Production place:"); ssp.SignatureProductionPlace.CountryName && info.push(" Country:" + ssp.SignatureProductionPlace.CountryName); ssp.SignatureProductionPlace.StateOrProvince && info.push(" State or province:" + ssp.SignatureProductionPlace.StateOrProvince); ssp.SignatureProductionPlace.City && info.push(" City:" + ssp.SignatureProductionPlace.City); ssp.SignatureProductionPlace.PostalCode && info.push(" Post code:" + ssp.SignatureProductionPlace.PostalCode); } if (ssp.SignaturePolicyIdentifier.Element) { info.push(" Signature policy identifier:"); var spi = ssp.SignaturePolicyIdentifier; spi.SignaturePolicyImplied && info.push(" Implied: true"); spi.SignaturePolicyId.Element && info.push(" Id: true"); } if (signature.SignedProperties.SignedDataObjectProperties.Element) { info.push("Signed data object properties:"); var sdop = signature.SignedProperties.SignedDataObjectProperties; sdop.DataObjectFormats.Count && info.push(" Data object format count: " + sdop.DataObjectFormats.Count); sdop.CommitmentTypeIndications.Count && info.push(" Commitment type indication count: " + sdop.CommitmentTypeIndications.Count); sdop.AllDataObjectsTimeStamps.Count && info.push(" All data objects TimeStamp count: " + sdop.AllDataObjectsTimeStamps.Count); sdop.IndividualDataObjectsTimeStamps.Count && info.push(" Individual data objects TimeStamp count: " + sdop.IndividualDataObjectsTimeStamps.Count); } if (signature.UnsignedProperties.Element) { info.push("Unsigned properties: true"); } $info.textContent = info.join("\n"); }) .catch(function (e) { error(e); }); } ================================================ FILE: examples/html/verify.html ================================================ XAdES

XAdES::Verify

Enveloped XAdES signature

Result

================================================ FILE: package.json ================================================ { "name": "xadesjs", "version": "2.4.4", "description": "A pure Typescript/Javascript implementation of XAdES based on XMLDSIGjs.", "main": "build/index.js", "types": "build/types/index.d.ts", "module": "build/index.es.js", "unpkg": "build/xades.js", "unpkgMin": "build/xades.min.js", "scripts": { "prepare": "npm run build", "test": "mocha", "clear": "rimraf build/*", "build": "npm run build:module && npm run build:types", "build:module": "rollup -c", "build:types": "tsc -p tsconfig.types.json", "rebuild": "npm run clear && npm run build", "lint": "eslint", "prepub": "npm run lint && npm run build", "postpub": "git push && git push --tags origin master", "pub": "npm version patch && npm publish", "prepub:next": "npm run lint && npm run build", "pub:next": "npm version prerelease --preid=next && npm publish --tag next", "postpub:next": "git push", "sync": "git ac && git pull --rebase && git push", "coverage": "nyc npm test" }, "repository": { "type": "git", "url": "git+https://github.com/PeculiarVentures/xadesjs.git" }, "keywords": [ "xml", "xmldsig", "xades", "webcrypto", "signature", "rsa", "ec" ], "author": "Peculiar Ventures, Inc.", "contributors": [ "Miroshin Stepan" ], "license": "MIT", "bugs": { "url": "https://github.com/PeculiarVentures/xadesjs/issues" }, "homepage": "https://github.com/PeculiarVentures/xadesjs#readme", "dependencies": { "xml-core": "^1.1.4", "xmldsigjs": "^2.5.0" }, "devDependencies": { "@babel/core": "^7.17.10", "@babel/plugin-proposal-class-properties": "^7.16.7", "@babel/plugin-proposal-object-rest-spread": "^7.17.3", "@babel/preset-env": "^7.17.10", "@peculiar/eslint-config-base": "^0.2.5", "@peculiar/webcrypto": "^1.3.3", "@rollup/plugin-node-resolve": "^13.3.0", "@types/dateformat": "^5.0.0", "@types/mocha": "^9.1.1", "@types/node": "^17.0.31", "@xmldom/xmldom": "^0.8.2", "mocha": "^10.0.0", "nyc": "^15.1.0", "rollup": "^2.72.1", "rollup-plugin-babel": "^4.4.0", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-terser": "^7.0.2", "rollup-plugin-typescript2": "^0.31.2", "ts-node": "^10.7.0", "tslib": "^2.4.0", "typescript": "^4.6.4" }, "nyc": { "extension": [ ".ts", ".tsx" ], "include": [ "src/**/*.ts" ], "exclude": [ "**/*.d.ts" ], "reporter": [ "lcov" ] }, "mocha": { "require": "ts-node/register", "extension": [ "ts" ], "spec": [ "test/**/*.ts" ] } } ================================================ FILE: rollup.config.js ================================================ import resolve from '@rollup/plugin-node-resolve'; import babel from 'rollup-plugin-babel'; import commonjs from 'rollup-plugin-commonjs'; import typescript from 'rollup-plugin-typescript2'; import { terser } from 'rollup-plugin-terser'; import pkg from './package.json'; const banner = [].join('\n'); const input = 'src/index.ts'; const external = Object.keys(pkg.dependencies) .concat(['events']); // main const main = { input, plugins: [ typescript({ check: true, clean: true, tsconfigOverride: { compilerOptions: { module: 'ES2015' } }, }), ], external, output: [ { banner, file: pkg.main, format: 'cjs', }, { banner, file: pkg.module, format: 'es', }, ], }; const browserExternals = { '@xmldom/xmldom': 'self', xpath: 'self', }; const browser = [ { input, plugins: [ resolve({ mainFields: ['esnext', 'module', 'main'], preferBuiltins: true, }), commonjs(), typescript({ check: true, clean: true, tsconfigOverride: { compilerOptions: { module: 'es2015' } }, }), ], external: Object.keys(browserExternals), output: [ { file: pkg.unpkg, format: 'es', globals: browserExternals, }, ], }, { input: pkg.unpkg, external: Object.keys(browserExternals), plugins: [ babel({ babelrc: false, runtimeHelpers: true, compact: false, comments: false, presets: [ ['@babel/env', { targets: { ie: '11', chrome: '60', }, useBuiltIns: 'entry', corejs: 3, }], ], plugins: [ ['@babel/plugin-proposal-class-properties'], ['@babel/proposal-object-rest-spread'], ], }), ], output: [ { banner, file: pkg.unpkg, globals: browserExternals, format: 'iife', name: 'XAdES', }, { banner, file: pkg.unpkgMin, globals: browserExternals, format: 'iife', name: 'XAdES', plugins: [ terser(), ], }, ], }, ]; export default [ main, ...browser, ]; ================================================ FILE: src/dateformat.ts ================================================ /* * Date Format 3.0.2 * (c) 2007-2009 Steven Levithan * MIT license * * Includes enhancements by Scott Trenda * and Kris Kowal * * Accepts a date, a mask, or a date and a mask. * Returns a formatted version of the given date. * The date defaults to the current date/time. * The mask defaults to dateFormat.masks.default. */ const token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZWN]|"[^"]*"|'[^']*'/g; const timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g; const timezoneClip = /[^-+\dA-Z]/g; export function dateFormat(date: any, mask: string, utc?: boolean, gmt?: boolean) { // You can't provide utc if you skip other args (use the 'UTC:' mask prefix) if (arguments.length === 1 && kindOf(date) === 'string' && !/\d/.test(date)) { mask = date; date = undefined; } date = date || new Date(); if (!(date instanceof Date)) { date = new Date(date); } if (isNaN(date)) { throw TypeError('Invalid date'); } mask = String(masks[mask] || mask || masks.default); // Allow setting the utc/gmt argument via the mask const maskSlice = mask.slice(0, 4); if (maskSlice === 'UTC:' || maskSlice === 'GMT:') { mask = mask.slice(4); utc = true; if (maskSlice === 'GMT:') { gmt = true; } } const _ = utc ? 'getUTC' : 'get'; const d = date[_ + 'Date'](); const D = date[_ + 'Day'](); const m = date[_ + 'Month'](); const y = date[_ + 'FullYear'](); const H = date[_ + 'Hours'](); const M = date[_ + 'Minutes'](); const s = date[_ + 'Seconds'](); const L = date[_ + 'Milliseconds'](); const o = utc ? 0 : date.getTimezoneOffset(); const W = getWeek(date); const N = getDayOfWeek(date); const flags: any = { d, dd: pad(d), ddd: i18n.dayNames[D], dddd: i18n.dayNames[D + 7], m: m + 1, mm: pad(m + 1), mmm: i18n.monthNames[m], mmmm: i18n.monthNames[m + 12], yy: String(y).slice(2), yyyy: y, h: H % 12 || 12, hh: pad(H % 12 || 12), H, HH: pad(H), M, MM: pad(M), s, ss: pad(s), l: pad(L, 3), L: pad(Math.round(L / 10)), t: H < 12 ? i18n.timeNames[0] : i18n.timeNames[1], tt: H < 12 ? i18n.timeNames[2] : i18n.timeNames[3], T: H < 12 ? i18n.timeNames[4] : i18n.timeNames[5], TT: H < 12 ? i18n.timeNames[6] : i18n.timeNames[7], // eslint-disable-next-line no-nested-ternary Z: gmt ? 'GMT' : utc ? 'UTC' : (String(date).match(timezone) || ['']).pop()?.replace(timezoneClip, ''), o: (o > 0 ? '-' : '+') + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), // S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10], W, N, }; return mask.replace(token, (match) => { if (match in flags) { return flags[match]; } return match.slice(1, match.length - 1); }); } const masks: Record = { default: 'ddd mmm dd yyyy HH:MM:ss', shortDate: 'm/d/yy', mediumDate: 'mmm d, yyyy', longDate: 'mmmm d, yyyy', fullDate: 'dddd, mmmm d, yyyy', shortTime: 'h:MM TT', mediumTime: 'h:MM:ss TT', longTime: 'h:MM:ss TT Z', isoDate: 'yyyy-mm-dd', isoTime: 'HH:MM:ss', isoDateTime: 'yyyy-mm-dd\'T\'HH:MM:sso', isoUtcDateTime: 'UTC:yyyy-mm-dd\'T\'HH:MM:ss\'Z\'', expiresHeaderFormat: 'ddd, dd mmm yyyy HH:MM:ss Z', }; // Internationalization strings const i18n = { dayNames: [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', ], monthNames: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December', ], timeNames: [ 'a', 'p', 'am', 'pm', 'A', 'P', 'AM', 'PM', ], }; function pad(val: any, len = 2) { val = String(val); while (val.length < len) { val = '0' + val; } return val; } /** * Get the ISO 8601 week number * Based on comments from * http://techblog.procurios.nl/k/n618/news/view/33796/14863/Calculate-ISO-8601-week-and-year-in-javascript.html * @param {Object} `date` * @return {Number} */ function getWeek(date: Date) { // Remove time components of date const targetThursday = new Date(date.getFullYear(), date.getMonth(), date.getDate()); // Change date to Thursday same week targetThursday.setDate(targetThursday.getDate() - ((targetThursday.getDay() + 6) % 7) + 3); // Take January 4th as it is always in week 1 (see ISO 8601) const firstThursday = new Date(targetThursday.getFullYear(), 0, 4); // Change date to Thursday same week firstThursday.setDate(firstThursday.getDate() - ((firstThursday.getDay() + 6) % 7) + 3); // Check if daylight-saving-time-switch occurred and correct for it const ds = targetThursday.getTimezoneOffset() - firstThursday.getTimezoneOffset(); targetThursday.setHours(targetThursday.getHours() - ds); // Number of weeks between target Thursday and first Thursday const weekDiff = (targetThursday.getTime() - firstThursday.getTime()) / (86400000 * 7); return 1 + Math.floor(weekDiff); } /** * Get ISO-8601 numeric representation of the day of the week * 1 (for Monday) through 7 (for Sunday) * @param {Object} `date` * @return {Number} */ function getDayOfWeek(date: Date) { let dow = date.getDay(); if (dow === 0) { dow = 7; } return dow; } /** * kind-of shortcut * @param {*} val * @return {String} */ function kindOf(val: any) { if (val === null) { return 'null'; } if (val === undefined) { return 'undefined'; } if (typeof val !== 'object') { return typeof val; } if (Array.isArray(val)) { return 'array'; } return {}.toString.call(val) .slice(8, -1).toLowerCase(); } ================================================ FILE: src/index.ts ================================================ export * as xml from './xml'; export * from './signed_xml'; export { Application } from 'xmldsigjs'; export { Select, Parse, Convert, } from 'xml-core'; ================================================ FILE: src/signed_xml.ts ================================================ import * as XmlCore from 'xml-core'; import * as XmlDSigJs from 'xmldsigjs'; import * as XAdES from './xml'; const XADES_REFERENCE_TYPE = 'http://uri.etsi.org/01903#SignedProperties'; export interface OptionsSignerRole { claimed?: string[]; certified?: string[]; } export interface OptionsProductionPlace { city?: string; state?: string; code?: string; country?: string; } export interface OptionsNoticeReference { organization: string; noticeNumbers: number[]; } export interface OptionsPolicyUserNotice { noticeRef?: OptionsNoticeReference; explicitText?: string; } export interface OptionsPolicyIdentifier { qualifier?: XAdES.IdentifierQualifier; value: string; description?: string; references?: string[]; } export interface OptionsPolicyId { identifier: OptionsPolicyIdentifier; transforms?: XmlDSigJs.OptionsSignTransform[]; hash: AlgorithmIdentifier; digestValue?: string; qualifiers?: (OptionsPolicyUserNotice | string)[]; } export interface OptionsSigningTime { /** * Signing time value. Default value if now */ value?: Date; /** * Format of the signing time. Default format is ISO */ format?: string; } export interface OptionsSigningCertificate { certificate: string; digestAlgorithm?: AlgorithmIdentifier; } export interface OptionsSigningCertificateV2 { certificate: string; digestAlgorithm?: AlgorithmIdentifier; } // eslint-disable-next-line import/namespace export interface OptionsXAdES extends XmlDSigJs.OptionsSign { /** * Sets a certificate of signer for signature. Optional */ signingCertificate?: string | OptionsSigningCertificate; /** * Sets a certificate of signer for signature. Optional */ signingCertificateV2?: string | OptionsSigningCertificateV2; /** * Sets signing time options */ signingTime?: OptionsSigningTime; policy?: OptionsPolicyId | boolean; productionPlace?: OptionsProductionPlace; signerRole?: OptionsSignerRole; } export class SignedXml extends XmlDSigJs.SignedXml { protected properties: XAdES.QualifyingProperties | null = null; get Properties(): XAdES.QualifyingProperties | null { return this.properties; } get SignedProperties(): XAdES.SignedProperties { if (!this.Properties) { throw new XmlCore.XmlError(XmlCore.XE.XML_EXCEPTION, 'Properties is empty'); } return this.Properties.SignedProperties; } get UnsignedProperties(): XAdES.UnsignedProperties { if (!this.Properties) { throw new XmlCore.XmlError(XmlCore.XE.XML_EXCEPTION, 'Properties is empty'); } return this.Properties.UnsignedProperties; } constructor(node?: Document | Element) { super(node); this.CreateQualifyingProperties(); } // #region Public methods public LoadXml(value: Element | string) { super.LoadXml(value as string); let properties: XAdES.QualifyingProperties | null = null; this.XmlSignature.ObjectList.Some((item) => { if (item.Element) { // Looking for for (let i = 0; i < item.Element.childNodes.length; i++) { const node = item.Element.childNodes.item(i); if (node.nodeType === XmlCore.XmlNodeType.Element && (node as Element).localName === XAdES.XmlXades.ElementNames.QualifyingProperties) { properties = XAdES.QualifyingProperties.LoadXml(node as Element); return true; } } } return false; }); this.properties = properties; } public async Sign( // eslint-disable-next-line @typescript-eslint/no-unused-vars algorithm: Algorithm, // eslint-disable-next-line @typescript-eslint/no-unused-vars key: CryptoKey, // eslint-disable-next-line @typescript-eslint/no-unused-vars data: Document | XmlDSigJs.DigestReferenceSource, // eslint-disable-next-line @typescript-eslint/no-unused-vars options?: OptionsXAdES, ) { // eslint-disable-next-line prefer-rest-params return super.Sign.apply(this, arguments as any); } // #endregion // #region Protected methods protected CreateQualifyingProperties() { if (this.Properties) { throw new XmlCore.XmlError(XmlCore.XE.XML_EXCEPTION, 'Cannot create QualifyingProperties cause current signature has got one. You must create CounterSignature'); } const rnd = XmlDSigJs.Application.crypto.getRandomValues(new Uint8Array(6)) as Uint8Array; const id = XmlCore.Convert.ToHex(rnd); this.XmlSignature.Id ||= `id-${id}`; const dataObject = new XAdES.DataObject(); dataObject.QualifyingProperties.Target = `#${this.XmlSignature.Id}`; dataObject.QualifyingProperties.SignedProperties.Id ||= `xades-${this.XmlSignature.Id}`; this.properties = dataObject.QualifyingProperties; this.XmlSignature.ObjectList.Add(dataObject); } protected async ApplySignOptions( signature: XmlDSigJs.Signature, algorithm: Algorithm, key: CryptoKey, options: OptionsXAdES, ) { await super.ApplySignOptions(signature, algorithm, key, options); if (this.Properties) { const sigProps = this.Properties.SignedProperties.SignedSignatureProperties; // #region Add SigningTime sigProps.SigningTime.Value = new Date(); if (options.signingTime) { if (options.signingTime.value) { sigProps.SigningTime.Value = options.signingTime.value; } if (options.signingTime.format) { sigProps.SigningTime.Format = options.signingTime.format; } } // #endregion // Add reference for SignedProperties const signingAlg = XmlCore.assign({}, algorithm, key.algorithm); const xadesRefHash = signingAlg.hash; const xadesRef = new XmlDSigJs.Reference(); xadesRef.Type = XADES_REFERENCE_TYPE; xadesRef.Uri = `#${this.Properties.SignedProperties.Id}`; xadesRef.DigestMethod.Algorithm = XmlDSigJs.CryptoConfig .GetHashAlgorithm(xadesRefHash).namespaceURI; signature.SignedInfo.References.Add(xadesRef); await this.ApplySigningCertificate(options.signingCertificate); await this.ApplySigningCertificateV2(options.signingCertificateV2); await this.ApplySignaturePolicyIdentifier(options.policy); this.ApplySignatureProductionPlace(options.productionPlace); this.ApplySignerRoles(options.signerRole); } } protected async ApplySigningCertificate(value?: string | OptionsSigningCertificate) { if (this.Properties && value) { const options: OptionsSigningCertificate = typeof value === 'string' ? { certificate: value } : value; if (!options.digestAlgorithm) { options.digestAlgorithm = 'SHA-256'; // set default alg if required } const raw = XmlCore.Convert.FromBase64(options.certificate); const cert = new XmlDSigJs.X509Certificate(raw); const ssp = this.Properties.SignedProperties.SignedSignatureProperties; if (ssp.SigningCertificate.Count) { throw new XmlCore.XmlError(XmlCore.XE.XML_EXCEPTION, 'Signature can contain only one SigningCertificate'); } const signingCertificate = new XAdES.Cert(); signingCertificate.IssuerSerial.X509IssuerName = cert.Issuer; signingCertificate.IssuerSerial.X509SerialNumber = cert.SerialNumber; const alg = XmlDSigJs.CryptoConfig.GetHashAlgorithm(options.digestAlgorithm); signingCertificate.CertDigest.DigestMethod.Algorithm = alg.namespaceURI; signingCertificate.CertDigest.DigestValue = new Uint8Array( await cert.Thumbprint(alg.algorithm.name), ); this.Properties.SignedProperties.SignedSignatureProperties.SigningCertificate.Add( signingCertificate, ); } } protected async ApplySigningCertificateV2(value?: string | OptionsSigningCertificateV2) { if (this.Properties && value) { const options: OptionsSigningCertificate = typeof value === 'string' ? { certificate: value } : value; if (!options.digestAlgorithm) { options.digestAlgorithm = 'SHA-256'; // set default alg if required } const raw = XmlCore.Convert.FromBase64(options.certificate); const cert = new XmlDSigJs.X509Certificate(raw); const ssp = this.Properties.SignedProperties.SignedSignatureProperties; if (ssp.SigningCertificateV2.Count) { throw new XmlCore.XmlError(XmlCore.XE.XML_EXCEPTION, 'Signature can contain only one SigningCertificateV2'); } const signingCertificate = new XAdES.CertV2(); // TODO: base64 encoded DER of IssuerSerial as defined by IETF RFC 5035 // signingCertificate.IssuerSerial const alg = XmlDSigJs.CryptoConfig.GetHashAlgorithm(options.digestAlgorithm); signingCertificate.CertDigest.DigestMethod.Algorithm = alg.namespaceURI; signingCertificate.CertDigest.DigestValue = new Uint8Array( await cert.Thumbprint(alg.algorithm.name), ); this.Properties.SignedProperties.SignedSignatureProperties.SigningCertificateV2.Add( signingCertificate, ); } } protected async ApplySignaturePolicyIdentifier(options?: OptionsPolicyId | boolean) { if (this.Properties) { const ssp = this.Properties.SignedProperties.SignedSignatureProperties; if (options && typeof options === 'object') { const policyId = new XAdES.SignaturePolicyId(); policyId.SigPolicyId = new XAdES.SigPolicyId(); policyId.SigPolicyId.Identifier = new XAdES.Identifier(); if (options.identifier.qualifier) { policyId.SigPolicyId.Identifier.Qualifier = options.identifier.qualifier; } policyId.SigPolicyId.Identifier.Value = options.identifier.value; if (options.identifier.description) { policyId.SigPolicyId.Description = options.identifier.description; } if (options.identifier.references) { policyId.SigPolicyId.DocumentationReferences = new XAdES.DocumentationReferences(); options.identifier.references.forEach((referenceValue) => { const reference = new XAdES.DocumentationReference(); reference.Uri = referenceValue; policyId.SigPolicyId.DocumentationReferences.Add(reference); }); } if (options.transforms && options.transforms.length) { policyId.Transforms = new XmlDSigJs.Transforms(); options.transforms.forEach((transform) => { policyId.Transforms.Add(this.ResolveTransform(transform)); }); } policyId.SigPolicyHash = new XAdES.SigPolicyHash(); policyId.SigPolicyHash.DigestMethod = new XmlDSigJs.DigestMethod(); const digestAlgorithm = XmlDSigJs.CryptoConfig.GetHashAlgorithm(options.hash); policyId.SigPolicyHash.DigestMethod.Algorithm = digestAlgorithm.namespaceURI; if (options.digestValue) { policyId.SigPolicyHash.DigestValue = XmlCore.Convert.FromBase64(options.digestValue); } else { const identifierDoc = policyId.SigPolicyId.Identifier .GetXml()?.cloneNode(true) as Element; this.CopyNamespaces(identifierDoc, identifierDoc, true); this.InjectNamespaces(this.GetSignatureNamespaces(), identifierDoc, true); let identifierContent: any = null; if (policyId.Transforms && policyId.Transforms.Count) { identifierContent = this.ApplyTransforms(policyId.Transforms, identifierDoc); } else { const c14n = new XmlDSigJs.XmlDsigC14NTransform(); c14n.LoadInnerXml(identifierDoc); identifierContent = c14n.GetOutput(); } policyId.SigPolicyHash.DigestValue = await digestAlgorithm.Digest(identifierContent); } if (options.qualifiers) { policyId.SigPolicyQualifiers = new XAdES.SigPolicyQualifiers(); options.qualifiers.forEach((qualifierValue) => { const container = new XAdES.SigPolicyQualifier(); if (typeof qualifierValue === 'string') { const qualifier = new XAdES.SPURI(); qualifier.Value = qualifierValue; container.Add(qualifier); } else { const qualifier = new XAdES.SPUserNotice(); if (qualifierValue.explicitText) { qualifier.ExplicitText = qualifierValue.explicitText; } if (qualifierValue.noticeRef) { qualifier.NoticeRef = new XAdES.NoticeReference(); qualifier.NoticeRef.Organization = qualifierValue.noticeRef.organization; qualifier.NoticeRef.NoticeNumbers = new XAdES.IntegerList(); if (qualifierValue.noticeRef.noticeNumbers) { qualifierValue.noticeRef.noticeNumbers.forEach((numberValue) => { const noticeNumber = new XAdES.Integer(); noticeNumber.Value = numberValue; qualifier.NoticeRef.NoticeNumbers.Add(noticeNumber); }); } } container.Add(qualifier); } policyId.SigPolicyQualifiers.Add(container); }); } ssp.SignaturePolicyIdentifier.SignaturePolicyId = policyId; ssp.SignaturePolicyIdentifier.SignaturePolicyImplied = false; } else if (options) { ssp.SignaturePolicyIdentifier.SignaturePolicyImplied = true; } } } protected ApplySignatureProductionPlace(options?: OptionsProductionPlace) { if (this.Properties && options) { const ssp = this.Properties.SignedProperties.SignedSignatureProperties; if (options.city) { ssp.SignatureProductionPlace.City = options.city; } if (options.code) { ssp.SignatureProductionPlace.PostalCode = options.code; } if (options.country) { ssp.SignatureProductionPlace.CountryName = options.country; } if (options.state) { ssp.SignatureProductionPlace.StateOrProvince = options.state; } } } protected ApplySignerRoles(options?: OptionsSignerRole) { if (this.Properties && options) { const ssp = this.Properties.SignedProperties.SignedSignatureProperties; if (options.claimed) { options.claimed.forEach((role) => { const claimedRole = new XAdES.ClaimedRole(); claimedRole.Value = role; ssp.SignerRole.ClaimedRoles.Add(claimedRole); }); } if (options.certified) { options.certified.forEach((role) => { const certifiedRole = new XAdES.CertifiedRole(); certifiedRole.Encoding = 'der'; certifiedRole.Value = XmlCore.Convert.FromBase64(role); ssp.SignerRole.CertifiedRoles.Add(certifiedRole); }); } } } protected async VerifySigningCertificate() { let x509: XmlDSigJs.X509Certificate | null = null; if (this.XmlSignature && this.Properties) { const ssp = this.Properties.SignedProperties.SignedSignatureProperties; if (ssp.SigningCertificate.Count !== 1) { throw new XmlCore.XmlError(XmlCore.XE.XML_EXCEPTION, 'Signature has got wrong amount of SigningCertificate, MUST be one'); } // find certificate by Thumbprint const alg = XmlDSigJs.CryptoConfig.GetHashAlgorithm('SHA-256'); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const signingCertificate = ssp.SigningCertificate.Item(0)!; const b64CertDigest = XmlCore.Convert.ToBase64(signingCertificate.CertDigest.DigestValue); const keyInfos = this.XmlSignature.KeyInfo; for (let i = 0; i < keyInfos.Count, !x509; i++) { const item = keyInfos.Item(i); if (item instanceof XmlDSigJs.KeyInfoX509Data) { const certs = item.Certificates; for (let j = 0; j < certs.length, !x509; j++) { const cert = certs[j]; if (!cert) { continue; } const hash = new Uint8Array(await cert.Thumbprint(alg.algorithm as any)); const b64Hash = XmlCore.Convert.ToBase64(hash); if (b64Hash === b64CertDigest) { x509 = cert; } } } } if (!( x509 && x509.Issuer === signingCertificate.IssuerSerial.X509IssuerName && x509.SerialNumber === signingCertificate.IssuerSerial.X509SerialNumber )) { throw new XmlCore.XmlError(XmlCore.XE.XML_EXCEPTION, 'SigningCertificate not found'); } } return x509; } // #endregion } ================================================ FILE: src/xml/any.ts ================================================ import { XmlContent, XmlElement } from 'xml-core'; import { XmlXades } from './xml'; import { XadesCollection, XadesObject } from './xml_base'; /** * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.Any }) export class Any extends XadesObject { @XmlContent() public Value: string; } @XmlElement({ localName: XmlXades.ElementNames.Any }) export class AnyCollection extends XadesCollection { } ================================================ FILE: src/xml/certificate_values.ts ================================================ import { XmlAttribute, XmlChildElement, XmlElement, } from 'xml-core'; import { Any } from './any'; import { EncapsulatedPKIData } from './encapsulated_pki_data'; import { XmlXades } from './xml'; import { XadesCollection, XadesObject } from './xml_base'; /** * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.OtherCertificate }) export class OtherCertificate extends Any { } @XmlElement({ localName: 'OtherCertificateCollection', parser: OtherCertificate, }) export class OtherCertificateCollection extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.EncapsulatedX509Certificate }) export class EncapsulatedX509Certificate extends EncapsulatedPKIData { } @XmlElement({ localName: 'EncapsulatedX509CertificateCollection', parser: EncapsulatedX509Certificate, }) export class EncapsulatedX509CertificateCollection extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.CertificateValues }) export class CertificateValues extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; @XmlChildElement({ parser: EncapsulatedX509CertificateCollection, noRoot: true, }) public EncapsulatedX509Certificates: EncapsulatedX509CertificateCollection; @XmlChildElement({ parser: OtherCertificateCollection, noRoot: true, }) public OtherCertificates: OtherCertificateCollection; } ================================================ FILE: src/xml/commitment_type_indication.ts ================================================ import { XmlChildElement, XmlContent, XmlElement, IConverter, } from 'xml-core'; import { Any } from './any'; import { ObjectIdentifier } from './object_identifier'; import { XmlXades } from './xml'; import { XadesCollection, XadesObject } from './xml_base'; /** * * * * * * * * * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.CommitmentTypeQualifier }) export class CommitmentTypeQualifier extends Any { } @XmlElement({ localName: XmlXades.ElementNames.CommitmentTypeQualifiers, parser: CommitmentTypeQualifier, }) export class CommitmentTypeQualifiers extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.ObjectReference }) export class ObjectReference extends XadesObject { @XmlContent({ required: true }) public Value: string; } @XmlElement({ localName: 'ObjectReferences', parser: ObjectReference, }) export class ObjectReferenceCollection extends XadesCollection { } const XmlAllSignedDataObjectsConverter: IConverter = { // eslint-disable-next-line @typescript-eslint/no-unused-vars set: (value: string) => { // if SignaturePolicyImplied exists then return true return true; }, // eslint-disable-next-line @typescript-eslint/no-unused-vars get: (value: boolean) => { return void 0; }, }; @XmlElement({ localName: XmlXades.ElementNames.CommitmentTypeIndication }) export class CommitmentTypeIndication extends XadesObject { @XmlChildElement({ localName: XmlXades.ElementNames.CommitmentTypeId, required: true, namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, parser: ObjectIdentifier, }) public CommitmentTypeId: ObjectIdentifier; @XmlChildElement({ parser: ObjectReferenceCollection, noRoot: true, }) public ObjectReference: ObjectReferenceCollection; @XmlChildElement({ localName: XmlXades.ElementNames.AllSignedDataObjects, namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, converter: XmlAllSignedDataObjectsConverter, defaultValue: false, }) public AllSignedDataObjects: boolean; @XmlChildElement({ localName: XmlXades.ElementNames.CommitmentTypeQualifiers, parser: CommitmentTypeQualifier, }) public CommitmentTypeQualifiers: CommitmentTypeQualifiers; } ================================================ FILE: src/xml/complete_certificate_refs.ts ================================================ import { XmlAttribute, XmlChildElement, XmlElement, } from 'xml-core'; import { CertIDList } from './signing_certificate'; import { UnsignedSignatureProperty } from './unsigned_signature_properties'; import { XmlXades } from './xml'; import { XadesObject } from './xml_base'; /** * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.CompleteCertificateRefs }) export class CompleteCertificateRefs extends XadesObject implements UnsignedSignatureProperty { @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; @XmlChildElement({ localName: XmlXades.ElementNames.CertRefs, parser: CertIDList, required: true, }) public CertRefs: CertIDList; } ================================================ FILE: src/xml/complete_revocation_refs.ts ================================================ import { XmlAttribute, XmlChildElement, XmlElement, XmlBase64Converter, XmlNumberConverter, } from 'xml-core'; import { Any } from './any'; import { XadesDateTime } from './date_time'; import { DigestAlgAndValueType } from './signing_certificate'; import { UnsignedSignatureProperty } from './unsigned_signature_properties'; import { XmlXades } from './xml'; import { XadesCollection, XadesObject } from './xml_base'; /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.OtherRef }) export class OtherRef extends Any { } @XmlElement({ localName: XmlXades.ElementNames.OtherRefs }) export class OtherRefs extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.OCSPIdentifier }) export class ResponderID extends XadesObject { @XmlChildElement({ localName: XmlXades.ElementNames.ByName, namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, required: true, }) public ByName: string; @XmlChildElement({ localName: XmlXades.ElementNames.ByKey, namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, converter: XmlBase64Converter, required: true, }) public ByKey: Uint8Array; } @XmlElement({ localName: XmlXades.ElementNames.OCSPIdentifier }) export class OCSPIdentifier extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.URI, defaultValue: '', }) public URI: string; @XmlChildElement({ parser: ResponderID, required: true, }) public ResponderID: ResponderID; @XmlChildElement({ localName: XmlXades.ElementNames.IssueTime, parser: XadesDateTime, required: true, }) public ProducedAt: XadesDateTime; } @XmlElement({ localName: XmlXades.ElementNames.OCSPRef }) export class OCSPRef extends XadesObject { @XmlChildElement({ parser: OCSPIdentifier }) public OCSPIdentifier: OCSPIdentifier; @XmlChildElement({ parser: DigestAlgAndValueType, required: true, }) public DigestAlgAndValue: DigestAlgAndValueType; } @XmlElement({ localName: XmlXades.ElementNames.OCSPRefs }) export class OCSPRefs extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.CRLIdentifier }) export class CRLIdentifier extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.URI, defaultValue: '', }) public URI: string; @XmlChildElement({ localName: XmlXades.ElementNames.Issuer, namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, required: true, }) public Issuer: string; @XmlChildElement({ localName: XmlXades.ElementNames.IssueTime, parser: XadesDateTime, required: true, }) public IssueTime: XadesDateTime; @XmlChildElement({ localName: XmlXades.ElementNames.Number, namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, converter: XmlNumberConverter, }) public Number: number; } @XmlElement({ localName: XmlXades.ElementNames.CRLRef }) export class CRLRef extends XadesObject { @XmlChildElement({ parser: DigestAlgAndValueType, required: true, }) public DigestAlgAndValue: DigestAlgAndValueType; @XmlChildElement({ parser: CRLIdentifier }) public CRLIdentifier: CRLIdentifier; } @XmlElement({ localName: XmlXades.ElementNames.CRLRefs }) export class CRLRefs extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.CompleteRevocationRefs }) export class CompleteRevocationRefs extends XadesObject implements UnsignedSignatureProperty { @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; @XmlChildElement({ parser: CRLRefs }) public CRLRefs: CRLRefs; @XmlChildElement({ parser: OCSPRefs }) public OCSPRefs: OCSPRefs; @XmlChildElement({ parser: OtherRefs }) public OtherRefs: OtherRefs; } ================================================ FILE: src/xml/converter.ts ================================================ import { IConverter } from 'xml-core'; export const XmlDateTimeConverter: IConverter = { /** * Converts value from Xml element to Date * @memberOf XmlDateTimeConverter */ set: (value: string) => new Date(value), /** * Converts value from Date to Xml element * @memberOf XmlDateTimeConverter */ get: (value: Date) => { if (value) { return value.toISOString(); } return undefined; }, }; ================================================ FILE: src/xml/counter_signature.ts ================================================ import { XmlChildElement, XmlElement } from 'xml-core'; import { Signature } from 'xmldsigjs'; import { UnsignedSignatureProperty } from './unsigned_signature_properties'; import { XmlXades } from './xml'; import { XadesObject } from './xml_base'; /** * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.CounterSignature }) export class CounterSignature extends XadesObject implements UnsignedSignatureProperty { @XmlChildElement({ parser: Signature, required: true, }) public Signature: Signature; } ================================================ FILE: src/xml/data_object.ts ================================================ import { XmlChildElement, XmlElement } from 'xml-core'; import { DataObject as XmlDSigDataObject, XmlSignature } from 'xmldsigjs'; import { QualifyingProperties } from './qualifying_properties'; @XmlElement({ localName: XmlSignature.ElementNames.Object }) export class DataObject extends XmlDSigDataObject { @XmlChildElement({ parser: QualifyingProperties }) public QualifyingProperties: QualifyingProperties; } ================================================ FILE: src/xml/data_object_format.ts ================================================ import { XmlAttribute, XmlChildElement, XmlElement, } from 'xml-core'; import { ObjectIdentifier } from './object_identifier'; import { XmlXades } from './xml'; import { XadesObject } from './xml_base'; /** * * * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.DataObjectFormat }) export class DataObjectFormat extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.ObjectReference, required: true, }) public ObjectReference: string; @XmlChildElement({ localName: XmlXades.ElementNames.Description, namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, }) public Description: string; @XmlChildElement({ parser: ObjectIdentifier }) public ObjectIdentifier: ObjectIdentifier; @XmlChildElement({ localName: XmlXades.ElementNames.MimeType, namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, }) public MimeType: string; @XmlChildElement({ localName: XmlXades.ElementNames.Encoding, namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, }) public Encoding: string; } ================================================ FILE: src/xml/date_time.ts ================================================ import { XmlContent, XmlElement } from 'xml-core'; import { dateFormat } from '../dateformat'; import { XmlXades } from './xml'; import { XadesObject } from './xml_base'; @XmlElement({ localName: 'XadesDateTime', namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, }) export class XadesDateTime extends XadesObject { @XmlContent({ defaultValue: new Date(), required: true, }) public Value: Date; /** * Format of the datetime value * * Check [dateformat]{@link https://www.npmjs.com/package/dateformat} for supported formatting options. * If not specified, [Date#toISOString()]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString} is used. */ public Format?: string; protected OnLoadXml(e: Element) { if (e.textContent) { this.Value = new Date(e.textContent); } } protected OnGetXml(e: Element) { if (this.Format) { e.textContent = dateFormat(this.Value, this.Format); } else { e.textContent = this.Value.toISOString(); } } } ================================================ FILE: src/xml/encapsulated_pki_data.ts ================================================ import { XmlAttribute, XmlContent, XmlElement, IConverter, XmlBase64Converter, } from 'xml-core'; import { XmlXades } from './xml'; import { XadesObject } from './xml_base'; /** * * * * * * * * * * * */ const XmlEncodingConverter: IConverter = { get: (value: EncodingType) => { switch (value) { case 'der': case 'ber': case 'cer': case 'per': case 'xer': return `http://uri.etsi.org/01903/v1.2.2#${value.toUpperCase()}`; } return void 0; }, set: (value: string) => { const regexp = /#(\w+)$/; const res = regexp.exec(value); if (res) { return res[1].toLowerCase() as EncodingType; } return null; }, }; export type EncodingType = 'der' | 'ber' | 'cer' | 'per' | 'xer' | null; @XmlElement({ localName: 'EncapsulatedPKIData' }) export class EncapsulatedPKIData extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; @XmlAttribute({ localName: XmlXades.AttributeNames.Encoding, defaultValue: null, converter: XmlEncodingConverter, }) public Encoding: EncodingType; @XmlContent({ required: true, converter: XmlBase64Converter, }) public Value: Uint8Array; } ================================================ FILE: src/xml/generic_time_stamp.ts ================================================ import { XmlAttribute, XmlChildElement, XmlElement, XmlBase64Converter, } from 'xml-core'; import { CanonicalizationMethod, DigestMethod, XmlSignature, } from 'xmldsigjs'; import { Any } from './any'; import { EncapsulatedPKIData } from './encapsulated_pki_data'; import { XmlXades } from './xml'; import { XadesCollection, XadesObject } from './xml_base'; /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.Include }) export class Include extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.URI, defaultValue: '', required: true, }) public Uri: string; @XmlAttribute({ localName: XmlXades.AttributeNames.ReferencedData, defaultValue: false, }) public ReferencedData: boolean; } @XmlElement({ localName: XmlXades.ElementNames.ReferenceInfo }) export class ReferenceInfo extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.URI, defaultValue: '', }) public Uri: string; @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; /** * Gets or sets the digest method Uniform Resource Identifier (URI) of the current */ @XmlChildElement({ required: true, parser: DigestMethod, }) public DigestMethod = new DigestMethod(); /** * Gets or sets the digest value of the current Reference. */ @XmlChildElement({ required: true, localName: XmlSignature.ElementNames.DigestValue, namespaceURI: XmlSignature.NamespaceURI, prefix: XmlSignature.DefaultPrefix, converter: XmlBase64Converter, }) public DigestValue: Uint8Array; } @XmlElement({ localName: 'ReferenceInfos', parser: ReferenceInfo, }) export class ReferenceInfos extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.EncapsulatedTimeStamp }) export class EncapsulatedTimeStamp extends EncapsulatedPKIData { } @XmlElement({ localName: 'EncapsulatedPKIDatas', parser: EncapsulatedTimeStamp, }) export class EncapsulatedTimeStampCollection extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.XMLTimeStamp }) export class XMLTimeStamp extends Any { } @XmlElement({ localName: 'XMLTimeStampCollection', parser: XMLTimeStamp, }) export class XMLTimeStampCollection extends XadesCollection { } @XmlElement({ localName: 'GenericTimeStamp' }) export class GenericTimeStamp extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; @XmlChildElement({ parser: Include }) public Include: Include; @XmlChildElement({ parser: ReferenceInfos, noRoot: true, }) public ReferenceInfo: ReferenceInfos; @XmlChildElement({ parser: CanonicalizationMethod }) public CanonicalizationMethod: CanonicalizationMethod; @XmlChildElement({ parser: EncapsulatedTimeStampCollection, noRoot: true, }) public EncapsulatedTimeStamp: EncapsulatedTimeStampCollection; @XmlChildElement({ parser: XMLTimeStampCollection, noRoot: true, }) public XMLTimeStamp: XMLTimeStampCollection; } ================================================ FILE: src/xml/index.ts ================================================ export * from './any'; export * from './certificate_values'; export * from './commitment_type_indication'; export * from './complete_certificate_refs'; export * from './complete_revocation_refs'; export * from './counter_signature'; export * from './data_object_format'; export * from './date_time'; export * from './encapsulated_pki_data'; export * from './generic_time_stamp'; export * from './object_identifier'; export * from './other_time_stamp'; export * from './qualifying_properties'; export * from './qualifying_properties_reference'; export * from './revocation_values'; export * from './signature_policy_identifier'; export * from './signature_product_place'; export * from './signed_data_object_properties'; export * from './signed_properties'; export * from './signed_signature_properties'; export * from './signer_role'; export * from './signing_certificate'; export * from './signing_certificate_v2'; export * from './unsigned_data_object_property'; export * from './unsigned_properties'; export * from './unsigned_signature_properties'; export * from './xades_time_stamp'; export * from './data_object'; export * from './xml'; ================================================ FILE: src/xml/object_identifier.ts ================================================ import { XmlAttribute, XmlChildElement, XmlContent, XmlElement, } from 'xml-core'; import { XmlXades } from './xml'; import { XadesCollection, XadesObject } from './xml_base'; /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ export type IdentifierQualifier = 'OIDAsURI' | 'OIDAsURN'; @XmlElement({ localName: XmlXades.ElementNames.Identifier }) export class Identifier extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.Qualifier }) public Qualifier: IdentifierQualifier; @XmlContent({ defaultValue: '', required: true, }) public Value: string; } @XmlElement({ localName: XmlXades.ElementNames.DocumentationReference }) export class DocumentationReference extends XadesObject { @XmlContent({ defaultValue: '', required: true, }) public Uri: string; protected OnLoadXml(e: Element) { if (e.textContent) { this.Uri = e.textContent; } } protected OnGetXml(e: Element) { if (this.Uri) { e.textContent = this.Uri; } } } @XmlElement({ localName: XmlXades.ElementNames.DocumentationReferences, parser: DocumentationReference, }) export class DocumentationReferences extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.ObjectIdentifier }) export class ObjectIdentifier extends XadesObject { @XmlChildElement({ parser: Identifier, required: true, }) public Identifier: Identifier; @XmlChildElement({ localName: XmlXades.ElementNames.Description, namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, defaultValue: '', }) public Description: string; @XmlChildElement({ parser: DocumentationReferences }) public DocumentationReferences: DocumentationReferences; } ================================================ FILE: src/xml/other_time_stamp.ts ================================================ import { XmlAttribute, XmlChildElement, XmlElement, } from 'xml-core'; import { CanonicalizationMethod } from 'xmldsigjs'; import { EncapsulatedTimeStampCollection, ReferenceInfos, XMLTimeStampCollection, } from './generic_time_stamp'; import { XmlXades } from './xml'; import { XadesObject } from './xml_base'; /** * * * * * * * * * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.OtherTimeStamp }) export class OtherTimeStamp extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; @XmlChildElement({ parser: ReferenceInfos, noRoot: true, }) public ReferenceInfo: ReferenceInfos; @XmlChildElement({ parser: CanonicalizationMethod }) public CanonicalizationMethod: CanonicalizationMethod; @XmlChildElement({ parser: EncapsulatedTimeStampCollection, noRoot: true, }) public EncapsulatedTimeStamp: EncapsulatedTimeStampCollection; @XmlChildElement({ parser: XMLTimeStampCollection, noRoot: true, }) public XMLTimeStamp: XMLTimeStampCollection; } ================================================ FILE: src/xml/qualifying_properties.ts ================================================ import { XmlAttribute, XmlChildElement, XmlElement, } from 'xml-core'; import { SignedProperties } from './signed_properties'; import { UnsignedProperties } from './unsigned_properties'; import { XmlXades } from './xml'; import { XadesObject } from './xml_base'; /** * * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.QualifyingProperties }) export class QualifyingProperties extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.Target, required: true, }) public Target: string; @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; @XmlChildElement({ parser: SignedProperties }) public SignedProperties: SignedProperties; @XmlChildElement({ parser: UnsignedProperties }) public UnsignedProperties: UnsignedProperties; } ================================================ FILE: src/xml/qualifying_properties_reference.ts ================================================ import { XmlAttribute, XmlElement } from 'xml-core'; import { XmlXades } from './xml'; import { XadesObject } from './xml_base'; /** * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.QualifyingPropertiesReference }) export class QualifyingPropertiesReference extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.URI, required: true, }) public Uri: string; @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; } ================================================ FILE: src/xml/revocation_values.ts ================================================ import { XmlAttribute, XmlChildElement, XmlElement, } from 'xml-core'; import { EncapsulatedPKIData } from './encapsulated_pki_data'; import { XmlXades } from './xml'; import { XadesCollection, XadesObject } from './xml_base'; /** * * * * * * * * * * * * * * * * * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.OtherValue }) export class OtherValue extends EncapsulatedPKIData { } @XmlElement({ localName: XmlXades.ElementNames.OCSPValues, parser: OtherValue, }) export class OtherValues extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.EncapsulatedOCSPValue }) export class EncapsulatedOCSPValue extends EncapsulatedPKIData { } @XmlElement({ localName: XmlXades.ElementNames.OCSPValues, parser: EncapsulatedOCSPValue, }) export class OCSPValues extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.EncapsulatedCRLValue }) export class EncapsulatedCRLValue extends EncapsulatedPKIData { } @XmlElement({ localName: XmlXades.ElementNames.CRLValues, parser: EncapsulatedCRLValue, }) export class CRLValues extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.RevocationValues }) export class RevocationValues extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; @XmlChildElement({ parser: CRLValues }) public CRLValues: CRLValues; @XmlChildElement({ parser: OCSPValues }) public OCSPValues: OCSPValues; @XmlChildElement({ parser: OtherValues }) public OtherValues: OtherValues; } ================================================ FILE: src/xml/signature_policy_identifier.ts ================================================ import { XmlChildElement, XmlContent, XmlElement, IConverter, XmlNumberConverter, } from 'xml-core'; import { Transforms } from 'xmldsigjs'; import { AnyCollection } from './any'; import { ObjectIdentifier } from './object_identifier'; import { DigestAlgAndValueType } from './signing_certificate'; import { XmlXades } from './xml'; import { XadesCollection, XadesObject } from './xml_base'; /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.SigPolicyId }) export class SigPolicyId extends ObjectIdentifier { } @XmlElement({ localName: XmlXades.ElementNames.SigPolicyHash }) export class SigPolicyHash extends DigestAlgAndValueType { } @XmlElement({ localName: XmlXades.ElementNames.SigPolicyQualifier }) export class SigPolicyQualifier extends AnyCollection { } @XmlElement({ localName: 'int' }) export class Integer extends XadesObject { @XmlContent({ converter: XmlNumberConverter, required: true, }) public Value: number; } @XmlElement({ localName: 'IntegerList', parser: Integer, }) export class IntegerList extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.NoticeRef }) export class NoticeReference extends XadesObject { @XmlChildElement({ localName: XmlXades.ElementNames.Organization, namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, required: true, }) public Organization: string; @XmlChildElement({ localName: XmlXades.ElementNames.NoticeNumbers, parser: IntegerList, required: true, }) public NoticeNumbers: IntegerList; } @XmlElement({ localName: XmlXades.ElementNames.SPUserNotice }) export class SPUserNotice extends XadesObject { @XmlChildElement({ localName: XmlXades.ElementNames.NoticeRef, parser: NoticeReference, }) public NoticeRef: NoticeReference; @XmlChildElement({ localName: XmlXades.ElementNames.ExplicitText, namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, }) public ExplicitText: string; } @XmlElement({ localName: XmlXades.ElementNames.SPURI }) export class SPURI extends XadesObject { @XmlContent() public Value: string; } @XmlElement({ localName: XmlXades.ElementNames.SigPolicyQualifiers, parser: SigPolicyQualifier, }) export class SigPolicyQualifiers extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.SignaturePolicyId }) export class SignaturePolicyId extends XadesObject { @XmlChildElement({ localName: XmlXades.ElementNames.SigPolicyId, parser: SigPolicyId, required: true, }) public SigPolicyId: SigPolicyId; @XmlChildElement({ parser: Transforms }) public Transforms: Transforms; @XmlChildElement({ localName: XmlXades.ElementNames.SigPolicyHash, parser: SigPolicyHash, required: true, }) public SigPolicyHash: SigPolicyHash; @XmlChildElement({ localName: XmlXades.ElementNames.SigPolicyQualifiers, parser: SigPolicyQualifiers, }) public SigPolicyQualifiers: SigPolicyQualifiers; } const XmlSignaturePolicyImpliedConverter: IConverter = { // eslint-disable-next-line @typescript-eslint/no-unused-vars set: (value: string) => { // if SignaturePolicyImplied exists then return true return true; }, // eslint-disable-next-line @typescript-eslint/no-unused-vars get: (value: boolean) => { return ''; }, }; @XmlElement({ localName: XmlXades.ElementNames.SignaturePolicyIdentifier }) export class SignaturePolicyIdentifier extends XadesObject { @XmlChildElement({ localName: XmlXades.ElementNames.SignaturePolicyId, namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, parser: SignaturePolicyId, }) public SignaturePolicyId: SignaturePolicyId; @XmlChildElement({ localName: XmlXades.ElementNames.SignaturePolicyImplied, namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, converter: XmlSignaturePolicyImpliedConverter, defaultValue: false, }) public SignaturePolicyImplied: boolean; } ================================================ FILE: src/xml/signature_product_place.ts ================================================ import { XmlChildElement, XmlElement } from 'xml-core'; import { XmlXades } from './xml'; import { XadesObject } from './xml_base'; /** * * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.SignatureProductionPlace }) export class SignatureProductionPlace extends XadesObject { @XmlChildElement({ localName: XmlXades.ElementNames.City, defaultValue: '', namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, }) public City: string; @XmlChildElement({ localName: XmlXades.ElementNames.StateOrProvince, defaultValue: '', namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, }) public StateOrProvince: string; @XmlChildElement({ localName: XmlXades.ElementNames.PostalCode, defaultValue: '', namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, }) public PostalCode: string; @XmlChildElement({ localName: XmlXades.ElementNames.CountryName, defaultValue: '', namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, }) public CountryName: string; } ================================================ FILE: src/xml/signed_data_object_properties.ts ================================================ import { XmlAttribute, XmlChildElement, XmlElement, } from 'xml-core'; import { CommitmentTypeIndication } from './commitment_type_indication'; import { DataObjectFormat } from './data_object_format'; import { XAdESTimeStamp } from './xades_time_stamp'; import { XmlXades } from './xml'; import { XadesCollection, XadesObject } from './xml_base'; /** * * * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.IndividualDataObjectsTimeStamp }) export class IndividualDataObjectsTimeStamp extends XAdESTimeStamp { } @XmlElement({ localName: 'IndividualDataObjectsTimeStampCollection', parser: IndividualDataObjectsTimeStamp, }) export class IndividualDataObjectsTimeStampCollection extends XadesCollection {} @XmlElement({ localName: XmlXades.ElementNames.AllDataObjectsTimeStamp }) export class AllDataObjectsTimeStamp extends XAdESTimeStamp { } @XmlElement({ localName: 'DataObjectFormatCollection', parser: DataObjectFormat, }) export class DataObjectFormatCollection extends XadesCollection { } @XmlElement({ localName: 'CommitmentTypeIndicationCollection', parser: CommitmentTypeIndication, }) export class CommitmentTypeIndicationCollection extends XadesCollection { } @XmlElement({ localName: 'AllDataObjectsTimeStampCollection', parser: AllDataObjectsTimeStamp, }) export class AllDataObjectsTimeStampCollection extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.SignedDataObjectProperties }) export class SignedDataObjectProperties extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; @XmlChildElement({ parser: DataObjectFormatCollection, noRoot: true, }) public DataObjectFormats: DataObjectFormatCollection; @XmlChildElement({ parser: CommitmentTypeIndicationCollection, noRoot: true, }) public CommitmentTypeIndications: CommitmentTypeIndicationCollection; @XmlChildElement({ parser: AllDataObjectsTimeStampCollection, noRoot: true, }) public AllDataObjectsTimeStamps: AllDataObjectsTimeStampCollection; @XmlChildElement({ parser: IndividualDataObjectsTimeStampCollection, noRoot: true, }) public IndividualDataObjectsTimeStamps: IndividualDataObjectsTimeStampCollection; } ================================================ FILE: src/xml/signed_properties.ts ================================================ import { XmlAttribute, XmlChildElement, XmlElement, } from 'xml-core'; import { SignedDataObjectProperties } from './signed_data_object_properties'; import { SignedSignatureProperties } from './signed_signature_properties'; import { XmlXades } from './xml'; import { XadesObject } from './xml_base'; /** * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.SignedProperties }) export class SignedProperties extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; @XmlChildElement({ parser: SignedSignatureProperties }) public SignedSignatureProperties: SignedSignatureProperties; @XmlChildElement({ parser: SignedDataObjectProperties }) public SignedDataObjectProperties: SignedDataObjectProperties; } ================================================ FILE: src/xml/signed_signature_properties.ts ================================================ import { XmlAttribute, XmlChildElement, XmlElement, } from 'xml-core'; import { XadesDateTime } from './date_time'; import { SignaturePolicyIdentifier } from './signature_policy_identifier'; import { SignatureProductionPlace } from './signature_product_place'; import { SignerRole } from './signer_role'; import { SigningCertificate } from './signing_certificate'; import { SigningCertificateV2 } from './signing_certificate_v2'; import { XmlXades } from './xml'; import { XadesObject } from './xml_base'; /** * * * * * * * * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.SignedSignatureProperties }) export class SignedSignatureProperties extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; @XmlChildElement({ localName: XmlXades.ElementNames.SigningTime, parser: XadesDateTime, }) public SigningTime: XadesDateTime; @XmlChildElement({ parser: SigningCertificate }) public SigningCertificate: SigningCertificate; @XmlChildElement({ parser: SigningCertificateV2 }) public SigningCertificateV2: SigningCertificateV2; @XmlChildElement({ parser: SignaturePolicyIdentifier }) public SignaturePolicyIdentifier: SignaturePolicyIdentifier; @XmlChildElement({ parser: SignatureProductionPlace }) public SignatureProductionPlace: SignatureProductionPlace; @XmlChildElement({ parser: SignerRole }) public SignerRole: SignerRole; } ================================================ FILE: src/xml/signer_role.ts ================================================ import { XmlChildElement, XmlElement } from 'xml-core'; import { Any } from './any'; import { EncapsulatedPKIData } from './encapsulated_pki_data'; import { XmlXades } from './xml'; import { XadesCollection, XadesObject } from './xml_base'; /** * * * * * * * * * * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.ClaimedRole }) export class ClaimedRole extends Any { } @XmlElement({ localName: XmlXades.ElementNames.ClaimedRoles, parser: ClaimedRole, }) export class ClaimedRoles extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.CertifiedRole }) export class CertifiedRole extends EncapsulatedPKIData { } @XmlElement({ localName: XmlXades.ElementNames.CertifiedRoles, parser: CertifiedRole, }) export class CertifiedRoles extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.SignerRole }) export class SignerRole extends XadesObject { @XmlChildElement({ parser: ClaimedRoles }) public ClaimedRoles: ClaimedRoles; @XmlChildElement({ parser: CertifiedRoles }) public CertifiedRoles: CertifiedRoles; } ================================================ FILE: src/xml/signing_certificate.ts ================================================ import { XmlAttribute, XmlChildElement, XmlElement, XmlBase64Converter, } from 'xml-core'; import { DigestMethod, X509IssuerSerial, XmlSignature, } from 'xmldsigjs'; import { XmlXades } from './xml'; import { XadesCollection, XadesObject } from './xml_base'; /** * * * * * * * * * * * * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.DigestAlgAndValue }) export class DigestAlgAndValueType extends XadesObject { @XmlChildElement({ parser: DigestMethod, required: true, }) public DigestMethod: DigestMethod; @XmlChildElement({ localName: XmlSignature.ElementNames.DigestValue, namespaceURI: XmlSignature.NamespaceURI, prefix: XmlSignature.DefaultPrefix, converter: XmlBase64Converter, required: true, }) public DigestValue: Uint8Array; } @XmlElement({ localName: XmlXades.ElementNames.IssuerSerial, namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, }) export class IssuerSerial extends X509IssuerSerial { } @XmlElement({ localName: XmlXades.ElementNames.Cert }) export class Cert extends XadesObject { @XmlChildElement({ localName: XmlXades.ElementNames.CertDigest, parser: DigestAlgAndValueType, required: true, }) public CertDigest: DigestAlgAndValueType; @XmlChildElement({ parser: IssuerSerial, required: true, }) public IssuerSerial: X509IssuerSerial; @XmlAttribute({ localName: XmlXades.AttributeNames.URI }) public Uri: string; } @XmlElement({ localName: 'CertIDList', parser: Cert, }) export class CertIDList extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.SigningCertificate }) export class SigningCertificate extends CertIDList { } ================================================ FILE: src/xml/signing_certificate_v2.ts ================================================ import { XmlAttribute, XmlChildElement, XmlElement, XmlBase64Converter, } from 'xml-core'; import { XmlXades } from './xml'; import { XadesCollection, XadesObject } from './xml_base'; import { DigestAlgAndValueType } from './signing_certificate'; /** * * * * * * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.Cert, parser: CertV2, }) export class CertV2 extends XadesObject { @XmlChildElement({ localName: XmlXades.ElementNames.CertDigest, parser: DigestAlgAndValueType, required: true, }) public CertDigest: DigestAlgAndValueType; @XmlChildElement({ localName: XmlXades.ElementNames.IssuerSerialV2, namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, converter: XmlBase64Converter, required: false, }) public IssuerSerial: Uint8Array; @XmlAttribute({ localName: XmlXades.AttributeNames.URI }) public Uri: string; } @XmlElement({ localName: 'CertIDListV2', parser: CertV2, }) export class CertIDListV2 extends XadesCollection { } @XmlElement({ localName: XmlXades.ElementNames.SigningCertificateV2 }) export class SigningCertificateV2 extends CertIDListV2 { } ================================================ FILE: src/xml/unsigned_data_object_property.ts ================================================ import { XmlAttribute, XmlElement } from 'xml-core'; import { Any } from './any'; import { XmlXades } from './xml'; import { XadesCollection } from './xml_base'; /** * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.UnsignedDataObjectProperty }) export class UnsignedDataObjectProperty extends Any { } @XmlElement({ localName: XmlXades.ElementNames.UnsignedSignatureProperties, parser: UnsignedDataObjectProperty, }) export class UnsignedDataObjectProperties extends XadesCollection { @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; } ================================================ FILE: src/xml/unsigned_properties.ts ================================================ import { XmlAttribute, XmlChildElement, XmlElement, } from 'xml-core'; import { UnsignedDataObjectProperties } from './unsigned_data_object_property'; import { UnsignedSignatureProperties } from './unsigned_signature_properties'; import { XmlXades } from './xml'; import { XadesObject } from './xml_base'; /** * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.UnsignedProperties }) export class UnsignedProperties extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; @XmlChildElement({ parser: UnsignedSignatureProperties }) public UnsignedSignatureProperties: UnsignedSignatureProperties; @XmlChildElement({ parser: UnsignedDataObjectProperties }) public UnsignedDataObjectProperties: UnsignedDataObjectProperties; } ================================================ FILE: src/xml/unsigned_signature_properties.ts ================================================ import { XmlAttribute, XmlElement, XmlNodeType, } from 'xml-core'; import { CertificateValues } from './certificate_values'; import { CompleteCertificateRefs } from './complete_certificate_refs'; import { CompleteRevocationRefs } from './complete_revocation_refs'; import { CounterSignature } from './counter_signature'; import { RevocationValues } from './revocation_values'; import { XAdESTimeStamp } from './xades_time_stamp'; import { XmlXades } from './xml'; import { XadesCollection, XadesObject } from './xml_base'; /** * * * * * * * * * * * * * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.SignatureTimeStamp }) export class SignatureTimeStamp extends XAdESTimeStamp implements UnsignedSignatureProperty { } @XmlElement({ localName: XmlXades.ElementNames.SigAndRefsTimeStamp }) export class SigAndRefsTimeStamp extends XAdESTimeStamp implements UnsignedSignatureProperty { } @XmlElement({ localName: XmlXades.ElementNames.RefsOnlyTimeStamp }) export class RefsOnlyTimeStamp extends XAdESTimeStamp implements UnsignedSignatureProperty { } @XmlElement({ localName: XmlXades.ElementNames.ArchiveTimeStamp }) export class ArchiveTimeStamp extends XAdESTimeStamp implements UnsignedSignatureProperty { } @XmlElement({ localName: XmlXades.ElementNames.AttributeCertificateRefs }) export class AttributeCertificateRefs extends CompleteCertificateRefs implements UnsignedSignatureProperty { } @XmlElement({ localName: XmlXades.ElementNames.AttributeRevocationRefs }) export class AttributeRevocationRefs extends CompleteRevocationRefs implements UnsignedSignatureProperty { } @XmlElement({ localName: XmlXades.ElementNames.AttrAuthoritiesCertValues }) export class AttrAuthoritiesCertValues extends CertificateValues implements UnsignedSignatureProperty { } @XmlElement({ localName: XmlXades.ElementNames.AttributeRevocationValues }) export class AttributeRevocationValues extends RevocationValues implements UnsignedSignatureProperty { } /** * Abstract class for UnsignedSignatureProperties * @export * @class UnsignedSignatureProperty * @extends {XadesObject} */ @XmlElement({ localName: 'UnsignedSignatureProperty' }) export class UnsignedSignatureProperty extends XadesObject { } @XmlElement({ localName: XmlXades.ElementNames.UnsignedSignatureProperties, parser: UnsignedSignatureProperty, }) export class UnsignedSignatureProperties extends XadesCollection { @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; public OnLoadXml(element: Element) { for (let i = 0; i < element.childNodes.length; i++) { const node = element.childNodes.item(i); if (node.nodeType !== XmlNodeType.Element) { continue; } let XmlClass: typeof UnsignedSignatureProperty | undefined; switch ((node as Element).localName) { case XmlXades.ElementNames.CounterSignature: XmlClass = CounterSignature; break; case XmlXades.ElementNames.SignatureTimeStamp: XmlClass = SignatureTimeStamp; break; case XmlXades.ElementNames.CompleteCertificateRefs: XmlClass = CompleteCertificateRefs; break; case XmlXades.ElementNames.CompleteRevocationRefs: XmlClass = CompleteRevocationRefs; break; case XmlXades.ElementNames.AttributeCertificateRefs: XmlClass = AttributeCertificateRefs; break; case XmlXades.ElementNames.AttributeRevocationRefs: XmlClass = AttributeRevocationRefs; break; case XmlXades.ElementNames.SigAndRefsTimeStamp: XmlClass = SigAndRefsTimeStamp; break; case XmlXades.ElementNames.RefsOnlyTimeStamp: XmlClass = RefsOnlyTimeStamp; break; case XmlXades.ElementNames.CertificateValues: XmlClass = CertificateValues; break; case XmlXades.ElementNames.RevocationValues: XmlClass = RevocationValues; break; case XmlXades.ElementNames.AttrAuthoritiesCertValues: XmlClass = AttrAuthoritiesCertValues; break; case XmlXades.ElementNames.AttributeRevocationValues: XmlClass = AttributeRevocationValues; break; case XmlXades.ElementNames.ArchiveTimeStamp: XmlClass = ArchiveTimeStamp; break; } if (XmlClass) { const item = XmlClass.LoadXml(node as Element); this.Add(item); } } } } ================================================ FILE: src/xml/xades.xsd ================================================ ================================================ FILE: src/xml/xades_time_stamp.ts ================================================ import { XmlAttribute, XmlChildElement, XmlElement, } from 'xml-core'; import { CanonicalizationMethod } from 'xmldsigjs'; import { EncapsulatedTimeStampCollection, Include, XMLTimeStampCollection, } from './generic_time_stamp'; import { XmlXades } from './xml'; import { XadesObject } from './xml_base'; /** * * * * * * * * * * * * * * * * * * */ @XmlElement({ localName: XmlXades.ElementNames.XAdESTimeStamp }) export class XAdESTimeStamp extends XadesObject { @XmlAttribute({ localName: XmlXades.AttributeNames.Id, defaultValue: '', }) public Id: string; @XmlChildElement({ parser: Include }) public Include: Include; @XmlChildElement({ parser: CanonicalizationMethod }) public CanonicalizationMethod: CanonicalizationMethod; @XmlChildElement({ parser: EncapsulatedTimeStampCollection, noRoot: true, }) public EncapsulatedTimeStamp: EncapsulatedTimeStampCollection; @XmlChildElement({ parser: XMLTimeStampCollection, noRoot: true, }) public XMLTimeStamp: XMLTimeStampCollection; } ================================================ FILE: src/xml/xml.ts ================================================ export const XmlXades = { DefaultPrefix: 'xades', /** * The XAdES XML namespace URI */ NamespaceURI: 'http://uri.etsi.org/01903/v1.3.2#', /** * Mandated type name for the Uri reference to the SignedProperties element */ SignedPropertiesType: 'http://uri.etsi.org/01903/v1.3.2#SignedProperties', ElementNames: { Any: 'Any', ByName: 'ByName', ByKey: 'ByKey', AttrAuthoritiesCertValues: 'AttrAuthoritiesCertValues', AttributeRevocationValues: 'AttributeRevocationValues', AttributeCertificateRefs: 'AttributeCertificateRefs', AttributeRevocationRefs: 'AttributeRevocationRefs', QualifyingProperties: 'QualifyingProperties', QualifyingPropertiesReference: 'QualifyingPropertiesReference', SignedProperties: 'SignedProperties', SignedSignatureProperties: 'SignedSignatureProperties', SignedDataObjectProperties: 'SignedDataObjectProperties', UnsignedProperties: 'UnsignedProperties', UnsignedSignatureProperties: 'UnsignedSignatureProperties', UnsignedDataObjectProperties: 'UnsignedDataObjectProperties', UnsignedDataObjectProperty: 'UnsignedDataObjectProperty', SigningTime: 'SigningTime', SigningCertificate: 'SigningCertificate', SigningCertificateV2: 'SigningCertificateV2', SignaturePolicyIdentifier: 'SignaturePolicyIdentifier', SignatureProductionPlace: 'SignatureProductionPlace', SignerRole: 'SignerRole', Cert: 'Cert', CertDigest: 'CertDigest', IssuerSerial: 'IssuerSerial', IssuerSerialV2: 'IssuerSerialV2', DataObjectFormat: 'DataObjectFormat', CommitmentTypeIndication: 'CommitmentTypeIndication', AllDataObjectsTimeStamp: 'AllDataObjectsTimeStamp', IndividualDataObjectsTimeStamp: 'IndividualDataObjectsTimeStamp', HashDataInfo: 'HashDataInfo', EncapsulatedTimeStamp: 'EncapsulatedTimeStamp', XMLTimeStamp: 'XMLTimeStamp', XAdESTimeStamp: 'XAdESTimeStamp', OtherTimeStamp: 'OtherTimeStamp', Description: 'Description', ObjectIdentifier: 'ObjectIdentifier', MimeType: 'MimeType', Encoding: 'Encoding', Identifier: 'Identifier', DocumentationReferences: 'DocumentationReferences', DocumentationReference: 'DocumentationReference', CommitmentTypeId: 'CommitmentTypeId', ObjectReference: 'ObjectReference', CommitmentTypeQualifiers: 'CommitmentTypeQualifiers', AllSignedDataObjects: 'AllSignedDataObjects', CommitmentTypeQualifier: 'CommitmentTypeQualifier', SignaturePolicyId: 'SignaturePolicyId', SignaturePolicyImplied: 'SignaturePolicyImplied', SigPolicyId: 'SigPolicyId', SigPolicyHash: 'SigPolicyHash', SigPolicyQualifier: 'SigPolicyQualifier', SigPolicyQualifiers: 'SigPolicyQualifiers', SPURI: 'SPURI', SPUserNotice: 'SPUserNotice', NoticeRef: 'NoticeRef', ExplicitText: 'ExplicitText', ClaimedRoles: 'ClaimedRoles', ClaimedRole: 'ClaimedRole', CertifiedRoles: 'CertifiedRoles', CertifiedRole: 'CertifiedRole', Organization: 'Organization', NoticeNumbers: 'NoticeNumbers', Int: 'int', City: 'City', PostalCode: 'PostalCode', StateOrProvince: 'StateOrProvince', CountryName: 'CountryName', CounterSignature: 'CounterSignature', SignatureTimeStamp: 'SignatureTimeStamp', CompleteCertificateRefs: 'CompleteCertificateRefs', CompleteRevocationRefs: 'CompleteRevocationRefs', SigAndRefsTimeStamp: 'SigAndRefsTimeStamp', RefsOnlyTimeStamp: 'RefsOnlyTimeStamp', CertificateValues: 'CertificateValues', RevocationValues: 'RevocationValues', ArchiveTimeStamp: 'ArchiveTimeStamp', CertRefs: 'CertRefs', CRLRefs: 'CRLRefs', CRLRef: 'CRLRef', OCSPRefs: 'OCSPRefs', OtherRefs: 'OtherRefs', OtherRef: 'OtherRef', DigestAlgAndValue: 'DigestAlgAndValue', CRLIdentifier: 'CRLIdentifier', Issuer: 'Issuer', IssueTime: 'IssueTime', Number: 'Number', OCSPRef: 'OCSPRef', OCSPIdentifier: 'OCSPIdentifier', ResponderID: 'ResponderID', ProducedAt: 'ProducedAt', EncapsulatedX509Certificate: 'EncapsulatedX509Certificate', OtherCertificate: 'OtherCertificate', CRLValues: 'CRLValues', OCSPValues: 'OCSPValues', OtherValues: 'OtherValues', OtherValue: 'OtherValue', EncapsulatedCRLValue: 'EncapsulatedCRLValue', EncapsulatedOCSPValue: 'EncapsulatedOCSPValue', ReferenceInfo: 'ReferenceInfo', Include: 'Include', }, AttributeNames: { Id: 'Id', Encoding: 'Encoding', Target: 'Target', ObjectReference: 'ObjectReference', Qualifier: 'Qualifier', Uri: 'uri', URI: 'URI', ReferencedData: 'referencedData', }, }; ================================================ FILE: src/xml/xml_base.ts ================================================ import * as XmlCore from 'xml-core'; import { XmlElement } from 'xml-core'; import { XmlXades } from './xml'; @XmlElement({ localName: 'xades', namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, }) export abstract class XadesObject extends XmlCore.XmlObject { } @XmlElement({ localName: 'xades_collection', namespaceURI: XmlXades.NamespaceURI, prefix: XmlXades.DefaultPrefix, }) export abstract class XadesCollection extends XmlCore.XmlCollection { } ================================================ FILE: test/signed_xml/signing.ts ================================================ import * as assert from 'assert'; import { Crypto } from '@peculiar/webcrypto'; import * as XmlCore from 'xml-core'; import * as XAdES from '../../src'; context('XAdES signing', () => { const cert = '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'; let keys: Required; const alg = { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256', publicExponent: new Uint8Array([1, 0, 1]), modulusLength: 1024, }; const xml = `Test`; before(async () => { const crypto = new Crypto(); XAdES.Application.setEngine('NodeJS', crypto); keys = await crypto.subtle.generateKey(alg, true, ['sign', 'verify']) as Required; }); it('Default signing (SigningTime, SignaturePolicyIdentifier)', (done) => { const signature = new XAdES.SignedXml(); signature.Sign( // Signing document alg, // algorithm keys.privateKey, // key XAdES.Parse(xml), // document { // options keyValue: keys.publicKey, references: [ { hash: 'SHA-256', transforms: ['enveloped'], }, ], }) .then(() => { const sig = signature.toString(); assert.equal(!!sig, true); const xades = new XAdES.SignedXml(XAdES.Parse(sig)); xades.LoadXml(signature.XmlSignature.GetXml()!); assert.equal(!!xades.SignedProperties, true); assert.equal(!!xades.SignedProperties.SignedSignatureProperties.SigningTime, true); assert.equal(!!xades.SignedProperties.SignedSignatureProperties.SigningTime.Value, true); assert.equal(xades.SignedProperties.SignedSignatureProperties.SignaturePolicyIdentifier.IsEmpty(), true); assert.equal(xades.SignedProperties.SignedSignatureProperties.SignerRole.IsEmpty(), true); assert.equal(xades.SignedProperties.SignedSignatureProperties.SigningCertificate.IsEmpty(), true); assert.equal(xades.SignedProperties.SignedSignatureProperties.SignatureProductionPlace.IsEmpty(), true); return xades.Verify(); }) .then((res) => { assert.equal(res, true, 'XAdES signature is not valid'); }) .then(done, done); }); it('Default signing with explicit policy (SigningTime, SigningCertificateV2, SignaturePolicyIdentifier)', (done) => { const signature = new XAdES.SignedXml(); const testDigest = 'Q0copBCnj1b8G1iZw1k0NuYasMcx6QctleltspAgXlM='; // echo 'content' | openssl dgst -sha256 -binary | openssl base64 | tr -d '\n' const keyInfoId = 'KeyInfoId001'; signature.XmlSignature.KeyInfo.Id = keyInfoId; signature.Sign( // Signing document alg, // algorithm keys.privateKey, // key XAdES.Parse(xml), // document { // options keyValue: keys.publicKey, references: [ { hash: 'SHA-256', transforms: ['enveloped'], }, { hash: 'SHA-256', uri: '#' + keyInfoId, }, ], policy: { identifier: { value: 'Identifier Value' }, hash: { name: 'SHA-256' }, digestValue: testDigest, }, signingCertificateV2: cert, x509: [cert], }) .then(() => { const sig = signature.toString(); assert.equal(!!sig, true); const xades = new XAdES.SignedXml(XAdES.Parse(sig)); xades.LoadXml(signature.XmlSignature.GetXml()!); assert.equal(!!xades.SignedProperties, true); assert.equal(!!xades.SignedProperties.SignedSignatureProperties.SigningTime, true); assert.equal(!!xades.SignedProperties.SignedSignatureProperties.SigningTime.Value, true); assert.equal(xades.SignedProperties.SignedSignatureProperties.SignaturePolicyIdentifier.IsEmpty(), false); assert.equal(xades.SignedProperties.SignedSignatureProperties.SignerRole.IsEmpty(), true); assert.equal(xades.SignedProperties.SignedSignatureProperties.SigningCertificate.IsEmpty(), true); assert.equal(xades.SignedProperties.SignedSignatureProperties.SignatureProductionPlace.IsEmpty(), true); assert.equal( XmlCore.Convert.ToBase64(xades.SignedProperties.SignedSignatureProperties.SignaturePolicyIdentifier.SignaturePolicyId.SigPolicyHash.DigestValue), testDigest); return xades.Verify(); }) .then((res) => { assert.equal(res, true, 'XAdES signature is not valid'); }) .then(done, done); }); it('SigningCertificate, SigningCertificateV2, SignatireProductionPlace, SignerRole', (done) => { const signature = new XAdES.SignedXml(); signature.Sign( // Signing document alg, // algorithm keys.privateKey, // key XAdES.Parse(xml), // document { // options keyValue: keys.publicKey, references: [ { hash: 'SHA-256', transforms: ['enveloped'], }, ], productionPlace: { country: 'Country', state: 'State', city: 'City', code: 'Code', }, signerRole: { claimed: ['1', '2', '3'] }, signingCertificate: cert, signingCertificateV2: cert, }) .then(() => { const sig = signature.toString(); assert.equal(!!sig, true); const xades = new XAdES.SignedXml(XAdES.Parse(sig)); xades.LoadXml(signature.XmlSignature.GetXml()!); assert.equal(!!xades.SignedProperties, true); assert.equal(!!xades.SignedProperties.SignedSignatureProperties.SigningTime, true); assert.equal(!!xades.SignedProperties.SignedSignatureProperties.SigningTime.Value, true); assert.equal(xades.SignedProperties.SignedSignatureProperties.SignaturePolicyIdentifier.SignaturePolicyImplied, false); assert.equal(xades.SignedProperties.SignedSignatureProperties.SignerRole.ClaimedRoles.Count, 3); assert.equal(xades.SignedProperties.SignedSignatureProperties.SigningCertificate.Count, 1); assert.equal(xades.SignedProperties.SignedSignatureProperties.SigningCertificateV2.Count, 1); assert.equal(xades.SignedProperties.SignedSignatureProperties.SignatureProductionPlace.CountryName, 'Country'); assert.equal(xades.SignedProperties.SignedSignatureProperties.SignatureProductionPlace.City, 'City'); assert.equal(xades.SignedProperties.SignedSignatureProperties.SignatureProductionPlace.StateOrProvince, 'State'); assert.equal(xades.SignedProperties.SignedSignatureProperties.SignatureProductionPlace.PostalCode, 'Code'); return xades.Verify(); }) .then((res) => { assert.equal(res, true, 'XAdES signature is not valid'); }) .then(done, done); }); }); ================================================ FILE: test/vectors/reading.ts ================================================ import * as assert from 'assert'; import { Crypto } from '@peculiar/webcrypto'; import { Application } from 'xmldsigjs'; import * as XAdES from '../../src'; import { SignedXml, xml } from '../../src'; const { QualifyingProperties, SignatureTimeStamp, CertificateValues, RevocationValues, ArchiveTimeStamp, } = xml; const { CounterSignature } = xml; Application.setEngine('NodeJS', new Crypto()); const X_AT_SIT_1 = `RYPCI7Bgg4yXSOBNABfWOl7jpMkI/6lbd8kh7w9uqyY=pIYqd/UZQQtVMhoQH+Zw2HFLHya+tP7wzEzwDArGTZk=xiXWFbPsEOUD69k51vrOKb84fCEq43SYD/pmQ2C8QmxkOTGlktFFYNhhXvxjyWPiytmBJmW2qHOGTcITvxJw1w==MIIErjCCA5agAwIBAgIEeZaQJDANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UEBhMCQVQxSDBGBgNVBAoMP0EtVHJ1c3QgR2VzLiBmLiBTaWNoZXJoZWl0c3N5c3RlbWUgaW0gZWxla3RyLiBEYXRlbnZlcmtlaHIgR21iSDEeMBwGA1UECwwVYS1zaWduLVByZW1pdW0tU2lnLTAyMR4wHAYDVQQDDBVhLXNpZ24tUHJlbWl1bS1TaWctMDIwHhcNMTYwMzI0MTYxOTIyWhcNMjEwMzI0MTUxOTIyWjB8MQswCQYDVQQGEwJBVDEbMBkGA1UEAwwSQWxleGFuZGVyIE1hcnNhbGVrMREwDwYDVQQEDAhNYXJzYWxlazESMBAGA1UEKgwJQWxleGFuZGVyMRUwEwYDVQQFEwwzNzg5MTkzMjE0NjMxEjAQBgNVBAwMCURpcGwuSW5nLjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABN7mOMa18/wZyZkotFRZ0VsLN3aKhAbxduaGeB66+A6RdhQgQ6vmlno3PNTtKERAfxjtZI9tDGJcZ8mYG+17YLyjggHlMIIB4TB7BggrBgEFBQcBAQRvMG0wQgYIKwYBBQUHMAKGNmh0dHA6Ly93d3cuYS10cnVzdC5hdC9jZXJ0cy9hLXNpZ24tUHJlbWl1bS1TaWctMDJhLmNydDAnBggrBgEFBQcwAYYbaHR0cDovL29jc3AuYS10cnVzdC5hdC9vY3NwMA4GA1UdDwEB/wQEAwIGwDAnBggrBgEFBQcBAwEB/wQYMBYwCAYGBACORgEBMAoGCCsGAQUFBwsBMIGaBgNVHR8EgZIwgY8wgYyggYmggYaGgYNsZGFwOi8vbGRhcC5hLXRydXN0LmF0L291PWEtc2lnbi1QcmVtaXVtLVNpZy0wMixvPUEtVHJ1c3QsYz1BVD9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0P2Jhc2U/b2JqZWN0Y2xhc3M9ZWlkQ2VydGlmaWNhdGlvbkF1dGhvcml0eTAJBgNVHRMEAjAAMFkGA1UdIARSMFAwCAYGBACLMAEBMEQGBiooABEBCzA6MDgGCCsGAQUFBwIBFixodHRwOi8vd3d3LmEtdHJ1c3QuYXQvZG9jcy9jcC9hLXNpZ24tUHJlbWl1bTATBgNVHSMEDDAKgAhN3+H/S9nJ3zARBgNVHQ4ECgQITpG2911UJ8swDQYJKoZIhvcNAQEFBQADggEBANOLX0OEeEL+BNd+68LDQjgk1zJoSkqzj1DQs4l4j2ug2ERtDk9Yh8MdO6cbbbMriltJrq2a7dDeri7Y8ZY3YBmHlsNb5yDj3YruKXwUDs6nEBeASt5nWaRXgjeLnbWe2J/71L8Gurip2+l0aStOjyvpCF5wUGbeReXCKwL6GVPwKFZJIdSqpP+FzN60ZLWx8TXwIf6weVodNFiYlg3eU33o4yY2sFNSUMKKyEEvl88bAq8v/iP5mIBYSxpGRF75L6LulAeFTG5CO3q95eJS/37+oyRPqhuu0Aqvva2Li0vmt+neMmW8O+jjArZaiBNMz8+5i91TmMOcM/y+2vfrhLw=2016-04-28T14:54:07ZXpGNNQXJ+Vd02hJtq2Ob8VdTJdY=CN=a-sign-Premium-Sig-02,OU=a-sign-Premium-Sig-02,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT2039910436text/xml77u/PHJvb3Q+PC9yb290Pg==`; const X_BE_CONN_10 = `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2016-04-18T09:10:09ZRng2CooXsen7dOYSNbDtwPggzsM=CN=GlobalSign PersonalSign 2 CA - SHA256 - G2,O=GlobalSign nv-sa,C=BE288350169419475868349393263988944744462yIiEUu5bMuMyvzmYuZhd87NlQ6s=CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R34835703278459828975317766application/octet-streamPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48Q29udGVudD4NCjxwPlNpZ25pbmcgbWV0aG9kIC0gVG9vbCAtIENvbmZvcm1hbmNlIGxldmVsIC0gUEtDUy9Db25uZWN0aXZlIHBsdWdpbiAtIEVuY3J5cHRpZTwvcD4NCjxwPlhBZEVTIC0gRFNTIC0gQiAtIFBLQ1MgLSBTSEE1MTIgLSBFbnZlbG9waW5nPC9wPg0KPC9Db250ZW50Pg==`; const X_BG_BOR_1 = `2016-04-11T13:47:15ZAzoH1LMpBhOQFKS80NgcGFtUFJI=2.5.4.20=#13102b333539203220392032313520313030,1.2.840.113549.1.9.1=#161263613571657340622d74727573742e6f7267,2.5.4.17=#130431373834,STREET=bul. Tsarigradsko shose No 117,CN=B-Trust Operational CA QES,OU=B-Trust,O=BORICA - BANKSERVICE AD\, EIK 201230426,L=Sofia,ST=Sofia,C=BG10027144Sofia1784bul. Tsar Boris 3 41,Sofia,PK:1612,EGN:8205301708BGПОДПИСАН ОТtext/xml`; const X_FR_CS_3 = `2016-04-12T10:34:36.132+02:00arKMp/9CG2nbErN89ysQMIo1xKZONGn9VJ+BmjRSse8=CN=Secu Test Intermediate1, OU=SECU, O=CS, C=FR41061.2.3s7DOPlXltkzAM96+KVFfxyBRYEVB4cR2BRF8eUaBPk8=Paris75013FranceMarketing manager1.2.840.113549.1.9.16.6.3`; const X_BE_CONN_26 = `2016-04-18T11:07:17Z13t0/E8vfe/xdM+VBjmfdSA6xxo=2.5.4.5=#1306323031333033,CN=Citizen CA,C=BE21267647932559255678179375349212923798ddcwZeM/LkMfMyoOyekc1gP9AWo=CN=Belgium Root CA2,C=BE4881694401549605148318437027298508885UcygcQr3cz00rNwZRQmfQ1x/xZ8=CN=Belgium Root CA2,C=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`; const X_IT_ICB_6 = `2016-04-22T14:23:00Z24o1xkhJejCjOcx00GUUSXZZx4hJK8lHk0+6jlU09Oo=CN=InfoCert Firma Qualificata 2,2.5.4.5=#130b3037393435323131303036,OU=Certificatore Accreditato,O=INFOCERT SPA,C=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AQAB2016-04-22T14:23:18Z24o1xkhJejCjOcx00GUUSXZZx4hJK8lHk0+6jlU09Oo=CN=InfoCert Firma Qualificata 2,2.5.4.5=#130b3037393435323131303036,OU=Certificatore Accreditato,O=INFOCERT SPA,C=IT95008`; context('Reading XAdES', () => { it('X_AT_SIT_1', async () => { const xades = new SignedXml(XAdES.Parse(X_AT_SIT_1)); xades.LoadXml(X_AT_SIT_1); if (!xades.Properties) { assert.fail('Properties is empty'); } assert.equal(xades.Properties.SignedProperties.SignedSignatureProperties.SigningTime.Value instanceof Date, true); assert.equal(xades.Properties.SignedProperties.SignedSignatureProperties.SigningTime.Value.getFullYear(), 2016); assert.equal(xades.Properties.SignedProperties.SignedSignatureProperties.SigningCertificate.Count, 1); assert.equal(xades.Properties.SignedProperties.SignedSignatureProperties.SigningCertificate.Item(0)!.IssuerSerial.X509IssuerName, 'CN=a-sign-Premium-Sig-02,OU=a-sign-Premium-Sig-02,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT'); assert.equal(xades.Properties.SignedProperties.SignedSignatureProperties.SigningCertificate.Item(0)!.IssuerSerial.X509SerialNumber, '2039910436'); assert.equal(xades.Properties.SignedProperties.SignedDataObjectProperties.DataObjectFormats.Count, 1); assert.equal(xades.Properties.SignedProperties.SignedDataObjectProperties.DataObjectFormats.Item(0)!.ObjectReference, '#r-id-1'); assert.equal(xades.Properties.SignedProperties.SignedDataObjectProperties.DataObjectFormats.Item(0)!.MimeType, 'text/xml'); const ok = await xades.Verify(); assert.equal(ok, true); }); it('X_BE_CONN_10', async () => { const xades = new SignedXml(XAdES.Parse(X_BE_CONN_10)); xades.LoadXml(X_BE_CONN_10); if (!xades.Properties) { assert.fail('Properties is empty'); } assert.equal(xades.Properties.SignedProperties.SignedSignatureProperties.SigningTime.Value instanceof Date, true); assert.equal(xades.Properties.SignedProperties.SignedSignatureProperties.SigningTime.Value.getFullYear(), 2016); assert.equal(xades.Properties.SignedProperties.SignedSignatureProperties.SigningCertificate.Count, 2); assert.equal(xades.Properties.SignedProperties.SignedSignatureProperties.SigningCertificate.Item(0)!.IssuerSerial.X509IssuerName, 'CN=GlobalSign PersonalSign 2 CA - SHA256 - G2,O=GlobalSign nv-sa,C=BE'); assert.equal(xades.Properties.SignedProperties.SignedSignatureProperties.SigningCertificate.Item(0)!.IssuerSerial.X509SerialNumber, '288350169419475868349393263988944744462'); assert.equal(xades.Properties.SignedProperties.SignedSignatureProperties.SigningCertificate.Item(0)!.CertDigest.DigestMethod.Algorithm, 'http://www.w3.org/2000/09/xmldsig#sha1'); assert.equal(xades.Properties.SignedProperties.SignedSignatureProperties.SigningCertificate.Item(0)!.CertDigest.DigestValue.byteLength, 20); assert.equal(xades.Properties.SignedProperties.SignedSignatureProperties.SigningCertificate.Item(1)!.IssuerSerial.X509IssuerName, 'CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R3'); assert.equal(xades.Properties.SignedProperties.SignedSignatureProperties.SigningCertificate.Item(1)!.IssuerSerial.X509SerialNumber, '4835703278459828975317766'); assert.equal(xades.Properties.SignedProperties.SignedDataObjectProperties.DataObjectFormats.Count, 1); assert.equal(xades.Properties.SignedProperties.SignedDataObjectProperties.DataObjectFormats.Item(0)!.ObjectReference, '#r-id-1'); assert.equal(xades.Properties.SignedProperties.SignedDataObjectProperties.DataObjectFormats.Item(0)!.MimeType, 'application/octet-stream'); const ok = await xades.Verify(); assert.equal(ok, true); }); it('X_FR_CS_3', () => { const xades = QualifyingProperties.LoadXml(X_FR_CS_3); assert.equal(xades.Target, '#PRF_2'); assert.equal(xades.SignedProperties.Id, 'PRF_2-SignedProperties'); const signaturePolicyIdentifier = xades.SignedProperties.SignedSignatureProperties.SignaturePolicyIdentifier; assert.equal(!!signaturePolicyIdentifier, true); const signaturePolicyId = signaturePolicyIdentifier.SignaturePolicyId; assert.equal(signaturePolicyId.SigPolicyId.Identifier.Value, '1.2.3'); assert.equal(signaturePolicyId.SigPolicyHash.DigestMethod.Algorithm, 'http://www.w3.org/2001/04/xmlenc#sha256'); assert.equal(signaturePolicyId.SigPolicyHash.DigestValue.byteLength, 32); const signerRole = xades.SignedProperties.SignedSignatureProperties.SignerRole; assert.equal(signerRole.ClaimedRoles.Count, 1); assert.equal(signerRole.ClaimedRoles.Item(0)!.Value, 'Marketing manager'); const signedDataObjectProperties = xades.SignedProperties.SignedDataObjectProperties; assert.equal(signedDataObjectProperties.DataObjectFormats.Count, 1); assert.equal(signedDataObjectProperties.DataObjectFormats.Item(0)!.ObjectReference, ''); assert.equal(signedDataObjectProperties.CommitmentTypeIndications.Count, 1); assert.equal(signedDataObjectProperties.CommitmentTypeIndications.Item(0)!.CommitmentTypeId.Identifier.Value, '1.2.840.113549.1.9.16.6.3'); assert.equal(signedDataObjectProperties.CommitmentTypeIndications.Item(0)!.AllSignedDataObjects, true); }); it('X_BG_BOR_1', () => { const xades = QualifyingProperties.LoadXml(X_BG_BOR_1); assert.equal(xades.Target, '#id-413b14fe0d49b47be2670d4dbe692ded'); assert.equal(xades.SignedProperties.Id, 'xades-id-413b14fe0d49b47be2670d4dbe692ded'); const signedSignatureProperties = xades.SignedProperties.SignedSignatureProperties; assert.equal(!!signedSignatureProperties, true); const cert = signedSignatureProperties.SigningCertificate.Item(0)!; assert.equal(!!cert, true); assert.equal(cert.CertDigest.DigestMethod.Algorithm, 'http://www.w3.org/2000/09/xmldsig#sha1'); assert.equal(cert.CertDigest.DigestValue.byteLength, 20); assert.equal(cert.IssuerSerial.X509IssuerName, '2.5.4.20=#13102b333539203220392032313520313030,1.2.840.113549.1.9.1=#161263613571657340622d74727573742e6f7267,2.5.4.17=#130431373834,STREET=bul. Tsarigradsko shose No 117,CN=B-Trust Operational CA QES,OU=B-Trust,O=BORICA - BANKSERVICE AD\, EIK 201230426,L=Sofia,ST=Sofia,C=BG'); assert.equal(cert.IssuerSerial.X509SerialNumber, '10027144'); const signaturePolicyIdentifier = signedSignatureProperties.SignaturePolicyIdentifier; assert.equal(!!signaturePolicyIdentifier, true); assert.equal(signaturePolicyIdentifier.SignaturePolicyImplied, true); const signatureProductionPlace = signedSignatureProperties.SignatureProductionPlace; assert.equal(!!signatureProductionPlace, true); assert.equal(signatureProductionPlace.City, 'Sofia'); assert.equal(signatureProductionPlace.PostalCode, '1784'); assert.equal(signatureProductionPlace.StateOrProvince, 'bul. Tsar Boris 3 41,Sofia,PK:1612,EGN:8205301708'); assert.equal(signatureProductionPlace.CountryName, 'BG'); const signerRole = signedSignatureProperties.SignerRole; assert.equal(!!signerRole, true); assert.equal(signerRole.ClaimedRoles.Count, 1); assert.equal(signerRole.ClaimedRoles.Item(0)!.Value, 'ПОДПИСАН ОТ'); const signedDataObjectProperties = xades.SignedProperties.SignedDataObjectProperties; assert.equal(!!signedDataObjectProperties, true); assert.equal(signedDataObjectProperties.DataObjectFormats.Count, 1); assert.equal(signedDataObjectProperties.DataObjectFormats.Item(0)!.ObjectReference, '#r-id-1'); assert.equal(signedDataObjectProperties.DataObjectFormats.Item(0)!.MimeType, 'text/xml'); }); it('X_BE_CONN_26', () => { const xades = QualifyingProperties.LoadXml(X_BE_CONN_26); assert.equal(xades.Target, '#id-b26a17d23edf045b392cf714167df701'); assert.equal(xades.SignedProperties.Id, 'xades-id-b26a17d23edf045b392cf714167df701'); assert.equal(xades.UnsignedProperties.UnsignedSignatureProperties.Count, 4); xades.UnsignedProperties.UnsignedSignatureProperties.Some((item) => { if (item instanceof SignatureTimeStamp) { assert.equal(item.Id, 'TS-e964b0fc-172d-4631-bc0e-fa456c429a5e'); assert.equal(item.CanonicalizationMethod.Algorithm, 'http://www.w3.org/2001/10/xml-exc-c14n#'); assert.equal(item.EncapsulatedTimeStamp.Count, 1); assert.equal(item.EncapsulatedTimeStamp.Item(0)!.Id, 'ETS-e964b0fc-172d-4631-bc0e-fa456c429a5e'); assert.equal(item.EncapsulatedTimeStamp.Item(0)!.Value.byteLength, 4758); return true; } return false; }); xades.UnsignedProperties.UnsignedSignatureProperties.Some((item) => { if (item instanceof CertificateValues) { assert.equal(item.EncapsulatedX509Certificates.Count, 2); assert.equal(item.EncapsulatedX509Certificates.Item(0)!.Value.byteLength, 914); return true; } return false; }); xades.UnsignedProperties.UnsignedSignatureProperties.Some((item) => { if (item instanceof RevocationValues) { assert.equal(item.CRLValues.Count, 1); assert.equal(item.CRLValues.Item(0)!.Value.byteLength, 830); return true; } return false; }); xades.UnsignedProperties.UnsignedSignatureProperties.Some((item) => { if (item instanceof ArchiveTimeStamp) { assert.equal(item.Id, 'TS-8081f955-d8c9-498f-8922-dea64a21128d'); assert.equal(item.CanonicalizationMethod.Algorithm, 'http://www.w3.org/2001/10/xml-exc-c14n#'); assert.equal(item.EncapsulatedTimeStamp.Count, 1); assert.equal(item.EncapsulatedTimeStamp.Item(0)!.Id, 'ETS-8081f955-d8c9-498f-8922-dea64a21128d'); assert.equal(item.EncapsulatedTimeStamp.Item(0)!.Value.byteLength, 4758); return true; } return false; }); }); it('X_IT_ICB_6', () => { const xades = QualifyingProperties.LoadXml(X_IT_ICB_6); assert.equal(xades.Target, '#signature-6758-0293-4666-9275'); assert.equal(xades.UnsignedProperties.UnsignedSignatureProperties.Count, 1); xades.UnsignedProperties.UnsignedSignatureProperties.Some((item) => { if (item instanceof CounterSignature) { assert.equal(item.Signature.Id, 'signature-3538-3546-1081-6658'); return true; } return false; }); }); }); ================================================ FILE: test/xml/date_time.ts ================================================ import * as assert from 'assert'; import { XMLSerializer } from '@xmldom/xmldom'; import * as XAdES from '../../src'; context('xml', () => { context('DateTime', () => { const DATE = new Date(); context('Get XML', () => { it('Default format', () => { const dt = new XAdES.xml.XadesDateTime(); dt.Value = DATE; const xml = dt.GetXml(); const test = new XMLSerializer().serializeToString(xml as Node); assert.equal(test, `${DATE.toISOString()}`); }); it('Format HH:mm:ss', () => { const dt = new XAdES.xml.XadesDateTime(); dt.Value = DATE; dt.Format = 'HH:mm:ss'; const xml = dt.GetXml(); const test = new XMLSerializer().serializeToString(xml as Node); assert.equal(/\\d+\:\d+\:\d+\<\/xades\:XadesDateTime\>/.test(test), true); }); it('Format yyyy-mm-dd\'T\'HH:MM:sso', () => { const dt = new XAdES.xml.XadesDateTime(); dt.Value = DATE; dt.Format = 'isoDateTime'; const xml = dt.GetXml(); const test = new XMLSerializer().serializeToString(xml as Node); assert.equal(/\\d+\-\d+\-\d+T\d{2}\:\d{2}\:\d{2}[\+\-]\d{4}\<\/xades\:XadesDateTime\>/.test(test), true); }); }); }); }); ================================================ FILE: test/xml/encapsulated_pki_data.ts ================================================ import * as assert from 'assert'; import * as XAdES from '../../src'; context('xml', () => { context('EncapsulatedPKIData', () => { it('Parse', () => { const xmlObject = new XAdES.xml.EncapsulatedPKIData(); xmlObject.Id = '123'; xmlObject.Encoding = 'der'; xmlObject.Value = new Uint8Array([1, 0, 1]); const xml = xmlObject.toString(); assert.equal(xml, `AQAB`); const xmlObject2 = XAdES.xml.EncapsulatedPKIData.LoadXml(xml); assert.equal(xmlObject2.Id, xmlObject.Id); assert.equal(xmlObject2.Encoding, xmlObject.Encoding); assert.equal(xmlObject2.Value.byteLength, 3); }); }); }); ================================================ FILE: test/xml/generic_time_stamp.ts ================================================ import * as assert from 'assert'; import { XmlDsigC14NTransform } from 'xmldsigjs'; import * as XAdES from '../../src'; context('xml', () => { context('GenericTimeStamp', () => { it('Parse', () => { const xmlObject = new XAdES.xml.GenericTimeStamp(); xmlObject.Id = '123'; const encTS = new XAdES.xml.EncapsulatedTimeStamp(); encTS.Value = new Uint8Array([1, 0, 1]); xmlObject.EncapsulatedTimeStamp.Add(encTS); xmlObject.Include.Uri = 'http://some.com'; xmlObject.Include.ReferencedData = true; const rInfo = new XAdES.xml.ReferenceInfo(); rInfo.DigestMethod.Algorithm = 'http://www.w3.org/2001/04/xmlenc#sha256'; rInfo.DigestValue = new Uint8Array([1, 0, 1]); rInfo.Id = '123'; rInfo.Uri = 'http://some.com'; xmlObject.ReferenceInfo.Add(rInfo); const xmlTS = new XAdES.xml.XMLTimeStamp(); xmlTS.Value = 'some'; xmlObject.XMLTimeStamp.Add(xmlTS); xmlObject.CanonicalizationMethod.Algorithm = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'; // fix xmldom namespace error const c14n = new XmlDsigC14NTransform(); c14n.LoadInnerXml(xmlObject.GetXml() !); const xml = c14n.GetOutput(); const testXml = `AQABAQABsome`; assert.equal(xml, testXml); const xmlObject2 = XAdES.xml.GenericTimeStamp.LoadXml(xml); assert.equal(xmlObject2.Id, xmlObject.Id); }); }); }); ================================================ FILE: test/xml/object_identifier.ts ================================================ import * as assert from 'assert'; import * as XAdES from '../../src'; context('xml', () => { context('ObjectIdentifier', () => { it('Parse', () => { const xmlObject = new XAdES.xml.ObjectIdentifier(); xmlObject.Description = 'Description'; xmlObject.Identifier.Value = 'uri:oid'; xmlObject.Identifier.Qualifier = 'OIDAsURI'; const ref = new XAdES.xml.DocumentationReference(); ref.Uri = 'http://some1.com'; xmlObject.DocumentationReferences.Add(ref); assert.equal(xmlObject.DocumentationReferences.Count, 1); const xml = xmlObject.toString(); assert.equal(xml, `uri:oidDescriptionhttp://some1.com`); const xmlObject2 = XAdES.xml.ObjectIdentifier.LoadXml(xml); assert.equal(xmlObject2.Description, xmlObject.Description); assert.equal(xmlObject2.Identifier.Value, xmlObject.Identifier.Value); assert.equal(xmlObject2.Identifier.Qualifier, xmlObject.Identifier.Qualifier); assert.equal(xmlObject2.DocumentationReferences.Count, 1); assert.equal(xmlObject2.DocumentationReferences.Item(0) !.Uri, ref.Uri); }); }); }); ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { "module": "commonjs", "moduleResolution": "node", "target": "ES2018", "lib": [ "dom", "es2015" ], "outDir": "build", "esModuleInterop": true, "noImplicitAny": false, "removeComments": true, "sourceMap": true, "noUnusedLocals": true, "noUnusedParameters": false, "strict": true, "strictPropertyInitialization": false, "strictNullChecks": true, "pretty": true, "noImplicitReturns": true, "experimentalDecorators": true, "importHelpers": true, "forceConsistentCasingInFileNames": true, "skipLibCheck": true }, "exclude": [ "build" ] } ================================================ FILE: tsconfig.types.json ================================================ { "extends": "./tsconfig.json", "compilerOptions": { "declaration": true, "emitDeclarationOnly": true, "removeComments": false, "outDir": "build/types" }, "exclude": ["test", "build"] }