summaryrefslogtreecommitdiffstats
path: root/toolkit/components/certviewer
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /toolkit/components/certviewer
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/certviewer')
-rw-r--r--toolkit/components/certviewer/AboutCertViewerChild.jsm12
-rw-r--r--toolkit/components/certviewer/AboutCertViewerParent.jsm49
-rw-r--r--toolkit/components/certviewer/content/.eslintrc.js17
-rw-r--r--toolkit/components/certviewer/content/README.md14
-rw-r--r--toolkit/components/certviewer/content/asn1js.js9
-rw-r--r--toolkit/components/certviewer/content/certDecoder.js561
-rw-r--r--toolkit/components/certviewer/content/certviewer.css8
-rw-r--r--toolkit/components/certviewer/content/certviewer.html84
-rw-r--r--toolkit/components/certviewer/content/certviewer.js471
-rw-r--r--toolkit/components/certviewer/content/components/about-certificate-items.js33
-rw-r--r--toolkit/components/certviewer/content/components/about-certificate-section.css7
-rw-r--r--toolkit/components/certviewer/content/components/about-certificate-section.js121
-rw-r--r--toolkit/components/certviewer/content/components/certificate-section.css67
-rw-r--r--toolkit/components/certviewer/content/components/certificate-section.js91
-rw-r--r--toolkit/components/certviewer/content/components/certificate-tabs-section.js123
-rw-r--r--toolkit/components/certviewer/content/components/error-section.css27
-rw-r--r--toolkit/components/certviewer/content/components/error-section.js31
-rw-r--r--toolkit/components/certviewer/content/components/info-group-container.js65
-rw-r--r--toolkit/components/certviewer/content/components/info-group.css33
-rw-r--r--toolkit/components/certviewer/content/components/info-group.js91
-rw-r--r--toolkit/components/certviewer/content/components/info-item.css64
-rw-r--r--toolkit/components/certviewer/content/components/info-item.js199
-rw-r--r--toolkit/components/certviewer/content/components/list-item.css46
-rw-r--r--toolkit/components/certviewer/content/components/list-item.js58
-rw-r--r--toolkit/components/certviewer/content/ctlognames.js170
-rw-r--r--toolkit/components/certviewer/content/package.json20
-rw-r--r--toolkit/components/certviewer/content/pkijs.js9
-rw-r--r--toolkit/components/certviewer/content/pvutils.js9
-rw-r--r--toolkit/components/certviewer/content/strings.js505
-rw-r--r--toolkit/components/certviewer/content/utils.js77
-rw-r--r--toolkit/components/certviewer/content/vendor/asn1js_bundle.js5877
-rw-r--r--toolkit/components/certviewer/content/vendor/pkijs_bundle.js47423
-rw-r--r--toolkit/components/certviewer/content/vendor/pvutils_bundle.js791
-rw-r--r--toolkit/components/certviewer/jar.mn30
-rw-r--r--toolkit/components/certviewer/moz.build19
-rw-r--r--toolkit/components/certviewer/tests/browser/adjustedCerts.js267
-rw-r--r--toolkit/components/certviewer/tests/browser/browser.ini22
-rw-r--r--toolkit/components/certviewer/tests/browser/browser_aboutcertificateviewer.js81
-rw-r--r--toolkit/components/certviewer/tests/browser/browser_certificateTabLink.js63
-rw-r--r--toolkit/components/certviewer/tests/browser/browser_checkAuthorityKeyID.js52
-rw-r--r--toolkit/components/certviewer/tests/browser/browser_checkLongHex.js41
-rw-r--r--toolkit/components/certviewer/tests/browser/browser_checkMissingCommonName.js49
-rw-r--r--toolkit/components/certviewer/tests/browser/browser_checkNonEmptyFields.js80
-rw-r--r--toolkit/components/certviewer/tests/browser/browser_checkNonRepeatedCertTabs.js129
-rw-r--r--toolkit/components/certviewer/tests/browser/browser_checkNonUndefinedStrings.js49
-rw-r--r--toolkit/components/certviewer/tests/browser/browser_checkOCSP.js47
-rw-r--r--toolkit/components/certviewer/tests/browser/browser_checkStandAlonePage.js93
-rw-r--r--toolkit/components/certviewer/tests/browser/browser_checkValiditySection.js57
-rw-r--r--toolkit/components/certviewer/tests/browser/browser_clickableLink.js44
-rw-r--r--toolkit/components/certviewer/tests/browser/browser_downloadLink.js110
-rw-r--r--toolkit/components/certviewer/tests/browser/browser_handleMultipleCertsURL.js236
-rw-r--r--toolkit/components/certviewer/tests/browser/browser_openTabAndSendCertInfo.js262
-rw-r--r--toolkit/components/certviewer/tests/browser/browser_renderCertToUI.js184
-rw-r--r--toolkit/components/certviewer/tests/browser/dummy_page.html9
-rw-r--r--toolkit/components/certviewer/tests/browser/head.js125
-rw-r--r--toolkit/components/certviewer/tests/chrome/.eslintrc.js7
-rw-r--r--toolkit/components/certviewer/tests/chrome/CSoutput.js147
-rw-r--r--toolkit/components/certviewer/tests/chrome/chrome.ini12
-rw-r--r--toolkit/components/certviewer/tests/chrome/parseOutput.js342
-rw-r--r--toolkit/components/certviewer/tests/chrome/test_adjustCertInformation.html49
-rw-r--r--toolkit/components/certviewer/tests/chrome/test_certDecoder.html44
-rw-r--r--toolkit/components/certviewer/tests/chrome/test_certDecoderFields.html88
-rw-r--r--toolkit/components/certviewer/tests/chrome/test_kebabCaseInAdjustCertInformation.html110
63 files changed, 60010 insertions, 0 deletions
diff --git a/toolkit/components/certviewer/AboutCertViewerChild.jsm b/toolkit/components/certviewer/AboutCertViewerChild.jsm
new file mode 100644
index 0000000000..418063aa92
--- /dev/null
+++ b/toolkit/components/certviewer/AboutCertViewerChild.jsm
@@ -0,0 +1,12 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var EXPORTED_SYMBOLS = ["AboutCertViewerChild"];
+
+const { RemotePageChild } = ChromeUtils.import(
+ "resource://gre/actors/RemotePageChild.jsm"
+);
+
+class AboutCertViewerChild extends RemotePageChild {}
diff --git a/toolkit/components/certviewer/AboutCertViewerParent.jsm b/toolkit/components/certviewer/AboutCertViewerParent.jsm
new file mode 100644
index 0000000000..16cedeafee
--- /dev/null
+++ b/toolkit/components/certviewer/AboutCertViewerParent.jsm
@@ -0,0 +1,49 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+var EXPORTED_SYMBOLS = ["AboutCertViewerParent"];
+
+const TYPE_UNKNOWN = 0;
+const TYPE_CA = 1;
+const TYPE_USER = 2;
+const TYPE_EMAIL = 4;
+const TYPE_SERVER = 8;
+
+class AboutCertViewerParent extends JSWindowActorParent {
+ getCertificates() {
+ let certs = {
+ [TYPE_UNKNOWN]: [],
+ [TYPE_CA]: [],
+ [TYPE_USER]: [],
+ [TYPE_EMAIL]: [],
+ [TYPE_SERVER]: [],
+ };
+ let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
+ Ci.nsIX509CertDB
+ );
+ let certcache = certdb.getCerts();
+ for (let cert of certcache) {
+ for (let certType of Object.keys(certs).map(Number)) {
+ if (certType & cert.certType) {
+ certs[certType].push({
+ displayName: cert.displayName,
+ derb64: cert.getBase64DERString(),
+ });
+ }
+ }
+ }
+ return certs;
+ }
+
+ receiveMessage(aMessage) {
+ switch (aMessage.name) {
+ case "getCertificates":
+ return this.getCertificates();
+ }
+
+ return undefined;
+ }
+}
diff --git a/toolkit/components/certviewer/content/.eslintrc.js b/toolkit/components/certviewer/content/.eslintrc.js
new file mode 100644
index 0000000000..53d23f831d
--- /dev/null
+++ b/toolkit/components/certviewer/content/.eslintrc.js
@@ -0,0 +1,17 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+module.exports = {
+ parserOptions: {
+ sourceType: "module",
+ },
+ env: {
+ node: true,
+ },
+ globals: {
+ asn1js: true,
+ pvutils: true,
+ pkijs: true,
+ },
+};
diff --git a/toolkit/components/certviewer/content/README.md b/toolkit/components/certviewer/content/README.md
new file mode 100644
index 0000000000..53f104072b
--- /dev/null
+++ b/toolkit/components/certviewer/content/README.md
@@ -0,0 +1,14 @@
+# Certificate Viewer
+
+## Dependencies
+
+[PKI.js](https://github.com/PeculiarVentures/PKI.js)
+[ASN1.js](https://github.com/PeculiarVentures/ASN1.js)
+[pvutils.js](https://github.com/PeculiarVentures/pvutils)
+[Browserify](http://browserify.org/)
+
+## Updating dependencies
+
+Install all the dependencies doing `npm i`.
+
+Run `npm run build` any time you add something new to `pvutils.js`, `pkijs.js`, `asn1.js` or any other file required in that one.
diff --git a/toolkit/components/certviewer/content/asn1js.js b/toolkit/components/certviewer/content/asn1js.js
new file mode 100644
index 0000000000..8ff2635325
--- /dev/null
+++ b/toolkit/components/certviewer/content/asn1js.js
@@ -0,0 +1,9 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const asn1js = require("asn1js"); // version 2.0.22
+
+module.exports = {
+ asn1js,
+};
diff --git a/toolkit/components/certviewer/content/certDecoder.js b/toolkit/components/certviewer/content/certDecoder.js
new file mode 100644
index 0000000000..123cd082cf
--- /dev/null
+++ b/toolkit/components/certviewer/content/certDecoder.js
@@ -0,0 +1,561 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const { fromBER } = asn1js.asn1js;
+const { Certificate } = pkijs.pkijs;
+import {
+ b64urltodec,
+ b64urltohex,
+ getObjPath,
+ hash,
+ hashify,
+} from "./utils.js";
+import { strings } from "./strings.js";
+import { ctLogNames } from "./ctlognames.js";
+
+const getTimeZone = () => {
+ let timeZone = new Date().toString().match(/\(([A-Za-z\s].*)\)/);
+ if (timeZone === null) {
+ // America/Chicago
+ timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
+ } else if (timeZone.length > 1) {
+ timeZone = timeZone[1]; // Central Daylight Time
+ } else {
+ timeZone = "Local Time"; // not sure if this is right, but let's go with it for now
+ }
+ return timeZone;
+};
+
+const getPublicKeyInfo = x509 => {
+ let spki = Object.assign(
+ {
+ crv: undefined,
+ e: undefined,
+ kty: undefined,
+ n: undefined,
+ keysize: undefined,
+ x: undefined,
+ xy: undefined,
+ y: undefined,
+ },
+ x509.subjectPublicKeyInfo
+ );
+
+ if (spki.kty === "RSA") {
+ spki.e = b64urltodec(spki.e); // exponent
+ spki.keysize = b64urltohex(spki.n).length * 8; // key size in bits
+ spki.n = hashify(b64urltohex(spki.n)); // modulus
+ } else if (spki.kty === "EC") {
+ spki.kty = "Elliptic Curve";
+ spki.keysize = parseInt(spki.crv.split("-")[1]); // this is a bit hacky
+ spki.x = hashify(b64urltohex(spki.x)); // x coordinate
+ spki.y = hashify(b64urltohex(spki.y)); // y coordinate
+ spki.xy = `04:${spki.x}:${spki.y}`; // 04 (uncompressed) public key
+ }
+ return spki;
+};
+
+const getX509Ext = (extensions, v) => {
+ for (var extension in extensions) {
+ if (extensions[extension].extnID === v) {
+ return extensions[extension];
+ }
+ }
+ return {
+ extnValue: undefined,
+ parsedValue: undefined,
+ };
+};
+
+const getKeyUsages = (x509, criticalExtensions) => {
+ let keyUsages = {
+ critical: criticalExtensions.includes("2.5.29.15"),
+ purposes: [],
+ };
+
+ let keyUsagesBS = getX509Ext(x509.extensions, "2.5.29.15").parsedValue;
+ if (keyUsagesBS !== undefined) {
+ // parse the bit string, shifting as necessary
+ let unusedBits = keyUsagesBS.valueBlock.unusedBits;
+ keyUsagesBS = parseInt(keyUsagesBS.valueBlock.valueHex, 16) >> unusedBits;
+
+ // iterate through the bit string
+ strings.keyUsages.slice(unusedBits - 1).forEach(usage => {
+ if (keyUsagesBS & 1) {
+ keyUsages.purposes.push(usage);
+ }
+
+ keyUsagesBS = keyUsagesBS >> 1;
+ });
+
+ // reverse the order for legibility
+ keyUsages.purposes.reverse();
+ }
+
+ return keyUsages;
+};
+
+const parseSubsidiary = distinguishedNames => {
+ const subsidiary = {
+ cn: "",
+ dn: [],
+ entries: [],
+ };
+
+ distinguishedNames.forEach(dn => {
+ const name = strings.names[dn.type];
+ const value = dn.value.valueBlock.value;
+
+ if (name === undefined) {
+ subsidiary.dn.push(`OID.${dn.type}=${value}`);
+ subsidiary.entries.push([`OID.${dn.type}`, value]);
+ } else if (name.short === undefined) {
+ subsidiary.dn.push(`OID.${dn.type}=${value}`);
+ subsidiary.entries.push([name.long, value]);
+ } else {
+ subsidiary.dn.push(`${name.short}=${value}`);
+ subsidiary.entries.push([name.long, value]);
+
+ // add the common name for tab display
+ if (name.short === "cn") {
+ subsidiary.cn = value;
+ }
+ }
+ });
+
+ // turn path into a string
+ subsidiary.dn = subsidiary.dn.join(", ");
+
+ return subsidiary;
+};
+
+const getSubjectAltNames = (x509, criticalExtensions) => {
+ let san = getX509Ext(x509.extensions, "2.5.29.17").parsedValue;
+ if (san && san.hasOwnProperty("altNames")) {
+ san = Object.keys(san.altNames).map(x => {
+ const type = san.altNames[x].type;
+
+ switch (type) {
+ case 4: // directory
+ return [
+ strings.san[type],
+ parseSubsidiary(san.altNames[x].value.typesAndValues).dn,
+ ];
+ case 7: // ip address
+ let address = san.altNames[x].value.valueBlock.valueHex;
+
+ if (address.length === 8) {
+ // ipv4
+ return [
+ strings.san[type],
+ address
+ .match(/.{1,2}/g)
+ .map(x => parseInt(x, 16))
+ .join("."),
+ ];
+ } else if (address.length === 32) {
+ // ipv6
+ return [
+ strings.san[type],
+ address
+ .toLowerCase()
+ .match(/.{1,4}/g)
+ .join(":")
+ .replace(/\b:?(?:0+:?){2,}/, "::"),
+ ];
+ }
+ return [strings.san[type], "Unknown IP address"];
+
+ default:
+ return [strings.san[type], san.altNames[x].value];
+ }
+ });
+ } else {
+ san = [];
+ }
+ san = {
+ altNames: san,
+ critical: criticalExtensions.includes("2.5.29.17"),
+ };
+ return san;
+};
+
+const getBasicConstraints = (x509, criticalExtensions) => {
+ let basicConstraints;
+ const basicConstraintsExt = getX509Ext(x509.extensions, "2.5.29.19");
+ if (basicConstraintsExt && basicConstraintsExt.parsedValue) {
+ basicConstraints = {
+ cA:
+ basicConstraintsExt.parsedValue.cA !== undefined &&
+ basicConstraintsExt.parsedValue.cA,
+ critical: criticalExtensions.includes("2.5.29.19"),
+ };
+ }
+ return basicConstraints;
+};
+
+const getEKeyUsages = (x509, criticalExtensions) => {
+ let eKeyUsages = getX509Ext(x509.extensions, "2.5.29.37").parsedValue;
+ if (eKeyUsages) {
+ eKeyUsages = {
+ critical: criticalExtensions.includes("2.5.29.37"),
+ purposes: eKeyUsages.keyPurposes.map(x => strings.eKU[x] || x),
+ };
+ }
+ return eKeyUsages;
+};
+
+const getSubjectKeyID = (x509, criticalExtensions) => {
+ let sKID = getX509Ext(x509.extensions, "2.5.29.14").parsedValue;
+ if (sKID) {
+ sKID = {
+ critical: criticalExtensions.includes("2.5.29.14"),
+ id: hashify(sKID.valueBlock.valueHex),
+ };
+ }
+ return sKID;
+};
+
+const getAuthorityKeyID = (x509, criticalExtensions) => {
+ let aKID = getX509Ext(x509.extensions, "2.5.29.35").parsedValue;
+ if (!aKID || !aKID.keyIdentifier) {
+ return null;
+ }
+ aKID = {
+ critical: criticalExtensions.includes("2.5.29.35"),
+ id: hashify(aKID.keyIdentifier.valueBlock.valueHex),
+ };
+ return aKID;
+};
+
+const getCRLPoints = (x509, criticalExtensions) => {
+ let crlPoints = getX509Ext(x509.extensions, "2.5.29.31").parsedValue;
+ if (crlPoints) {
+ crlPoints = {
+ critical: criticalExtensions.includes("2.5.29.31"),
+ points: crlPoints.distributionPoints.map(
+ x => x.distributionPoint[0].value
+ ),
+ };
+ }
+ return crlPoints;
+};
+
+const getOcspStaple = (x509, criticalExtensions) => {
+ let ocspStaple = getX509Ext(x509.extensions, "1.3.6.1.5.5.7.1.24").extnValue;
+ if (ocspStaple && ocspStaple.valueBlock.valueHex === "3003020105") {
+ ocspStaple = {
+ critical: criticalExtensions.includes("1.3.6.1.5.5.7.1.24"),
+ required: true,
+ };
+ } else {
+ ocspStaple = {
+ critical: criticalExtensions.includes("1.3.6.1.5.5.7.1.24"),
+ required: false,
+ };
+ }
+ return ocspStaple;
+};
+
+const getAuthorityInfoAccess = (x509, criticalExtensions) => {
+ let aia = getX509Ext(x509.extensions, "1.3.6.1.5.5.7.1.1").parsedValue;
+ if (aia) {
+ aia = aia.accessDescriptions.map(x => {
+ return {
+ location: x.accessLocation.value,
+ method: strings.aia[x.accessMethod],
+ };
+ });
+ }
+
+ aia = {
+ descriptions: aia,
+ critical: criticalExtensions.includes("1.3.6.1.5.5.7.1.1"),
+ };
+ return aia;
+};
+
+const getSCTs = (x509, criticalExtensions) => {
+ let scts = getX509Ext(x509.extensions, "1.3.6.1.4.1.11129.2.4.2").parsedValue;
+ if (scts) {
+ scts = Object.keys(scts.timestamps).map(x => {
+ let logId = scts.timestamps[x].logID.toLowerCase();
+ let sctsTimestamp = scts.timestamps[x].timestamp;
+ return {
+ logId: hashify(logId),
+ name: ctLogNames.hasOwnProperty(logId) ? ctLogNames[logId] : undefined,
+ signatureAlgorithm: `${scts.timestamps[x].hashAlgorithm.replace(
+ "sha",
+ "SHA-"
+ )} ${scts.timestamps[x].signatureAlgorithm.toUpperCase()}`,
+ timestamp: `${sctsTimestamp.toLocaleString()} (${getTimeZone()})`,
+ timestampUTC: sctsTimestamp.toUTCString(),
+ version: scts.timestamps[x].version + 1,
+ };
+ });
+ } else {
+ scts = [];
+ }
+
+ scts = {
+ critical: criticalExtensions.includes("1.3.6.1.4.1.11129.2.4.2"),
+ timestamps: scts,
+ };
+ return scts;
+};
+
+const getCertificatePolicies = (x509, criticalExtensions) => {
+ let cp = getX509Ext(x509.extensions, "2.5.29.32").parsedValue;
+ if (cp && cp.hasOwnProperty("certificatePolicies")) {
+ cp = cp.certificatePolicies.map(x => {
+ let id = x.policyIdentifier;
+ let name = strings.cps.hasOwnProperty(id)
+ ? strings.cps[id].name
+ : undefined;
+ let qualifiers = undefined;
+ let value = strings.cps.hasOwnProperty(id)
+ ? strings.cps[id].value
+ : undefined;
+
+ // ansi organization identifiers
+ if (id.startsWith("2.16.840.")) {
+ value = id;
+ id = "2.16.840";
+ name = strings.cps["2.16.840"].name;
+ }
+
+ // statement identifiers
+ if (id.startsWith("1.3.6.1.4.1")) {
+ value = id;
+ id = "1.3.6.1.4.1";
+ name = strings.cps["1.3.6.1.4.1"].name;
+ }
+
+ if (x.hasOwnProperty("policyQualifiers")) {
+ qualifiers = x.policyQualifiers.map(qualifier => {
+ let id = qualifier.policyQualifierId;
+ let name = strings.cps.hasOwnProperty(id)
+ ? strings.cps[id].name
+ : undefined;
+ let value = qualifier.qualifier.valueBlock.value;
+
+ // sometimes they are multiple qualifier subblocks, and for now we'll
+ // only return the first one because it's getting really messy at this point
+ if (Array.isArray(value) && value.length === 1) {
+ value = value[0].valueBlock.value;
+ } else if (Array.isArray(value) && value.length > 1) {
+ value = "(currently unsupported)";
+ }
+
+ return {
+ id,
+ name,
+ value,
+ };
+ });
+ }
+
+ return {
+ id,
+ name,
+ qualifiers,
+ value,
+ };
+ });
+ }
+
+ cp = {
+ critical: criticalExtensions.includes("2.5.29.32"),
+ policies: cp,
+ };
+ return cp;
+};
+
+const getMicrosoftCryptographicExtensions = (x509, criticalExtensions) => {
+ // now let's parse the Microsoft cryptographic extensions
+ let msCrypto = {
+ caVersion: getX509Ext(x509.extensions, "1.3.6.1.4.1.311.21.1").parsedValue,
+ certificatePolicies: getX509Ext(x509.extensions, "1.3.6.1.4.1.311.21.10")
+ .parsedValue,
+ certificateTemplate: getX509Ext(x509.extensions, "1.3.6.1.4.1.311.21.7")
+ .parsedValue,
+ certificateType: getX509Ext(x509.extensions, "1.3.6.1.4.1.311.20.2")
+ .parsedValue,
+ previousHash: getX509Ext(x509.extensions, "1.3.6.1.4.1.311.21.2")
+ .parsedValue,
+ };
+
+ if (
+ msCrypto.caVersion &&
+ Number.isInteger(msCrypto.caVersion.keyIndex) &&
+ Number.isInteger(msCrypto.caVersion.certificateIndex)
+ ) {
+ msCrypto.caVersion = {
+ critical: criticalExtensions.includes("1.3.6.1.4.1.311.21.1"),
+ caRenewals: msCrypto.caVersion.certificateIndex,
+ keyReuses:
+ msCrypto.caVersion.certificateIndex - msCrypto.caVersion.keyIndex,
+ };
+ }
+
+ if (msCrypto.certificatePolicies) {
+ msCrypto.certificatePolicies = {
+ critical: criticalExtensions.includes("1.3.6.1.4.1.311.21.10"),
+ purposes: msCrypto.certificatePolicies.certificatePolicies.map(
+ x => strings.eKU[x.policyIdentifier] || x.policyIdentifier
+ ),
+ };
+ }
+
+ if (msCrypto.certificateTemplate) {
+ msCrypto.certificateTemplate = {
+ critical: criticalExtensions.includes("1.3.6.1.4.1.311.21.7"),
+ id: msCrypto.certificateTemplate.extnID,
+ major: msCrypto.certificateTemplate.templateMajorVersion,
+ minor: msCrypto.certificateTemplate.templateMinorVersion,
+ };
+ }
+
+ if (msCrypto.certificateType) {
+ msCrypto.certificateType = {
+ critical: criticalExtensions.includes("1.3.6.1.4.1.311.20.2"),
+ type:
+ strings.microsoftCertificateTypes[
+ msCrypto.certificateType.valueBlock.value
+ ] || "Unknown",
+ };
+ }
+
+ if (msCrypto.previousHash) {
+ msCrypto.previousHash = {
+ critical: criticalExtensions.includes("1.3.6.1.4.1.311.21.2"),
+ previousHash: hashify(msCrypto.previousHash.valueBlock.valueHex),
+ };
+ }
+
+ msCrypto.exists = !!(
+ msCrypto.caVersion ||
+ msCrypto.certificatePolicies ||
+ msCrypto.certificateTemplate ||
+ msCrypto.certificateType ||
+ msCrypto.previousHash
+ );
+
+ return msCrypto;
+};
+
+export const parse = async certificate => {
+ // certificate could be an array of BER or an array of buffers
+ const supportedExtensions = [
+ "1.3.6.1.4.1.311.20.2", // microsoft certificate type
+ "1.3.6.1.4.1.311.21.2", // microsoft certificate previous hash
+ "1.3.6.1.4.1.311.21.7", // microsoft certificate template
+ "1.3.6.1.4.1.311.21.1", // microsoft certification authority renewal
+ "1.3.6.1.4.1.311.21.10", // microsoft certificate policies
+ "1.3.6.1.4.1.11129.2.4.2", // embedded scts
+ "1.3.6.1.5.5.7.1.1", // authority info access
+ "1.3.6.1.5.5.7.1.24", // ocsp stapling
+ "1.3.101.77", // ct redaction - deprecated and not displayed
+ "2.5.29.14", // subject key identifier
+ "2.5.29.15", // key usages
+ "2.5.29.17", // subject alt names
+ "2.5.29.19", // basic constraints
+ "2.5.29.31", // crl points
+ "2.5.29.32", // certificate policies
+ "2.5.29.35", // authority key identifier
+ "2.5.29.37", // extended key usage
+ ];
+
+ let timeZone = getTimeZone();
+
+ // parse the certificate
+ const asn1 = fromBER(certificate);
+
+ let x509 = new Certificate({ schema: asn1.result });
+ x509 = x509.toJSON();
+
+ // convert the cert to PEM
+ const certBTOA = window
+ .btoa(String.fromCharCode.apply(null, new Uint8Array(certificate)))
+ .match(/.{1,64}/g)
+ .join("\r\n");
+
+ // get which extensions are critical
+ const criticalExtensions = [];
+ if (x509.extensions) {
+ x509.extensions.forEach(ext => {
+ if (ext.hasOwnProperty("critical") && ext.critical === true) {
+ criticalExtensions.push(ext.extnID);
+ }
+ });
+ }
+ const spki = getPublicKeyInfo(x509);
+ const keyUsages = getKeyUsages(x509, criticalExtensions);
+ const san = getSubjectAltNames(x509, criticalExtensions);
+ const basicConstraints = getBasicConstraints(x509, criticalExtensions);
+ const eKeyUsages = getEKeyUsages(x509, criticalExtensions);
+ const sKID = getSubjectKeyID(x509, criticalExtensions);
+ const aKID = getAuthorityKeyID(x509, criticalExtensions);
+ const crlPoints = getCRLPoints(x509, criticalExtensions);
+ const ocspStaple = getOcspStaple(x509, criticalExtensions);
+ const aia = getAuthorityInfoAccess(x509, criticalExtensions);
+ const scts = getSCTs(x509, criticalExtensions);
+ const cp = getCertificatePolicies(x509, criticalExtensions);
+ const msCrypto = getMicrosoftCryptographicExtensions(
+ x509,
+ criticalExtensions
+ );
+
+ // determine which extensions weren't supported
+ let unsupportedExtensions = [];
+ if (x509.extensions) {
+ x509.extensions.forEach(ext => {
+ if (!supportedExtensions.includes(ext.extnID)) {
+ unsupportedExtensions.push(ext.extnID);
+ }
+ });
+ }
+
+ // the output shell
+ return {
+ ext: {
+ aia,
+ aKID,
+ basicConstraints,
+ crlPoints,
+ cp,
+ eKeyUsages,
+ keyUsages,
+ msCrypto,
+ ocspStaple,
+ scts,
+ sKID,
+ san,
+ },
+ files: {
+ der: undefined, // TODO: implement!
+ pem: encodeURI(
+ `-----BEGIN CERTIFICATE-----\r\n${certBTOA}\r\n-----END CERTIFICATE-----\r\n`
+ ),
+ },
+ fingerprint: {
+ sha1: await hash("SHA-1", certificate),
+ sha256: await hash("SHA-256", certificate),
+ },
+ issuer: parseSubsidiary(x509.issuer.typesAndValues),
+ notBefore: `${x509.notBefore.value.toLocaleString()} (${timeZone})`,
+ notBeforeUTC: x509.notBefore.value.toUTCString(),
+ notAfter: `${x509.notAfter.value.toLocaleString()} (${timeZone})`,
+ notAfterUTC: x509.notAfter.value.toUTCString(),
+ subject: parseSubsidiary(x509.subject.typesAndValues),
+ serialNumber: hashify(getObjPath(x509, "serialNumber.valueBlock.valueHex")),
+ signature: {
+ name: strings.signature[getObjPath(x509, "signature.algorithmId")],
+ type: getObjPath(x509, "signature.algorithmId"),
+ },
+ subjectPublicKeyInfo: spki,
+ unsupportedExtensions,
+ version: (x509.version + 1).toString(),
+ };
+};
diff --git a/toolkit/components/certviewer/content/certviewer.css b/toolkit/components/certviewer/content/certviewer.css
new file mode 100644
index 0000000000..1d5bd52917
--- /dev/null
+++ b/toolkit/components/certviewer/content/certviewer.css
@@ -0,0 +1,8 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+body {
+ max-width: 800px;
+ margin: 0 auto;
+}
diff --git a/toolkit/components/certviewer/content/certviewer.html b/toolkit/components/certviewer/content/certviewer.html
new file mode 100644
index 0000000000..3f097e48ad
--- /dev/null
+++ b/toolkit/components/certviewer/content/certviewer.html
@@ -0,0 +1,84 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE html>
+
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width" />
+ <meta http-equiv="Content-Security-Policy" content="default-src chrome:; object-src 'none'" />
+ <link rel="localization" href="toolkit/about/certviewer.ftl">
+ <link rel="localization" href="branding/brand.ftl">
+ <script defer="defer" src="chrome://global/content/certviewer/pvutils_bundle.js"></script>
+ <script defer="defer" src="chrome://global/content/certviewer/asn1js_bundle.js"></script>
+ <script defer="defer" src="chrome://global/content/certviewer/pkijs_bundle.js"></script>
+ <script defer="defer" type="module" src="chrome://global/content/certviewer/ctlognames.js"></script>
+ <script defer="defer" type="module" src="chrome://global/content/certviewer/strings.js"></script>
+ <script defer="defer" type="module" src="chrome://global/content/certviewer/utils.js"></script>
+ <script defer="defer" type="module" src="chrome://global/content/certviewer/certDecoder.js"></script>
+ <script defer="defer" type="module" src="chrome://global/content/certviewer/certviewer.js"></script>
+ <script defer="defer" type="module" src="chrome://global/content/certviewer/components/list-item.js"></script>
+ <script defer="defer" type="module" src="chrome://global/content/certviewer/components/info-group.js"></script>
+ <script defer="defer" type="module" src="chrome://global/content/certviewer/components/info-group-container.js"></script>
+ <script defer="defer" type="module" src="chrome://global/content/certviewer/components/info-item.js"></script>
+ <script defer="defer" type="module" src="chrome://global/content/certviewer/components/certificate-tabs-section.js"></script>
+ <script defer="defer" type="module" src="chrome://global/content/certviewer/components/certificate-section.js"></script>
+ <script defer="defer" type="module" src="chrome://global/content/certviewer/components/error-section.js"></script>
+ <script defer="defer" type="module" src="chrome://global/content/certviewer/components/about-certificate-section.js"></script>
+ <script defer="defer" type="module" src="chrome://global/content/certviewer/components/about-certificate-items.js"></script>
+ <link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
+ <link rel="stylesheet" href="chrome://global/content/certviewer/certviewer.css">
+ <title id="certTitle">about:certificate</title>
+ </head>
+ <body>
+ <template id="certificate-section-template" class="section">
+ <link rel="stylesheet" href="chrome://global/content/certviewer/components/certificate-section.css">
+ <h1 class="title"></h1>
+ </template>
+
+ <template id="certificate-tabs-template">
+ <div class="certificate-tabs" role="tablist"></div>
+ </template>
+
+ <template id="info-groups-template">
+ </template>
+
+ <template id="info-item-template">
+ <link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
+ <link rel="stylesheet" href="chrome://global/content/certviewer/components/info-item.css">
+ <label></label>
+ <span class="info"></span>
+ </template>
+
+ <template id="info-group-template">
+ <link rel="stylesheet" href="chrome://global/content/certviewer/components/info-group.css">
+ <span class="extension">
+ <img src="chrome://browser/skin/critical.svg" id="critical-info" data-l10n-id="certificate-viewer-critical-extension">
+ <span class="info-group-title"></span>
+ </span>
+ <span class="info-group-title-hr"></span>
+ </template>
+
+ <template id="error-section-template">
+ <link rel="stylesheet" href="chrome://global/content/certviewer/components/error-section.css">
+ <h1 class="title"></h1>
+ <span class="error"></span>
+ </template>
+
+ <template id="about-certificate-template" class="section">
+ <link rel="stylesheet" href="chrome://global/content/certviewer/components/certificate-section.css">
+ <h1 class="title"></h1>
+ </template>
+
+ <template id="about-certificate-items-template">
+ <link rel="stylesheet" href="chrome://global/content/certviewer/components/about-certificate-section.css">
+ </template>
+
+ <template id="list-item-template">
+ <link rel="stylesheet" href="chrome://global/content/certviewer/components/list-item.css">
+ <a class="cert-url"><span class="item-name"></span></a>
+ <button class="export"></button>
+ </template>
+ </body>
+</html>
diff --git a/toolkit/components/certviewer/content/certviewer.js b/toolkit/components/certviewer/content/certviewer.js
new file mode 100644
index 0000000000..1edea7a3af
--- /dev/null
+++ b/toolkit/components/certviewer/content/certviewer.js
@@ -0,0 +1,471 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* eslint-env mozilla/frame-script */
+
+"use strict";
+
+import { parse } from "./certDecoder.js";
+import { pemToDER, normalizeToKebabCase } from "./utils.js";
+
+document.addEventListener("DOMContentLoaded", async e => {
+ let url = new URL(document.URL);
+ let certInfo = url.searchParams.getAll("cert");
+ if (certInfo.length === 0) {
+ render({}, false, true);
+ return;
+ }
+ certInfo = certInfo.map(cert => decodeURIComponent(cert));
+ await buildChain(certInfo);
+});
+
+export const updateSelectedItem = (() => {
+ let state;
+ return selectedItem => {
+ let certificateSection =
+ document.querySelector("certificate-section") ||
+ document.querySelector("about-certificate-section");
+ if (selectedItem) {
+ if (state !== selectedItem) {
+ state = selectedItem;
+ certificateSection.updateCertificateSource(selectedItem);
+ certificateSection.updateSelectedTab(selectedItem);
+ }
+ }
+ return state;
+ };
+})();
+
+const createEntryItem = (labelId, info, isHex = false) => {
+ if (
+ labelId == null ||
+ info == null ||
+ (Array.isArray(info) && !info.length)
+ ) {
+ return null;
+ }
+ return {
+ labelId,
+ info,
+ isHex,
+ };
+};
+
+const addToResultUsing = (callback, certItems, sectionId, Critical) => {
+ let items = callback();
+ if (items.length) {
+ certItems.push({
+ sectionId,
+ sectionItems: items,
+ Critical,
+ });
+ }
+};
+
+const getElementByPathOrFalse = (obj, pathString) => {
+ let pathArray = pathString.split(".");
+ let result = obj;
+ for (let entry of pathArray) {
+ result = result[entry];
+ if (result == null) {
+ return false;
+ }
+ }
+ return result ? result : false;
+};
+
+export const adjustCertInformation = cert => {
+ let certItems = [];
+ let tabName = cert?.subject?.cn || "";
+ if (cert && !tabName) {
+ // No common name, use the value of the last item in the cert's entries.
+ tabName = cert.subject?.entries?.slice(-1)[0]?.[1] || "";
+ }
+
+ if (!cert) {
+ return {
+ certItems,
+ tabName,
+ };
+ }
+
+ addToResultUsing(
+ () => {
+ let items = [];
+ if (cert.subject && cert.subject.entries) {
+ items = cert.subject.entries
+ .map(entry =>
+ createEntryItem(normalizeToKebabCase(entry[0]), entry[1])
+ )
+ .filter(elem => elem != null);
+ }
+ return items;
+ },
+ certItems,
+ "subject-name",
+ false
+ );
+
+ addToResultUsing(
+ () => {
+ let items = [];
+ if (cert.issuer && cert.issuer.entries) {
+ items = cert.issuer.entries
+ .map(entry =>
+ createEntryItem(normalizeToKebabCase(entry[0]), entry[1])
+ )
+ .filter(elem => elem != null);
+ }
+ return items;
+ },
+ certItems,
+ "issuer-name",
+ false
+ );
+
+ addToResultUsing(
+ () => {
+ let items = [];
+ if (cert.notBefore && cert.notAfter) {
+ items = [
+ createEntryItem("not-before", {
+ local: cert.notBefore,
+ utc: cert.notBeforeUTC,
+ }),
+ createEntryItem("not-after", {
+ local: cert.notAfter,
+ utc: cert.notAfterUTC,
+ }),
+ ].filter(elem => elem != null);
+ }
+ return items;
+ },
+ certItems,
+ "validity",
+ false
+ );
+
+ addToResultUsing(
+ () => {
+ let items = [];
+ if (cert.ext && cert.ext.san && cert.ext.san.altNames) {
+ items = cert.ext.san.altNames
+ .map(entry =>
+ createEntryItem(normalizeToKebabCase(entry[0]), entry[1])
+ )
+ .filter(elem => elem != null);
+ }
+ return items;
+ },
+ certItems,
+ "subject-alt-names",
+ getElementByPathOrFalse(cert, "ext.san.critical")
+ );
+
+ addToResultUsing(
+ () => {
+ let items = [];
+ if (cert.subjectPublicKeyInfo) {
+ items = [
+ createEntryItem("algorithm", cert.subjectPublicKeyInfo.kty),
+ createEntryItem("key-size", cert.subjectPublicKeyInfo.keysize),
+ createEntryItem("curve", cert.subjectPublicKeyInfo.crv),
+ createEntryItem("public-value", cert.subjectPublicKeyInfo.xy, true),
+ createEntryItem("exponent", cert.subjectPublicKeyInfo.e),
+ createEntryItem("modulus", cert.subjectPublicKeyInfo.n, true),
+ ].filter(elem => elem != null);
+ }
+ return items;
+ },
+ certItems,
+ "public-key-info",
+ false
+ );
+
+ addToResultUsing(
+ () => {
+ let items = [
+ createEntryItem("serial-number", cert.serialNumber, true),
+ createEntryItem(
+ "signature-algorithm",
+ cert.signature ? cert.signature.name : null
+ ),
+ createEntryItem("version", cert.version),
+ createEntryItem("download", cert.files ? cert.files.pem : null),
+ ].filter(elem => elem != null);
+ return items;
+ },
+ certItems,
+ "miscellaneous",
+ false
+ );
+
+ addToResultUsing(
+ () => {
+ let items = [];
+ if (cert.fingerprint) {
+ items = [
+ createEntryItem("sha-256", cert.fingerprint.sha256, true),
+ createEntryItem("sha-1", cert.fingerprint.sha1, true),
+ ].filter(elem => elem != null);
+ }
+ return items;
+ },
+ certItems,
+ "fingerprints",
+ false
+ );
+
+ if (!cert.ext) {
+ return {
+ certItems,
+ tabName,
+ };
+ }
+
+ addToResultUsing(
+ () => {
+ let items = [];
+ if (cert.ext.basicConstraints) {
+ items = [
+ createEntryItem(
+ "certificate-authority",
+ cert.ext.basicConstraints.cA
+ ),
+ ].filter(elem => elem != null);
+ }
+ return items;
+ },
+ certItems,
+ "basic-constraints",
+ getElementByPathOrFalse(cert, "ext.basicConstraints.critical")
+ );
+
+ addToResultUsing(
+ () => {
+ let items = [];
+ if (cert.ext.keyUsages) {
+ items = [
+ createEntryItem("purposes", cert.ext.keyUsages.purposes),
+ ].filter(elem => elem != null);
+ }
+ return items;
+ },
+ certItems,
+ "key-usages",
+ getElementByPathOrFalse(cert, "ext.keyUsages.critical")
+ );
+
+ addToResultUsing(
+ () => {
+ let items = [];
+ if (cert.ext.eKeyUsages) {
+ items = [
+ createEntryItem("purposes", cert.ext.eKeyUsages.purposes),
+ ].filter(elem => elem != null);
+ }
+ return items;
+ },
+ certItems,
+ "extended-key-usages",
+ getElementByPathOrFalse(cert, "ext.eKeyUsages.critical")
+ );
+
+ addToResultUsing(
+ () => {
+ let items = [];
+ if (cert.ext.ocspStaple && cert.ext.ocspStaple.required) {
+ items = [createEntryItem("required", true)];
+ }
+ return items;
+ },
+ certItems,
+ "ocsp-stapling",
+ getElementByPathOrFalse(cert, "ext.ocspStaple.critical")
+ );
+
+ addToResultUsing(
+ () => {
+ let items = [];
+ if (cert.ext.sKID) {
+ items = [createEntryItem("key-id", cert.ext.sKID.id, true)].filter(
+ elem => elem != null
+ );
+ }
+ return items;
+ },
+ certItems,
+ "subject-key-id",
+ getElementByPathOrFalse(cert, "ext.sKID.critical")
+ );
+
+ addToResultUsing(
+ () => {
+ let items = [];
+ if (cert.ext.aKID) {
+ items = [createEntryItem("key-id", cert.ext.aKID.id, true)].filter(
+ elem => elem != null
+ );
+ }
+ return items;
+ },
+ certItems,
+ "authority-key-id",
+ getElementByPathOrFalse(cert, "ext.aKID.critical")
+ );
+
+ addToResultUsing(
+ () => {
+ let items = [];
+ if (cert.ext.crlPoints && cert.ext.crlPoints.points) {
+ items = cert.ext.crlPoints.points
+ .map(entry => {
+ let label = "distribution-point";
+ return createEntryItem(label, entry);
+ })
+ .filter(elem => elem != null);
+ }
+ return items;
+ },
+ certItems,
+ "crl-endpoints",
+ getElementByPathOrFalse(cert, "ext.crlPoints.critical")
+ );
+
+ addToResultUsing(
+ () => {
+ let items = [];
+ if (cert.ext.aia && cert.ext.aia.descriptions) {
+ cert.ext.aia.descriptions.forEach(entry => {
+ items.push(createEntryItem("location", entry.location));
+ items.push(createEntryItem("method", entry.method));
+ });
+ }
+ return items.filter(elem => elem != null);
+ },
+ certItems,
+ "authority-info-aia",
+ getElementByPathOrFalse(cert, "ext.aia.critical")
+ );
+
+ addToResultUsing(
+ () => {
+ let items = [];
+ if (cert.ext.cp && cert.ext.cp.policies) {
+ cert.ext.cp.policies.forEach(entry => {
+ if (entry.name && entry.id) {
+ items.push(
+ createEntryItem("policy", entry.name + " ( " + entry.id + " )")
+ );
+ }
+ items.push(createEntryItem("value", entry.value));
+ if (entry.qualifiers) {
+ entry.qualifiers.forEach(qualifier => {
+ if (qualifier.name && qualifier.id) {
+ items.push(
+ createEntryItem(
+ "qualifier",
+ qualifier.name + " ( " + qualifier.id + " )"
+ )
+ );
+ }
+ items.push(createEntryItem("value", qualifier.value));
+ });
+ }
+ });
+ }
+ return items.filter(elem => elem != null);
+ },
+ certItems,
+ "certificate-policies",
+ getElementByPathOrFalse(cert, "ext.cp.critical")
+ );
+
+ addToResultUsing(
+ () => {
+ let items = [];
+ if (cert.ext.scts && cert.ext.scts.timestamps) {
+ cert.ext.scts.timestamps.forEach(entry => {
+ let timestamps = {};
+ for (let key of Object.keys(entry)) {
+ if (key.includes("timestamp")) {
+ timestamps[key.includes("UTC") ? "utc" : "local"] = entry[key];
+ } else {
+ let isHex = false;
+ if (key == "logId") {
+ isHex = true;
+ }
+ items.push(
+ createEntryItem(normalizeToKebabCase(key), entry[key], isHex)
+ );
+ }
+ }
+ items.push(createEntryItem("timestamp", timestamps));
+ });
+ }
+ return items.filter(elem => elem != null);
+ },
+ certItems,
+ "embedded-scts",
+ getElementByPathOrFalse(cert, "ext.scts.critical")
+ );
+
+ return {
+ certItems,
+ tabName,
+ };
+};
+
+// isAboutCertificate means to the standalone page about:certificate, which
+// uses a different customElement than opening a certain certificate
+const render = async (certs, error, isAboutCertificate = false) => {
+ if (isAboutCertificate) {
+ await customElements.whenDefined("about-certificate-section");
+ const AboutCertificateSection = customElements.get(
+ "about-certificate-section"
+ );
+ document.querySelector("body").append(new AboutCertificateSection());
+ } else {
+ await customElements.whenDefined("certificate-section");
+ const CertificateSection = customElements.get("certificate-section");
+ document.querySelector("body").append(new CertificateSection(certs, error));
+ }
+ return Promise.resolve();
+};
+
+const buildChain = async chain => {
+ await Promise.all(
+ chain
+ .map(cert => {
+ try {
+ return pemToDER(cert);
+ } catch (err) {
+ return Promise.reject(err);
+ }
+ })
+ .map(cert => {
+ try {
+ return parse(cert);
+ } catch (err) {
+ return Promise.reject(err);
+ }
+ })
+ )
+ .then(certs => {
+ if (certs.length === 0) {
+ return Promise.reject();
+ }
+ let certTitle = document.querySelector("#certTitle");
+ let firstCertCommonName = certs[0].subject.cn;
+ document.l10n.setAttributes(certTitle, "certificate-viewer-tab-title", {
+ firstCertName: firstCertCommonName,
+ });
+
+ let adjustedCerts = certs.map(cert => adjustCertInformation(cert));
+ return render(adjustedCerts, false);
+ })
+ .catch(err => {
+ render(null, true);
+ });
+};
diff --git a/toolkit/components/certviewer/content/components/about-certificate-items.js b/toolkit/components/certviewer/content/components/about-certificate-items.js
new file mode 100644
index 0000000000..1d056d50f2
--- /dev/null
+++ b/toolkit/components/certviewer/content/components/about-certificate-items.js
@@ -0,0 +1,33 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* eslint-env mozilla/frame-script */
+
+import { ListItem } from "./list-item.js";
+
+export class AboutCertificateItems extends HTMLElement {
+ constructor(id, data) {
+ super();
+ this.id = id;
+ this.data = data;
+ }
+
+ connectedCallback() {
+ let template = document.getElementById("about-certificate-items-template");
+ let templateHtml = template.content.cloneNode(true);
+
+ this.attachShadow({ mode: "open" }).appendChild(templateHtml);
+
+ document.l10n.connectRoot(this.shadowRoot);
+
+ this.render();
+ }
+
+ render() {
+ for (let cert of this.data) {
+ this.shadowRoot.append(new ListItem(cert));
+ }
+ }
+}
+customElements.define("about-certificate-items", AboutCertificateItems);
diff --git a/toolkit/components/certviewer/content/components/about-certificate-section.css b/toolkit/components/certviewer/content/components/about-certificate-section.css
new file mode 100644
index 0000000000..4f472b57d5
--- /dev/null
+++ b/toolkit/components/certviewer/content/components/about-certificate-section.css
@@ -0,0 +1,7 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+:host {
+ margin: 2em;
+}
diff --git a/toolkit/components/certviewer/content/components/about-certificate-section.js b/toolkit/components/certviewer/content/components/about-certificate-section.js
new file mode 100644
index 0000000000..1c940ac484
--- /dev/null
+++ b/toolkit/components/certviewer/content/components/about-certificate-section.js
@@ -0,0 +1,121 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* eslint-env mozilla/frame-script */
+
+import { InfoGroupContainer } from "./info-group-container.js";
+import { CertificateTabsSection } from "./certificate-tabs-section.js";
+
+const TYPE_UNKNOWN = 0;
+const TYPE_CA = 1;
+const TYPE_USER = 2;
+const TYPE_EMAIL = 4;
+const TYPE_SERVER = 8;
+
+export class AboutCertificateSection extends HTMLElement {
+ constructor() {
+ super();
+ }
+
+ connectedCallback() {
+ let template = document.getElementById("about-certificate-template");
+ let templateHtml = template.content.cloneNode(true);
+
+ this.attachShadow({ mode: "open" }).appendChild(templateHtml);
+
+ document.l10n.connectRoot(this.shadowRoot);
+
+ this.certificateTabsSection = new CertificateTabsSection(true);
+ this.shadowRoot.appendChild(this.certificateTabsSection.tabsElement);
+ this.infoGroupsContainers = new InfoGroupContainer(true);
+
+ this.render();
+ }
+
+ render() {
+ RPMSendQuery("getCertificates").then(this.filterCerts.bind(this));
+
+ let title = this.shadowRoot.querySelector(".title");
+ title.setAttribute(
+ "data-l10n-id",
+ "certificate-viewer-certificate-section-title"
+ );
+ }
+
+ filterCerts(srcCerts) {
+ let certs = [];
+ if (srcCerts[TYPE_USER].length) {
+ certs.push({
+ name: "certificate-viewer-tab-mine",
+ data: srcCerts[TYPE_USER],
+ });
+ }
+ if (srcCerts[TYPE_EMAIL].length) {
+ certs.push({
+ name: "certificate-viewer-tab-people",
+ data: srcCerts[TYPE_EMAIL],
+ });
+ }
+ if (srcCerts[TYPE_SERVER].length) {
+ certs.push({
+ name: "certificate-viewer-tab-servers",
+ data: srcCerts[TYPE_SERVER],
+ });
+ }
+ if (srcCerts[TYPE_CA].length) {
+ certs.push({
+ name: "certificate-viewer-tab-ca",
+ data: srcCerts[TYPE_CA],
+ });
+ }
+ if (srcCerts[TYPE_UNKNOWN].length) {
+ certs.push({
+ name: "certificate-viewer-tab-unkonwn",
+ data: srcCerts[TYPE_UNKNOWN],
+ });
+ }
+
+ let i = 0;
+ for (let cert of certs) {
+ let final = i == certs.length - 1;
+ this.infoGroupsContainers.createInfoGroupsContainers({}, i, final, cert);
+ this.shadowRoot.appendChild(
+ this.infoGroupsContainers.infoGroupsContainers[i]
+ );
+ this.certificateTabsSection.createTabSection(cert.name, i);
+ this.infoGroupsContainers.addClass("selected", 0);
+ i++;
+ }
+ this.setAccessibilityEventListeners();
+ this.addClassForPadding();
+ }
+
+ // Adds class selector for items that need padding,
+ // as nth-child/parent-based selectors aren't supported
+ // due to the encapsulation of custom-element CSS.
+ addClassForPadding() {
+ let embeddedScts = this.shadowRoot.querySelector(".embedded-scts");
+ if (!embeddedScts) {
+ return;
+ }
+ let items = embeddedScts.shadowRoot.querySelectorAll(".version");
+
+ for (let i = 0; i < items.length; i++) {
+ items[i].classList.add("padding");
+ }
+ }
+
+ setAccessibilityEventListeners() {
+ this.certificateTabsSection.setAccessibilityEventListeners();
+ }
+
+ updateSelectedTab(index) {
+ this.certificateTabsSection.updateSelectedTab(index);
+ }
+
+ updateCertificateSource(index) {
+ this.infoGroupsContainers.updateCertificateSource(index);
+ }
+}
+customElements.define("about-certificate-section", AboutCertificateSection);
diff --git a/toolkit/components/certviewer/content/components/certificate-section.css b/toolkit/components/certviewer/content/components/certificate-section.css
new file mode 100644
index 0000000000..c48735e9f1
--- /dev/null
+++ b/toolkit/components/certviewer/content/components/certificate-section.css
@@ -0,0 +1,67 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+h1 {
+ font-size: 1.5em;
+ font-weight: lighter;
+ margin: 3em 0 1em;
+}
+
+.certificate-tabs {
+ display: flex;
+ text-align: center;
+ border-bottom: 1px solid var(--in-content-border-active);
+ box-shadow: var(--card-shadow);
+}
+
+.info-groups {
+ display: none;
+ outline: none;
+ background-color: var(--in-content-box-background);
+ box-shadow: var(--card-shadow);
+ margin-bottom: 2em;
+ border-radius: 0 0 4px 4px;
+}
+
+.info-groups.selected {
+ display: block;
+}
+
+.tab {
+ margin: 0;
+ border-radius: 0;
+ padding: 18px;
+ padding-bottom: 15px; /* compensate for border-bottom below */
+ border: none;
+ border-bottom: 3px solid transparent;
+ background-color: var(--in-content-box-background);
+ color: var(--in-content-text-color);
+ flex: 1 1 auto;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ font-size: 1.363rem;
+}
+
+/* .tab can be LTR (by `dir="auto"`) for `about:certificate?cert=`
+ pages, so set the border-radius according to the parent's direction. */
+.certificate-tabs:dir(rtl) > .tab:first-of-type,
+.certificate-tabs:dir(ltr) > .tab:last-of-type {
+ border-top-right-radius: 4px;
+}
+
+.certificate-tabs:dir(ltr) > .tab:first-of-type,
+.certificate-tabs:dir(rtl) > .tab:last-of-type {
+ border-top-left-radius: 4px;
+}
+
+.tab:hover {
+ border-bottom-color: var(--in-content-border-active-shadow);
+}
+
+.tab.selected {
+ border-bottom-color: var(--in-content-border-active);
+ color: var(--in-content-link-color);
+ text-overflow: unset;
+ overflow: visible;
+}
diff --git a/toolkit/components/certviewer/content/components/certificate-section.js b/toolkit/components/certviewer/content/components/certificate-section.js
new file mode 100644
index 0000000000..2502931754
--- /dev/null
+++ b/toolkit/components/certviewer/content/components/certificate-section.js
@@ -0,0 +1,91 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import { ErrorSection } from "./error-section.js";
+import { InfoGroupContainer } from "./info-group-container.js";
+import { CertificateTabsSection } from "./certificate-tabs-section.js";
+
+class CertificateSection extends HTMLElement {
+ constructor(certs, error) {
+ super();
+ this.certs = certs;
+ this.error = error;
+ }
+
+ connectedCallback() {
+ let template = document.getElementById("certificate-section-template");
+ let templateHtml = template.content.cloneNode(true);
+
+ this.attachShadow({ mode: "open" }).appendChild(templateHtml);
+
+ document.l10n.connectRoot(this.shadowRoot);
+ document.l10n.translateFragment(this.shadowRoot);
+
+ this.certificateTabsSection = new CertificateTabsSection();
+ this.shadowRoot.appendChild(this.certificateTabsSection.tabsElement);
+ this.infoGroupsContainers = new InfoGroupContainer();
+
+ this.render();
+ }
+
+ render() {
+ let title = this.shadowRoot.querySelector(".title");
+ title.setAttribute(
+ "data-l10n-id",
+ "certificate-viewer-certificate-section-title"
+ );
+
+ if (this.error) {
+ title.classList.add("error");
+ this.certificateTabsSection.appendChild(new ErrorSection());
+ return;
+ }
+ let final = false;
+ for (let i = 0; i < this.certs.length; i++) {
+ if (i === this.certs.length - 1) {
+ final = true;
+ }
+ this.infoGroupsContainers.createInfoGroupsContainers(
+ this.certs[i].certItems,
+ i,
+ final
+ );
+ this.shadowRoot.appendChild(
+ this.infoGroupsContainers.infoGroupsContainers[i]
+ );
+ this.certificateTabsSection.createTabSection(this.certs[i].tabName, i);
+ this.infoGroupsContainers.addClass("selected", 0);
+ }
+ this.setAccessibilityEventListeners();
+ this.addClassForPadding();
+ }
+
+ // Adds class selector for items that need padding,
+ // as nth-child/parent-based selectors aren't supported
+ // due to the encapsulation of custom-element CSS.
+ addClassForPadding() {
+ let embeddedScts = this.shadowRoot.querySelector(".embedded-scts");
+ if (!embeddedScts) {
+ return;
+ }
+ let items = embeddedScts.shadowRoot.querySelectorAll(".version");
+
+ for (let i = 0; i < items.length; i++) {
+ items[i].classList.add("padding");
+ }
+ }
+
+ setAccessibilityEventListeners() {
+ this.certificateTabsSection.setAccessibilityEventListeners();
+ }
+
+ updateSelectedTab(index) {
+ this.certificateTabsSection.updateSelectedTab(index);
+ }
+
+ updateCertificateSource(index) {
+ this.infoGroupsContainers.updateCertificateSource(index);
+ }
+}
+customElements.define("certificate-section", CertificateSection);
diff --git a/toolkit/components/certviewer/content/components/certificate-tabs-section.js b/toolkit/components/certviewer/content/components/certificate-tabs-section.js
new file mode 100644
index 0000000000..e0e14d44cf
--- /dev/null
+++ b/toolkit/components/certviewer/content/components/certificate-tabs-section.js
@@ -0,0 +1,123 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import { normalizeToKebabCase } from "../utils.js";
+import { updateSelectedItem } from "../certviewer.js";
+
+export class CertificateTabsSection extends HTMLElement {
+ constructor(isAboutCertificate) {
+ super();
+ this.isAboutCertificate = isAboutCertificate || false;
+ this.connectedCallback();
+ }
+
+ connectedCallback() {
+ let certificateTabsTemplate = document.getElementById(
+ "certificate-tabs-template"
+ );
+ this.attachShadow({ mode: "open" }).appendChild(
+ certificateTabsTemplate.content.cloneNode(true)
+ );
+ this.render();
+ }
+
+ render() {
+ this.tabsElement = this.shadowRoot.querySelector(".certificate-tabs");
+ }
+
+ appendChild(child) {
+ this.tabsElement.appendChild(child);
+ }
+
+ createTabSection(tabName, i) {
+ let tab = document.createElement("button");
+ if (tabName) {
+ tab.textContent = tabName;
+ } else {
+ tab.setAttribute(
+ "data-l10n-id",
+ "certificate-viewer-unknown-group-label"
+ );
+ }
+ tab.setAttribute("id", normalizeToKebabCase(tabName));
+ tab.setAttribute("aria-controls", "panel" + i);
+ tab.setAttribute("idnumber", i);
+ tab.setAttribute("role", "tab");
+ tab.classList.add("certificate-tab");
+ tab.classList.add("tab");
+ if (this.isAboutCertificate) {
+ tab.setAttribute("data-l10n-id", tabName);
+ } else {
+ // Display tabs on `about:certificate?cert=` pages as dir=auto
+ // to avoid text like `mozilla.org.*` in RTL.
+ // Not needed in the standalone version of about:certificate
+ // because the tab text there should be localized.
+ tab.dir = "auto";
+ }
+ this.tabsElement.appendChild(tab);
+
+ // If it is the first tab, allow it to be tabbable by the user.
+ // If it isn't the first tab, do not allow tab functionality,
+ // as arrow functionality is implemented in certviewer.js.
+ if (i === 0) {
+ tab.classList.add("selected");
+ tab.setAttribute("tabindex", 0);
+ } else {
+ tab.setAttribute("tabindex", -1);
+ }
+ }
+
+ updateSelectedTab(index) {
+ let tabs = this.tabsElement.querySelectorAll(".certificate-tab");
+
+ for (let tab of tabs) {
+ tab.classList.remove("selected");
+ }
+ tabs[index].classList.add("selected");
+ }
+
+ /* Information on setAccessibilityEventListeners() can be found
+ * at https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Tab_Role */
+ setAccessibilityEventListeners() {
+ let tabs = this.tabsElement.querySelectorAll('[role="tab"]');
+
+ // Add a click event handler to each tab
+ for (let tab of tabs) {
+ tab.addEventListener("click", e =>
+ updateSelectedItem(e.target.getAttribute("idnumber"))
+ );
+ }
+
+ // Enable arrow navigation between tabs in the tab list
+ let tabFocus = 0;
+
+ this.tabsElement.addEventListener("keydown", e => {
+ // Move right
+ if (e.keyCode === 39 || e.keyCode === 37) {
+ // After navigating away from the current tab,
+ // prevent that tab from being tabbable -
+ // so as to only allow arrow navigation within the tablist.
+ tabs[tabFocus].setAttribute("tabindex", -1);
+ if (e.keyCode === 39) {
+ tabFocus++;
+ // If we're at the end, go to the start
+ if (tabFocus > tabs.length - 1) {
+ tabFocus = 0;
+ }
+ // Move left
+ } else if (e.keyCode === 37) {
+ tabFocus--;
+ // If we're at the start, move to the end
+ if (tabFocus < 0) {
+ tabFocus = tabs.length;
+ }
+ }
+ tabs[tabFocus].setAttribute("tabindex", 0);
+ tabs[tabFocus].focus();
+ }
+ });
+ }
+}
+
+customElements.define("certificate-tabs-section", CertificateTabsSection);
diff --git a/toolkit/components/certviewer/content/components/error-section.css b/toolkit/components/certviewer/content/components/error-section.css
new file mode 100644
index 0000000000..1c642800ef
--- /dev/null
+++ b/toolkit/components/certviewer/content/components/error-section.css
@@ -0,0 +1,27 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+:host {
+ background-image: url("chrome://browser/skin/illustrations/error-malformed-url.svg");
+ min-height: 300px;
+ background-repeat: no-repeat;
+ padding-inline-start: 30%;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ margin: 0 auto;
+ max-width: 500px;
+ background-size: 30%;
+ background-position: left center;
+}
+
+:host(:dir(rtl)) {
+ background-position-x: right;
+}
+
+h1 {
+ text-align: center;
+ font-size: 2.5em;
+ font-weight: lighter;
+}
diff --git a/toolkit/components/certviewer/content/components/error-section.js b/toolkit/components/certviewer/content/components/error-section.js
new file mode 100644
index 0000000000..80a16b7684
--- /dev/null
+++ b/toolkit/components/certviewer/content/components/error-section.js
@@ -0,0 +1,31 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+export class ErrorSection extends HTMLElement {
+ constructor() {
+ super();
+ }
+
+ connectedCallback() {
+ let template = document.getElementById("error-section-template");
+ let templateHtml = template.content.cloneNode(true);
+
+ this.attachShadow({ mode: "open" }).appendChild(templateHtml);
+
+ document.l10n.connectRoot(this.shadowRoot);
+ this.render();
+ }
+
+ render() {
+ let title = this.shadowRoot.querySelector(".title");
+ title.setAttribute("data-l10n-id", "certificate-viewer-error-title");
+
+ let errorMessage = this.shadowRoot.querySelector(".error");
+ errorMessage.setAttribute(
+ "data-l10n-id",
+ "certificate-viewer-error-message"
+ );
+ }
+}
+customElements.define("error-section", ErrorSection);
diff --git a/toolkit/components/certviewer/content/components/info-group-container.js b/toolkit/components/certviewer/content/components/info-group-container.js
new file mode 100644
index 0000000000..eaf5ecf65d
--- /dev/null
+++ b/toolkit/components/certviewer/content/components/info-group-container.js
@@ -0,0 +1,65 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import { InfoGroup } from "./info-group.js";
+import { AboutCertificateItems } from "./about-certificate-items.js";
+
+export class InfoGroupContainer extends HTMLElement {
+ constructor(isAboutCertificate = false) {
+ super();
+ this.infoGroupsContainers = [];
+ this.isAboutCertificate = isAboutCertificate;
+ }
+
+ connectedCallback() {
+ let infoGroupContainerTemplate = document.getElementById(
+ "info-groups-template"
+ );
+ this.attachShadow({ mode: "open" }).appendChild(
+ infoGroupContainerTemplate.content.cloneNode(true)
+ );
+ this.render();
+ }
+
+ render() {}
+
+ createInfoGroupsContainers(certArray, i, final, certData = []) {
+ this.infoGroupsContainers[i] = document.createElement("div");
+ this.infoGroupsContainers[i].setAttribute("id", "panel" + i);
+ this.infoGroupsContainers[i].setAttribute("role", "tabpanel");
+ this.infoGroupsContainers[i].setAttribute("tabindex", 0);
+ this.infoGroupsContainers[i].setAttribute("aria-labelledby", "tab" + i);
+ // Hiding all the certificzte contents except for the first tab that is
+ // selected and shown by default
+ if (i !== 0) {
+ this.infoGroupsContainers[i].setAttribute("hidden", true);
+ }
+ this.infoGroupsContainers[i].classList.add("info-groups");
+
+ if (this.isAboutCertificate) {
+ this.infoGroupsContainers[i].appendChild(
+ new AboutCertificateItems(certData.name, certData.data)
+ );
+ } else {
+ for (let j = 0; j < certArray.length; j++) {
+ this.infoGroupsContainers[i].appendChild(
+ new InfoGroup(certArray[j], final)
+ );
+ }
+ }
+ }
+
+ addClass(className, index) {
+ this.infoGroupsContainers[index].classList.add(className);
+ }
+
+ updateCertificateSource(index) {
+ for (let i = 0; i < this.infoGroupsContainers.length; i++) {
+ this.infoGroupsContainers[i].classList.remove("selected");
+ }
+ this.infoGroupsContainers[index].classList.add("selected");
+ }
+}
+
+customElements.define("info-group-container", InfoGroupContainer);
diff --git a/toolkit/components/certviewer/content/components/info-group.css b/toolkit/components/certviewer/content/components/info-group.css
new file mode 100644
index 0000000000..86db12896b
--- /dev/null
+++ b/toolkit/components/certviewer/content/components/info-group.css
@@ -0,0 +1,33 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+:host {
+ display: grid;
+ grid-template-columns: minmax(8em, 25%) minmax(50%, 75%);
+ grid-gap: 0 2em;
+ padding: 1.75em 30px;
+ align-items: center;
+ border-top: 1px solid var(--in-content-border-color);
+}
+
+:host:first-of-type {
+ border-top: none;
+}
+
+.info-group-title {
+ text-align: end;
+ font-weight: 700;
+ color: var(--in-content-text-color);
+ font-size: 1em;
+}
+
+#critical-info {
+ height: 13px;
+ width: 13px;
+}
+
+.extension {
+ text-align: end;
+ margin-block-end: 1em;
+}
diff --git a/toolkit/components/certviewer/content/components/info-group.js b/toolkit/components/certviewer/content/components/info-group.js
new file mode 100644
index 0000000000..cea6d3b184
--- /dev/null
+++ b/toolkit/components/certviewer/content/components/info-group.js
@@ -0,0 +1,91 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import { InfoItem } from "./info-item.js";
+import { updateSelectedItem } from "../certviewer.js";
+import { normalizeToKebabCase } from "../utils.js";
+
+export class InfoGroup extends HTMLElement {
+ constructor(item, final) {
+ super();
+ this.item = item;
+ this.final = final;
+ }
+
+ connectedCallback() {
+ let infoGroupTemplate = document.getElementById("info-group-template");
+ this.attachShadow({ mode: "open" }).appendChild(
+ infoGroupTemplate.content.cloneNode(true)
+ );
+ document.l10n.connectRoot(this.shadowRoot);
+ document.l10n.translateFragment(this.shadowRoot);
+ this.render();
+ }
+
+ render() {
+ let title = this.shadowRoot.querySelector(".info-group-title");
+ title.setAttribute(
+ "data-l10n-id",
+ "certificate-viewer-" + this.item.sectionId
+ );
+
+ // Adds a class with the section title's name, to make
+ // it easier to find when highlighting errors.
+ this.classList.add(this.item.sectionId);
+ for (let i = 0; i < this.item.sectionItems.length; i++) {
+ this.shadowRoot.append(new InfoItem(this.item.sectionItems[i]));
+ }
+
+ if (this.item.sectionId === "issuer-name") {
+ this.setLinkToTab();
+ }
+
+ let criticalIcon = this.shadowRoot.querySelector("#critical-info");
+ if (!this.item.Critical) {
+ criticalIcon.style.visibility = "hidden";
+ }
+ }
+
+ setLinkToTab() {
+ if (this.final) {
+ return;
+ }
+
+ let issuerLabelElement =
+ this.shadowRoot.querySelector(".common-name") ||
+ this.shadowRoot.querySelector(".organizational-unit");
+
+ issuerLabelElement = issuerLabelElement?.shadowRoot.querySelector(".info");
+
+ if (!issuerLabelElement) {
+ return;
+ }
+
+ let link = document.createElement("a");
+ link.textContent = issuerLabelElement.textContent;
+ if (!link.textContent) {
+ link.setAttribute(
+ "data-l10n-id",
+ "certificate-viewer-unknown-group-label"
+ );
+ }
+ link.setAttribute("href", "#");
+
+ issuerLabelElement.textContent = "";
+ issuerLabelElement.appendChild(link);
+
+ link.addEventListener("click", () => {
+ let id = normalizeToKebabCase(link.textContent);
+ let issuerTab = document
+ .querySelector("certificate-section")
+ .shadowRoot.getElementById(id);
+
+ let index = issuerTab.getAttribute("idnumber");
+
+ updateSelectedItem(index);
+ });
+ }
+}
+
+customElements.define("info-group", InfoGroup);
diff --git a/toolkit/components/certviewer/content/components/info-item.css b/toolkit/components/certviewer/content/components/info-item.css
new file mode 100644
index 0000000000..585d19046f
--- /dev/null
+++ b/toolkit/components/certviewer/content/components/info-item.css
@@ -0,0 +1,64 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+:host {
+ line-height: 22px;
+ display: contents;
+ word-break: break-word;
+}
+
+:host * {
+ padding: 1px 0;
+}
+
+label {
+ text-align: end;
+ margin-inline-end: 0;
+ color: var(--in-content-deemphasized-text);
+ font-weight: 600;
+ font-size: 1em;
+}
+
+.hex {
+ overflow: hidden;
+ word-break: break-all;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.download-link-chain {
+ margin: 0 5px;
+}
+
+.long-hex:hover {
+ border-block: 1px solid var(--in-content-border-color);
+ background-color: var(--in-content-box-background-hover);
+ padding: 0;
+}
+
+.hex-open {
+ white-space: normal;
+}
+
+:host(.value) *,
+:host(.method) *,
+:host(.padding) * {
+ padding-bottom: 10px;
+}
+
+/* Elements that always need to be forced to LTR */
+.hex,
+:host(.dns-name) .info,
+.url {
+ direction: ltr;
+ text-align: match-parent;
+}
+
+/* Display some elements according to their text directionality */
+:host(.common-name) .info,
+:host(.name) .info,
+:host(.organization) .info {
+ unicode-bidi: plaintext;
+ text-align: match-parent;
+}
diff --git a/toolkit/components/certviewer/content/components/info-item.js b/toolkit/components/certviewer/content/components/info-item.js
new file mode 100644
index 0000000000..f248c395b2
--- /dev/null
+++ b/toolkit/components/certviewer/content/components/info-item.js
@@ -0,0 +1,199 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import { normalizeToKebabCase } from "../utils.js";
+
+export class InfoItem extends HTMLElement {
+ constructor(item) {
+ super();
+ this.item = item;
+ }
+
+ connectedCallback() {
+ let infoItemTemplate = document.getElementById("info-item-template");
+
+ this.attachShadow({ mode: "open" }).appendChild(
+ infoItemTemplate.content.cloneNode(true)
+ );
+
+ document.l10n.connectRoot(this.shadowRoot);
+ document.l10n.translateFragment(this.shadowRoot);
+
+ this.render();
+ }
+
+ handleTimeZone(infoElement) {
+ let localTime = this.item.info.local;
+ let UTCTime = this.item.info.utc;
+ infoElement.textContent = UTCTime;
+ infoElement.setAttribute("title", localTime);
+ }
+
+ addLongHexOverflow(info) {
+ info.classList.add("hex");
+
+ // For visual appeal, we want to collapse large hex values into single
+ // line items that can be clicked to expand.
+ // This function measures the size of the info item relative to its
+ // container and adds the "long-hex" class if it's overflowing. Since the
+ // container size changes on window resize this function is hooked up to
+ // a resize event listener.
+ function resize() {
+ if (info.classList.contains("hex-open")) {
+ info.classList.toggle("long-hex", true);
+ return;
+ }
+
+ // If the item is not currently drawn and we can't measure its dimensions
+ // then attach an observer that will measure it once it appears.
+ if (info.clientWidth <= 0) {
+ let observer = new IntersectionObserver(function([
+ { intersectionRatio },
+ ]) {
+ if (intersectionRatio > 0) {
+ info.classList.toggle(
+ "long-hex",
+ info.scrollWidth > info.clientWidth
+ );
+ observer.unobserve(info);
+ }
+ },
+ {});
+
+ observer.observe(info);
+ }
+ info.classList.toggle("long-hex", info.scrollWidth > info.clientWidth);
+ }
+ window.addEventListener("resize", resize);
+ window.requestAnimationFrame(resize);
+
+ this.addEventListener("mouseup", () => {
+ // If a range of text is selected, don't toggle the class that
+ // hides/shows additional text.
+ if (
+ info.classList.contains("long-hex") &&
+ window.getSelection().type !== "Range"
+ ) {
+ info.classList.toggle("hex-open");
+ }
+ });
+ }
+
+ render() {
+ let label = this.shadowRoot.querySelector("label");
+ let labelId = this.item.labelId;
+
+ // Map specific elements to a different message ID, to allow updates to
+ // existing labels and avoid duplicates.
+ let stringMapping = {
+ signaturealgorithm: "signature-algorithm",
+ "rfc-822-name": "email-address",
+ };
+ let fluentID = stringMapping[labelId] || labelId;
+
+ label.setAttribute("data-l10n-id", "certificate-viewer-" + fluentID);
+
+ this.classList.add(labelId);
+
+ let info = this.shadowRoot.querySelector(".info");
+ if (this.item.info.hasOwnProperty("utc")) {
+ this.handleTimeZone(info);
+ return;
+ }
+ if (labelId === "other-name") {
+ info.setAttribute("data-l10n-id", "certificate-viewer-unsupported");
+ return;
+ }
+ if (typeof this.item.info === "boolean") {
+ document.l10n.setAttributes(info, "certificate-viewer-boolean", {
+ boolean: this.item.info,
+ });
+ } else {
+ info.textContent = Array.isArray(this.item.info)
+ ? this.item.info.join(", ")
+ : this.item.info;
+ }
+
+ this.classList.add(labelId);
+
+ if (this.item.isHex) {
+ this.addLongHexOverflow(info);
+ }
+
+ let isURL = false;
+ if (
+ typeof this.item.info === "string" &&
+ this.item.info.startsWith("http")
+ ) {
+ try {
+ new URL(this.item.info);
+ isURL = true;
+ } catch (e) {}
+ }
+
+ if (isURL) {
+ info.classList.add("url");
+ let link = document.createElement("a");
+ link.setAttribute("href", this.item.info);
+ link.setAttribute("rel", "noreferrer noopener");
+ link.setAttribute("target", "_blank");
+ link.textContent = this.item.info;
+ info.textContent = "";
+ info.appendChild(link);
+ }
+
+ if (labelId === "download") {
+ this.setDownloadLinkInformation(info);
+ }
+ }
+
+ setDownloadLinkInformation(info) {
+ let link = document.createElement("a");
+ link.setAttribute("href", "data:," + this.item.info);
+ link.classList.add("download-link");
+
+ let url = new URL(document.URL);
+ let certArray = url.searchParams.getAll("cert");
+ let encodedCertArray = [];
+ for (let i = 0; i < certArray.length; i++) {
+ encodedCertArray.push(
+ encodeURI(
+ `-----BEGIN CERTIFICATE-----\r\n${certArray[i]}\r\n-----END CERTIFICATE-----\r\n`
+ )
+ );
+ }
+ encodedCertArray = encodedCertArray.join("");
+
+ let chainLink = document.createElement("a");
+ chainLink.setAttribute("href", "data:," + encodedCertArray);
+ chainLink.classList.add("download-link");
+ chainLink.classList.add("download-link-chain");
+
+ info.textContent = "";
+ info.appendChild(link);
+ info.appendChild(chainLink);
+
+ let commonName = document
+ .querySelector("certificate-section")
+ .shadowRoot.querySelector(".subject-name")
+ .shadowRoot.querySelector(".common-name")
+ .shadowRoot.querySelector(".info");
+
+ let fileName = normalizeToKebabCase(commonName.textContent);
+
+ document.l10n.setAttributes(link, "certificate-viewer-download-pem", {
+ fileName,
+ });
+
+ document.l10n.setAttributes(
+ chainLink,
+ "certificate-viewer-download-pem-chain",
+ {
+ fileName,
+ }
+ );
+ }
+}
+
+customElements.define("info-item", InfoItem);
diff --git a/toolkit/components/certviewer/content/components/list-item.css b/toolkit/components/certviewer/content/components/list-item.css
new file mode 100644
index 0000000000..6745a8e4ad
--- /dev/null
+++ b/toolkit/components/certviewer/content/components/list-item.css
@@ -0,0 +1,46 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+:host {
+ display: grid;
+ padding: 1em 0 1em;
+ background-color: var(--in-content-box-background);
+ border-block: 0.5px solid var(--in-content-box-border-color);
+ border-inline: 0.5px solid transparent;
+ position: relative;
+}
+
+:host(:hover) {
+ background-color: var(--in-content-box-background-hover);
+ border-inline-color: var(--in-content-box-border-color);
+ cursor: pointer;
+}
+
+a {
+ text-decoration: none;
+ color: inherit;
+}
+
+.cert-url {
+ height: 100%;
+ width: 100%;
+ position: absolute;
+ align-items: center;
+ display: flex;
+}
+
+.cert-url > .item-name {
+ padding-inline-start: 0.8em;
+}
+
+.export {
+ position: absolute;
+ top: 0.3em;
+ inset-inline-end: 2em;
+ font-size: 1em;
+}
+
+.export a {
+ position: relative;
+}
diff --git a/toolkit/components/certviewer/content/components/list-item.js b/toolkit/components/certviewer/content/components/list-item.js
new file mode 100644
index 0000000000..7d12e273a8
--- /dev/null
+++ b/toolkit/components/certviewer/content/components/list-item.js
@@ -0,0 +1,58 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import { normalizeToKebabCase } from "../utils.js";
+
+export class ListItem extends HTMLElement {
+ constructor(item) {
+ super();
+ this.item = item;
+ }
+
+ connectedCallback() {
+ let ListItemTemplate = document.getElementById("list-item-template");
+
+ this.attachShadow({ mode: "open" }).appendChild(
+ ListItemTemplate.content.cloneNode(true)
+ );
+
+ document.l10n.translateFragment(this.shadowRoot);
+ document.l10n.connectRoot(this.shadowRoot);
+
+ this.render();
+ }
+
+ render() {
+ let label = this.shadowRoot.querySelector(".item-name");
+ label.textContent = this.item.displayName;
+
+ this.handleExport();
+
+ let link = this.shadowRoot.querySelector(".cert-url");
+ let derb64 = encodeURIComponent(this.item.derb64);
+ let url = `about:certificate?cert=${derb64}`;
+ link.setAttribute("href", url);
+ }
+
+ handleExport() {
+ let exportButton = this.shadowRoot.querySelector(".export");
+ // Wrap the Base64 string into lines of 64 characters,
+ // with CRLF line breaks (as specified in RFC 1421).
+ let wrapped = this.item.derb64.replace(/(\S{64}(?!$))/g, "$1\r\n");
+ let download =
+ "-----BEGIN CERTIFICATE-----\r\n" +
+ wrapped +
+ "\r\n-----END CERTIFICATE-----\r\n";
+
+ let element = document.createElement("a");
+ element.setAttribute("href", "data:," + encodeURI(download));
+ let fileName = normalizeToKebabCase(this.item.displayName);
+ document.l10n.setAttributes(element, "certificate-viewer-export", {
+ fileName,
+ });
+ exportButton.appendChild(element);
+ }
+}
+
+customElements.define("list-item", ListItem);
diff --git a/toolkit/components/certviewer/content/ctlognames.js b/toolkit/components/certviewer/content/ctlognames.js
new file mode 100644
index 0000000000..e3b2116f37
--- /dev/null
+++ b/toolkit/components/certviewer/content/ctlognames.js
@@ -0,0 +1,170 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+export const ctLogNames = {
+ "9606c02c690033aa1d145f59c6e2648d0549f0df96aab8db915a70d8ecf390a5":
+ "Akamai CT",
+ "39376f545f7b4607f59742d768cd5d2437bf3473b6534a4834bcf72e681c83c9":
+ "Alpha CT",
+ a577ac9ced7548dd8f025b67a241089df86e0f476ec203c2ecbedb185f282638: "CNNIC CT",
+ cdb5179b7fc1c046feea31136a3f8f002e6182faf8896fecc8b2f5b5ab604900: "Certly.IO",
+ "1fbc36e002ede97f40199e86b3573b8a4217d80187746ad0da03a06054d20df4":
+ "Cloudflare “Nimbus2017”",
+ db74afeecb29ecb1feca3e716d2ce5b9aabb36f7847183c75d9d4f37b61fbf64:
+ "Cloudflare “Nimbus2018”",
+ "747eda8331ad331091219cce254f4270c2bffd5e422008c6373579e6107bcc56":
+ "Cloudflare “Nimbus2019”",
+ "5ea773f9df56c0e7b536487dd049e0327a919a0c84a112128418759681714558":
+ "Cloudflare “Nimbus2020”",
+ "4494652eb0eeceafc44007d8a8fe28c0dae682bed8cb31b53fd33396b5b681a8":
+ "Cloudflare “Nimbus2021”",
+ "41c8cab1df22464a10c6a13a0942875e4e318b1b03ebeb4bc768f090629606f6":
+ "Cloudflare “Nimbus2022”",
+ "7a328c54d8b72db620ea38e0521ee98416703213854d3bd22bc13a57a352eb52":
+ "Cloudflare “Nimbus2023”",
+ "6ff141b5647e4222f7ef052cefae7c21fd608e27d2af5a6e9f4b8a37d6633ee5":
+ "DigiCert Nessie2018",
+ fe446108b1d01ab78a62ccfeab6ab2b2babff3abdad80a4d8b30df2d0008830c:
+ "DigiCert Nessie2019",
+ c652a0ec48ceb3fcab170992c43a87413309e80065a26252401ba3362a17c565:
+ "DigiCert Nessie2020",
+ eec095ee8d72640f92e3c3b91bc712a3696a097b4b6a1a1438e647b2cbedc5f9:
+ "DigiCert Nessie2021",
+ "51a3b0f5fd01799c566db837788f0ca47acc1b27cbf79e88429a0dfed48b05e5":
+ "DigiCert Nessie2022",
+ b3737707e18450f86386d605a9dc11094a792db1670c0b87dcf0030e7936a59a:
+ "DigiCert Nessie2023",
+ "5614069a2fd7c2ecd3f5e1bd44b23ec74676b9bc99115cc0ef949855d689d0dd":
+ "DigiCert Server",
+ "8775bfe7597cf88c43995fbdf36eff568d475636ff4ab560c1b4eaff5ea0830f":
+ "DigiCert Server 2",
+ c1164ae0a772d2d4392dc80ac10770d4f0c49bde991a4840c1fa075164f63360:
+ "DigiCert Yeti2018",
+ e2694bae26e8e94009e8861bb63b83d43ee7fe7488fba48f2893019dddf1dbfe:
+ "DigiCert Yeti2019",
+ f095a459f200d18240102d2f93888ead4bfe1d47e399e1d034a6b0a8aa8eb273:
+ "DigiCert Yeti2020",
+ "5cdc4392fee6ab4544b15e9ad456e61037fbd5fa47dca17394b25ee6f6c70eca":
+ "DigiCert Yeti2021",
+ "2245450759552456963fa12ff1f76d86e0232663adc04b7f5dc6835c6ee20f02":
+ "DigiCert Yeti2022",
+ "35cf191bbfb16c57bf0fad4c6d42cbbbb627202651ea3fe12aefa803c33bd64c":
+ "DigiCert Yeti2023",
+ "717ea7420975be84a2723553f1777c26dd51af4e102144094d9019b462fb6668": "GDCA 1",
+ "14308d90ccd030135005c01ca526d81e84e87624e39b6248e08f724aea3bb42a": "GDCA 2",
+ c9cf890a21109c666cc17a3ed065c930d0e0135a9feba85af14210b8072421aa:
+ "GDCA CT #1",
+ "924a30f909336ff435d6993a10ac75a2c641728e7fc2d659ae6188ffad40ce01":
+ "GDCA CT #2",
+ fad4c97cc49ee2f8ac85c5ea5cea09d0220dbbf4e49c6b50662ff868f86b8c28:
+ "Google “Argon2017”",
+ a4501269055a15545e6211ab37bc103f62ae5576a45e4b1714453e1b22106a25:
+ "Google “Argon2018”",
+ "63f2dbcde83bcc2ccf0b728427576b33a48d61778fbd75a638b1c768544bd88d":
+ "Google “Argon2019”",
+ b21e05cc8ba2cd8a204e8766f92bb98a2520676bdafa70e7b249532def8b905e:
+ "Google “Argon2020”",
+ f65c942fd1773022145418083094568ee34d131933bfdf0c2f200bcc4ef164e3:
+ "Google “Argon2021”",
+ "2979bef09e393921f056739f63a577e5be577d9c600af8f94d5d265c255dc784":
+ "Google “Argon2022”",
+ "68f698f81f6482be3a8ceeb9281d4cfc71515d6793d444d10a67acbb4f4ffbc4":
+ "Google “Aviator”",
+ c3bf03a7e1ca8841c607bae3ff4270fca5ec45b186ebbe4e2cf3fc778630f5f6:
+ "Google “Crucible”",
+ "1d024b8eb1498b344dfd87ea3efc0996f7506f235d1d497061a4773c439c25fb":
+ "Google “Daedalus”",
+ "293c519654c83965baaa50fc5807d4b76fbf587a2972dca4c30cf4e54547f478":
+ "Google “Icarus”",
+ a4b90990b418581487bb13a2cc67700a3c359804f91bdfb8e377cd0ec80ddc10:
+ "Google “Pilot”",
+ ee4bbdb775ce60bae142691fabe19e66a30f7e5fb072d88300c47b897aa8fdcb:
+ "Google “Rocketeer”",
+ bbd9dfbc1f8a71b593942397aa927b473857950aab52e81a909664368e1ed185:
+ "Google “Skydiver”",
+ "52eb4b225ec896974850675f23e43bc1d021e3214ce52ecd5fa87c203cdfca03":
+ "Google “Solera2018”",
+ "0b760e9a8b9a682f88985b15e947501a56446bba8830785c3842994386450c00":
+ "Google “Solera2019”",
+ "1fc72ce5a1b799f400c359bff96ca3913548e8644220610952e9ba1774f7bac7":
+ "Google “Solera2020”",
+ a3c99845e80ab7ce00157b3742df0207dd272b2b602ecf98ee2c12db9c5ae7e7:
+ "Google “Solera2021”",
+ "697aafca1a6b536fae21205046debad7e0eaea13d2432e6e9d8fb379f2b9aaf3":
+ "Google “Solera2022”",
+ a899d8780c9290aaf462f31880ccfbd52451e970d0fbf591ef75b0d99b645681:
+ "Google “Submariner”",
+ b0cc83e5a5f97d6baf7c09cc284904872ac7e88b132c6350b7c6fd26e16c6c77:
+ "Google “Testtube”",
+ b10cd559a6d67846811f7df9a51532739ac48d703bea0323da5d38755bc0ad4e:
+ "Google “Xenon2018”",
+ "084114980071532c16190460bcfc47fdc2653afa292c72b37ff863ae29ccc9f0":
+ "Google “Xenon2019”",
+ "07b75c1be57d68fff1b0c61d2315c7bae6577c5794b76aeebc613a1a69d3a21c":
+ "Google “Xenon2020”",
+ "7d3ef2f88fff88556824c2c0ca9e5289792bc50e78097f2e6a9768997e22f0d7":
+ "Google “Xenon2021”",
+ "46a555eb75fa912030b5a28969f4f37d112c4174befd49b885abf2fc70fe6d47":
+ "Google “Xenon2022”",
+ "7461b4a09cfb3d41d75159575b2e7649a445a8d27709b0cc564a6482b7eb41a3": "Izenpe",
+ "8941449c70742e06b9fc9ce7b116ba0024aa36d59af44f0204404f00f7ea8566":
+ "Izenpe “Argi”",
+ "296afa2d568bca0d2ea844956ae9721fc35fa355ecda99693aafd458a71aefdd":
+ "Let“s Encrypt ”Clicky”",
+ "537b69a3564335a9c04904e39593b2c298eb8d7a6e83023635c627248cd6b440":
+ "Nordu “flimsy”",
+ aae70b7f3cb8d566c86c2f16979c9f445f69ab0eb4535589b2f77a030104f3cd:
+ "Nordu “plausible”",
+ e0127629e90496564e3d0147984498aa48f8adb16600eb7902a1ef9909906273:
+ "PuChuangSiDa CT",
+ cf55e28923497c340d5206d05353aeb25834b52f1f8dc9526809f212efdd7ca6:
+ "SHECA CT 1",
+ "32dc59c2d4c41968d56e14bc61ac8f0e45db39faf3c155aa4252f5001fa0c623":
+ "SHECA CT 2",
+ db76fdadac65e7d09508886e2159bd8b90352f5fead3e3dc5e22eb350acc7b98:
+ "Sectigo (Comodo) “Dodo” CT",
+ "6f5376ac31f03119d89900a45115ff77151c11d902c10029068db2089a37d913":
+ "Sectigo (Comodo) “Mammoth” CT",
+ "5581d4c2169036014aea0b9b573c53f0c0e43878702508172fa3aa1d0713d30c":
+ "Sectigo (Comodo) “Sabre” CT",
+ "34bb6ad6c3df9c03eea8a499ff7891486c9d5e5cac92d01f7bfd1bce19db48ef":
+ "StartCom",
+ ddeb1d2b7a0d4fa6208b81ad8168707e2e8e9d01d55c888d3d11c4cdb6ecbecc: "Symantec",
+ a7ce4a4e6207e0addee5fdaa4b1f86768767b5d002a55d47310e7e670a95eab2:
+ "Symantec Deneb",
+ "15970488d7b997a05beb52512adee8d2e8b4a3165264121a9fabfbd5f85ad93f":
+ "Symantec “Sirius”",
+ bc78e1dfc5f63c684649334da10fa15f0979692009c081b4f3f6917f3ed9b8a5:
+ "Symantec “Vega”",
+ b0b784bc81c0ddc47544e883f05985bb9077d134d8ab88b2b2e533980b8e508b:
+ "Up In The Air “Behind the Sofa”",
+ ac3b9aed7fa9674757159e6d7d575672f9d98100941e9bdeffeca1313b75782d: "Venafi",
+ "03019df3fd85a69a8ebd1facc6da9ba73e469774fe77f579fc5a08b8328c1d6b":
+ "Venafi Gen2 CT",
+ "41b2dc2e89e63ce4af1ba7bb29bf68c6dee6f9f1cc047e30dffae3b3ba259263": "WoSign",
+ "63d0006026dde10bb0601f452446965ee2b6ea2cd4fbc95ac866a550af9075b7":
+ "WoSign 2",
+ "9e4ff73dc3ce220b69217c899e468076abf8d78636d5ccfc85a31a75628ba88b":
+ "WoSign CT #1",
+ "659b3350f43b12cc5ea5ab4ec765d3fde6c88243777778e72003f9eb2b8c3129":
+ "Let's Encrypt Oak 2019",
+ e712f2b0377e1a62fb8ec90c6184f1ea7b37cb561d11265bf3e0f34bf241546e:
+ "Let's Encrypt Oak 2020",
+ "9420bc1e8ed58d6c88731f828b222c0dd1da4d5e6c4f943d61db4e2f584da2c2":
+ "Let's Encrypt Oak 2021",
+ dfa55eab68824f1f6cadeeb85f4e3e5aeacda212a46a5e8e3b12c020445c2a73:
+ "Let's Encrypt Oak 2022",
+ b73efb24df9c4dba75f239c5ba58f46c5dfc42cf7a9f35c49e1d098125edb499:
+ "Let's Encrypt Oak 2023",
+ "849f5f7f58d2bf7b54ecbd74611cea45c49c98f1d6481bc6f69e8c174f24f3cf":
+ "Let's Encrypt Testflume 2019",
+ c63f2218c37d56a6aa06b596da8e53d4d7156d1e9bac8e44d2202de64d69d9dc:
+ "Let's Encrypt Testflume 2020",
+ "03edf1da9776b6f38c341e39ed9d707a7570369cf9844f327fe9e14138361b60":
+ "Let's Encrypt Testflume 2021",
+ "2327efda352510dbc019ef491ae3ff1cc5a479bce37878360ee318cffb64f8c8":
+ "Let's Encrypt Testflume 2022",
+ "5534b7ab5a6ac3a7cbeba65487b2a2d71b48f650fa17c5197c97a0cb2076f3c6":
+ "Let's Encrypt Testflume 2023",
+};
diff --git a/toolkit/components/certviewer/content/package.json b/toolkit/components/certviewer/content/package.json
new file mode 100644
index 0000000000..d2bebf51e9
--- /dev/null
+++ b/toolkit/components/certviewer/content/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "certviewer",
+ "version": "1.0.0",
+ "description": "",
+ "scripts": {
+ "build-pvutils": "./node_modules/browserify/bin/cmd.js pvutils.js --standalone pvutils -o ./vendor/pvutils_bundle.js",
+ "build-asn1js": "./node_modules/browserify/bin/cmd.js asn1js.js --standalone asn1js -o ./vendor/asn1js_bundle.js",
+ "build-pkijs": "./node_modules/browserify/bin/cmd.js pkijs.js --standalone pkijs -o ./vendor/pkijs_bundle.js",
+ "build": "npm run build-pvutils && npm run build-asn1js && npm run build-pkijs"
+ },
+ "license": "MPL-2.0",
+ "dependencies": {
+ "asn1js": "^2.0.22",
+ "pkijs": "^2.1.81",
+ "pvutils": "^1.0.17"
+ },
+ "devDependencies": {
+ "browserify": "^16.2.3"
+ }
+}
diff --git a/toolkit/components/certviewer/content/pkijs.js b/toolkit/components/certviewer/content/pkijs.js
new file mode 100644
index 0000000000..31b877543b
--- /dev/null
+++ b/toolkit/components/certviewer/content/pkijs.js
@@ -0,0 +1,9 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const pkijs = require("pkijs"); // version 2.1.78
+
+module.exports = {
+ pkijs,
+};
diff --git a/toolkit/components/certviewer/content/pvutils.js b/toolkit/components/certviewer/content/pvutils.js
new file mode 100644
index 0000000000..550c8a11a2
--- /dev/null
+++ b/toolkit/components/certviewer/content/pvutils.js
@@ -0,0 +1,9 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const pvutils = require("pvutils"); // version 1.0.17
+
+module.exports = {
+ pvutils,
+};
diff --git a/toolkit/components/certviewer/content/strings.js b/toolkit/components/certviewer/content/strings.js
new file mode 100644
index 0000000000..dd9075a775
--- /dev/null
+++ b/toolkit/components/certviewer/content/strings.js
@@ -0,0 +1,505 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+export const strings = {
+ ux: {
+ upload: "Upload Certificate",
+ },
+
+ names: {
+ // Directory Pilot Attributes
+ "0.9.2342.19200300.100.1.1": {
+ short: "uid",
+ long: "User ID",
+ },
+ "0.9.2342.19200300.100.1.25": {
+ short: "dc",
+ long: "Domain Component",
+ },
+
+ // PKCS-9
+ "1.2.840.113549.1.9.1": {
+ short: "e",
+ long: "Email Address",
+ },
+
+ // Incorporated Locations
+ "1.3.6.1.4.1.311.60.2.1.1": {
+ short: undefined,
+ long: "Inc. Locality",
+ },
+ "1.3.6.1.4.1.311.60.2.1.2": {
+ short: undefined,
+ long: "Inc. State / Province",
+ },
+ "1.3.6.1.4.1.311.60.2.1.3": {
+ short: undefined,
+ long: "Inc. Country",
+ },
+
+ // microsoft cryptographic extensions
+ "1.3.6.1.4.1.311.21.7": {
+ name: {
+ short: "Certificate Template",
+ long: "Microsoft Certificate Template",
+ },
+ },
+ "1.3.6.1.4.1.311.21.10": {
+ name: {
+ short: "Certificate Policies",
+ long: "Microsoft Certificate Policies",
+ },
+ },
+
+ // certificate extensions
+ "1.3.6.1.4.1.11129.2.4.2": {
+ name: {
+ short: "Embedded SCTs",
+ long: "Embedded Signed Certificate Timestamps",
+ },
+ },
+ "1.3.6.1.5.5.7.1.1": {
+ name: {
+ short: undefined,
+ long: "Authority Information Access",
+ },
+ },
+ "1.3.6.1.5.5.7.1.24": {
+ name: {
+ short: "OCSP Stapling",
+ long: "Online Certificate Status Protocol Stapling",
+ },
+ },
+
+ // X.500 attribute types
+ "2.5.4.1": {
+ short: undefined,
+ long: "Aliased Entry",
+ },
+ "2.5.4.2": {
+ short: undefined,
+ long: "Knowledge Information",
+ },
+ "2.5.4.3": {
+ short: "cn",
+ long: "Common Name",
+ },
+ "2.5.4.4": {
+ short: "sn",
+ long: "Surname",
+ },
+ "2.5.4.5": {
+ short: "serialNumber",
+ long: "Serial Number",
+ },
+ "2.5.4.6": {
+ short: "c",
+ long: "Country",
+ },
+ "2.5.4.7": {
+ short: "l",
+ long: "Locality",
+ },
+ "2.5.4.8": {
+ short: "s",
+ long: "State / Province",
+ },
+ "2.5.4.9": {
+ short: "street",
+ long: "Stress Address",
+ },
+ "2.5.4.10": {
+ short: "o",
+ long: "Organization",
+ },
+ "2.5.4.11": {
+ short: "ou",
+ long: "Organizational Unit",
+ },
+ "2.5.4.12": {
+ short: "t",
+ long: "Title",
+ },
+ "2.5.4.13": {
+ short: "description",
+ long: "Description",
+ },
+ "2.5.4.14": {
+ short: undefined,
+ long: "Search Guide",
+ },
+ "2.5.4.15": {
+ short: undefined,
+ long: "Business Category",
+ },
+ "2.5.4.16": {
+ short: undefined,
+ long: "Postal Address",
+ },
+ "2.5.4.17": {
+ short: "postalCode",
+ long: "Postal Code",
+ },
+ "2.5.4.18": {
+ short: "POBox",
+ long: "PO Box",
+ },
+ "2.5.4.19": {
+ short: undefined,
+ long: "Physical Delivery Office Name",
+ },
+ "2.5.4.20": {
+ short: "phone",
+ long: "Phone Number",
+ },
+ "2.5.4.21": {
+ short: undefined,
+ long: "Telex Number",
+ },
+ "2.5.4.22": {
+ short: undefined,
+ long: "Teletex Terminal Identifier",
+ },
+ "2.5.4.23": {
+ short: undefined,
+ long: "Fax Number",
+ },
+ "2.5.4.24": {
+ short: undefined,
+ long: "X.121 Address",
+ },
+ "2.5.4.25": {
+ short: undefined,
+ long: "International ISDN Number",
+ },
+ "2.5.4.26": {
+ short: undefined,
+ long: "Registered Address",
+ },
+ "2.5.4.27": {
+ short: undefined,
+ long: "Destination Indicator",
+ },
+ "2.5.4.28": {
+ short: undefined,
+ long: "Preferred Delivery Method",
+ },
+ "2.5.4.29": {
+ short: undefined,
+ long: "Presentation Address",
+ },
+ "2.5.4.30": {
+ short: undefined,
+ long: "Supported Application Context",
+ },
+ "2.5.4.31": {
+ short: undefined,
+ long: "Member",
+ },
+ "2.5.4.32": {
+ short: undefined,
+ long: "Owner",
+ },
+ "2.5.4.33": {
+ short: undefined,
+ long: "Role Occupant",
+ },
+ "2.5.4.34": {
+ short: undefined,
+ long: "See Also",
+ },
+ "2.5.4.35": {
+ short: undefined,
+ long: "User Password",
+ },
+ "2.5.4.36": {
+ short: undefined,
+ long: "User Certificate",
+ },
+ "2.5.4.37": {
+ short: undefined,
+ long: "CA Certificate",
+ },
+ "2.5.4.38": {
+ short: undefined,
+ long: "Authority Revocation List",
+ },
+ "2.5.4.39": {
+ short: undefined,
+ long: "Certificate Revocation List",
+ },
+ "2.5.4.40": {
+ short: undefined,
+ long: "Cross-certificate Pair",
+ },
+ "2.5.4.41": {
+ short: undefined,
+ long: "Name",
+ },
+ "2.5.4.42": {
+ short: "g",
+ long: "Given Name",
+ },
+ "2.5.4.43": {
+ short: "i",
+ long: "Initials",
+ },
+ "2.5.4.44": {
+ short: undefined,
+ long: "Generation Qualifier",
+ },
+ "2.5.4.45": {
+ short: undefined,
+ long: "Unique Identifier",
+ },
+ "2.5.4.46": {
+ short: undefined,
+ long: "DN Qualifier",
+ },
+ "2.5.4.47": {
+ short: undefined,
+ long: "Enhanced Search Guide",
+ },
+ "2.5.4.48": {
+ short: undefined,
+ long: "Protocol Information",
+ },
+ "2.5.4.49": {
+ short: "dn",
+ long: "Distinguished Name",
+ },
+ "2.5.4.50": {
+ short: undefined,
+ long: "Unique Member",
+ },
+ "2.5.4.51": {
+ short: undefined,
+ long: "House Identifier",
+ },
+ "2.5.4.52": {
+ short: undefined,
+ long: "Supported Algorithms",
+ },
+ "2.5.4.53": {
+ short: undefined,
+ long: "Delta Revocation List",
+ },
+ "2.5.4.58": {
+ short: undefined,
+ long: "Attribute Certificate Attribute", // huh
+ },
+ "2.5.4.65": {
+ short: undefined,
+ long: "Pseudonym",
+ },
+
+ // extensions
+ "2.5.29.14": {
+ name: {
+ short: "Subject Key ID",
+ long: "Subject Key Identifier",
+ },
+ },
+ "2.5.29.15": {
+ name: {
+ short: undefined,
+ long: "Key Usages",
+ },
+ },
+ "2.5.29.17": {
+ name: {
+ short: "Subject Alt Names",
+ long: "Subject Alternative Names",
+ },
+ },
+ "2.5.29.19": {
+ name: {
+ short: undefined,
+ long: "Basic Constraints",
+ },
+ },
+ "2.5.29.31": {
+ name: {
+ short: "CRL Endpoints",
+ long: "Certificate Revocation List Endpoints",
+ },
+ },
+ "2.5.29.32": {
+ name: {
+ short: undefined,
+ long: "Certificate Policies",
+ },
+ },
+ "2.5.29.35": {
+ name: {
+ short: "Authority Key ID",
+ long: "Authority Key Identifier",
+ },
+ },
+ "2.5.29.37": {
+ name: {
+ short: undefined,
+ long: "Extended Key Usages",
+ },
+ },
+ },
+
+ keyUsages: [
+ "CRL Signing",
+ "Certificate Signing",
+ "Key Agreement",
+ "Data Encipherment",
+ "Key Encipherment",
+ "Non-Repudiation",
+ "Digital Signature",
+ ],
+
+ san: [
+ "Other Name",
+ "RFC 822 Name",
+ "DNS Name",
+ "X.400 Address",
+ "Directory Name",
+ "EDI Party Name",
+ "URI",
+ "IP Address",
+ "Registered ID",
+ ],
+
+ eKU: {
+ "1.3.6.1.4.1.311.10.3.1": "Certificate Trust List (CTL) Signing",
+ "1.3.6.1.4.1.311.10.3.2": "Timestamp Signing",
+ "1.3.6.1.4.1.311.10.3.4": "EFS Encryption",
+ "1.3.6.1.4.1.311.10.3.4.1": "EFS Recovery",
+ "1.3.6.1.4.1.311.10.3.5":
+ "Windows Hardware Quality Labs (WHQL) Cryptography",
+ "1.3.6.1.4.1.311.10.3.7": "Windows NT 5 Cryptography",
+ "1.3.6.1.4.1.311.10.3.8": "Windows NT Embedded Cryptography",
+ "1.3.6.1.4.1.311.10.3.10": "Qualified Subordination",
+ "1.3.6.1.4.1.311.10.3.11": "Escrowed Key Recovery",
+ "1.3.6.1.4.1.311.10.3.12": "Document Signing",
+ "1.3.6.1.4.1.311.10.5.1": "Digital Rights Management",
+ "1.3.6.1.4.1.311.10.6.1": "Key Pack Licenses",
+ "1.3.6.1.4.1.311.10.6.2": "License Server",
+ "1.3.6.1.4.1.311.20.2.1": "Enrollment Agent",
+ "1.3.6.1.4.1.311.20.2.2": "Smartcard Login",
+ "1.3.6.1.4.1.311.21.5": "Certificate Authority Private Key Archival",
+ "1.3.6.1.4.1.311.21.6": "Key Recovery Agent",
+ "1.3.6.1.4.1.311.21.19": "Directory Service Email Replication",
+ "1.3.6.1.5.5.7.3.1": "Server Authentication",
+ "1.3.6.1.5.5.7.3.2": "Client Authentication",
+ "1.3.6.1.5.5.7.3.3": "Code Signing",
+ "1.3.6.1.5.5.7.3.4": "E-mail Protection",
+ "1.3.6.1.5.5.7.3.5": "IPsec End System",
+ "1.3.6.1.5.5.7.3.6": "IPsec Tunnel",
+ "1.3.6.1.5.5.7.3.7": "IPSec User",
+ "1.3.6.1.5.5.7.3.8": "Timestamping",
+ "1.3.6.1.5.5.7.3.9": "OCSP Signing",
+ "1.3.6.1.5.5.8.2.2": "Internet Key Exchange (IKE)",
+ },
+
+ signature: {
+ "1.2.840.113549.1.1.4": "MD5 with RSA Encryption",
+ "1.2.840.113549.1.1.5": "SHA-1 with RSA Encryption",
+ "1.2.840.113549.1.1.11": "SHA-256 with RSA Encryption",
+ "1.2.840.113549.1.1.12": "SHA-384 with RSA Encryption",
+ "1.2.840.113549.1.1.13": "SHA-512 with RSA Encryption",
+ "1.2.840.10040.4.3": "DSA with SHA-1",
+ "2.16.840.1.101.3.4.3.2": "DSA with SHA-256",
+ "1.2.840.10045.4.1": "ECDSA with SHA-1",
+ "1.2.840.10045.4.3.2": "ECDSA with SHA-256",
+ "1.2.840.10045.4.3.3": "ECDSA with SHA-384",
+ "1.2.840.10045.4.3.4": "ECDSA with SHA-512",
+ },
+
+ aia: {
+ "1.3.6.1.5.5.7.48.1": "Online Certificate Status Protocol (OCSP)",
+ "1.3.6.1.5.5.7.48.2": "CA Issuers",
+ },
+
+ // this includes qualifiers as well
+ cps: {
+ "1.3.6.1.4.1": {
+ name: "Statement Identifier",
+ value: undefined,
+ },
+ "1.3.6.1.5.5.7.2.1": {
+ name: "Practices Statement",
+ value: undefined,
+ },
+ "1.3.6.1.5.5.7.2.2": {
+ name: "User Notice",
+ value: undefined,
+ },
+ "2.16.840": {
+ name: "ANSI Organizational Identifier",
+ value: undefined,
+ },
+ "2.23.140.1.1": {
+ name: "Certificate Type",
+ value: "Extended Validation",
+ },
+ "2.23.140.1.2.1": {
+ name: "Certificate Type",
+ value: "Domain Validation",
+ },
+ "2.23.140.1.2.2": {
+ name: "Certificate Type",
+ value: "Organization Validation",
+ },
+ "2.23.140.1.2.3": {
+ name: "Certificate Type",
+ value: "Individual Validation",
+ },
+ "2.23.140.1.3": {
+ name: "Certificate Type",
+ value: "Extended Validation (Code Signing)",
+ },
+ "2.23.140.1.31": {
+ name: "Certificate Type",
+ value: ".onion Extended Validation",
+ },
+ "2.23.140.2.1": {
+ name: "Certificate Type",
+ value: "Test Certificate",
+ },
+ },
+
+ microsoftCertificateTypes: {
+ Administrator: "Administrator",
+ CA: "Root Certification Authority",
+ CAExchange: "CA Exchange",
+ CEPEncryption: "CEP Encryption",
+ CertificateRequestAgent: "Certificate Request Agent",
+ ClientAuth: "Authenticated Session",
+ CodeSigning: "Code Signing",
+ CrossCA: "Cross Certification Authority",
+ CTLSigning: "Trust List Signing",
+ DirectoryEmailReplication: "Directory Email Replication",
+ DomainController: "Domain Controller",
+ DomainControllerAuthentication: "Domain Controller Authentication",
+ EFS: "Basic EFS",
+ EFSRecovery: "EFS Recovery Agent",
+ EnrollmentAgent: "Enrollment Agent",
+ EnrollmentAgentOffline: "Exchange Enrollment Agent (Offline request)",
+ ExchangeUser: "Exchange User",
+ ExchangeUserSignature: "Exchange Signature Only",
+ IPSECIntermediateOffline: "IPSec (Offline request)",
+ IPSECIntermediateOnline: "IPSEC",
+ KerberosAuthentication: "Kerberos Authentication",
+ KeyRecoveryAgent: "Key Recovery Agent",
+ Machine: "Computer",
+ MachineEnrollmentAgent: "Enrollment Agent (Computer)",
+ OCSPResponseSigning: "OCSP Response Signing",
+ OfflineRouter: "Router (Offline request)",
+ RASAndIASServer: "RAS and IAS Server",
+ SmartcardLogon: "Smartcard Logon",
+ SmartcardUser: "Smartcard User",
+ SubCA: "Subordinate Certification Authority",
+ User: "User",
+ UserSignature: "User Signature Only",
+ WebServer: "Web Server",
+ Workstation: "Workstation Authentication",
+ },
+};
diff --git a/toolkit/components/certviewer/content/utils.js b/toolkit/components/certviewer/content/utils.js
new file mode 100644
index 0000000000..892de1740c
--- /dev/null
+++ b/toolkit/components/certviewer/content/utils.js
@@ -0,0 +1,77 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const { Integer } = asn1js.asn1js;
+const { fromBase64, stringToArrayBuffer } = pvutils.pvutils;
+
+export const b64urltodec = b64 => {
+ return new Integer({
+ valueHex: stringToArrayBuffer(fromBase64("AQAB", true, true)),
+ }).valueBlock._valueDec;
+};
+
+export const b64urltohex = b64 => {
+ const hexBuffer = new Integer({
+ valueHex: stringToArrayBuffer(fromBase64(b64, true, true)),
+ }).valueBlock._valueHex;
+ const hexArray = Array.from(new Uint8Array(hexBuffer));
+
+ return hexArray.map(b => ("00" + b.toString(16)).slice(-2));
+};
+
+// this particular prototype override makes it easy to chain down complex objects
+export const getObjPath = (obj, path) => {
+ path = path.split(".");
+ for (let i = 0, len = path.length; i < len; i++) {
+ if (Array.isArray(obj[path[i]])) {
+ obj = obj[path[i]][path[i + 1]];
+ i++;
+ } else {
+ obj = obj[path[i]];
+ }
+ }
+ return obj;
+};
+
+export const hash = async (algo, buffer) => {
+ const hashBuffer = await crypto.subtle.digest(algo, buffer);
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
+
+ return hashArray
+ .map(b => ("00" + b.toString(16)).slice(-2))
+ .join(":")
+ .toUpperCase();
+};
+
+export const hashify = hash => {
+ if (typeof hash === "string") {
+ return hash
+ .match(/.{2}/g)
+ .join(":")
+ .toUpperCase();
+ }
+ return hash.join(":").toUpperCase();
+};
+
+export const pemToDER = pem => {
+ return stringToArrayBuffer(window.atob(pem));
+};
+
+export const normalizeToKebabCase = string => {
+ let kebabString = string
+ // Turn all dots into dashes
+ .replace(/\./g, "-")
+ // Turn whitespace into dashes
+ .replace(/\s+/g, "-")
+ // Remove all non-characters or numbers
+ .replace(/[^a-z0-9\-]/gi, "")
+ // De-dupe dashes
+ .replace(/--/g, "-")
+ // Remove trailing and leading dashes
+ .replace(/^-/g, "")
+ .replace(/-$/g, "")
+ .toLowerCase();
+
+ return kebabString;
+};
diff --git a/toolkit/components/certviewer/content/vendor/asn1js_bundle.js b/toolkit/components/certviewer/content/vendor/asn1js_bundle.js
new file mode 100644
index 0000000000..8e4dd5f2d9
--- /dev/null
+++ b/toolkit/components/certviewer/content/vendor/asn1js_bundle.js
@@ -0,0 +1,5877 @@
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.asn1js = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ const asn1js = require("asn1js"); // version 2.0.22
+
+ module.exports = {
+ asn1js,
+ };
+
+},{"asn1js":2}],2:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.RawData = exports.Repeated = exports.Any = exports.Choice = exports.TIME = exports.Duration = exports.DateTime = exports.TimeOfDay = exports.DATE = exports.GeneralizedTime = exports.UTCTime = exports.CharacterString = exports.GeneralString = exports.VisibleString = exports.GraphicString = exports.IA5String = exports.VideotexString = exports.TeletexString = exports.PrintableString = exports.NumericString = exports.UniversalString = exports.BmpString = exports.Utf8String = exports.ObjectIdentifier = exports.Enumerated = exports.Integer = exports.BitString = exports.OctetString = exports.Null = exports.Set = exports.Sequence = exports.Boolean = exports.EndOfContent = exports.Constructed = exports.Primitive = exports.BaseBlock = undefined;
+exports.fromBER = fromBER;
+exports.compareSchema = compareSchema;
+exports.verifySchema = verifySchema;
+exports.fromJSON = fromJSON;
+
+var _pvutils = require("pvutils");
+
+//**************************************************************************************
+//region Declaration of global variables
+//**************************************************************************************
+const powers2 = [new Uint8Array([1])]; /* eslint-disable indent */
+/*
+ * Copyright (c) 2016-2018, Peculiar Ventures
+ * All rights reserved.
+ *
+ * Author 2016-2018, Yury Strozhevsky <www.strozhevsky.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ */
+//**************************************************************************************
+
+const digitsString = "0123456789";
+//**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration for "LocalBaseBlock" class
+//**************************************************************************************
+/**
+ * Class used as a base block for all remaining ASN.1 classes
+ * @typedef LocalBaseBlock
+ * @interface
+ * @property {number} blockLength
+ * @property {string} error
+ * @property {Array.<string>} warnings
+ * @property {ArrayBuffer} valueBeforeDecode
+ */
+class LocalBaseBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalBaseBlock" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueBeforeDecode]
+ */
+ constructor(parameters = {}) {
+ /**
+ * @type {number} blockLength
+ */
+ this.blockLength = (0, _pvutils.getParametersValue)(parameters, "blockLength", 0);
+ /**
+ * @type {string} error
+ */
+ this.error = (0, _pvutils.getParametersValue)(parameters, "error", "");
+ /**
+ * @type {Array.<string>} warnings
+ */
+ this.warnings = (0, _pvutils.getParametersValue)(parameters, "warnings", []);
+ //noinspection JSCheckFunctionSignatures
+ /**
+ * @type {ArrayBuffer} valueBeforeDecode
+ */
+ if ("valueBeforeDecode" in parameters) this.valueBeforeDecode = parameters.valueBeforeDecode.slice(0);else this.valueBeforeDecode = new ArrayBuffer(0);
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "baseBlock";
+ }
+ //**********************************************************************************
+ /**
+ * Convertion for the block to JSON object
+ * @returns {{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
+ */
+ toJSON() {
+ return {
+ blockName: this.constructor.blockName(),
+ blockLength: this.blockLength,
+ error: this.error,
+ warnings: this.warnings,
+ valueBeforeDecode: (0, _pvutils.bufferToHexCodes)(this.valueBeforeDecode, 0, this.valueBeforeDecode.byteLength)
+ };
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Description for "LocalHexBlock" class
+//**************************************************************************************
+/**
+ * Class used as a base block for all remaining ASN.1 classes
+ * @extends LocalBaseBlock
+ * @typedef LocalHexBlock
+ * @property {number} blockLength
+ * @property {string} error
+ * @property {Array.<string>} warnings
+ * @property {ArrayBuffer} valueBeforeDecode
+ * @property {boolean} isHexOnly
+ * @property {ArrayBuffer} valueHex
+ */
+//noinspection JSUnusedLocalSymbols
+const LocalHexBlock = BaseClass => class LocalHexBlockMixin extends BaseClass {
+ //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+ /**
+ * Constructor for "LocalHexBlock" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ /**
+ * @type {boolean}
+ */
+ this.isHexOnly = (0, _pvutils.getParametersValue)(parameters, "isHexOnly", false);
+ /**
+ * @type {ArrayBuffer}
+ */
+ if ("valueHex" in parameters) this.valueHex = parameters.valueHex.slice(0);else this.valueHex = new ArrayBuffer(0);
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "hexBlock";
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1;
+ //endregion
+
+ //region Getting Uint8Array from ArrayBuffer
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
+ //endregion
+
+ //region Initial checks
+ if (intBuffer.length === 0) {
+ this.warnings.push("Zero buffer length");
+ return inputOffset;
+ }
+ //endregion
+
+ //region Copy input buffer to internal buffer
+ this.valueHex = inputBuffer.slice(inputOffset, inputOffset + inputLength);
+ //endregion
+
+ this.blockLength = inputLength;
+
+ return inputOffset + inputLength;
+ }
+ //**********************************************************************************
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toBER(sizeOnly = false) {
+ if (this.isHexOnly !== true) {
+ this.error = "Flag \"isHexOnly\" is not set, abort";
+ return new ArrayBuffer(0);
+ }
+
+ if (sizeOnly === true) return new ArrayBuffer(this.valueHex.byteLength);
+
+ //noinspection JSCheckFunctionSignatures
+ return this.valueHex.slice(0);
+ }
+ //**********************************************************************************
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.blockName = this.constructor.blockName();
+ object.isHexOnly = this.isHexOnly;
+ object.valueHex = (0, _pvutils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
+
+ return object;
+ }
+ //**********************************************************************************
+};
+//**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of identification block class
+//**************************************************************************************
+class LocalIdentificationBlock extends LocalHexBlock(LocalBaseBlock) {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalBaseBlock" class
+ * @param {Object} [parameters={}]
+ * @property {Object} [idBlock]
+ */
+ constructor(parameters = {}) {
+ super();
+
+ if ("idBlock" in parameters) {
+ //region Properties from hexBlock class
+ this.isHexOnly = (0, _pvutils.getParametersValue)(parameters.idBlock, "isHexOnly", false);
+ this.valueHex = (0, _pvutils.getParametersValue)(parameters.idBlock, "valueHex", new ArrayBuffer(0));
+ //endregion
+
+ this.tagClass = (0, _pvutils.getParametersValue)(parameters.idBlock, "tagClass", -1);
+ this.tagNumber = (0, _pvutils.getParametersValue)(parameters.idBlock, "tagNumber", -1);
+ this.isConstructed = (0, _pvutils.getParametersValue)(parameters.idBlock, "isConstructed", false);
+ } else {
+ this.tagClass = -1;
+ this.tagNumber = -1;
+ this.isConstructed = false;
+ }
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "identificationBlock";
+ }
+ //**********************************************************************************
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toBER(sizeOnly = false) {
+ //region Initial variables
+ let firstOctet = 0;
+ let retBuf;
+ let retView;
+ //endregion
+
+ switch (this.tagClass) {
+ case 1:
+ firstOctet |= 0x00; // UNIVERSAL
+ break;
+ case 2:
+ firstOctet |= 0x40; // APPLICATION
+ break;
+ case 3:
+ firstOctet |= 0x80; // CONTEXT-SPECIFIC
+ break;
+ case 4:
+ firstOctet |= 0xC0; // PRIVATE
+ break;
+ default:
+ this.error = "Unknown tag class";
+ return new ArrayBuffer(0);
+ }
+
+ if (this.isConstructed) firstOctet |= 0x20;
+
+ if (this.tagNumber < 31 && !this.isHexOnly) {
+ retBuf = new ArrayBuffer(1);
+ retView = new Uint8Array(retBuf);
+
+ if (!sizeOnly) {
+ let number = this.tagNumber;
+ number &= 0x1F;
+ firstOctet |= number;
+
+ retView[0] = firstOctet;
+ }
+
+ return retBuf;
+ }
+
+ if (this.isHexOnly === false) {
+ const encodedBuf = (0, _pvutils.utilToBase)(this.tagNumber, 7);
+ const encodedView = new Uint8Array(encodedBuf);
+ const size = encodedBuf.byteLength;
+
+ retBuf = new ArrayBuffer(size + 1);
+ retView = new Uint8Array(retBuf);
+ retView[0] = firstOctet | 0x1F;
+
+ if (!sizeOnly) {
+ for (let i = 0; i < size - 1; i++) retView[i + 1] = encodedView[i] | 0x80;
+
+ retView[size] = encodedView[size - 1];
+ }
+
+ return retBuf;
+ }
+
+ retBuf = new ArrayBuffer(this.valueHex.byteLength + 1);
+ retView = new Uint8Array(retBuf);
+
+ retView[0] = firstOctet | 0x1F;
+
+ if (sizeOnly === false) {
+ const curView = new Uint8Array(this.valueHex);
+
+ for (let i = 0; i < curView.length - 1; i++) retView[i + 1] = curView[i] | 0x80;
+
+ retView[this.valueHex.byteLength] = curView[curView.length - 1];
+ }
+
+ return retBuf;
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number}
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1;
+ //endregion
+
+ //region Getting Uint8Array from ArrayBuffer
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
+ //endregion
+
+ //region Initial checks
+ if (intBuffer.length === 0) {
+ this.error = "Zero buffer length";
+ return -1;
+ }
+ //endregion
+
+ //region Find tag class
+ const tagClassMask = intBuffer[0] & 0xC0;
+
+ switch (tagClassMask) {
+ case 0x00:
+ this.tagClass = 1; // UNIVERSAL
+ break;
+ case 0x40:
+ this.tagClass = 2; // APPLICATION
+ break;
+ case 0x80:
+ this.tagClass = 3; // CONTEXT-SPECIFIC
+ break;
+ case 0xC0:
+ this.tagClass = 4; // PRIVATE
+ break;
+ default:
+ this.error = "Unknown tag class";
+ return -1;
+ }
+ //endregion
+
+ //region Find it's constructed or not
+ this.isConstructed = (intBuffer[0] & 0x20) === 0x20;
+ //endregion
+
+ //region Find tag number
+ this.isHexOnly = false;
+
+ const tagNumberMask = intBuffer[0] & 0x1F;
+
+ //region Simple case (tag number < 31)
+ if (tagNumberMask !== 0x1F) {
+ this.tagNumber = tagNumberMask;
+ this.blockLength = 1;
+ }
+ //endregion
+ //region Tag number bigger or equal to 31
+ else {
+ let count = 1;
+
+ this.valueHex = new ArrayBuffer(255);
+ let tagNumberBufferMaxLength = 255;
+ let intTagNumberBuffer = new Uint8Array(this.valueHex);
+
+ //noinspection JSBitwiseOperatorUsage
+ while (intBuffer[count] & 0x80) {
+ intTagNumberBuffer[count - 1] = intBuffer[count] & 0x7F;
+ count++;
+
+ if (count >= intBuffer.length) {
+ this.error = "End of input reached before message was fully decoded";
+ return -1;
+ }
+
+ //region In case if tag number length is greater than 255 bytes (rare but possible case)
+ if (count === tagNumberBufferMaxLength) {
+ tagNumberBufferMaxLength += 255;
+
+ const tempBuffer = new ArrayBuffer(tagNumberBufferMaxLength);
+ const tempBufferView = new Uint8Array(tempBuffer);
+
+ for (let i = 0; i < intTagNumberBuffer.length; i++) tempBufferView[i] = intTagNumberBuffer[i];
+
+ this.valueHex = new ArrayBuffer(tagNumberBufferMaxLength);
+ intTagNumberBuffer = new Uint8Array(this.valueHex);
+ }
+ //endregion
+ }
+
+ this.blockLength = count + 1;
+ intTagNumberBuffer[count - 1] = intBuffer[count] & 0x7F; // Write last byte to buffer
+
+ //region Cut buffer
+ const tempBuffer = new ArrayBuffer(count);
+ const tempBufferView = new Uint8Array(tempBuffer);
+
+ for (let i = 0; i < count; i++) tempBufferView[i] = intTagNumberBuffer[i];
+
+ this.valueHex = new ArrayBuffer(count);
+ intTagNumberBuffer = new Uint8Array(this.valueHex);
+ intTagNumberBuffer.set(tempBufferView);
+ //endregion
+
+ //region Try to convert long tag number to short form
+ if (this.blockLength <= 9) this.tagNumber = (0, _pvutils.utilFromBase)(intTagNumberBuffer, 7);else {
+ this.isHexOnly = true;
+ this.warnings.push("Tag too long, represented as hex-coded");
+ }
+ //endregion
+ }
+ //endregion
+ //endregion
+
+ //region Check if constructed encoding was using for primitive type
+ if (this.tagClass === 1 && this.isConstructed) {
+ switch (this.tagNumber) {
+ case 1: // Boolean
+ case 2: // REAL
+ case 5: // Null
+ case 6: // OBJECT IDENTIFIER
+ case 9: // REAL
+ case 14: // Time
+ case 23:
+ case 24:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ this.error = "Constructed encoding used for primitive type";
+ return -1;
+ default:
+ }
+ }
+ //endregion
+
+ return inputOffset + this.blockLength; // Return current offset in input buffer
+ }
+ //**********************************************************************************
+ /**
+ * Convertion for the block to JSON object
+ * @returns {{blockName: string,
+ * tagClass: number,
+ * tagNumber: number,
+ * isConstructed: boolean,
+ * isHexOnly: boolean,
+ * valueHex: ArrayBuffer,
+ * blockLength: number,
+ * error: string, warnings: Array.<string>,
+ * valueBeforeDecode: string}}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.blockName = this.constructor.blockName();
+ object.tagClass = this.tagClass;
+ object.tagNumber = this.tagNumber;
+ object.isConstructed = this.isConstructed;
+
+ return object;
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of length block class
+//**************************************************************************************
+class LocalLengthBlock extends LocalBaseBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalLengthBlock" class
+ * @param {Object} [parameters={}]
+ * @property {Object} [lenBlock]
+ */
+ constructor(parameters = {}) {
+ super();
+
+ if ("lenBlock" in parameters) {
+ this.isIndefiniteForm = (0, _pvutils.getParametersValue)(parameters.lenBlock, "isIndefiniteForm", false);
+ this.longFormUsed = (0, _pvutils.getParametersValue)(parameters.lenBlock, "longFormUsed", false);
+ this.length = (0, _pvutils.getParametersValue)(parameters.lenBlock, "length", 0);
+ } else {
+ this.isIndefiniteForm = false;
+ this.longFormUsed = false;
+ this.length = 0;
+ }
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "lengthBlock";
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number}
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1;
+ //endregion
+
+ //region Getting Uint8Array from ArrayBuffer
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
+ //endregion
+
+ //region Initial checks
+ if (intBuffer.length === 0) {
+ this.error = "Zero buffer length";
+ return -1;
+ }
+
+ if (intBuffer[0] === 0xFF) {
+ this.error = "Length block 0xFF is reserved by standard";
+ return -1;
+ }
+ //endregion
+
+ //region Check for length form type
+ this.isIndefiniteForm = intBuffer[0] === 0x80;
+ //endregion
+
+ //region Stop working in case of indefinite length form
+ if (this.isIndefiniteForm === true) {
+ this.blockLength = 1;
+ return inputOffset + this.blockLength;
+ }
+ //endregion
+
+ //region Check is long form of length encoding using
+ this.longFormUsed = !!(intBuffer[0] & 0x80);
+ //endregion
+
+ //region Stop working in case of short form of length value
+ if (this.longFormUsed === false) {
+ this.length = intBuffer[0];
+ this.blockLength = 1;
+ return inputOffset + this.blockLength;
+ }
+ //endregion
+
+ //region Calculate length value in case of long form
+ const count = intBuffer[0] & 0x7F;
+
+ if (count > 8) // Too big length value
+ {
+ this.error = "Too big integer";
+ return -1;
+ }
+
+ if (count + 1 > intBuffer.length) {
+ this.error = "End of input reached before message was fully decoded";
+ return -1;
+ }
+
+ const lengthBufferView = new Uint8Array(count);
+
+ for (let i = 0; i < count; i++) lengthBufferView[i] = intBuffer[i + 1];
+
+ if (lengthBufferView[count - 1] === 0x00) this.warnings.push("Needlessly long encoded length");
+
+ this.length = (0, _pvutils.utilFromBase)(lengthBufferView, 8);
+
+ if (this.longFormUsed && this.length <= 127) this.warnings.push("Unneccesary usage of long length form");
+
+ this.blockLength = count + 1;
+ //endregion
+
+ return inputOffset + this.blockLength; // Return current offset in input buffer
+ }
+ //**********************************************************************************
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toBER(sizeOnly = false) {
+ //region Initial variables
+ let retBuf;
+ let retView;
+ //endregion
+
+ if (this.length > 127) this.longFormUsed = true;
+
+ if (this.isIndefiniteForm) {
+ retBuf = new ArrayBuffer(1);
+
+ if (sizeOnly === false) {
+ retView = new Uint8Array(retBuf);
+ retView[0] = 0x80;
+ }
+
+ return retBuf;
+ }
+
+ if (this.longFormUsed === true) {
+ const encodedBuf = (0, _pvutils.utilToBase)(this.length, 8);
+
+ if (encodedBuf.byteLength > 127) {
+ this.error = "Too big length";
+ return new ArrayBuffer(0);
+ }
+
+ retBuf = new ArrayBuffer(encodedBuf.byteLength + 1);
+
+ if (sizeOnly === true) return retBuf;
+
+ const encodedView = new Uint8Array(encodedBuf);
+ retView = new Uint8Array(retBuf);
+
+ retView[0] = encodedBuf.byteLength | 0x80;
+
+ for (let i = 0; i < encodedBuf.byteLength; i++) retView[i + 1] = encodedView[i];
+
+ return retBuf;
+ }
+
+ retBuf = new ArrayBuffer(1);
+
+ if (sizeOnly === false) {
+ retView = new Uint8Array(retBuf);
+
+ retView[0] = this.length;
+ }
+
+ return retBuf;
+ }
+ //**********************************************************************************
+ /**
+ * Convertion for the block to JSON object
+ * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.blockName = this.constructor.blockName();
+ object.isIndefiniteForm = this.isIndefiniteForm;
+ object.longFormUsed = this.longFormUsed;
+ object.length = this.length;
+
+ return object;
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of value block class
+//**************************************************************************************
+class LocalValueBlock extends LocalBaseBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalValueBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "valueBlock";
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedLocalSymbols,JSUnusedLocalSymbols,JSUnusedLocalSymbols
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number}
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Throw an exception for a function which needs to be specified in extended classes
+ throw TypeError("User need to make a specific function in a class which extends \"LocalValueBlock\"");
+ //endregion
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedLocalSymbols
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toBER(sizeOnly = false) {
+ //region Throw an exception for a function which needs to be specified in extended classes
+ throw TypeError("User need to make a specific function in a class which extends \"LocalValueBlock\"");
+ //endregion
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of basic ASN.1 block class
+//**************************************************************************************
+class BaseBlock extends LocalBaseBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "BaseBlock" class
+ * @param {Object} [parameters={}]
+ * @property {Object} [primitiveSchema]
+ * @property {string} [name]
+ * @property {boolean} [optional]
+ * @param valueBlockType Type of value block
+ */
+ constructor(parameters = {}, valueBlockType = LocalValueBlock) {
+ super(parameters);
+
+ if ("name" in parameters) this.name = parameters.name;
+ if ("optional" in parameters) this.optional = parameters.optional;
+ if ("primitiveSchema" in parameters) this.primitiveSchema = parameters.primitiveSchema;
+
+ this.idBlock = new LocalIdentificationBlock(parameters);
+ this.lenBlock = new LocalLengthBlock(parameters);
+ this.valueBlock = new valueBlockType(parameters);
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "BaseBlock";
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number}
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+ return resultOffset;
+ }
+
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+
+ if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
+
+ return resultOffset;
+ }
+ //**********************************************************************************
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toBER(sizeOnly = false) {
+ let retBuf;
+
+ const idBlockBuf = this.idBlock.toBER(sizeOnly);
+ const valueBlockSizeBuf = this.valueBlock.toBER(true);
+
+ this.lenBlock.length = valueBlockSizeBuf.byteLength;
+ const lenBlockBuf = this.lenBlock.toBER(sizeOnly);
+
+ retBuf = (0, _pvutils.utilConcatBuf)(idBlockBuf, lenBlockBuf);
+
+ let valueBlockBuf;
+
+ if (sizeOnly === false) valueBlockBuf = this.valueBlock.toBER(sizeOnly);else valueBlockBuf = new ArrayBuffer(this.lenBlock.length);
+
+ retBuf = (0, _pvutils.utilConcatBuf)(retBuf, valueBlockBuf);
+
+ if (this.lenBlock.isIndefiniteForm === true) {
+ const indefBuf = new ArrayBuffer(2);
+
+ if (sizeOnly === false) {
+ const indefView = new Uint8Array(indefBuf);
+
+ indefView[0] = 0x00;
+ indefView[1] = 0x00;
+ }
+
+ retBuf = (0, _pvutils.utilConcatBuf)(retBuf, indefBuf);
+ }
+
+ return retBuf;
+ }
+ //**********************************************************************************
+ /**
+ * Convertion for the block to JSON object
+ * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.idBlock = this.idBlock.toJSON();
+ object.lenBlock = this.lenBlock.toJSON();
+ object.valueBlock = this.valueBlock.toJSON();
+
+ if ("name" in this) object.name = this.name;
+ if ("optional" in this) object.optional = this.optional;
+ if ("primitiveSchema" in this) object.primitiveSchema = this.primitiveSchema.toJSON();
+
+ return object;
+ }
+ //**********************************************************************************
+}
+exports.BaseBlock = BaseBlock; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of basic block for all PRIMITIVE types
+//**************************************************************************************
+
+class LocalPrimitiveValueBlock extends LocalValueBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalPrimitiveValueBlock" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueBeforeDecode]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ //region Variables from "hexBlock" class
+ if ("valueHex" in parameters) this.valueHex = parameters.valueHex.slice(0);else this.valueHex = new ArrayBuffer(0);
+
+ this.isHexOnly = (0, _pvutils.getParametersValue)(parameters, "isHexOnly", true);
+ //endregion
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number}
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1;
+ //endregion
+
+ //region Getting Uint8Array from ArrayBuffer
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
+ //endregion
+
+ //region Initial checks
+ if (intBuffer.length === 0) {
+ this.warnings.push("Zero buffer length");
+ return inputOffset;
+ }
+ //endregion
+
+ //region Copy input buffer into internal buffer
+ this.valueHex = new ArrayBuffer(intBuffer.length);
+ const valueHexView = new Uint8Array(this.valueHex);
+
+ for (let i = 0; i < intBuffer.length; i++) valueHexView[i] = intBuffer[i];
+ //endregion
+
+ this.blockLength = inputLength;
+
+ return inputOffset + inputLength;
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedLocalSymbols
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toBER(sizeOnly = false) {
+ return this.valueHex.slice(0);
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "PrimitiveValueBlock";
+ }
+ //**********************************************************************************
+ /**
+ * Convertion for the block to JSON object
+ * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.valueHex = (0, _pvutils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
+ object.isHexOnly = this.isHexOnly;
+
+ return object;
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+class Primitive extends BaseBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "Primitive" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalPrimitiveValueBlock);
+
+ this.idBlock.isConstructed = false;
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "PRIMITIVE";
+ }
+ //**********************************************************************************
+}
+exports.Primitive = Primitive; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of basic block for all CONSTRUCTED types
+//**************************************************************************************
+
+class LocalConstructedValueBlock extends LocalValueBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalConstructedValueBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.value = (0, _pvutils.getParametersValue)(parameters, "value", []);
+ this.isIndefiniteForm = (0, _pvutils.getParametersValue)(parameters, "isIndefiniteForm", false);
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number}
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Store initial offset and length
+ const initialOffset = inputOffset;
+ const initialLength = inputLength;
+ //endregion
+
+ //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1;
+ //endregion
+
+ //region Getting Uint8Array from ArrayBuffer
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
+ //endregion
+
+ //region Initial checks
+ if (intBuffer.length === 0) {
+ this.warnings.push("Zero buffer length");
+ return inputOffset;
+ }
+ //endregion
+
+ //region Aux function
+ function checkLen(indefiniteLength, length) {
+ if (indefiniteLength === true) return 1;
+
+ return length;
+ }
+ //endregion
+
+ let currentOffset = inputOffset;
+
+ while (checkLen(this.isIndefiniteForm, inputLength) > 0) {
+ const returnObject = LocalFromBER(inputBuffer, currentOffset, inputLength);
+ if (returnObject.offset === -1) {
+ this.error = returnObject.result.error;
+ this.warnings.concat(returnObject.result.warnings);
+ return -1;
+ }
+
+ currentOffset = returnObject.offset;
+
+ this.blockLength += returnObject.result.blockLength;
+ inputLength -= returnObject.result.blockLength;
+
+ this.value.push(returnObject.result);
+
+ if (this.isIndefiniteForm === true && returnObject.result.constructor.blockName() === EndOfContent.blockName()) break;
+ }
+
+ if (this.isIndefiniteForm === true) {
+ if (this.value[this.value.length - 1].constructor.blockName() === EndOfContent.blockName()) this.value.pop();else this.warnings.push("No EndOfContent block encoded");
+ }
+
+ //region Copy "inputBuffer" to "valueBeforeDecode"
+ this.valueBeforeDecode = inputBuffer.slice(initialOffset, initialOffset + initialLength);
+ //endregion
+
+ return currentOffset;
+ }
+ //**********************************************************************************
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toBER(sizeOnly = false) {
+ let retBuf = new ArrayBuffer(0);
+
+ for (let i = 0; i < this.value.length; i++) {
+ const valueBuf = this.value[i].toBER(sizeOnly);
+ retBuf = (0, _pvutils.utilConcatBuf)(retBuf, valueBuf);
+ }
+
+ return retBuf;
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "ConstructedValueBlock";
+ }
+ //**********************************************************************************
+ /**
+ * Convertion for the block to JSON object
+ * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.isIndefiniteForm = this.isIndefiniteForm;
+ object.value = [];
+ for (let i = 0; i < this.value.length; i++) object.value.push(this.value[i].toJSON());
+
+ return object;
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+class Constructed extends BaseBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "Constructed" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalConstructedValueBlock);
+
+ this.idBlock.isConstructed = true;
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "CONSTRUCTED";
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number}
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ this.valueBlock.isIndefiniteForm = this.lenBlock.isIndefiniteForm;
+
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+ return resultOffset;
+ }
+
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+
+ if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
+
+ return resultOffset;
+ }
+ //**********************************************************************************
+}
+exports.Constructed = Constructed; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 EndOfContent type class
+//**************************************************************************************
+
+class LocalEndOfContentValueBlock extends LocalValueBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalEndOfContentValueBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedLocalSymbols,JSUnusedLocalSymbols
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number}
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region There is no "value block" for EndOfContent type and we need to return the same offset
+ return inputOffset;
+ //endregion
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedLocalSymbols
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toBER(sizeOnly = false) {
+ return new ArrayBuffer(0);
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "EndOfContentValueBlock";
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+class EndOfContent extends BaseBlock {
+ //**********************************************************************************
+ constructor(paramaters = {}) {
+ super(paramaters, LocalEndOfContentValueBlock);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 0; // EndOfContent
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "EndOfContent";
+ }
+ //**********************************************************************************
+}
+exports.EndOfContent = EndOfContent; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 Boolean type class
+//**************************************************************************************
+
+class LocalBooleanValueBlock extends LocalValueBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalBooleanValueBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.value = (0, _pvutils.getParametersValue)(parameters, "value", false);
+ this.isHexOnly = (0, _pvutils.getParametersValue)(parameters, "isHexOnly", false);
+
+ if ("valueHex" in parameters) this.valueHex = parameters.valueHex.slice(0);else {
+ this.valueHex = new ArrayBuffer(1);
+ if (this.value === true) {
+ const view = new Uint8Array(this.valueHex);
+ view[0] = 0xFF;
+ }
+ }
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1;
+ //endregion
+
+ //region Getting Uint8Array from ArrayBuffer
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
+ //endregion
+
+ if (inputLength > 1) this.warnings.push("Boolean value encoded in more then 1 octet");
+
+ this.isHexOnly = true;
+
+ //region Copy input buffer to internal array
+ this.valueHex = new ArrayBuffer(intBuffer.length);
+ const view = new Uint8Array(this.valueHex);
+
+ for (let i = 0; i < intBuffer.length; i++) view[i] = intBuffer[i];
+ //endregion
+
+ if (_pvutils.utilDecodeTC.call(this) !== 0) this.value = true;else this.value = false;
+
+ this.blockLength = inputLength;
+
+ return inputOffset + inputLength;
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedLocalSymbols
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toBER(sizeOnly = false) {
+ return this.valueHex;
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "BooleanValueBlock";
+ }
+ //**********************************************************************************
+ /**
+ * Convertion for the block to JSON object
+ * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.value = this.value;
+ object.isHexOnly = this.isHexOnly;
+ object.valueHex = (0, _pvutils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
+
+ return object;
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+class Boolean extends BaseBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "Boolean" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalBooleanValueBlock);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 1; // Boolean
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "Boolean";
+ }
+ //**********************************************************************************
+}
+exports.Boolean = Boolean; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 Sequence and Set type classes
+//**************************************************************************************
+
+class Sequence extends Constructed {
+ //**********************************************************************************
+ /**
+ * Constructor for "Sequence" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 16; // Sequence
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "Sequence";
+ }
+ //**********************************************************************************
+}
+exports.Sequence = Sequence; //**************************************************************************************
+
+class Set extends Constructed {
+ //**********************************************************************************
+ /**
+ * Constructor for "Set" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 17; // Set
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "Set";
+ }
+ //**********************************************************************************
+}
+exports.Set = Set; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 Null type class
+//**************************************************************************************
+
+class Null extends BaseBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "Null" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalBaseBlock); // We will not have a call to "Null value block" because of specified "fromBER" and "toBER" functions
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 5; // Null
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "Null";
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedLocalSymbols
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ if (this.lenBlock.length > 0) this.warnings.push("Non-zero length of value block for Null type");
+
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+
+ this.blockLength += inputLength;
+
+ if (inputOffset + inputLength > inputBuffer.byteLength) {
+ this.error = "End of input reached before message was fully decoded (inconsistent offset and length values)";
+ return -1;
+ }
+
+ return inputOffset + inputLength;
+ }
+ //**********************************************************************************
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toBER(sizeOnly = false) {
+ const retBuf = new ArrayBuffer(2);
+
+ if (sizeOnly === true) return retBuf;
+
+ const retView = new Uint8Array(retBuf);
+ retView[0] = 0x05;
+ retView[1] = 0x00;
+
+ return retBuf;
+ }
+ //**********************************************************************************
+}
+exports.Null = Null; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 OctetString type class
+//**************************************************************************************
+
+class LocalOctetStringValueBlock extends LocalHexBlock(LocalConstructedValueBlock) {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalOctetStringValueBlock" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.isConstructed = (0, _pvutils.getParametersValue)(parameters, "isConstructed", false);
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ let resultOffset = 0;
+
+ if (this.isConstructed === true) {
+ this.isHexOnly = false;
+
+ resultOffset = LocalConstructedValueBlock.prototype.fromBER.call(this, inputBuffer, inputOffset, inputLength);
+ if (resultOffset === -1) return resultOffset;
+
+ for (let i = 0; i < this.value.length; i++) {
+ const currentBlockName = this.value[i].constructor.blockName();
+
+ if (currentBlockName === EndOfContent.blockName()) {
+ if (this.isIndefiniteForm === true) break;else {
+ this.error = "EndOfContent is unexpected, OCTET STRING may consists of OCTET STRINGs only";
+ return -1;
+ }
+ }
+
+ if (currentBlockName !== OctetString.blockName()) {
+ this.error = "OCTET STRING may consists of OCTET STRINGs only";
+ return -1;
+ }
+ }
+ } else {
+ this.isHexOnly = true;
+
+ resultOffset = super.fromBER(inputBuffer, inputOffset, inputLength);
+ this.blockLength = inputLength;
+ }
+
+ return resultOffset;
+ }
+ //**********************************************************************************
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toBER(sizeOnly = false) {
+ if (this.isConstructed === true) return LocalConstructedValueBlock.prototype.toBER.call(this, sizeOnly);
+
+ let retBuf = new ArrayBuffer(this.valueHex.byteLength);
+
+ if (sizeOnly === true) return retBuf;
+
+ if (this.valueHex.byteLength === 0) return retBuf;
+
+ retBuf = this.valueHex.slice(0);
+
+ return retBuf;
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "OctetStringValueBlock";
+ }
+ //**********************************************************************************
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.isConstructed = this.isConstructed;
+ object.isHexOnly = this.isHexOnly;
+ object.valueHex = (0, _pvutils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
+
+ return object;
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+class OctetString extends BaseBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "OctetString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalOctetStringValueBlock);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 4; // OctetString
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ this.valueBlock.isConstructed = this.idBlock.isConstructed;
+ this.valueBlock.isIndefiniteForm = this.lenBlock.isIndefiniteForm;
+
+ //region Ability to encode empty OCTET STRING
+ if (inputLength === 0) {
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+
+ return inputOffset;
+ }
+ //endregion
+
+ return super.fromBER(inputBuffer, inputOffset, inputLength);
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "OctetString";
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+ /**
+ * Checking that two OCTETSTRINGs are equal
+ * @param {OctetString} octetString
+ */
+ isEqual(octetString) {
+ //region Check input type
+ if (octetString instanceof OctetString === false) return false;
+ //endregion
+
+ //region Compare two JSON strings
+ if (JSON.stringify(this) !== JSON.stringify(octetString)) return false;
+ //endregion
+
+ return true;
+ }
+ //**********************************************************************************
+}
+exports.OctetString = OctetString; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 BitString type class
+//**************************************************************************************
+
+class LocalBitStringValueBlock extends LocalHexBlock(LocalConstructedValueBlock) {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalBitStringValueBlock" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.unusedBits = (0, _pvutils.getParametersValue)(parameters, "unusedBits", 0);
+ this.isConstructed = (0, _pvutils.getParametersValue)(parameters, "isConstructed", false);
+ this.blockLength = this.valueHex.byteLength;
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Ability to decode zero-length BitString value
+ if (inputLength === 0) return inputOffset;
+ //endregion
+
+ let resultOffset = -1;
+
+ //region If the BISTRING supposed to be a constructed value
+ if (this.isConstructed === true) {
+ resultOffset = LocalConstructedValueBlock.prototype.fromBER.call(this, inputBuffer, inputOffset, inputLength);
+ if (resultOffset === -1) return resultOffset;
+
+ for (let i = 0; i < this.value.length; i++) {
+ const currentBlockName = this.value[i].constructor.blockName();
+
+ if (currentBlockName === EndOfContent.blockName()) {
+ if (this.isIndefiniteForm === true) break;else {
+ this.error = "EndOfContent is unexpected, BIT STRING may consists of BIT STRINGs only";
+ return -1;
+ }
+ }
+
+ if (currentBlockName !== BitString.blockName()) {
+ this.error = "BIT STRING may consists of BIT STRINGs only";
+ return -1;
+ }
+
+ if (this.unusedBits > 0 && this.value[i].valueBlock.unusedBits > 0) {
+ this.error = "Usign of \"unused bits\" inside constructive BIT STRING allowed for least one only";
+ return -1;
+ }
+
+ this.unusedBits = this.value[i].valueBlock.unusedBits;
+ if (this.unusedBits > 7) {
+ this.error = "Unused bits for BitString must be in range 0-7";
+ return -1;
+ }
+ }
+
+ return resultOffset;
+ }
+ //endregion
+ //region If the BitString supposed to be a primitive value
+ //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1;
+ //endregion
+
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
+
+ this.unusedBits = intBuffer[0];
+
+ if (this.unusedBits > 7) {
+ this.error = "Unused bits for BitString must be in range 0-7";
+ return -1;
+ }
+
+ //region Copy input buffer to internal buffer
+ this.valueHex = new ArrayBuffer(intBuffer.length - 1);
+ const view = new Uint8Array(this.valueHex);
+ for (let i = 0; i < inputLength - 1; i++) view[i] = intBuffer[i + 1];
+ //endregion
+
+ this.blockLength = intBuffer.length;
+
+ return inputOffset + inputLength;
+ //endregion
+ }
+ //**********************************************************************************
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toBER(sizeOnly = false) {
+ if (this.isConstructed === true) return LocalConstructedValueBlock.prototype.toBER.call(this, sizeOnly);
+
+ if (sizeOnly === true) return new ArrayBuffer(this.valueHex.byteLength + 1);
+
+ if (this.valueHex.byteLength === 0) return new ArrayBuffer(0);
+
+ const curView = new Uint8Array(this.valueHex);
+
+ const retBuf = new ArrayBuffer(this.valueHex.byteLength + 1);
+ const retView = new Uint8Array(retBuf);
+
+ retView[0] = this.unusedBits;
+
+ for (let i = 0; i < this.valueHex.byteLength; i++) retView[i + 1] = curView[i];
+
+ return retBuf;
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "BitStringValueBlock";
+ }
+ //**********************************************************************************
+ /**
+ * Convertion for the block to JSON object
+ * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.unusedBits = this.unusedBits;
+ object.isConstructed = this.isConstructed;
+ object.isHexOnly = this.isHexOnly;
+ object.valueHex = (0, _pvutils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
+
+ return object;
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+class BitString extends BaseBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "BitString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalBitStringValueBlock);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 3; // BitString
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "BitString";
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Ability to encode empty BitString
+ if (inputLength === 0) return inputOffset;
+ //endregion
+
+ this.valueBlock.isConstructed = this.idBlock.isConstructed;
+ this.valueBlock.isIndefiniteForm = this.lenBlock.isIndefiniteForm;
+
+ return super.fromBER(inputBuffer, inputOffset, inputLength);
+ }
+ //**********************************************************************************
+ /**
+ * Checking that two BITSTRINGs are equal
+ * @param {BitString} bitString
+ */
+ isEqual(bitString) {
+ //region Check input type
+ if (bitString instanceof BitString === false) return false;
+ //endregion
+
+ //region Compare two JSON strings
+ if (JSON.stringify(this) !== JSON.stringify(bitString)) return false;
+ //endregion
+
+ return true;
+ }
+ //**********************************************************************************
+}
+exports.BitString = BitString; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 Integer type class
+//**************************************************************************************
+/**
+ * @extends LocalValueBlock
+ */
+
+class LocalIntegerValueBlock extends LocalHexBlock(LocalValueBlock) {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalIntegerValueBlock" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ if ("value" in parameters) this.valueDec = parameters.value;
+ }
+ //**********************************************************************************
+ /**
+ * Setter for "valueHex"
+ * @param {ArrayBuffer} _value
+ */
+ set valueHex(_value) {
+ this._valueHex = _value.slice(0);
+
+ if (_value.byteLength >= 4) {
+ this.warnings.push("Too big Integer for decoding, hex only");
+ this.isHexOnly = true;
+ this._valueDec = 0;
+ } else {
+ this.isHexOnly = false;
+
+ if (_value.byteLength > 0) this._valueDec = _pvutils.utilDecodeTC.call(this);
+ }
+ }
+ //**********************************************************************************
+ /**
+ * Getter for "valueHex"
+ * @returns {ArrayBuffer}
+ */
+ get valueHex() {
+ return this._valueHex;
+ }
+ //**********************************************************************************
+ /**
+ * Getter for "valueDec"
+ * @param {number} _value
+ */
+ set valueDec(_value) {
+ this._valueDec = _value;
+
+ this.isHexOnly = false;
+ this._valueHex = (0, _pvutils.utilEncodeTC)(_value);
+ }
+ //**********************************************************************************
+ /**
+ * Getter for "valueDec"
+ * @returns {number}
+ */
+ get valueDec() {
+ return this._valueDec;
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from DER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 DER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 DER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @param {number} [expectedLength=0] Expected length of converted "valueHex" buffer
+ * @returns {number} Offset after least decoded byte
+ */
+ fromDER(inputBuffer, inputOffset, inputLength, expectedLength = 0) {
+ const offset = this.fromBER(inputBuffer, inputOffset, inputLength);
+ if (offset === -1) return offset;
+
+ const view = new Uint8Array(this._valueHex);
+
+ if (view[0] === 0x00 && (view[1] & 0x80) !== 0) {
+ const updatedValueHex = new ArrayBuffer(this._valueHex.byteLength - 1);
+ const updatedView = new Uint8Array(updatedValueHex);
+
+ updatedView.set(new Uint8Array(this._valueHex, 1, this._valueHex.byteLength - 1));
+
+ this._valueHex = updatedValueHex.slice(0);
+ } else {
+ if (expectedLength !== 0) {
+ if (this._valueHex.byteLength < expectedLength) {
+ if (expectedLength - this._valueHex.byteLength > 1) expectedLength = this._valueHex.byteLength + 1;
+
+ const updatedValueHex = new ArrayBuffer(expectedLength);
+ const updatedView = new Uint8Array(updatedValueHex);
+
+ updatedView.set(view, expectedLength - this._valueHex.byteLength);
+
+ this._valueHex = updatedValueHex.slice(0);
+ }
+ }
+ }
+
+ return offset;
+ }
+ //**********************************************************************************
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (DER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toDER(sizeOnly = false) {
+ const view = new Uint8Array(this._valueHex);
+
+ switch (true) {
+ case (view[0] & 0x80) !== 0:
+ {
+ const updatedValueHex = new ArrayBuffer(this._valueHex.byteLength + 1);
+ const updatedView = new Uint8Array(updatedValueHex);
+
+ updatedView[0] = 0x00;
+ updatedView.set(view, 1);
+
+ this._valueHex = updatedValueHex.slice(0);
+ }
+ break;
+ case view[0] === 0x00 && (view[1] & 0x80) === 0:
+ {
+ const updatedValueHex = new ArrayBuffer(this._valueHex.byteLength - 1);
+ const updatedView = new Uint8Array(updatedValueHex);
+
+ updatedView.set(new Uint8Array(this._valueHex, 1, this._valueHex.byteLength - 1));
+
+ this._valueHex = updatedValueHex.slice(0);
+ }
+ break;
+ default:
+ }
+
+ return this.toBER(sizeOnly);
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ const resultOffset = super.fromBER(inputBuffer, inputOffset, inputLength);
+ if (resultOffset === -1) return resultOffset;
+
+ this.blockLength = inputLength;
+
+ return inputOffset + inputLength;
+ }
+ //**********************************************************************************
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toBER(sizeOnly = false) {
+ //noinspection JSCheckFunctionSignatures
+ return this.valueHex.slice(0);
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "IntegerValueBlock";
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.valueDec = this.valueDec;
+
+ return object;
+ }
+ //**********************************************************************************
+ /**
+ * Convert current value to decimal string representation
+ */
+ toString() {
+ //region Aux functions
+ function viewAdd(first, second) {
+ //region Initial variables
+ const c = new Uint8Array([0]);
+
+ let firstView = new Uint8Array(first);
+ let secondView = new Uint8Array(second);
+
+ let firstViewCopy = firstView.slice(0);
+ const firstViewCopyLength = firstViewCopy.length - 1;
+ let secondViewCopy = secondView.slice(0);
+ const secondViewCopyLength = secondViewCopy.length - 1;
+
+ let value = 0;
+
+ const max = secondViewCopyLength < firstViewCopyLength ? firstViewCopyLength : secondViewCopyLength;
+
+ let counter = 0;
+ //endregion
+
+ for (let i = max; i >= 0; i--, counter++) {
+ switch (true) {
+ case counter < secondViewCopy.length:
+ value = firstViewCopy[firstViewCopyLength - counter] + secondViewCopy[secondViewCopyLength - counter] + c[0];
+ break;
+ default:
+ value = firstViewCopy[firstViewCopyLength - counter] + c[0];
+ }
+
+ c[0] = value / 10;
+
+ switch (true) {
+ case counter >= firstViewCopy.length:
+ firstViewCopy = (0, _pvutils.utilConcatView)(new Uint8Array([value % 10]), firstViewCopy);
+ break;
+ default:
+ firstViewCopy[firstViewCopyLength - counter] = value % 10;
+ }
+ }
+
+ if (c[0] > 0) firstViewCopy = (0, _pvutils.utilConcatView)(c, firstViewCopy);
+
+ return firstViewCopy.slice(0);
+ }
+
+ function power2(n) {
+ if (n >= powers2.length) {
+ for (let p = powers2.length; p <= n; p++) {
+ const c = new Uint8Array([0]);
+ let digits = powers2[p - 1].slice(0);
+
+ for (let i = digits.length - 1; i >= 0; i--) {
+ const newValue = new Uint8Array([(digits[i] << 1) + c[0]]);
+ c[0] = newValue[0] / 10;
+ digits[i] = newValue[0] % 10;
+ }
+
+ if (c[0] > 0) digits = (0, _pvutils.utilConcatView)(c, digits);
+
+ powers2.push(digits);
+ }
+ }
+
+ return powers2[n];
+ }
+
+ function viewSub(first, second) {
+ //region Initial variables
+ let b = 0;
+
+ let firstView = new Uint8Array(first);
+ let secondView = new Uint8Array(second);
+
+ let firstViewCopy = firstView.slice(0);
+ const firstViewCopyLength = firstViewCopy.length - 1;
+ let secondViewCopy = secondView.slice(0);
+ const secondViewCopyLength = secondViewCopy.length - 1;
+
+ let value;
+
+ let counter = 0;
+ //endregion
+
+ for (let i = secondViewCopyLength; i >= 0; i--, counter++) {
+ value = firstViewCopy[firstViewCopyLength - counter] - secondViewCopy[secondViewCopyLength - counter] - b;
+
+ switch (true) {
+ case value < 0:
+ b = 1;
+ firstViewCopy[firstViewCopyLength - counter] = value + 10;
+ break;
+ default:
+ b = 0;
+ firstViewCopy[firstViewCopyLength - counter] = value;
+ }
+ }
+
+ if (b > 0) {
+ for (let i = firstViewCopyLength - secondViewCopyLength + 1; i >= 0; i--, counter++) {
+ value = firstViewCopy[firstViewCopyLength - counter] - b;
+
+ if (value < 0) {
+ b = 1;
+ firstViewCopy[firstViewCopyLength - counter] = value + 10;
+ } else {
+ b = 0;
+ firstViewCopy[firstViewCopyLength - counter] = value;
+ break;
+ }
+ }
+ }
+
+ return firstViewCopy.slice();
+ }
+ //endregion
+
+ //region Initial variables
+ const firstBit = this._valueHex.byteLength * 8 - 1;
+
+ let digits = new Uint8Array(this._valueHex.byteLength * 8 / 3);
+ let bitNumber = 0;
+ let currentByte;
+
+ const asn1View = new Uint8Array(this._valueHex);
+
+ let result = "";
+
+ let flag = false;
+ //endregion
+
+ //region Calculate number
+ for (let byteNumber = this._valueHex.byteLength - 1; byteNumber >= 0; byteNumber--) {
+ currentByte = asn1View[byteNumber];
+
+ for (let i = 0; i < 8; i++) {
+ if ((currentByte & 1) === 1) {
+ switch (bitNumber) {
+ case firstBit:
+ digits = viewSub(power2(bitNumber), digits);
+ result = "-";
+ break;
+ default:
+ digits = viewAdd(digits, power2(bitNumber));
+ }
+ }
+
+ bitNumber++;
+ currentByte >>= 1;
+ }
+ }
+ //endregion
+
+ //region Print number
+ for (let i = 0; i < digits.length; i++) {
+ if (digits[i]) flag = true;
+
+ if (flag) result += digitsString.charAt(digits[i]);
+ }
+
+ if (flag === false) result += digitsString.charAt(0);
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+class Integer extends BaseBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "Integer" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalIntegerValueBlock);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 2; // Integer
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "Integer";
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+ /**
+ * Compare two Integer object, or Integer and ArrayBuffer objects
+ * @param {!Integer|ArrayBuffer} otherValue
+ * @returns {boolean}
+ */
+ isEqual(otherValue) {
+ if (otherValue instanceof Integer) {
+ if (this.valueBlock.isHexOnly && otherValue.valueBlock.isHexOnly) // Compare two ArrayBuffers
+ return (0, _pvutils.isEqualBuffer)(this.valueBlock.valueHex, otherValue.valueBlock.valueHex);
+
+ if (this.valueBlock.isHexOnly === otherValue.valueBlock.isHexOnly) return this.valueBlock.valueDec === otherValue.valueBlock.valueDec;
+
+ return false;
+ }
+
+ if (otherValue instanceof ArrayBuffer) return (0, _pvutils.isEqualBuffer)(this.valueBlock.valueHex, otherValue);
+
+ return false;
+ }
+ //**********************************************************************************
+ /**
+ * Convert current Integer value from BER into DER format
+ * @returns {Integer}
+ */
+ convertToDER() {
+ const integer = new Integer({ valueHex: this.valueBlock.valueHex });
+ integer.valueBlock.toDER();
+
+ return integer;
+ }
+ //**********************************************************************************
+ /**
+ * Convert current Integer value from DER to BER format
+ * @returns {Integer}
+ */
+ convertFromDER() {
+ const expectedLength = this.valueBlock.valueHex.byteLength % 2 ? this.valueBlock.valueHex.byteLength + 1 : this.valueBlock.valueHex.byteLength;
+ const integer = new Integer({ valueHex: this.valueBlock.valueHex });
+ integer.valueBlock.fromDER(integer.valueBlock.valueHex, 0, integer.valueBlock.valueHex.byteLength, expectedLength);
+
+ return integer;
+ }
+ //**********************************************************************************
+}
+exports.Integer = Integer; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 Enumerated type class
+//**************************************************************************************
+
+class Enumerated extends Integer {
+ //**********************************************************************************
+ /**
+ * Constructor for "Enumerated" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 10; // Enumerated
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "Enumerated";
+ }
+ //**********************************************************************************
+}
+exports.Enumerated = Enumerated; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 ObjectIdentifier type class
+//**************************************************************************************
+
+class LocalSidValueBlock extends LocalHexBlock(LocalBaseBlock) {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalSidValueBlock" class
+ * @param {Object} [parameters={}]
+ * @property {number} [valueDec]
+ * @property {boolean} [isFirstSid]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.valueDec = (0, _pvutils.getParametersValue)(parameters, "valueDec", -1);
+ this.isFirstSid = (0, _pvutils.getParametersValue)(parameters, "isFirstSid", false);
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "sidBlock";
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ if (inputLength === 0) return inputOffset;
+
+ //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1;
+ //endregion
+
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
+
+ this.valueHex = new ArrayBuffer(inputLength);
+ let view = new Uint8Array(this.valueHex);
+
+ for (let i = 0; i < inputLength; i++) {
+ view[i] = intBuffer[i] & 0x7F;
+
+ this.blockLength++;
+
+ if ((intBuffer[i] & 0x80) === 0x00) break;
+ }
+
+ //region Ajust size of valueHex buffer
+ const tempValueHex = new ArrayBuffer(this.blockLength);
+ const tempView = new Uint8Array(tempValueHex);
+
+ for (let i = 0; i < this.blockLength; i++) tempView[i] = view[i];
+
+ //noinspection JSCheckFunctionSignatures
+ this.valueHex = tempValueHex.slice(0);
+ view = new Uint8Array(this.valueHex);
+ //endregion
+
+ if ((intBuffer[this.blockLength - 1] & 0x80) !== 0x00) {
+ this.error = "End of input reached before message was fully decoded";
+ return -1;
+ }
+
+ if (view[0] === 0x00) this.warnings.push("Needlessly long format of SID encoding");
+
+ if (this.blockLength <= 8) this.valueDec = (0, _pvutils.utilFromBase)(view, 7);else {
+ this.isHexOnly = true;
+ this.warnings.push("Too big SID for decoding, hex only");
+ }
+
+ return inputOffset + this.blockLength;
+ }
+ //**********************************************************************************
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toBER(sizeOnly = false) {
+ //region Initial variables
+ let retBuf;
+ let retView;
+ //endregion
+
+ if (this.isHexOnly) {
+ if (sizeOnly === true) return new ArrayBuffer(this.valueHex.byteLength);
+
+ const curView = new Uint8Array(this.valueHex);
+
+ retBuf = new ArrayBuffer(this.blockLength);
+ retView = new Uint8Array(retBuf);
+
+ for (let i = 0; i < this.blockLength - 1; i++) retView[i] = curView[i] | 0x80;
+
+ retView[this.blockLength - 1] = curView[this.blockLength - 1];
+
+ return retBuf;
+ }
+
+ const encodedBuf = (0, _pvutils.utilToBase)(this.valueDec, 7);
+ if (encodedBuf.byteLength === 0) {
+ this.error = "Error during encoding SID value";
+ return new ArrayBuffer(0);
+ }
+
+ retBuf = new ArrayBuffer(encodedBuf.byteLength);
+
+ if (sizeOnly === false) {
+ const encodedView = new Uint8Array(encodedBuf);
+ retView = new Uint8Array(retBuf);
+
+ for (let i = 0; i < encodedBuf.byteLength - 1; i++) retView[i] = encodedView[i] | 0x80;
+
+ retView[encodedBuf.byteLength - 1] = encodedView[encodedBuf.byteLength - 1];
+ }
+
+ return retBuf;
+ }
+ //**********************************************************************************
+ /**
+ * Create string representation of current SID block
+ * @returns {string}
+ */
+ toString() {
+ let result = "";
+
+ if (this.isHexOnly === true) result = (0, _pvutils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);else {
+ if (this.isFirstSid) {
+ let sidValue = this.valueDec;
+
+ if (this.valueDec <= 39) result = "0.";else {
+ if (this.valueDec <= 79) {
+ result = "1.";
+ sidValue -= 40;
+ } else {
+ result = "2.";
+ sidValue -= 80;
+ }
+ }
+
+ result += sidValue.toString();
+ } else result = this.valueDec.toString();
+ }
+
+ return result;
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.valueDec = this.valueDec;
+ object.isFirstSid = this.isFirstSid;
+
+ return object;
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+class LocalObjectIdentifierValueBlock extends LocalValueBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalObjectIdentifierValueBlock" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.fromString((0, _pvutils.getParametersValue)(parameters, "value", ""));
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ let resultOffset = inputOffset;
+
+ while (inputLength > 0) {
+ const sidBlock = new LocalSidValueBlock();
+ resultOffset = sidBlock.fromBER(inputBuffer, resultOffset, inputLength);
+ if (resultOffset === -1) {
+ this.blockLength = 0;
+ this.error = sidBlock.error;
+ return resultOffset;
+ }
+
+ if (this.value.length === 0) sidBlock.isFirstSid = true;
+
+ this.blockLength += sidBlock.blockLength;
+ inputLength -= sidBlock.blockLength;
+
+ this.value.push(sidBlock);
+ }
+
+ return resultOffset;
+ }
+ //**********************************************************************************
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toBER(sizeOnly = false) {
+ let retBuf = new ArrayBuffer(0);
+
+ for (let i = 0; i < this.value.length; i++) {
+ const valueBuf = this.value[i].toBER(sizeOnly);
+ if (valueBuf.byteLength === 0) {
+ this.error = this.value[i].error;
+ return new ArrayBuffer(0);
+ }
+
+ retBuf = (0, _pvutils.utilConcatBuf)(retBuf, valueBuf);
+ }
+
+ return retBuf;
+ }
+ //**********************************************************************************
+ /**
+ * Create "LocalObjectIdentifierValueBlock" class from string
+ * @param {string} string Input string to convert from
+ * @returns {boolean}
+ */
+ fromString(string) {
+ this.value = []; // Clear existing SID values
+
+ let pos1 = 0;
+ let pos2 = 0;
+
+ let sid = "";
+
+ let flag = false;
+
+ do {
+ pos2 = string.indexOf(".", pos1);
+ if (pos2 === -1) sid = string.substr(pos1);else sid = string.substr(pos1, pos2 - pos1);
+
+ pos1 = pos2 + 1;
+
+ if (flag) {
+ const sidBlock = this.value[0];
+
+ let plus = 0;
+
+ switch (sidBlock.valueDec) {
+ case 0:
+ break;
+ case 1:
+ plus = 40;
+ break;
+ case 2:
+ plus = 80;
+ break;
+ default:
+ this.value = []; // clear SID array
+ return false; // ???
+ }
+
+ const parsedSID = parseInt(sid, 10);
+ if (isNaN(parsedSID)) return true;
+
+ sidBlock.valueDec = parsedSID + plus;
+
+ flag = false;
+ } else {
+ const sidBlock = new LocalSidValueBlock();
+ sidBlock.valueDec = parseInt(sid, 10);
+ if (isNaN(sidBlock.valueDec)) return true;
+
+ if (this.value.length === 0) {
+ sidBlock.isFirstSid = true;
+ flag = true;
+ }
+
+ this.value.push(sidBlock);
+ }
+ } while (pos2 !== -1);
+
+ return true;
+ }
+ //**********************************************************************************
+ /**
+ * Converts "LocalObjectIdentifierValueBlock" class to string
+ * @returns {string}
+ */
+ toString() {
+ let result = "";
+ let isHexOnly = false;
+
+ for (let i = 0; i < this.value.length; i++) {
+ isHexOnly = this.value[i].isHexOnly;
+
+ let sidStr = this.value[i].toString();
+
+ if (i !== 0) result = `${result}.`;
+
+ if (isHexOnly) {
+ sidStr = `{${sidStr}}`;
+
+ if (this.value[i].isFirstSid) result = `2.{${sidStr} - 80}`;else result += sidStr;
+ } else result += sidStr;
+ }
+
+ return result;
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "ObjectIdentifierValueBlock";
+ }
+ //**********************************************************************************
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.value = this.toString();
+ object.sidArray = [];
+ for (let i = 0; i < this.value.length; i++) object.sidArray.push(this.value[i].toJSON());
+
+ return object;
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+/**
+ * @extends BaseBlock
+ */
+class ObjectIdentifier extends BaseBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "ObjectIdentifier" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalObjectIdentifierValueBlock);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 6; // OBJECT IDENTIFIER
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "ObjectIdentifier";
+ }
+ //**********************************************************************************
+}
+exports.ObjectIdentifier = ObjectIdentifier; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of all string's classes
+//**************************************************************************************
+
+class LocalUtf8StringValueBlock extends LocalHexBlock(LocalBaseBlock) {
+ //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+ /**
+ * Constructor for "LocalUtf8StringValueBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.isHexOnly = true;
+ this.value = ""; // String representation of decoded ArrayBuffer
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "Utf8StringValueBlock";
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.value = this.value;
+
+ return object;
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+/**
+ * @extends BaseBlock
+ */
+class Utf8String extends BaseBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "Utf8String" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalUtf8StringValueBlock);
+
+ if ("value" in parameters) this.fromString(parameters.value);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 12; // Utf8String
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "Utf8String";
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+ return resultOffset;
+ }
+
+ this.fromBuffer(this.valueBlock.valueHex);
+
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+
+ if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
+
+ return resultOffset;
+ }
+ //**********************************************************************************
+ /**
+ * Function converting ArrayBuffer into ASN.1 internal string
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ */
+ fromBuffer(inputBuffer) {
+ this.valueBlock.value = String.fromCharCode.apply(null, new Uint8Array(inputBuffer));
+
+ try {
+ //noinspection JSDeprecatedSymbols
+ this.valueBlock.value = decodeURIComponent(escape(this.valueBlock.value));
+ } catch (ex) {
+ this.warnings.push(`Error during "decodeURIComponent": ${ex}, using raw string`);
+ }
+ }
+ //**********************************************************************************
+ /**
+ * Function converting JavaScript string into ASN.1 internal class
+ * @param {!string} inputString ASN.1 BER encoded array
+ */
+ fromString(inputString) {
+ //noinspection JSDeprecatedSymbols
+ const str = unescape(encodeURIComponent(inputString));
+ const strLen = str.length;
+
+ this.valueBlock.valueHex = new ArrayBuffer(strLen);
+ const view = new Uint8Array(this.valueBlock.valueHex);
+
+ for (let i = 0; i < strLen; i++) view[i] = str.charCodeAt(i);
+
+ this.valueBlock.value = inputString;
+ }
+ //**********************************************************************************
+}
+exports.Utf8String = Utf8String; //**************************************************************************************
+/**
+ * @extends LocalBaseBlock
+ * @extends LocalHexBlock
+ */
+
+class LocalBmpStringValueBlock extends LocalHexBlock(LocalBaseBlock) {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalBmpStringValueBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.isHexOnly = true;
+ this.value = "";
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "BmpStringValueBlock";
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.value = this.value;
+
+ return object;
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+/**
+ * @extends BaseBlock
+ */
+class BmpString extends BaseBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "BmpString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalBmpStringValueBlock);
+
+ if ("value" in parameters) this.fromString(parameters.value);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 30; // BmpString
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "BmpString";
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+ return resultOffset;
+ }
+
+ this.fromBuffer(this.valueBlock.valueHex);
+
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+
+ if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
+
+ return resultOffset;
+ }
+ //**********************************************************************************
+ /**
+ * Function converting ArrayBuffer into ASN.1 internal string
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ */
+ fromBuffer(inputBuffer) {
+ //noinspection JSCheckFunctionSignatures
+ const copyBuffer = inputBuffer.slice(0);
+ const valueView = new Uint8Array(copyBuffer);
+
+ for (let i = 0; i < valueView.length; i += 2) {
+ const temp = valueView[i];
+
+ valueView[i] = valueView[i + 1];
+ valueView[i + 1] = temp;
+ }
+
+ this.valueBlock.value = String.fromCharCode.apply(null, new Uint16Array(copyBuffer));
+ }
+ //**********************************************************************************
+ /**
+ * Function converting JavaScript string into ASN.1 internal class
+ * @param {!string} inputString ASN.1 BER encoded array
+ */
+ fromString(inputString) {
+ const strLength = inputString.length;
+
+ this.valueBlock.valueHex = new ArrayBuffer(strLength * 2);
+ const valueHexView = new Uint8Array(this.valueBlock.valueHex);
+
+ for (let i = 0; i < strLength; i++) {
+ const codeBuf = (0, _pvutils.utilToBase)(inputString.charCodeAt(i), 8);
+ const codeView = new Uint8Array(codeBuf);
+ if (codeView.length > 2) continue;
+
+ const dif = 2 - codeView.length;
+
+ for (let j = codeView.length - 1; j >= 0; j--) valueHexView[i * 2 + j + dif] = codeView[j];
+ }
+
+ this.valueBlock.value = inputString;
+ }
+ //**********************************************************************************
+}
+exports.BmpString = BmpString; //**************************************************************************************
+
+class LocalUniversalStringValueBlock extends LocalHexBlock(LocalBaseBlock) {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalUniversalStringValueBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.isHexOnly = true;
+ this.value = "";
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "UniversalStringValueBlock";
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.value = this.value;
+
+ return object;
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+/**
+ * @extends BaseBlock
+ */
+class UniversalString extends BaseBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "UniversalString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalUniversalStringValueBlock);
+
+ if ("value" in parameters) this.fromString(parameters.value);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 28; // UniversalString
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "UniversalString";
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+ return resultOffset;
+ }
+
+ this.fromBuffer(this.valueBlock.valueHex);
+
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+
+ if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
+
+ return resultOffset;
+ }
+ //**********************************************************************************
+ /**
+ * Function converting ArrayBuffer into ASN.1 internal string
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ */
+ fromBuffer(inputBuffer) {
+ //noinspection JSCheckFunctionSignatures
+ const copyBuffer = inputBuffer.slice(0);
+ const valueView = new Uint8Array(copyBuffer);
+
+ for (let i = 0; i < valueView.length; i += 4) {
+ valueView[i] = valueView[i + 3];
+ valueView[i + 1] = valueView[i + 2];
+ valueView[i + 2] = 0x00;
+ valueView[i + 3] = 0x00;
+ }
+
+ this.valueBlock.value = String.fromCharCode.apply(null, new Uint32Array(copyBuffer));
+ }
+ //**********************************************************************************
+ /**
+ * Function converting JavaScript string into ASN.1 internal class
+ * @param {!string} inputString ASN.1 BER encoded array
+ */
+ fromString(inputString) {
+ const strLength = inputString.length;
+
+ this.valueBlock.valueHex = new ArrayBuffer(strLength * 4);
+ const valueHexView = new Uint8Array(this.valueBlock.valueHex);
+
+ for (let i = 0; i < strLength; i++) {
+ const codeBuf = (0, _pvutils.utilToBase)(inputString.charCodeAt(i), 8);
+ const codeView = new Uint8Array(codeBuf);
+ if (codeView.length > 4) continue;
+
+ const dif = 4 - codeView.length;
+
+ for (let j = codeView.length - 1; j >= 0; j--) valueHexView[i * 4 + j + dif] = codeView[j];
+ }
+
+ this.valueBlock.value = inputString;
+ }
+ //**********************************************************************************
+}
+exports.UniversalString = UniversalString; //**************************************************************************************
+
+class LocalSimpleStringValueBlock extends LocalHexBlock(LocalBaseBlock) {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalSimpleStringValueBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.value = "";
+ this.isHexOnly = true;
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "SimpleStringValueBlock";
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.value = this.value;
+
+ return object;
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+/**
+ * @extends BaseBlock
+ */
+class LocalSimpleStringBlock extends BaseBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "LocalSimpleStringBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalSimpleStringValueBlock);
+
+ if ("value" in parameters) this.fromString(parameters.value);
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "SIMPLESTRING";
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+ return resultOffset;
+ }
+
+ this.fromBuffer(this.valueBlock.valueHex);
+
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+
+ if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
+
+ return resultOffset;
+ }
+ //**********************************************************************************
+ /**
+ * Function converting ArrayBuffer into ASN.1 internal string
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ */
+ fromBuffer(inputBuffer) {
+ this.valueBlock.value = String.fromCharCode.apply(null, new Uint8Array(inputBuffer));
+ }
+ //**********************************************************************************
+ /**
+ * Function converting JavaScript string into ASN.1 internal class
+ * @param {!string} inputString ASN.1 BER encoded array
+ */
+ fromString(inputString) {
+ const strLen = inputString.length;
+
+ this.valueBlock.valueHex = new ArrayBuffer(strLen);
+ const view = new Uint8Array(this.valueBlock.valueHex);
+
+ for (let i = 0; i < strLen; i++) view[i] = inputString.charCodeAt(i);
+
+ this.valueBlock.value = inputString;
+ }
+ //**********************************************************************************
+}
+//**************************************************************************************
+/**
+ * @extends LocalSimpleStringBlock
+ */
+class NumericString extends LocalSimpleStringBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "NumericString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 18; // NumericString
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "NumericString";
+ }
+ //**********************************************************************************
+}
+exports.NumericString = NumericString; //**************************************************************************************
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+class PrintableString extends LocalSimpleStringBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "PrintableString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 19; // PrintableString
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "PrintableString";
+ }
+ //**********************************************************************************
+}
+exports.PrintableString = PrintableString; //**************************************************************************************
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+class TeletexString extends LocalSimpleStringBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "TeletexString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 20; // TeletexString
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "TeletexString";
+ }
+ //**********************************************************************************
+}
+exports.TeletexString = TeletexString; //**************************************************************************************
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+class VideotexString extends LocalSimpleStringBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "VideotexString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 21; // VideotexString
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "VideotexString";
+ }
+ //**********************************************************************************
+}
+exports.VideotexString = VideotexString; //**************************************************************************************
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+class IA5String extends LocalSimpleStringBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "IA5String" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 22; // IA5String
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "IA5String";
+ }
+ //**********************************************************************************
+}
+exports.IA5String = IA5String; //**************************************************************************************
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+class GraphicString extends LocalSimpleStringBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "GraphicString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 25; // GraphicString
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "GraphicString";
+ }
+ //**********************************************************************************
+}
+exports.GraphicString = GraphicString; //**************************************************************************************
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+class VisibleString extends LocalSimpleStringBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "VisibleString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 26; // VisibleString
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "VisibleString";
+ }
+ //**********************************************************************************
+}
+exports.VisibleString = VisibleString; //**************************************************************************************
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+class GeneralString extends LocalSimpleStringBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "GeneralString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 27; // GeneralString
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "GeneralString";
+ }
+ //**********************************************************************************
+}
+exports.GeneralString = GeneralString; //**************************************************************************************
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+class CharacterString extends LocalSimpleStringBlock {
+ //**********************************************************************************
+ /**
+ * Constructor for "CharacterString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 29; // CharacterString
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "CharacterString";
+ }
+ //**********************************************************************************
+}
+exports.CharacterString = CharacterString; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of all date and time classes
+//**************************************************************************************
+/**
+ * @extends VisibleString
+ */
+
+class UTCTime extends VisibleString {
+ //**********************************************************************************
+ /**
+ * Constructor for "UTCTime" class
+ * @param {Object} [parameters={}]
+ * @property {string} [value] String representatio of the date
+ * @property {Date} [valueDate] JavaScript "Date" object
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.year = 0;
+ this.month = 0;
+ this.day = 0;
+ this.hour = 0;
+ this.minute = 0;
+ this.second = 0;
+
+ //region Create UTCTime from ASN.1 UTC string value
+ if ("value" in parameters) {
+ this.fromString(parameters.value);
+
+ this.valueBlock.valueHex = new ArrayBuffer(parameters.value.length);
+ const view = new Uint8Array(this.valueBlock.valueHex);
+
+ for (let i = 0; i < parameters.value.length; i++) view[i] = parameters.value.charCodeAt(i);
+ }
+ //endregion
+ //region Create GeneralizedTime from JavaScript Date type
+ if ("valueDate" in parameters) {
+ this.fromDate(parameters.valueDate);
+ this.valueBlock.valueHex = this.toBuffer();
+ }
+ //endregion
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 23; // UTCTime
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+ return resultOffset;
+ }
+
+ this.fromBuffer(this.valueBlock.valueHex);
+
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+
+ if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
+
+ return resultOffset;
+ }
+ //**********************************************************************************
+ /**
+ * Function converting ArrayBuffer into ASN.1 internal string
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ */
+ fromBuffer(inputBuffer) {
+ this.fromString(String.fromCharCode.apply(null, new Uint8Array(inputBuffer)));
+ }
+ //**********************************************************************************
+ /**
+ * Function converting ASN.1 internal string into ArrayBuffer
+ * @returns {ArrayBuffer}
+ */
+ toBuffer() {
+ const str = this.toString();
+
+ const buffer = new ArrayBuffer(str.length);
+ const view = new Uint8Array(buffer);
+
+ for (let i = 0; i < str.length; i++) view[i] = str.charCodeAt(i);
+
+ return buffer;
+ }
+ //**********************************************************************************
+ /**
+ * Function converting "Date" object into ASN.1 internal string
+ * @param {!Date} inputDate JavaScript "Date" object
+ */
+ fromDate(inputDate) {
+ this.year = inputDate.getUTCFullYear();
+ this.month = inputDate.getUTCMonth() + 1;
+ this.day = inputDate.getUTCDate();
+ this.hour = inputDate.getUTCHours();
+ this.minute = inputDate.getUTCMinutes();
+ this.second = inputDate.getUTCSeconds();
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+ /**
+ * Function converting ASN.1 internal string into "Date" object
+ * @returns {Date}
+ */
+ toDate() {
+ return new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second));
+ }
+ //**********************************************************************************
+ /**
+ * Function converting JavaScript string into ASN.1 internal class
+ * @param {!string} inputString ASN.1 BER encoded array
+ */
+ fromString(inputString) {
+ //region Parse input string
+ const parser = /(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})Z/ig;
+ const parserArray = parser.exec(inputString);
+ if (parserArray === null) {
+ this.error = "Wrong input string for convertion";
+ return;
+ }
+ //endregion
+
+ //region Store parsed values
+ const year = parseInt(parserArray[1], 10);
+ if (year >= 50) this.year = 1900 + year;else this.year = 2000 + year;
+
+ this.month = parseInt(parserArray[2], 10);
+ this.day = parseInt(parserArray[3], 10);
+ this.hour = parseInt(parserArray[4], 10);
+ this.minute = parseInt(parserArray[5], 10);
+ this.second = parseInt(parserArray[6], 10);
+ //endregion
+ }
+ //**********************************************************************************
+ /**
+ * Function converting ASN.1 internal class into JavaScript string
+ * @returns {string}
+ */
+ toString() {
+ const outputArray = new Array(7);
+
+ outputArray[0] = (0, _pvutils.padNumber)(this.year < 2000 ? this.year - 1900 : this.year - 2000, 2);
+ outputArray[1] = (0, _pvutils.padNumber)(this.month, 2);
+ outputArray[2] = (0, _pvutils.padNumber)(this.day, 2);
+ outputArray[3] = (0, _pvutils.padNumber)(this.hour, 2);
+ outputArray[4] = (0, _pvutils.padNumber)(this.minute, 2);
+ outputArray[5] = (0, _pvutils.padNumber)(this.second, 2);
+ outputArray[6] = "Z";
+
+ return outputArray.join("");
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "UTCTime";
+ }
+ //**********************************************************************************
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.year = this.year;
+ object.month = this.month;
+ object.day = this.day;
+ object.hour = this.hour;
+ object.minute = this.minute;
+ object.second = this.second;
+
+ return object;
+ }
+ //**********************************************************************************
+}
+exports.UTCTime = UTCTime; //**************************************************************************************
+/**
+ * @extends VisibleString
+ */
+
+class GeneralizedTime extends VisibleString {
+ //**********************************************************************************
+ /**
+ * Constructor for "GeneralizedTime" class
+ * @param {Object} [parameters={}]
+ * @property {string} [value] String representatio of the date
+ * @property {Date} [valueDate] JavaScript "Date" object
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.year = 0;
+ this.month = 0;
+ this.day = 0;
+ this.hour = 0;
+ this.minute = 0;
+ this.second = 0;
+ this.millisecond = 0;
+
+ //region Create UTCTime from ASN.1 UTC string value
+ if ("value" in parameters) {
+ this.fromString(parameters.value);
+
+ this.valueBlock.valueHex = new ArrayBuffer(parameters.value.length);
+ const view = new Uint8Array(this.valueBlock.valueHex);
+
+ for (let i = 0; i < parameters.value.length; i++) view[i] = parameters.value.charCodeAt(i);
+ }
+ //endregion
+ //region Create GeneralizedTime from JavaScript Date type
+ if ("valueDate" in parameters) {
+ this.fromDate(parameters.valueDate);
+ this.valueBlock.valueHex = this.toBuffer();
+ }
+ //endregion
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 24; // GeneralizedTime
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+ return resultOffset;
+ }
+
+ this.fromBuffer(this.valueBlock.valueHex);
+
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+
+ if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
+
+ return resultOffset;
+ }
+ //**********************************************************************************
+ /**
+ * Function converting ArrayBuffer into ASN.1 internal string
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ */
+ fromBuffer(inputBuffer) {
+ this.fromString(String.fromCharCode.apply(null, new Uint8Array(inputBuffer)));
+ }
+ //**********************************************************************************
+ /**
+ * Function converting ASN.1 internal string into ArrayBuffer
+ * @returns {ArrayBuffer}
+ */
+ toBuffer() {
+ const str = this.toString();
+
+ const buffer = new ArrayBuffer(str.length);
+ const view = new Uint8Array(buffer);
+
+ for (let i = 0; i < str.length; i++) view[i] = str.charCodeAt(i);
+
+ return buffer;
+ }
+ //**********************************************************************************
+ /**
+ * Function converting "Date" object into ASN.1 internal string
+ * @param {!Date} inputDate JavaScript "Date" object
+ */
+ fromDate(inputDate) {
+ this.year = inputDate.getUTCFullYear();
+ this.month = inputDate.getUTCMonth() + 1;
+ this.day = inputDate.getUTCDate();
+ this.hour = inputDate.getUTCHours();
+ this.minute = inputDate.getUTCMinutes();
+ this.second = inputDate.getUTCSeconds();
+ this.millisecond = inputDate.getUTCMilliseconds();
+ }
+ //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+ /**
+ * Function converting ASN.1 internal string into "Date" object
+ * @returns {Date}
+ */
+ toDate() {
+ return new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second, this.millisecond));
+ }
+ //**********************************************************************************
+ /**
+ * Function converting JavaScript string into ASN.1 internal class
+ * @param {!string} inputString ASN.1 BER encoded array
+ */
+ fromString(inputString) {
+ //region Initial variables
+ let isUTC = false;
+
+ let timeString = "";
+ let dateTimeString = "";
+ let fractionPart = 0;
+
+ let parser;
+
+ let hourDifference = 0;
+ let minuteDifference = 0;
+ //endregion
+
+ //region Convert as UTC time
+ if (inputString[inputString.length - 1] === "Z") {
+ timeString = inputString.substr(0, inputString.length - 1);
+
+ isUTC = true;
+ }
+ //endregion
+ //region Convert as local time
+ else {
+ //noinspection JSPrimitiveTypeWrapperUsage
+ const number = new Number(inputString[inputString.length - 1]);
+
+ if (isNaN(number.valueOf())) throw new Error("Wrong input string for convertion");
+
+ timeString = inputString;
+ }
+ //endregion
+
+ //region Check that we do not have a "+" and "-" symbols inside UTC time
+ if (isUTC) {
+ if (timeString.indexOf("+") !== -1) throw new Error("Wrong input string for convertion");
+
+ if (timeString.indexOf("-") !== -1) throw new Error("Wrong input string for convertion");
+ }
+ //endregion
+ //region Get "UTC time difference" in case of local time
+ else {
+ let multiplier = 1;
+ let differencePosition = timeString.indexOf("+");
+ let differenceString = "";
+
+ if (differencePosition === -1) {
+ differencePosition = timeString.indexOf("-");
+ multiplier = -1;
+ }
+
+ if (differencePosition !== -1) {
+ differenceString = timeString.substr(differencePosition + 1);
+ timeString = timeString.substr(0, differencePosition);
+
+ if (differenceString.length !== 2 && differenceString.length !== 4) throw new Error("Wrong input string for convertion");
+
+ //noinspection JSPrimitiveTypeWrapperUsage
+ let number = new Number(differenceString.substr(0, 2));
+
+ if (isNaN(number.valueOf())) throw new Error("Wrong input string for convertion");
+
+ hourDifference = multiplier * number;
+
+ if (differenceString.length === 4) {
+ //noinspection JSPrimitiveTypeWrapperUsage
+ number = new Number(differenceString.substr(2, 2));
+
+ if (isNaN(number.valueOf())) throw new Error("Wrong input string for convertion");
+
+ minuteDifference = multiplier * number;
+ }
+ }
+ }
+ //endregion
+
+ //region Get position of fraction point
+ let fractionPointPosition = timeString.indexOf("."); // Check for "full stop" symbol
+ if (fractionPointPosition === -1) fractionPointPosition = timeString.indexOf(","); // Check for "comma" symbol
+ //endregion
+
+ //region Get fraction part
+ if (fractionPointPosition !== -1) {
+ //noinspection JSPrimitiveTypeWrapperUsage
+ const fractionPartCheck = new Number(`0${timeString.substr(fractionPointPosition)}`);
+
+ if (isNaN(fractionPartCheck.valueOf())) throw new Error("Wrong input string for convertion");
+
+ fractionPart = fractionPartCheck.valueOf();
+
+ dateTimeString = timeString.substr(0, fractionPointPosition);
+ } else dateTimeString = timeString;
+ //endregion
+
+ //region Parse internal date
+ switch (true) {
+ case dateTimeString.length === 8:
+ // "YYYYMMDD"
+ parser = /(\d{4})(\d{2})(\d{2})/ig;
+ if (fractionPointPosition !== -1) throw new Error("Wrong input string for convertion"); // Here we should not have a "fraction point"
+ break;
+ case dateTimeString.length === 10:
+ // "YYYYMMDDHH"
+ parser = /(\d{4})(\d{2})(\d{2})(\d{2})/ig;
+
+ if (fractionPointPosition !== -1) {
+ let fractionResult = 60 * fractionPart;
+ this.minute = Math.floor(fractionResult);
+
+ fractionResult = 60 * (fractionResult - this.minute);
+ this.second = Math.floor(fractionResult);
+
+ fractionResult = 1000 * (fractionResult - this.second);
+ this.millisecond = Math.floor(fractionResult);
+ }
+ break;
+ case dateTimeString.length === 12:
+ // "YYYYMMDDHHMM"
+ parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/ig;
+
+ if (fractionPointPosition !== -1) {
+ let fractionResult = 60 * fractionPart;
+ this.second = Math.floor(fractionResult);
+
+ fractionResult = 1000 * (fractionResult - this.second);
+ this.millisecond = Math.floor(fractionResult);
+ }
+ break;
+ case dateTimeString.length === 14:
+ // "YYYYMMDDHHMMSS"
+ parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/ig;
+
+ if (fractionPointPosition !== -1) {
+ const fractionResult = 1000 * fractionPart;
+ this.millisecond = Math.floor(fractionResult);
+ }
+ break;
+ default:
+ throw new Error("Wrong input string for convertion");
+ }
+ //endregion
+
+ //region Put parsed values at right places
+ const parserArray = parser.exec(dateTimeString);
+ if (parserArray === null) throw new Error("Wrong input string for convertion");
+
+ for (let j = 1; j < parserArray.length; j++) {
+ switch (j) {
+ case 1:
+ this.year = parseInt(parserArray[j], 10);
+ break;
+ case 2:
+ this.month = parseInt(parserArray[j], 10);
+ break;
+ case 3:
+ this.day = parseInt(parserArray[j], 10);
+ break;
+ case 4:
+ this.hour = parseInt(parserArray[j], 10) + hourDifference;
+ break;
+ case 5:
+ this.minute = parseInt(parserArray[j], 10) + minuteDifference;
+ break;
+ case 6:
+ this.second = parseInt(parserArray[j], 10);
+ break;
+ default:
+ throw new Error("Wrong input string for convertion");
+ }
+ }
+ //endregion
+
+ //region Get final date
+ if (isUTC === false) {
+ const tempDate = new Date(this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond);
+
+ this.year = tempDate.getUTCFullYear();
+ this.month = tempDate.getUTCMonth();
+ this.day = tempDate.getUTCDay();
+ this.hour = tempDate.getUTCHours();
+ this.minute = tempDate.getUTCMinutes();
+ this.second = tempDate.getUTCSeconds();
+ this.millisecond = tempDate.getUTCMilliseconds();
+ }
+ //endregion
+ }
+ //**********************************************************************************
+ /**
+ * Function converting ASN.1 internal class into JavaScript string
+ * @returns {string}
+ */
+ toString() {
+ const outputArray = [];
+
+ outputArray.push((0, _pvutils.padNumber)(this.year, 4));
+ outputArray.push((0, _pvutils.padNumber)(this.month, 2));
+ outputArray.push((0, _pvutils.padNumber)(this.day, 2));
+ outputArray.push((0, _pvutils.padNumber)(this.hour, 2));
+ outputArray.push((0, _pvutils.padNumber)(this.minute, 2));
+ outputArray.push((0, _pvutils.padNumber)(this.second, 2));
+ if (this.millisecond !== 0) {
+ outputArray.push(".");
+ outputArray.push((0, _pvutils.padNumber)(this.millisecond, 3));
+ }
+ outputArray.push("Z");
+
+ return outputArray.join("");
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "GeneralizedTime";
+ }
+ //**********************************************************************************
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+ toJSON() {
+ let object = {};
+
+ //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+ try {
+ object = super.toJSON();
+ } catch (ex) {}
+ //endregion
+
+ object.year = this.year;
+ object.month = this.month;
+ object.day = this.day;
+ object.hour = this.hour;
+ object.minute = this.minute;
+ object.second = this.second;
+ object.millisecond = this.millisecond;
+
+ return object;
+ }
+ //**********************************************************************************
+}
+exports.GeneralizedTime = GeneralizedTime; //**************************************************************************************
+/**
+ * @extends Utf8String
+ */
+
+class DATE extends Utf8String {
+ //**********************************************************************************
+ /**
+ * Constructor for "DATE" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 31; // DATE
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "DATE";
+ }
+ //**********************************************************************************
+}
+exports.DATE = DATE; //**************************************************************************************
+/**
+ * @extends Utf8String
+ */
+
+class TimeOfDay extends Utf8String {
+ //**********************************************************************************
+ /**
+ * Constructor for "TimeOfDay" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 32; // TimeOfDay
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "TimeOfDay";
+ }
+ //**********************************************************************************
+}
+exports.TimeOfDay = TimeOfDay; //**************************************************************************************
+/**
+ * @extends Utf8String
+ */
+
+class DateTime extends Utf8String {
+ //**********************************************************************************
+ /**
+ * Constructor for "DateTime" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 33; // DateTime
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "DateTime";
+ }
+ //**********************************************************************************
+}
+exports.DateTime = DateTime; //**************************************************************************************
+/**
+ * @extends Utf8String
+ */
+
+class Duration extends Utf8String {
+ //**********************************************************************************
+ /**
+ * Constructor for "Duration" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 34; // Duration
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "Duration";
+ }
+ //**********************************************************************************
+}
+exports.Duration = Duration; //**************************************************************************************
+/**
+ * @extends Utf8String
+ */
+
+class TIME extends Utf8String {
+ //**********************************************************************************
+ /**
+ * Constructor for "Time" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 14; // Time
+ }
+ //**********************************************************************************
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+ static blockName() {
+ return "TIME";
+ }
+ //**********************************************************************************
+}
+exports.TIME = TIME; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of special ASN.1 schema type Choice
+//**************************************************************************************
+
+class Choice {
+ //**********************************************************************************
+ /**
+ * Constructor for "Choice" class
+ * @param {Object} [parameters={}]
+ * @property {Array} [value] Array of ASN.1 types for make a choice from
+ * @property {boolean} [optional]
+ */
+ constructor(parameters = {}) {
+ this.value = (0, _pvutils.getParametersValue)(parameters, "value", []);
+ this.optional = (0, _pvutils.getParametersValue)(parameters, "optional", false);
+ }
+ //**********************************************************************************
+}
+exports.Choice = Choice; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of special ASN.1 schema type Any
+//**************************************************************************************
+
+class Any {
+ //**********************************************************************************
+ /**
+ * Constructor for "Any" class
+ * @param {Object} [parameters={}]
+ * @property {string} [name]
+ * @property {boolean} [optional]
+ */
+ constructor(parameters = {}) {
+ this.name = (0, _pvutils.getParametersValue)(parameters, "name", "");
+ this.optional = (0, _pvutils.getParametersValue)(parameters, "optional", false);
+ }
+ //**********************************************************************************
+}
+exports.Any = Any; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of special ASN.1 schema type Repeated
+//**************************************************************************************
+
+class Repeated {
+ //**********************************************************************************
+ /**
+ * Constructor for "Repeated" class
+ * @param {Object} [parameters={}]
+ * @property {string} [name]
+ * @property {boolean} [optional]
+ */
+ constructor(parameters = {}) {
+ this.name = (0, _pvutils.getParametersValue)(parameters, "name", "");
+ this.optional = (0, _pvutils.getParametersValue)(parameters, "optional", false);
+ this.value = (0, _pvutils.getParametersValue)(parameters, "value", new Any());
+ this.local = (0, _pvutils.getParametersValue)(parameters, "local", false); // Could local or global array to store elements
+ }
+ //**********************************************************************************
+}
+exports.Repeated = Repeated; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of special ASN.1 schema type RawData
+//**************************************************************************************
+/**
+ * @description Special class providing ability to have "toBER/fromBER" for raw ArrayBuffer
+ */
+
+class RawData {
+ //**********************************************************************************
+ /**
+ * Constructor for "Repeated" class
+ * @param {Object} [parameters={}]
+ * @property {string} [name]
+ * @property {boolean} [optional]
+ */
+ constructor(parameters = {}) {
+ this.data = (0, _pvutils.getParametersValue)(parameters, "data", new ArrayBuffer(0));
+ }
+ //**********************************************************************************
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ this.data = inputBuffer.slice(inputOffset, inputLength);
+ return inputOffset + inputLength;
+ }
+ //**********************************************************************************
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+ toBER(sizeOnly = false) {
+ return this.data;
+ }
+ //**********************************************************************************
+}
+exports.RawData = RawData; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Major ASN.1 BER decoding function
+//**************************************************************************************
+/**
+ * Internal library function for decoding ASN.1 BER
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {{offset: number, result: Object}}
+ */
+
+function LocalFromBER(inputBuffer, inputOffset, inputLength) {
+ const incomingOffset = inputOffset; // Need to store initial offset since "inputOffset" is changing in the function
+
+ //region Local function changing a type for ASN.1 classes
+ function localChangeType(inputObject, newType) {
+ if (inputObject instanceof newType) return inputObject;
+
+ const newObject = new newType();
+ newObject.idBlock = inputObject.idBlock;
+ newObject.lenBlock = inputObject.lenBlock;
+ newObject.warnings = inputObject.warnings;
+ //noinspection JSCheckFunctionSignatures
+ newObject.valueBeforeDecode = inputObject.valueBeforeDecode.slice(0);
+
+ return newObject;
+ }
+ //endregion
+
+ //region Create a basic ASN.1 type since we need to return errors and warnings from the function
+ let returnObject = new BaseBlock({}, Object);
+ //endregion
+
+ //region Basic check for parameters
+ if ((0, _pvutils.checkBufferParams)(new LocalBaseBlock(), inputBuffer, inputOffset, inputLength) === false) {
+ returnObject.error = "Wrong input parameters";
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ }
+ //endregion
+
+ //region Getting Uint8Array from ArrayBuffer
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
+ //endregion
+
+ //region Initial checks
+ if (intBuffer.length === 0) {
+ this.error = "Zero buffer length";
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ }
+ //endregion
+
+ //region Decode indentifcation block of ASN.1 BER structure
+ let resultOffset = returnObject.idBlock.fromBER(inputBuffer, inputOffset, inputLength);
+ returnObject.warnings.concat(returnObject.idBlock.warnings);
+ if (resultOffset === -1) {
+ returnObject.error = returnObject.idBlock.error;
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ }
+
+ inputOffset = resultOffset;
+ inputLength -= returnObject.idBlock.blockLength;
+ //endregion
+
+ //region Decode length block of ASN.1 BER structure
+ resultOffset = returnObject.lenBlock.fromBER(inputBuffer, inputOffset, inputLength);
+ returnObject.warnings.concat(returnObject.lenBlock.warnings);
+ if (resultOffset === -1) {
+ returnObject.error = returnObject.lenBlock.error;
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ }
+
+ inputOffset = resultOffset;
+ inputLength -= returnObject.lenBlock.blockLength;
+ //endregion
+
+ //region Check for usign indefinite length form in encoding for primitive types
+ if (returnObject.idBlock.isConstructed === false && returnObject.lenBlock.isIndefiniteForm === true) {
+ returnObject.error = "Indefinite length form used for primitive encoding form";
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ }
+ //endregion
+
+ //region Switch ASN.1 block type
+ let newASN1Type = BaseBlock;
+
+ switch (returnObject.idBlock.tagClass) {
+ //region UNIVERSAL
+ case 1:
+ //region Check for reserved tag numbers
+ if (returnObject.idBlock.tagNumber >= 37 && returnObject.idBlock.isHexOnly === false) {
+ returnObject.error = "UNIVERSAL 37 and upper tags are reserved by ASN.1 standard";
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ }
+ //endregion
+
+ switch (returnObject.idBlock.tagNumber) {
+ //region EndOfContent type
+ case 0:
+ //region Check for EndOfContent type
+ if (returnObject.idBlock.isConstructed === true && returnObject.lenBlock.length > 0) {
+ returnObject.error = "Type [UNIVERSAL 0] is reserved";
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ }
+ //endregion
+
+ newASN1Type = EndOfContent;
+
+ break;
+ //endregion
+ //region Boolean type
+ case 1:
+ newASN1Type = Boolean;
+ break;
+ //endregion
+ //region Integer type
+ case 2:
+ newASN1Type = Integer;
+ break;
+ //endregion
+ //region BitString type
+ case 3:
+ newASN1Type = BitString;
+ break;
+ //endregion
+ //region OctetString type
+ case 4:
+ newASN1Type = OctetString;
+ break;
+ //endregion
+ //region Null type
+ case 5:
+ newASN1Type = Null;
+ break;
+ //endregion
+ //region OBJECT IDENTIFIER type
+ case 6:
+ newASN1Type = ObjectIdentifier;
+ break;
+ //endregion
+ //region Enumerated type
+ case 10:
+ newASN1Type = Enumerated;
+ break;
+ //endregion
+ //region Utf8String type
+ case 12:
+ newASN1Type = Utf8String;
+ break;
+ //endregion
+ //region Time type
+ case 14:
+ newASN1Type = TIME;
+ break;
+ //endregion
+ //region ASN.1 reserved type
+ case 15:
+ returnObject.error = "[UNIVERSAL 15] is reserved by ASN.1 standard";
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ //endregion
+ //region Sequence type
+ case 16:
+ newASN1Type = Sequence;
+ break;
+ //endregion
+ //region Set type
+ case 17:
+ newASN1Type = Set;
+ break;
+ //endregion
+ //region NumericString type
+ case 18:
+ newASN1Type = NumericString;
+ break;
+ //endregion
+ //region PrintableString type
+ case 19:
+ newASN1Type = PrintableString;
+ break;
+ //endregion
+ //region TeletexString type
+ case 20:
+ newASN1Type = TeletexString;
+ break;
+ //endregion
+ //region VideotexString type
+ case 21:
+ newASN1Type = VideotexString;
+ break;
+ //endregion
+ //region IA5String type
+ case 22:
+ newASN1Type = IA5String;
+ break;
+ //endregion
+ //region UTCTime type
+ case 23:
+ newASN1Type = UTCTime;
+ break;
+ //endregion
+ //region GeneralizedTime type
+ case 24:
+ newASN1Type = GeneralizedTime;
+ break;
+ //endregion
+ //region GraphicString type
+ case 25:
+ newASN1Type = GraphicString;
+ break;
+ //endregion
+ //region VisibleString type
+ case 26:
+ newASN1Type = VisibleString;
+ break;
+ //endregion
+ //region GeneralString type
+ case 27:
+ newASN1Type = GeneralString;
+ break;
+ //endregion
+ //region UniversalString type
+ case 28:
+ newASN1Type = UniversalString;
+ break;
+ //endregion
+ //region CharacterString type
+ case 29:
+ newASN1Type = CharacterString;
+ break;
+ //endregion
+ //region BmpString type
+ case 30:
+ newASN1Type = BmpString;
+ break;
+ //endregion
+ //region DATE type
+ case 31:
+ newASN1Type = DATE;
+ break;
+ //endregion
+ //region TimeOfDay type
+ case 32:
+ newASN1Type = TimeOfDay;
+ break;
+ //endregion
+ //region Date-Time type
+ case 33:
+ newASN1Type = DateTime;
+ break;
+ //endregion
+ //region Duration type
+ case 34:
+ newASN1Type = Duration;
+ break;
+ //endregion
+ //region default
+ default:
+ {
+ let newObject;
+
+ if (returnObject.idBlock.isConstructed === true) newObject = new Constructed();else newObject = new Primitive();
+
+ newObject.idBlock = returnObject.idBlock;
+ newObject.lenBlock = returnObject.lenBlock;
+ newObject.warnings = returnObject.warnings;
+
+ returnObject = newObject;
+
+ resultOffset = returnObject.fromBER(inputBuffer, inputOffset, inputLength);
+ }
+ //endregion
+ }
+ break;
+ //endregion
+ //region All other tag classes
+ case 2: // APPLICATION
+ case 3: // CONTEXT-SPECIFIC
+ case 4: // PRIVATE
+ default:
+ {
+ if (returnObject.idBlock.isConstructed === true) newASN1Type = Constructed;else newASN1Type = Primitive;
+ }
+ //endregion
+ }
+ //endregion
+
+ //region Change type and perform BER decoding
+ returnObject = localChangeType(returnObject, newASN1Type);
+ resultOffset = returnObject.fromBER(inputBuffer, inputOffset, returnObject.lenBlock.isIndefiniteForm === true ? inputLength : returnObject.lenBlock.length);
+ //endregion
+
+ //region Coping incoming buffer for entire ASN.1 block
+ returnObject.valueBeforeDecode = inputBuffer.slice(incomingOffset, incomingOffset + returnObject.blockLength);
+ //endregion
+
+ return {
+ offset: resultOffset,
+ result: returnObject
+ };
+}
+//**************************************************************************************
+/**
+ * Major function for decoding ASN.1 BER array into internal library structuries
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array of bytes
+ */
+function fromBER(inputBuffer) {
+ if (inputBuffer.byteLength === 0) {
+ const result = new BaseBlock({}, Object);
+ result.error = "Input buffer has zero length";
+
+ return {
+ offset: -1,
+ result
+ };
+ }
+
+ return LocalFromBER(inputBuffer, 0, inputBuffer.byteLength);
+}
+//**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Major scheme verification function
+//**************************************************************************************
+/**
+ * Compare of two ASN.1 object trees
+ * @param {!Object} root Root of input ASN.1 object tree
+ * @param {!Object} inputData Input ASN.1 object tree
+ * @param {!Object} inputSchema Input ASN.1 schema to compare with
+ * @return {{verified: boolean}|{verified:boolean, result: Object}}
+ */
+function compareSchema(root, inputData, inputSchema) {
+ //region Special case for Choice schema element type
+ if (inputSchema instanceof Choice) {
+ const choiceResult = false;
+
+ for (let j = 0; j < inputSchema.value.length; j++) {
+ const result = compareSchema(root, inputData, inputSchema.value[j]);
+ if (result.verified === true) {
+ return {
+ verified: true,
+ result: root
+ };
+ }
+ }
+
+ if (choiceResult === false) {
+ const _result = {
+ verified: false,
+ result: {
+ error: "Wrong values for Choice type"
+ }
+ };
+
+ if (inputSchema.hasOwnProperty("name")) _result.name = inputSchema.name;
+
+ return _result;
+ }
+ }
+ //endregion
+
+ //region Special case for Any schema element type
+ if (inputSchema instanceof Any) {
+ //region Add named component of ASN.1 schema
+ if (inputSchema.hasOwnProperty("name")) root[inputSchema.name] = inputData;
+ //endregion
+
+ return {
+ verified: true,
+ result: root
+ };
+ }
+ //endregion
+
+ //region Initial check
+ if (root instanceof Object === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong root object" }
+ };
+ }
+
+ if (inputData instanceof Object === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 data" }
+ };
+ }
+
+ if (inputSchema instanceof Object === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+
+ if ("idBlock" in inputSchema === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+ //endregion
+
+ //region Comparing idBlock properties in ASN.1 data and ASN.1 schema
+ //region Encode and decode ASN.1 schema idBlock
+ /// <remarks>This encoding/decoding is neccessary because could be an errors in schema definition</remarks>
+ if ("fromBER" in inputSchema.idBlock === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+
+ if ("toBER" in inputSchema.idBlock === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+
+ const encodedId = inputSchema.idBlock.toBER(false);
+ if (encodedId.byteLength === 0) {
+ return {
+ verified: false,
+ result: { error: "Error encoding idBlock for ASN.1 schema" }
+ };
+ }
+
+ const decodedOffset = inputSchema.idBlock.fromBER(encodedId, 0, encodedId.byteLength);
+ if (decodedOffset === -1) {
+ return {
+ verified: false,
+ result: { error: "Error decoding idBlock for ASN.1 schema" }
+ };
+ }
+ //endregion
+
+ //region tagClass
+ if (inputSchema.idBlock.hasOwnProperty("tagClass") === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+
+ if (inputSchema.idBlock.tagClass !== inputData.idBlock.tagClass) {
+ return {
+ verified: false,
+ result: root
+ };
+ }
+ //endregion
+ //region tagNumber
+ if (inputSchema.idBlock.hasOwnProperty("tagNumber") === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+
+ if (inputSchema.idBlock.tagNumber !== inputData.idBlock.tagNumber) {
+ return {
+ verified: false,
+ result: root
+ };
+ }
+ //endregion
+ //region isConstructed
+ if (inputSchema.idBlock.hasOwnProperty("isConstructed") === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+
+ if (inputSchema.idBlock.isConstructed !== inputData.idBlock.isConstructed) {
+ return {
+ verified: false,
+ result: root
+ };
+ }
+ //endregion
+ //region isHexOnly
+ if ("isHexOnly" in inputSchema.idBlock === false) // Since 'isHexOnly' is an inhirited property
+ {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+
+ if (inputSchema.idBlock.isHexOnly !== inputData.idBlock.isHexOnly) {
+ return {
+ verified: false,
+ result: root
+ };
+ }
+ //endregion
+ //region valueHex
+ if (inputSchema.idBlock.isHexOnly === true) {
+ if ("valueHex" in inputSchema.idBlock === false) // Since 'valueHex' is an inhirited property
+ {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+
+ const schemaView = new Uint8Array(inputSchema.idBlock.valueHex);
+ const asn1View = new Uint8Array(inputData.idBlock.valueHex);
+
+ if (schemaView.length !== asn1View.length) {
+ return {
+ verified: false,
+ result: root
+ };
+ }
+
+ for (let i = 0; i < schemaView.length; i++) {
+ if (schemaView[i] !== asn1View[1]) {
+ return {
+ verified: false,
+ result: root
+ };
+ }
+ }
+ }
+ //endregion
+ //endregion
+
+ //region Add named component of ASN.1 schema
+ if (inputSchema.hasOwnProperty("name")) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
+ if (inputSchema.name !== "") root[inputSchema.name] = inputData;
+ }
+ //endregion
+
+ //region Getting next ASN.1 block for comparition
+ if (inputSchema.idBlock.isConstructed === true) {
+ let admission = 0;
+ let result = { verified: false };
+
+ let maxLength = inputSchema.valueBlock.value.length;
+
+ if (maxLength > 0) {
+ if (inputSchema.valueBlock.value[0] instanceof Repeated) maxLength = inputData.valueBlock.value.length;
+ }
+
+ //region Special case when constructive value has no elements
+ if (maxLength === 0) {
+ return {
+ verified: true,
+ result: root
+ };
+ }
+ //endregion
+
+ //region Special case when "inputData" has no values and "inputSchema" has all optional values
+ if (inputData.valueBlock.value.length === 0 && inputSchema.valueBlock.value.length !== 0) {
+ let _optional = true;
+
+ for (let i = 0; i < inputSchema.valueBlock.value.length; i++) _optional = _optional && (inputSchema.valueBlock.value[i].optional || false);
+
+ if (_optional === true) {
+ return {
+ verified: true,
+ result: root
+ };
+ }
+
+ //region Delete early added name of block
+ if (inputSchema.hasOwnProperty("name")) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
+ if (inputSchema.name !== "") delete root[inputSchema.name];
+ }
+ //endregion
+
+ root.error = "Inconsistent object length";
+
+ return {
+ verified: false,
+ result: root
+ };
+ }
+ //endregion
+
+ for (let i = 0; i < maxLength; i++) {
+ //region Special case when there is an "optional" element of ASN.1 schema at the end
+ if (i - admission >= inputData.valueBlock.value.length) {
+ if (inputSchema.valueBlock.value[i].optional === false) {
+ const _result = {
+ verified: false,
+ result: root
+ };
+
+ root.error = "Inconsistent length between ASN.1 data and schema";
+
+ //region Delete early added name of block
+ if (inputSchema.hasOwnProperty("name")) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
+ if (inputSchema.name !== "") {
+ delete root[inputSchema.name];
+ _result.name = inputSchema.name;
+ }
+ }
+ //endregion
+
+ return _result;
+ }
+ }
+ //endregion
+ else {
+ //region Special case for Repeated type of ASN.1 schema element
+ if (inputSchema.valueBlock.value[0] instanceof Repeated) {
+ result = compareSchema(root, inputData.valueBlock.value[i], inputSchema.valueBlock.value[0].value);
+ if (result.verified === false) {
+ if (inputSchema.valueBlock.value[0].optional === true) admission++;else {
+ //region Delete early added name of block
+ if (inputSchema.hasOwnProperty("name")) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
+ if (inputSchema.name !== "") delete root[inputSchema.name];
+ }
+ //endregion
+
+ return result;
+ }
+ }
+
+ if ("name" in inputSchema.valueBlock.value[0] && inputSchema.valueBlock.value[0].name.length > 0) {
+ let arrayRoot = {};
+
+ if ("local" in inputSchema.valueBlock.value[0] && inputSchema.valueBlock.value[0].local === true) arrayRoot = inputData;else arrayRoot = root;
+
+ if (typeof arrayRoot[inputSchema.valueBlock.value[0].name] === "undefined") arrayRoot[inputSchema.valueBlock.value[0].name] = [];
+
+ arrayRoot[inputSchema.valueBlock.value[0].name].push(inputData.valueBlock.value[i]);
+ }
+ }
+ //endregion
+ else {
+ result = compareSchema(root, inputData.valueBlock.value[i - admission], inputSchema.valueBlock.value[i]);
+ if (result.verified === false) {
+ if (inputSchema.valueBlock.value[i].optional === true) admission++;else {
+ //region Delete early added name of block
+ if (inputSchema.hasOwnProperty("name")) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
+ if (inputSchema.name !== "") delete root[inputSchema.name];
+ }
+ //endregion
+
+ return result;
+ }
+ }
+ }
+ }
+ }
+
+ if (result.verified === false) // The situation may take place if last element is "optional" and verification failed
+ {
+ const _result = {
+ verified: false,
+ result: root
+ };
+
+ //region Delete early added name of block
+ if (inputSchema.hasOwnProperty("name")) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
+ if (inputSchema.name !== "") {
+ delete root[inputSchema.name];
+ _result.name = inputSchema.name;
+ }
+ }
+ //endregion
+
+ return _result;
+ }
+
+ return {
+ verified: true,
+ result: root
+ };
+ }
+ //endregion
+ //region Ability to parse internal value for primitive-encoded value (value of OctetString, for example)
+ if ("primitiveSchema" in inputSchema && "valueHex" in inputData.valueBlock) {
+ //region Decoding of raw ASN.1 data
+ const asn1 = fromBER(inputData.valueBlock.valueHex);
+ if (asn1.offset === -1) {
+ const _result = {
+ verified: false,
+ result: asn1.result
+ };
+
+ //region Delete early added name of block
+ if (inputSchema.hasOwnProperty("name")) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
+ if (inputSchema.name !== "") {
+ delete root[inputSchema.name];
+ _result.name = inputSchema.name;
+ }
+ }
+ //endregion
+
+ return _result;
+ }
+ //endregion
+
+ return compareSchema(root, asn1.result, inputSchema.primitiveSchema);
+ }
+
+ return {
+ verified: true,
+ result: root
+ };
+ //endregion
+}
+//**************************************************************************************
+//noinspection JSUnusedGlobalSymbols
+/**
+ * ASN.1 schema verification for ArrayBuffer data
+ * @param {!ArrayBuffer} inputBuffer Input BER-encoded ASN.1 data
+ * @param {!Object} inputSchema Input ASN.1 schema to verify against to
+ * @return {{verified: boolean}|{verified:boolean, result: Object}}
+ */
+function verifySchema(inputBuffer, inputSchema) {
+ //region Initial check
+ if (inputSchema instanceof Object === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema type" }
+ };
+ }
+ //endregion
+
+ //region Decoding of raw ASN.1 data
+ const asn1 = fromBER(inputBuffer);
+ if (asn1.offset === -1) {
+ return {
+ verified: false,
+ result: asn1.result
+ };
+ }
+ //endregion
+
+ //region Compare ASN.1 struct with input schema
+ return compareSchema(asn1.result, asn1.result, inputSchema);
+ //endregion
+}
+//**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Major function converting JSON to ASN.1 objects
+//**************************************************************************************
+//noinspection JSUnusedGlobalSymbols
+/**
+ * Converting from JSON to ASN.1 objects
+ * @param {string|Object} json JSON string or object to convert to ASN.1 objects
+ */
+function fromJSON(json) {}
+// TODO Implement
+
+//**************************************************************************************
+//endregion
+//**************************************************************************************
+
+},{"pvutils":3}],3:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.getUTCDate = getUTCDate;
+exports.getParametersValue = getParametersValue;
+exports.bufferToHexCodes = bufferToHexCodes;
+exports.checkBufferParams = checkBufferParams;
+exports.utilFromBase = utilFromBase;
+exports.utilToBase = utilToBase;
+exports.utilConcatBuf = utilConcatBuf;
+exports.utilConcatView = utilConcatView;
+exports.utilDecodeTC = utilDecodeTC;
+exports.utilEncodeTC = utilEncodeTC;
+exports.isEqualBuffer = isEqualBuffer;
+exports.padNumber = padNumber;
+exports.toBase64 = toBase64;
+exports.fromBase64 = fromBase64;
+exports.arrayBufferToString = arrayBufferToString;
+exports.stringToArrayBuffer = stringToArrayBuffer;
+exports.nearestPowerOf2 = nearestPowerOf2;
+exports.clearProps = clearProps;
+//**************************************************************************************
+/**
+ * Making UTC date from local date
+ * @param {Date} date Date to convert from
+ * @returns {Date}
+ */
+function getUTCDate(date) {
+ // noinspection NestedFunctionCallJS, MagicNumberJS
+ return new Date(date.getTime() + date.getTimezoneOffset() * 60000);
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleReturnPointsJS
+/**
+ * Get value for input parameters, or set a default value
+ * @param {Object} parameters
+ * @param {string} name
+ * @param defaultValue
+ */
+function getParametersValue(parameters, name, defaultValue) {
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS
+ if (parameters instanceof Object === false) return defaultValue;
+
+ // noinspection NonBlockStatementBodyJS
+ if (name in parameters) return parameters[name];
+
+ return defaultValue;
+}
+//**************************************************************************************
+/**
+ * Converts "ArrayBuffer" into a hexdecimal string
+ * @param {ArrayBuffer} inputBuffer
+ * @param {number} [inputOffset=0]
+ * @param {number} [inputLength=inputBuffer.byteLength]
+ * @param {boolean} [insertSpace=false]
+ * @returns {string}
+ */
+function bufferToHexCodes(inputBuffer, inputOffset = 0, inputLength = inputBuffer.byteLength - inputOffset, insertSpace = false) {
+ let result = "";
+
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = new Uint8Array(inputBuffer, inputOffset, inputLength)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ const item = _step.value;
+
+ // noinspection ChainedFunctionCallJS
+ const str = item.toString(16).toUpperCase();
+
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS
+ if (str.length === 1) result += "0";
+
+ result += str;
+
+ // noinspection NonBlockStatementBodyJS
+ if (insertSpace) result += " ";
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+
+ return result.trim();
+}
+//**************************************************************************************
+// noinspection JSValidateJSDoc, FunctionWithMultipleReturnPointsJS
+/**
+ * Check input "ArrayBuffer" for common functions
+ * @param {LocalBaseBlock} baseBlock
+ * @param {ArrayBuffer} inputBuffer
+ * @param {number} inputOffset
+ * @param {number} inputLength
+ * @returns {boolean}
+ */
+function checkBufferParams(baseBlock, inputBuffer, inputOffset, inputLength) {
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (inputBuffer instanceof ArrayBuffer === false) {
+ // noinspection JSUndefinedPropertyAssignment
+ baseBlock.error = "Wrong parameter: inputBuffer must be \"ArrayBuffer\"";
+ return false;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (inputBuffer.byteLength === 0) {
+ // noinspection JSUndefinedPropertyAssignment
+ baseBlock.error = "Wrong parameter: inputBuffer has zero length";
+ return false;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (inputOffset < 0) {
+ // noinspection JSUndefinedPropertyAssignment
+ baseBlock.error = "Wrong parameter: inputOffset less than zero";
+ return false;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (inputLength < 0) {
+ // noinspection JSUndefinedPropertyAssignment
+ baseBlock.error = "Wrong parameter: inputLength less than zero";
+ return false;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (inputBuffer.byteLength - inputOffset - inputLength < 0) {
+ // noinspection JSUndefinedPropertyAssignment
+ baseBlock.error = "End of input reached before message was fully decoded (inconsistent offset and length values)";
+ return false;
+ }
+
+ return true;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleReturnPointsJS
+/**
+ * Convert number from 2^base to 2^10
+ * @param {Uint8Array} inputBuffer
+ * @param {number} inputBase
+ * @returns {number}
+ */
+function utilFromBase(inputBuffer, inputBase) {
+ let result = 0;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS
+ if (inputBuffer.length === 1) return inputBuffer[0];
+
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS
+ for (let i = inputBuffer.length - 1; i >= 0; i--) result += inputBuffer[inputBuffer.length - 1 - i] * Math.pow(2, inputBase * i);
+
+ return result;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS, FunctionWithMultipleReturnPointsJS
+/**
+ * Convert number from 2^10 to 2^base
+ * @param {!number} value The number to convert
+ * @param {!number} base The base for 2^base
+ * @param {number} [reserved=0] Pre-defined number of bytes in output array (-1 = limited by function itself)
+ * @returns {ArrayBuffer}
+ */
+function utilToBase(value, base, reserved = -1) {
+ const internalReserved = reserved;
+ let internalValue = value;
+
+ let result = 0;
+ let biggest = Math.pow(2, base);
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ for (let i = 1; i < 8; i++) {
+ if (value < biggest) {
+ let retBuf;
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (internalReserved < 0) {
+ retBuf = new ArrayBuffer(i);
+ result = i;
+ } else {
+ // noinspection NonBlockStatementBodyJS
+ if (internalReserved < i) return new ArrayBuffer(0);
+
+ retBuf = new ArrayBuffer(internalReserved);
+
+ result = internalReserved;
+ }
+
+ const retView = new Uint8Array(retBuf);
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ for (let j = i - 1; j >= 0; j--) {
+ const basis = Math.pow(2, j * base);
+
+ retView[result - j - 1] = Math.floor(internalValue / basis);
+ internalValue -= retView[result - j - 1] * basis;
+ }
+
+ return retBuf;
+ }
+
+ biggest *= Math.pow(2, base);
+ }
+
+ return new ArrayBuffer(0);
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS
+/**
+ * Concatenate two ArrayBuffers
+ * @param {...ArrayBuffer} buffers Set of ArrayBuffer
+ */
+function utilConcatBuf(...buffers) {
+ //region Initial variables
+ let outputLength = 0;
+ let prevLength = 0;
+ //endregion
+
+ //region Calculate output length
+
+ // noinspection NonBlockStatementBodyJS
+ var _iteratorNormalCompletion2 = true;
+ var _didIteratorError2 = false;
+ var _iteratorError2 = undefined;
+
+ try {
+ for (var _iterator2 = buffers[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+ const buffer = _step2.value;
+
+ outputLength += buffer.byteLength;
+ } //endregion
+ } catch (err) {
+ _didIteratorError2 = true;
+ _iteratorError2 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion2 && _iterator2.return) {
+ _iterator2.return();
+ }
+ } finally {
+ if (_didIteratorError2) {
+ throw _iteratorError2;
+ }
+ }
+ }
+
+ const retBuf = new ArrayBuffer(outputLength);
+ const retView = new Uint8Array(retBuf);
+
+ var _iteratorNormalCompletion3 = true;
+ var _didIteratorError3 = false;
+ var _iteratorError3 = undefined;
+
+ try {
+ for (var _iterator3 = buffers[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
+ const buffer = _step3.value;
+
+ // noinspection NestedFunctionCallJS
+ retView.set(new Uint8Array(buffer), prevLength);
+ prevLength += buffer.byteLength;
+ }
+ } catch (err) {
+ _didIteratorError3 = true;
+ _iteratorError3 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion3 && _iterator3.return) {
+ _iterator3.return();
+ }
+ } finally {
+ if (_didIteratorError3) {
+ throw _iteratorError3;
+ }
+ }
+ }
+
+ return retBuf;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS
+/**
+ * Concatenate two Uint8Array
+ * @param {...Uint8Array} views Set of Uint8Array
+ */
+function utilConcatView(...views) {
+ //region Initial variables
+ let outputLength = 0;
+ let prevLength = 0;
+ //endregion
+
+ //region Calculate output length
+ // noinspection NonBlockStatementBodyJS
+ var _iteratorNormalCompletion4 = true;
+ var _didIteratorError4 = false;
+ var _iteratorError4 = undefined;
+
+ try {
+ for (var _iterator4 = views[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
+ const view = _step4.value;
+
+ outputLength += view.length;
+ } //endregion
+ } catch (err) {
+ _didIteratorError4 = true;
+ _iteratorError4 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion4 && _iterator4.return) {
+ _iterator4.return();
+ }
+ } finally {
+ if (_didIteratorError4) {
+ throw _iteratorError4;
+ }
+ }
+ }
+
+ const retBuf = new ArrayBuffer(outputLength);
+ const retView = new Uint8Array(retBuf);
+
+ var _iteratorNormalCompletion5 = true;
+ var _didIteratorError5 = false;
+ var _iteratorError5 = undefined;
+
+ try {
+ for (var _iterator5 = views[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
+ const view = _step5.value;
+
+ retView.set(view, prevLength);
+ prevLength += view.length;
+ }
+ } catch (err) {
+ _didIteratorError5 = true;
+ _iteratorError5 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion5 && _iterator5.return) {
+ _iterator5.return();
+ }
+ } finally {
+ if (_didIteratorError5) {
+ throw _iteratorError5;
+ }
+ }
+ }
+
+ return retView;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS
+/**
+ * Decoding of "two complement" values
+ * The function must be called in scope of instance of "hexBlock" class ("valueHex" and "warnings" properties must be present)
+ * @returns {number}
+ */
+function utilDecodeTC() {
+ const buf = new Uint8Array(this.valueHex);
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (this.valueHex.byteLength >= 2) {
+ //noinspection JSBitwiseOperatorUsage, ConstantOnRightSideOfComparisonJS, LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const condition1 = buf[0] === 0xFF && buf[1] & 0x80;
+ // noinspection ConstantOnRightSideOfComparisonJS, LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const condition2 = buf[0] === 0x00 && (buf[1] & 0x80) === 0x00;
+
+ // noinspection NonBlockStatementBodyJS
+ if (condition1 || condition2) this.warnings.push("Needlessly long format");
+ }
+
+ //region Create big part of the integer
+ const bigIntBuffer = new ArrayBuffer(this.valueHex.byteLength);
+ const bigIntView = new Uint8Array(bigIntBuffer);
+ // noinspection NonBlockStatementBodyJS
+ for (let i = 0; i < this.valueHex.byteLength; i++) bigIntView[i] = 0;
+
+ // noinspection MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ bigIntView[0] = buf[0] & 0x80; // mask only the biggest bit
+
+ const bigInt = utilFromBase(bigIntView, 8);
+ //endregion
+
+ //region Create small part of the integer
+ const smallIntBuffer = new ArrayBuffer(this.valueHex.byteLength);
+ const smallIntView = new Uint8Array(smallIntBuffer);
+ // noinspection NonBlockStatementBodyJS
+ for (let j = 0; j < this.valueHex.byteLength; j++) smallIntView[j] = buf[j];
+
+ // noinspection MagicNumberJS
+ smallIntView[0] &= 0x7F; // mask biggest bit
+
+ const smallInt = utilFromBase(smallIntView, 8);
+ //endregion
+
+ return smallInt - bigInt;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS, FunctionWithMultipleReturnPointsJS
+/**
+ * Encode integer value to "two complement" format
+ * @param {number} value Value to encode
+ * @returns {ArrayBuffer}
+ */
+function utilEncodeTC(value) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConditionalExpressionJS
+ const modValue = value < 0 ? value * -1 : value;
+ let bigInt = 128;
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ for (let i = 1; i < 8; i++) {
+ if (modValue <= bigInt) {
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (value < 0) {
+ const smallInt = bigInt - modValue;
+
+ const retBuf = utilToBase(smallInt, 8, i);
+ const retView = new Uint8Array(retBuf);
+
+ // noinspection MagicNumberJS
+ retView[0] |= 0x80;
+
+ return retBuf;
+ }
+
+ let retBuf = utilToBase(modValue, 8, i);
+ let retView = new Uint8Array(retBuf);
+
+ //noinspection JSBitwiseOperatorUsage, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ if (retView[0] & 0x80) {
+ //noinspection JSCheckFunctionSignatures
+ const tempBuf = retBuf.slice(0);
+ const tempView = new Uint8Array(tempBuf);
+
+ retBuf = new ArrayBuffer(retBuf.byteLength + 1);
+ // noinspection ReuseOfLocalVariableJS
+ retView = new Uint8Array(retBuf);
+
+ // noinspection NonBlockStatementBodyJS
+ for (let k = 0; k < tempBuf.byteLength; k++) retView[k + 1] = tempView[k];
+
+ // noinspection MagicNumberJS
+ retView[0] = 0x00;
+ }
+
+ return retBuf;
+ }
+
+ bigInt *= Math.pow(2, 8);
+ }
+
+ return new ArrayBuffer(0);
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleReturnPointsJS, ParameterNamingConventionJS
+/**
+ * Compare two array buffers
+ * @param {!ArrayBuffer} inputBuffer1
+ * @param {!ArrayBuffer} inputBuffer2
+ * @returns {boolean}
+ */
+function isEqualBuffer(inputBuffer1, inputBuffer2) {
+ // noinspection NonBlockStatementBodyJS
+ if (inputBuffer1.byteLength !== inputBuffer2.byteLength) return false;
+
+ // noinspection LocalVariableNamingConventionJS
+ const view1 = new Uint8Array(inputBuffer1);
+ // noinspection LocalVariableNamingConventionJS
+ const view2 = new Uint8Array(inputBuffer2);
+
+ for (let i = 0; i < view1.length; i++) {
+ // noinspection NonBlockStatementBodyJS
+ if (view1[i] !== view2[i]) return false;
+ }
+
+ return true;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleReturnPointsJS
+/**
+ * Pad input number with leade "0" if needed
+ * @returns {string}
+ * @param {number} inputNumber
+ * @param {number} fullLength
+ */
+function padNumber(inputNumber, fullLength) {
+ const str = inputNumber.toString(10);
+
+ // noinspection NonBlockStatementBodyJS
+ if (fullLength < str.length) return "";
+
+ const dif = fullLength - str.length;
+
+ const padding = new Array(dif);
+ // noinspection NonBlockStatementBodyJS
+ for (let i = 0; i < dif; i++) padding[i] = "0";
+
+ const paddingString = padding.join("");
+
+ return paddingString.concat(str);
+}
+//**************************************************************************************
+const base64Template = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+const base64UrlTemplate = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=";
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS, OverlyComplexFunctionJS, FunctionTooLongJS, FunctionNamingConventionJS
+/**
+ * Encode string into BASE64 (or "base64url")
+ * @param {string} input
+ * @param {boolean} useUrlTemplate If "true" then output would be encoded using "base64url"
+ * @param {boolean} skipPadding Skip BASE-64 padding or not
+ * @param {boolean} skipLeadingZeros Skip leading zeros in input data or not
+ * @returns {string}
+ */
+function toBase64(input, useUrlTemplate = false, skipPadding = false, skipLeadingZeros = false) {
+ let i = 0;
+
+ // noinspection LocalVariableNamingConventionJS
+ let flag1 = 0;
+ // noinspection LocalVariableNamingConventionJS
+ let flag2 = 0;
+
+ let output = "";
+
+ // noinspection ConditionalExpressionJS
+ const template = useUrlTemplate ? base64UrlTemplate : base64Template;
+
+ if (skipLeadingZeros) {
+ let nonZeroPosition = 0;
+
+ for (let i = 0; i < input.length; i++) {
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (input.charCodeAt(i) !== 0) {
+ nonZeroPosition = i;
+ // noinspection BreakStatementJS
+ break;
+ }
+ }
+
+ // noinspection AssignmentToFunctionParameterJS
+ input = input.slice(nonZeroPosition);
+ }
+
+ while (i < input.length) {
+ // noinspection LocalVariableNamingConventionJS, IncrementDecrementResultUsedJS
+ const chr1 = input.charCodeAt(i++);
+ // noinspection NonBlockStatementBodyJS
+ if (i >= input.length) flag1 = 1;
+ // noinspection LocalVariableNamingConventionJS, IncrementDecrementResultUsedJS
+ const chr2 = input.charCodeAt(i++);
+ // noinspection NonBlockStatementBodyJS
+ if (i >= input.length) flag2 = 1;
+ // noinspection LocalVariableNamingConventionJS, IncrementDecrementResultUsedJS
+ const chr3 = input.charCodeAt(i++);
+
+ // noinspection LocalVariableNamingConventionJS
+ const enc1 = chr1 >> 2;
+ // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const enc2 = (chr1 & 0x03) << 4 | chr2 >> 4;
+ // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ let enc3 = (chr2 & 0x0F) << 2 | chr3 >> 6;
+ // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ let enc4 = chr3 & 0x3F;
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (flag1 === 1) {
+ // noinspection NestedAssignmentJS, AssignmentResultUsedJS, MagicNumberJS
+ enc3 = enc4 = 64;
+ } else {
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (flag2 === 1) {
+ // noinspection MagicNumberJS
+ enc4 = 64;
+ }
+ }
+
+ // noinspection NonBlockStatementBodyJS
+ if (skipPadding) {
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS, MagicNumberJS
+ if (enc3 === 64) output += `${template.charAt(enc1)}${template.charAt(enc2)}`;else {
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS, MagicNumberJS
+ if (enc4 === 64) output += `${template.charAt(enc1)}${template.charAt(enc2)}${template.charAt(enc3)}`;else output += `${template.charAt(enc1)}${template.charAt(enc2)}${template.charAt(enc3)}${template.charAt(enc4)}`;
+ }
+ } else output += `${template.charAt(enc1)}${template.charAt(enc2)}${template.charAt(enc3)}${template.charAt(enc4)}`;
+ }
+
+ return output;
+}
+//**************************************************************************************
+// noinspection FunctionWithMoreThanThreeNegationsJS, FunctionWithMultipleLoopsJS, OverlyComplexFunctionJS, FunctionNamingConventionJS
+/**
+ * Decode string from BASE64 (or "base64url")
+ * @param {string} input
+ * @param {boolean} [useUrlTemplate=false] If "true" then output would be encoded using "base64url"
+ * @param {boolean} [cutTailZeros=false] If "true" then cut tailing zeroz from function result
+ * @returns {string}
+ */
+function fromBase64(input, useUrlTemplate = false, cutTailZeros = false) {
+ // noinspection ConditionalExpressionJS
+ const template = useUrlTemplate ? base64UrlTemplate : base64Template;
+
+ //region Aux functions
+ // noinspection FunctionWithMultipleReturnPointsJS, NestedFunctionJS
+ function indexof(toSearch) {
+ // noinspection ConstantOnRightSideOfComparisonJS, MagicNumberJS
+ for (let i = 0; i < 64; i++) {
+ // noinspection NonBlockStatementBodyJS
+ if (template.charAt(i) === toSearch) return i;
+ }
+
+ // noinspection MagicNumberJS
+ return 64;
+ }
+
+ // noinspection NestedFunctionJS
+ function test(incoming) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConditionalExpressionJS, MagicNumberJS
+ return incoming === 64 ? 0x00 : incoming;
+ }
+ //endregion
+
+ let i = 0;
+
+ let output = "";
+
+ while (i < input.length) {
+ // noinspection NestedFunctionCallJS, LocalVariableNamingConventionJS, IncrementDecrementResultUsedJS
+ const enc1 = indexof(input.charAt(i++));
+ // noinspection NestedFunctionCallJS, LocalVariableNamingConventionJS, ConditionalExpressionJS, MagicNumberJS, IncrementDecrementResultUsedJS
+ const enc2 = i >= input.length ? 0x00 : indexof(input.charAt(i++));
+ // noinspection NestedFunctionCallJS, LocalVariableNamingConventionJS, ConditionalExpressionJS, MagicNumberJS, IncrementDecrementResultUsedJS
+ const enc3 = i >= input.length ? 0x00 : indexof(input.charAt(i++));
+ // noinspection NestedFunctionCallJS, LocalVariableNamingConventionJS, ConditionalExpressionJS, MagicNumberJS, IncrementDecrementResultUsedJS
+ const enc4 = i >= input.length ? 0x00 : indexof(input.charAt(i++));
+
+ // noinspection LocalVariableNamingConventionJS, NonShortCircuitBooleanExpressionJS
+ const chr1 = test(enc1) << 2 | test(enc2) >> 4;
+ // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const chr2 = (test(enc2) & 0x0F) << 4 | test(enc3) >> 2;
+ // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const chr3 = (test(enc3) & 0x03) << 6 | test(enc4);
+
+ output += String.fromCharCode(chr1);
+
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS, MagicNumberJS
+ if (enc3 !== 64) output += String.fromCharCode(chr2);
+
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS, MagicNumberJS
+ if (enc4 !== 64) output += String.fromCharCode(chr3);
+ }
+
+ if (cutTailZeros) {
+ const outputLength = output.length;
+ let nonZeroStart = -1;
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ for (let i = outputLength - 1; i >= 0; i--) {
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (output.charCodeAt(i) !== 0) {
+ nonZeroStart = i;
+ // noinspection BreakStatementJS
+ break;
+ }
+ }
+
+ // noinspection NonBlockStatementBodyJS, NegatedIfStatementJS
+ if (nonZeroStart !== -1) output = output.slice(0, nonZeroStart + 1);else output = "";
+ }
+
+ return output;
+}
+//**************************************************************************************
+function arrayBufferToString(buffer) {
+ let resultString = "";
+ const view = new Uint8Array(buffer);
+
+ // noinspection NonBlockStatementBodyJS
+ var _iteratorNormalCompletion6 = true;
+ var _didIteratorError6 = false;
+ var _iteratorError6 = undefined;
+
+ try {
+ for (var _iterator6 = view[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
+ const element = _step6.value;
+
+ resultString += String.fromCharCode(element);
+ }
+ } catch (err) {
+ _didIteratorError6 = true;
+ _iteratorError6 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion6 && _iterator6.return) {
+ _iterator6.return();
+ }
+ } finally {
+ if (_didIteratorError6) {
+ throw _iteratorError6;
+ }
+ }
+ }
+
+ return resultString;
+}
+//**************************************************************************************
+function stringToArrayBuffer(str) {
+ const stringLength = str.length;
+
+ const resultBuffer = new ArrayBuffer(stringLength);
+ const resultView = new Uint8Array(resultBuffer);
+
+ // noinspection NonBlockStatementBodyJS
+ for (let i = 0; i < stringLength; i++) resultView[i] = str.charCodeAt(i);
+
+ return resultBuffer;
+}
+//**************************************************************************************
+const log2 = Math.log(2);
+//**************************************************************************************
+// noinspection FunctionNamingConventionJS
+/**
+ * Get nearest to input length power of 2
+ * @param {number} length Current length of existing array
+ * @returns {number}
+ */
+function nearestPowerOf2(length) {
+ const base = Math.log(length) / log2;
+
+ const floor = Math.floor(base);
+ const round = Math.round(base);
+
+ // noinspection ConditionalExpressionJS
+ return floor === round ? floor : round;
+}
+//**************************************************************************************
+/**
+ * Delete properties by name from specified object
+ * @param {Object} object Object to delete properties from
+ * @param {Array.<string>} propsArray Array of properties names
+ */
+function clearProps(object, propsArray) {
+ var _iteratorNormalCompletion7 = true;
+ var _didIteratorError7 = false;
+ var _iteratorError7 = undefined;
+
+ try {
+ for (var _iterator7 = propsArray[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
+ const prop = _step7.value;
+
+ delete object[prop];
+ }
+ } catch (err) {
+ _didIteratorError7 = true;
+ _iteratorError7 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion7 && _iterator7.return) {
+ _iterator7.return();
+ }
+ } finally {
+ if (_didIteratorError7) {
+ throw _iteratorError7;
+ }
+ }
+ }
+}
+//**************************************************************************************
+
+},{}]},{},[1])(1)
+});
diff --git a/toolkit/components/certviewer/content/vendor/pkijs_bundle.js b/toolkit/components/certviewer/content/vendor/pkijs_bundle.js
new file mode 100644
index 0000000000..09e4db9932
--- /dev/null
+++ b/toolkit/components/certviewer/content/vendor/pkijs_bundle.js
@@ -0,0 +1,47423 @@
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.pkijs = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.parseByteMap = parseByteMap;
+/*
+ * Copyright (c) 2016-2018, Peculiar Ventures
+ * All rights reserved.
+ *
+ * Author 2016-2018, Yury Strozhevsky <www.strozhevsky.com>.
+ *
+ */
+//**************************************************************************************
+class ByteStream {
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleLoopsJS
+ /**
+ * Constructor for ByteStream class
+ * @param {{[length]: number, [stub]: number, [view]: Uint8Array, [buffer]: ArrayBuffer, [string]: string, [hexstring]: string}} parameters
+ */
+ constructor(parameters = {}) {
+ this.clear();
+
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = Object.keys(parameters)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ const key = _step.value;
+
+ switch (key) {
+ case "length":
+ this.length = parameters.length;
+ break;
+ case "stub":
+ // noinspection NonBlockStatementBodyJS
+ for (let i = 0; i < this._view.length; i++) this._view[i] = parameters.stub;
+ break;
+ case "view":
+ this.fromUint8Array(parameters.view);
+ break;
+ case "buffer":
+ this.fromArrayBuffer(parameters.buffer);
+ break;
+ case "string":
+ this.fromString(parameters.string);
+ break;
+ case "hexstring":
+ this.fromHexString(parameters.hexstring);
+ break;
+ default:
+ }
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+ }
+ //**********************************************************************************
+ /**
+ * Setter for "buffer"
+ * @param {ArrayBuffer} value
+ */
+ set buffer(value) {
+ this._buffer = value.slice(0);
+ this._view = new Uint8Array(this._buffer);
+ }
+ //**********************************************************************************
+ /**
+ * Getter for "buffer"
+ * @returns {ArrayBuffer}
+ */
+ get buffer() {
+ return this._buffer;
+ }
+ //**********************************************************************************
+ /**
+ * Setter for "view"
+ * @param {Uint8Array} value
+ */
+ set view(value) {
+ this._buffer = new ArrayBuffer(value.length);
+ this._view = new Uint8Array(this._buffer);
+
+ this._view.set(value);
+ }
+ //**********************************************************************************
+ /**
+ * Getter for "view"
+ * @returns {Uint8Array}
+ */
+ get view() {
+ return this._view;
+ }
+ //**********************************************************************************
+ /**
+ * Getter for "length"
+ * @returns {number}
+ */
+ get length() {
+ return this._buffer.byteLength;
+ }
+ //**********************************************************************************
+ /**
+ * Setter for "length"
+ * @param {number} value
+ */
+ set length(value) {
+ this._buffer = new ArrayBuffer(value);
+ this._view = new Uint8Array(this._buffer);
+ }
+ //**********************************************************************************
+ /**
+ * Clear existing stream
+ */
+ clear() {
+ this._buffer = new ArrayBuffer(0);
+ this._view = new Uint8Array(this._buffer);
+ }
+ //**********************************************************************************
+ /**
+ * Initialize "Stream" object from existing "ArrayBuffer"
+ * @param {!ArrayBuffer} array The ArrayBuffer to copy from
+ */
+ fromArrayBuffer(array) {
+ this.buffer = array;
+ }
+ //**********************************************************************************
+ // noinspection FunctionNamingConventionJS
+ /**
+ * Initialize "Stream" object from existing "Uint8Array"
+ * @param {!Uint8Array} array The Uint8Array to copy from
+ */
+ fromUint8Array(array) {
+ this._buffer = new ArrayBuffer(array.length);
+ this._view = new Uint8Array(this._buffer);
+
+ this._view.set(array);
+ }
+ //**********************************************************************************
+ /**
+ * Initialize "Stream" object from existing string
+ * @param {string} string The string to initialize from
+ */
+ fromString(string) {
+ const stringLength = string.length;
+
+ this.length = stringLength;
+
+ // noinspection NonBlockStatementBodyJS
+ for (let i = 0; i < stringLength; i++) this.view[i] = string.charCodeAt(i);
+ }
+ //**********************************************************************************
+ /**
+ * Represent "Stream" object content as a string
+ * @param {number} [start] Start position to convert to string
+ * @param {number} [length] Length of array to convert to string
+ * @returns {string}
+ */
+ toString(start = 0, length = this.view.length - start) {
+ //region Initial variables
+ let result = "";
+ //endregion
+
+ //region Check input parameters
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start >= this.view.length || start < 0) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = 0;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length >= this.view.length || length < 0) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.view.length - start;
+ }
+ //endregion
+
+ //region Convert array of bytes to string
+ // noinspection NonBlockStatementBodyJS
+ for (let i = start; i < start + length; i++) result += String.fromCharCode(this.view[i]);
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection FunctionTooLongJS
+ /**
+ * Initialize "Stream" object from existing hexdecimal string
+ * @param {string} hexString String to initialize from
+ */
+ fromHexString(hexString) {
+ //region Initial variables
+ const stringLength = hexString.length;
+
+ this.buffer = new ArrayBuffer(stringLength >> 1);
+ this.view = new Uint8Array(this.buffer);
+
+ const hexMap = new Map();
+
+ // noinspection MagicNumberJS
+ hexMap.set("0", 0x00);
+ // noinspection MagicNumberJS
+ hexMap.set("1", 0x01);
+ // noinspection MagicNumberJS
+ hexMap.set("2", 0x02);
+ // noinspection MagicNumberJS
+ hexMap.set("3", 0x03);
+ // noinspection MagicNumberJS
+ hexMap.set("4", 0x04);
+ // noinspection MagicNumberJS
+ hexMap.set("5", 0x05);
+ // noinspection MagicNumberJS
+ hexMap.set("6", 0x06);
+ // noinspection MagicNumberJS
+ hexMap.set("7", 0x07);
+ // noinspection MagicNumberJS
+ hexMap.set("8", 0x08);
+ // noinspection MagicNumberJS
+ hexMap.set("9", 0x09);
+ // noinspection MagicNumberJS
+ hexMap.set("A", 0x0A);
+ // noinspection MagicNumberJS
+ hexMap.set("a", 0x0A);
+ // noinspection MagicNumberJS
+ hexMap.set("B", 0x0B);
+ // noinspection MagicNumberJS
+ hexMap.set("b", 0x0B);
+ // noinspection MagicNumberJS
+ hexMap.set("C", 0x0C);
+ // noinspection MagicNumberJS
+ hexMap.set("c", 0x0C);
+ // noinspection MagicNumberJS
+ hexMap.set("D", 0x0D);
+ // noinspection MagicNumberJS
+ hexMap.set("d", 0x0D);
+ // noinspection MagicNumberJS
+ hexMap.set("E", 0x0E);
+ // noinspection MagicNumberJS
+ hexMap.set("e", 0x0E);
+ // noinspection MagicNumberJS
+ hexMap.set("F", 0x0F);
+ // noinspection MagicNumberJS
+ hexMap.set("f", 0x0F);
+
+ let j = 0;
+ // noinspection MagicNumberJS
+ let temp = 0x00;
+ //endregion
+
+ //region Convert char-by-char
+ for (let i = 0; i < stringLength; i++) {
+ // noinspection NegatedIfStatementJS
+ if (!(i % 2)) {
+ // noinspection NestedFunctionCallJS
+ temp = hexMap.get(hexString.charAt(i)) << 4;
+ } else {
+ // noinspection NestedFunctionCallJS
+ temp |= hexMap.get(hexString.charAt(i));
+
+ this.view[j] = temp;
+ j++;
+ }
+ }
+ //endregion
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Represent "Stream" object content as a hexdecimal string
+ * @param {number} [start=0] Start position to convert to string
+ * @param {number} [length=(this.view.length - start)] Length of array to convert to string
+ * @returns {string}
+ */
+ toHexString(start = 0, length = this.view.length - start) {
+ //region Initial variables
+ let result = "";
+ //endregion
+
+ //region Check input parameters
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start >= this.view.length || start < 0) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = 0;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length >= this.view.length || length < 0) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.view.length - start;
+ }
+ //endregion
+
+ for (let i = start; i < start + length; i++) {
+ // noinspection ChainedFunctionCallJS
+ const str = this.view[i].toString(16).toUpperCase();
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, ConditionalExpressionJS, EqualityComparisonWithCoercionJS
+ result = result + (str.length == 1 ? "0" : "") + str;
+ }
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleReturnPointsJS
+ /**
+ * Return copy of existing "Stream"
+ * @param {number} [start=0] Start position of the copy
+ * @param {number} [length=this.view.length] Length of the copy
+ * @returns {ByteStream}
+ */
+ copy(start = 0, length = this._buffer.byteLength - start) {
+ //region Check input parameters
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (start === 0 && this._buffer.byteLength === 0) return new ByteStream();
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (start < 0 || start > this._buffer.byteLength - 1) throw new Error(`Wrong start position: ${start}`);
+ //endregion
+
+ const stream = new ByteStream();
+
+ stream._buffer = this._buffer.slice(start, start + length);
+ stream._view = new Uint8Array(stream._buffer);
+
+ return stream;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS
+ /**
+ * Return slice of existing "Stream"
+ * @param {number} [start=0] Start position of the slice
+ * @param {number} [end=this._buffer.byteLength] End position of the slice
+ * @returns {ByteStream}
+ */
+ slice(start = 0, end = this._buffer.byteLength) {
+ //region Check input parameters
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (start === 0 && this._buffer.byteLength === 0) return new ByteStream();
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (start < 0 || start > this._buffer.byteLength - 1) throw new Error(`Wrong start position: ${start}`);
+ //endregion
+
+ const stream = new ByteStream();
+
+ stream._buffer = this._buffer.slice(start, end);
+ stream._view = new Uint8Array(stream._buffer);
+
+ return stream;
+ }
+ //**********************************************************************************
+ /**
+ * Change size of existing "Stream"
+ * @param {!number} size Size for new "Stream"
+ */
+ realloc(size) {
+ //region Initial variables
+ const buffer = new ArrayBuffer(size);
+ const view = new Uint8Array(buffer);
+ //endregion
+
+ //region Create a new ArrayBuffer content
+ // noinspection NonBlockStatementBodyJS
+ if (size > this._view.length) view.set(this._view);else {
+ // noinspection NestedFunctionCallJS
+ view.set(new Uint8Array(this._buffer, 0, size));
+ }
+ //endregion
+
+ //region Initialize "Stream" with new "ArrayBuffer"
+ this._buffer = buffer.slice(0);
+ this._view = new Uint8Array(this._buffer);
+ //endregion
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Append a new "Stream" content to the current "Stream"
+ * @param {ByteStream} stream A new "stream" to append to current "stream"
+ */
+ append(stream) {
+ //region Initial variables
+ const initialSize = this._buffer.byteLength;
+ const streamViewLength = stream._buffer.byteLength;
+
+ const copyView = stream._view.slice();
+ //endregion
+
+ //region Re-allocate current internal buffer
+ this.realloc(initialSize + streamViewLength);
+ //endregion
+
+ //region Copy input stream content to a new place
+ this._view.set(copyView, initialSize);
+ //endregion
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS
+ /**
+ * Insert "Stream" content to the current "Stream" at specific position
+ * @param {ByteStream} stream A new "stream" to insert to current "stream"
+ * @param {number} [start=0] Start position to insert to
+ * @param {number} [length]
+ * @returns {boolean}
+ */
+ insert(stream, start = 0, length = this._buffer.byteLength - start) {
+ //region Initial variables
+ // noinspection NonBlockStatementBodyJS
+ if (start > this._buffer.byteLength - 1) return false;
+
+ if (length > this._buffer.byteLength - start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this._buffer.byteLength - start;
+ }
+ //endregion
+
+ //region Check input variables
+ if (length > stream._buffer.byteLength) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = stream._buffer.byteLength;
+ }
+ //endregion
+
+ //region Update content of the current stream
+ // noinspection NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (length == stream._buffer.byteLength) this._view.set(stream._view, start);else {
+ // noinspection NestedFunctionCallJS
+ this._view.set(stream._view.slice(0, length), start);
+ }
+ //endregion
+
+ return true;
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleReturnPointsJS
+ /**
+ * Check that two "Stream" objects has equal content
+ * @param {ByteStream} stream Stream to compare with
+ * @returns {boolean}
+ */
+ isEqual(stream) {
+ //region Check length of both buffers
+ // noinspection NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (this._buffer.byteLength != stream._buffer.byteLength) return false;
+ //endregion
+
+ //region Compare each byte of both buffers
+ for (let i = 0; i < stream._buffer.byteLength; i++) {
+ // noinspection NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (this.view[i] != stream.view[i]) return false;
+ }
+ //endregion
+
+ return true;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS
+ /**
+ * Check that current "Stream" objects has equal content with input "Uint8Array"
+ * @param {Uint8Array} view View to compare with
+ * @returns {boolean}
+ */
+ isEqualView(view) {
+ //region Check length of both buffers
+ // noinspection NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (view.length != this.view.length) return false;
+ //endregion
+
+ //region Compare each byte of both buffers
+ for (let i = 0; i < view.length; i++) {
+ // noinspection NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (this.view[i] != view[i]) return false;
+ }
+ //endregion
+
+ return true;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleLoopsJS, FunctionWithMultipleReturnPointsJS, OverlyComplexFunctionJS, FunctionTooLongJS
+ /**
+ * Find any byte pattern in "Stream"
+ * @param {ByteStream} pattern Stream having pattern value
+ * @param {?number} [start] Start position to search from
+ * @param {?number} [length] Length of byte block to search at
+ * @param {boolean} [backward] Flag to search in backward order
+ * @returns {number}
+ */
+ findPattern(pattern, start = null, length = null, backward = false) {
+ //region Check input variables
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start == null) {
+ // noinspection AssignmentToFunctionParameterJS, ConditionalExpressionJS
+ start = backward ? this.buffer.byteLength : 0;
+ }
+
+ if (start > this.buffer.byteLength) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = this.buffer.byteLength;
+ }
+
+ if (backward) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = start;
+ }
+
+ if (length > start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = start;
+ }
+ } else {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ if (length > this.buffer.byteLength - start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+ }
+ //endregion
+
+ //region Initial variables
+ const patternLength = pattern.buffer.byteLength;
+ // noinspection NonBlockStatementBodyJS
+ if (patternLength > length) return -1;
+ //endregion
+
+ //region Make a "pre-read" array for pattern
+ const patternArray = [];
+ // noinspection NonBlockStatementBodyJS
+ for (let i = 0; i < patternLength; i++) patternArray.push(pattern.view[i]);
+ //endregion
+
+ //region Search for pattern
+ for (let i = 0; i <= length - patternLength; i++) {
+ let equal = true;
+ // noinspection ConditionalExpressionJS
+ const equalStart = backward ? start - patternLength - i : start + i;
+
+ for (let j = 0; j < patternLength; j++) {
+ // noinspection EqualityComparisonWithCoercionJS
+ if (this.view[j + equalStart] != patternArray[j]) {
+ equal = false;
+ // noinspection BreakStatementJS
+ break;
+ }
+ }
+
+ if (equal) {
+ // noinspection ConditionalExpressionJS
+ return backward ? start - patternLength - i : start + patternLength + i; // Position after the pattern found
+ }
+ }
+ //endregion
+
+ return -1;
+ }
+ //**********************************************************************************
+ // noinspection OverlyComplexFunctionJS
+ /**
+ * Find first position of any pattern from input array
+ * @param {Array.<ByteStream>} patterns Array with patterns which should be found
+ * @param {?number} [start] Start position to search from
+ * @param {?number} [length] Length of byte block to search at
+ * @param {boolean} [backward=false] Flag to search in backward order
+ * @returns {{id: number, position: number}}
+ */
+ findFirstIn(patterns, start = null, length = null, backward = false) {
+ //region Initial variables
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start == null) {
+ // noinspection AssignmentToFunctionParameterJS, ConditionalExpressionJS
+ start = backward ? this.buffer.byteLength : 0;
+ }
+
+ if (start > this.buffer.byteLength) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = this.buffer.byteLength;
+ }
+
+ if (backward) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = start;
+ }
+
+ if (length > start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = start;
+ }
+ } else {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ if (length > this.buffer.byteLength - start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+ }
+
+ // noinspection ConditionalExpressionJS
+ const result = {
+ id: -1,
+ position: backward ? 0 : start + length,
+ length: 0
+ };
+ //endregion
+
+ for (let i = 0; i < patterns.length; i++) {
+ const position = this.findPattern(patterns[i], start, length, backward);
+ // noinspection EqualityComparisonWithCoercionJS
+ if (position != -1) {
+ let valid = false;
+ const patternLength = patterns[i].length;
+
+ if (backward) {
+ // noinspection NonBlockStatementBodyJS
+ if (position - patternLength >= result.position - result.length) valid = true;
+ } else {
+ // noinspection NonBlockStatementBodyJS
+ if (position - patternLength <= result.position - result.length) valid = true;
+ }
+
+ if (valid) {
+ result.position = position;
+ result.id = i;
+ result.length = patternLength;
+ }
+ }
+ }
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleReturnPointsJS
+ /**
+ * Find all positions of any pattern from input array
+ * @param {Array.<ByteStream>} patterns Array with patterns which should be found
+ * @param {?number} [start] Start position to search from
+ * @param {?number} [length] Length of byte block to search at
+ * @returns {Array}
+ */
+ findAllIn(patterns, start = 0, length = this.buffer.byteLength - start) {
+ //region Initial variables
+ const result = [];
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = 0;
+ }
+
+ // noinspection NonBlockStatementBodyJS
+ if (start > this.buffer.byteLength - 1) return result;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ if (length > this.buffer.byteLength - start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ let patternFound = {
+ id: -1,
+ position: start
+ };
+ //endregion
+
+ //region Find all accurences of patterns
+ do {
+ const position = patternFound.position;
+
+ patternFound = this.findFirstIn(patterns, patternFound.position, length);
+
+ // noinspection EqualityComparisonWithCoercionJS
+ if (patternFound.id == -1) {
+ // noinspection BreakStatementJS
+ break;
+ }
+
+ // noinspection AssignmentToFunctionParameterJS
+ length -= patternFound.position - position;
+
+ result.push({
+ id: patternFound.id,
+ position: patternFound.position
+ });
+ } while (true); // eslint-disable-line
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleLoopsJS, FunctionWithMultipleReturnPointsJS
+ /**
+ * Find all positions of a pattern
+ * @param {ByteStream} pattern Stream having pattern value
+ * @param {?number} [start] Start position to search from
+ * @param {?number} [length] Length of byte block to search at
+ * @returns {Array|number} Array with all pattern positions or (-1) if failed
+ */
+ findAllPatternIn(pattern, start = 0, length = this.buffer.byteLength - start) {
+ //region Check input variables
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = 0;
+ }
+
+ if (start > this.buffer.byteLength) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = this.buffer.byteLength;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ if (length > this.buffer.byteLength - start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+ //endregion
+
+ //region Initial variables
+ const result = [];
+
+ const patternLength = pattern.buffer.byteLength;
+ // noinspection NonBlockStatementBodyJS
+ if (patternLength > length) return -1;
+ //endregion
+
+ //region Make a "pre-read" array for pattern
+ const patternArray = Array.from(pattern.view);
+ //endregion
+
+ //region Search for pattern
+ for (let i = 0; i <= length - patternLength; i++) {
+ let equal = true;
+ const equalStart = start + i;
+
+ for (let j = 0; j < patternLength; j++) {
+ // noinspection EqualityComparisonWithCoercionJS
+ if (this.view[j + equalStart] != patternArray[j]) {
+ equal = false;
+ // noinspection BreakStatementJS
+ break;
+ }
+ }
+
+ if (equal) {
+ result.push(start + patternLength + i); // Position after the pattern found
+ i += patternLength - 1; // On next step of "for" we will have "i++"
+ }
+ }
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection OverlyComplexFunctionJS, FunctionTooLongJS
+ /**
+ * Find first position of data, not included in patterns from input array
+ * @param {Array.<ByteStream>} patterns Array with patterns which should be ommited
+ * @param {?number} [start] Start position to search from
+ * @param {?number} [length] Length of byte block to search at
+ * @param {boolean} [backward=false] Flag to search in backward order
+ * @returns {{left: {id: number, position: *}, right: {id: number, position: number}, value: ByteStream}}
+ */
+ findFirstNotIn(patterns, start = null, length = null, backward = false) {
+ //region Initial variables
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start == null) {
+ // noinspection AssignmentToFunctionParameterJS, ConditionalExpressionJS
+ start = backward ? this.buffer.byteLength : 0;
+ }
+
+ if (start > this.buffer.byteLength) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = this.buffer.byteLength;
+ }
+
+ if (backward) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = start;
+ }
+
+ if (length > start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = start;
+ }
+ } else {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ if (length > this.buffer.byteLength - start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+ }
+
+ const result = {
+ left: {
+ id: -1,
+ position: start
+ },
+ right: {
+ id: -1,
+ position: 0
+ },
+ value: new ByteStream()
+ };
+
+ let currentLength = length;
+ //endregion
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ while (currentLength > 0) {
+ //region Search for nearest "pattern"
+ // noinspection ConditionalExpressionJS
+ result.right = this.findFirstIn(patterns, backward ? start - length + currentLength : start + length - currentLength, currentLength, backward);
+ //endregion
+
+ //region No pattern at all
+ // noinspection EqualityComparisonWithCoercionJS
+ if (result.right.id == -1) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = currentLength;
+
+ if (backward) {
+ // noinspection AssignmentToFunctionParameterJS
+ start -= length;
+ } else {
+ // noinspection AssignmentToFunctionParameterJS
+ start = result.left.position;
+ }
+
+ result.value = new ByteStream();
+
+ result.value._buffer = this._buffer.slice(start, start + length);
+ result.value._view = new Uint8Array(result.value._buffer);
+
+ // noinspection BreakStatementJS
+ break;
+ }
+ //endregion
+
+ //region Check distance between two patterns
+ // noinspection ConditionalExpressionJS, EqualityComparisonWithCoercionJS
+ if (result.right.position != (backward ? result.left.position - patterns[result.right.id].buffer.byteLength : result.left.position + patterns[result.right.id].buffer.byteLength)) {
+ if (backward) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = result.right.position + patterns[result.right.id].buffer.byteLength;
+ // noinspection AssignmentToFunctionParameterJS
+ length = result.left.position - result.right.position - patterns[result.right.id].buffer.byteLength;
+ } else {
+ // noinspection AssignmentToFunctionParameterJS
+ start = result.left.position;
+ // noinspection AssignmentToFunctionParameterJS
+ length = result.right.position - result.left.position - patterns[result.right.id].buffer.byteLength;
+ }
+
+ result.value = new ByteStream();
+
+ result.value._buffer = this._buffer.slice(start, start + length);
+ result.value._view = new Uint8Array(result.value._buffer);
+
+ // noinspection BreakStatementJS
+ break;
+ }
+ //endregion
+
+ //region Store information about previous pattern
+ result.left = result.right;
+ //endregion
+
+ //region Change current length
+ currentLength -= patterns[result.right.id]._buffer.byteLength;
+ //endregion
+ }
+
+ //region Swap "patterns" in case of backward order
+ if (backward) {
+ const temp = result.right;
+ result.right = result.left;
+ result.left = temp;
+ }
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleReturnPointsJS
+ /**
+ * Find all positions of data, not included in patterns from input array
+ * @param {Array.<ByteStream>} patterns Array with patterns which should be ommited
+ * @param {?number} [start] Start position to search from
+ * @param {?number} [length] Length of byte block to search at
+ * @returns {Array}
+ */
+ findAllNotIn(patterns, start = null, length = null) {
+ //region Initial variables
+ const result = [];
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = 0;
+ }
+
+ // noinspection NonBlockStatementBodyJS
+ if (start > this.buffer.byteLength - 1) return result;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ if (length > this.buffer.byteLength - start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ let patternFound = {
+ left: {
+ id: -1,
+ position: start
+ },
+ right: {
+ id: -1,
+ position: start
+ },
+ value: new ByteStream()
+ };
+ //endregion
+
+ //region Find all accurences of patterns
+ // noinspection EqualityComparisonWithCoercionJS
+ do {
+ const position = patternFound.right.position;
+
+ patternFound = this.findFirstNotIn(patterns, patternFound.right.position, length);
+
+ // noinspection AssignmentToFunctionParameterJS
+ length -= patternFound.right.position - position;
+
+ result.push({
+ left: {
+ id: patternFound.left.id,
+ position: patternFound.left.position
+ },
+ right: {
+ id: patternFound.right.id,
+ position: patternFound.right.position
+ },
+ value: patternFound.value
+ });
+ } while (patternFound.right.id != -1);
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleReturnPointsJS, OverlyComplexFunctionJS
+ /**
+ * Find position of a sequence of any patterns from input array
+ * @param {Array.<ByteStream>} patterns Array of pattern to look for
+ * @param {?number} [start] Start position to search from
+ * @param {?number} [length] Length of byte block to search at
+ * @param {boolean} [backward=false] Flag to search in backward order
+ * @returns {*}
+ */
+ findFirstSequence(patterns, start = null, length = null, backward = false) {
+ //region Initial variables
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start == null) {
+ // noinspection AssignmentToFunctionParameterJS, ConditionalExpressionJS
+ start = backward ? this.buffer.byteLength : 0;
+ }
+
+ if (start > this.buffer.byteLength) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = this.buffer.byteLength;
+ }
+
+ if (backward) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = start;
+ }
+
+ if (length > start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = start;
+ }
+ } else {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ if (length > this.buffer.byteLength - start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+ }
+ //endregion
+
+ //region Find first byte from sequence
+ const firstIn = this.skipNotPatterns(patterns, start, length, backward);
+ // noinspection EqualityComparisonWithCoercionJS
+ if (firstIn == -1) {
+ return {
+ position: -1,
+ value: new ByteStream()
+ };
+ }
+ //endregion
+
+ //region Find first byte not in sequence
+ // noinspection ConditionalExpressionJS
+ const firstNotIn = this.skipPatterns(patterns, firstIn, length - (backward ? start - firstIn : firstIn - start), backward);
+ //endregion
+
+ //region Make output value
+ if (backward) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = firstNotIn;
+ // noinspection AssignmentToFunctionParameterJS
+ length = firstIn - firstNotIn;
+ } else {
+ // noinspection AssignmentToFunctionParameterJS
+ start = firstIn;
+ // noinspection AssignmentToFunctionParameterJS
+ length = firstNotIn - firstIn;
+ }
+
+ const value = new ByteStream();
+
+ value._buffer = this._buffer.slice(start, start + length);
+ value._view = new Uint8Array(value._buffer);
+ //endregion
+
+ return {
+ position: firstNotIn,
+ value
+ };
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleReturnPointsJS
+ /**
+ * Find all positions of a sequence of any patterns from input array
+ * @param {Array.<ByteStream>} patterns Array of patterns to search for
+ * @param {?number} [start] Start position to search from
+ * @param {?number} [length] Length of byte block to search at
+ * @returns {Array}
+ */
+ findAllSequences(patterns, start = null, length = null) {
+ //region Initial variables
+ const result = [];
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = 0;
+ }
+
+ // noinspection NonBlockStatementBodyJS
+ if (start > this.buffer.byteLength - 1) return result;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ if (length > this.buffer.byteLength - start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ let patternFound = {
+ position: start,
+ value: new ByteStream()
+ };
+ //endregion
+
+ //region Find all accurences of patterns
+ // noinspection EqualityComparisonWithCoercionJS
+ do {
+ const position = patternFound.position;
+
+ patternFound = this.findFirstSequence(patterns, patternFound.position, length);
+
+ // noinspection EqualityComparisonWithCoercionJS
+ if (patternFound.position != -1) {
+ // noinspection AssignmentToFunctionParameterJS
+ length -= patternFound.position - position;
+
+ result.push({
+ position: patternFound.position,
+ value: patternFound.value
+ });
+ }
+ } while (patternFound.position != -1);
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleLoopsJS, FunctionWithMultipleReturnPointsJS, OverlyComplexFunctionJS, FunctionTooLongJS
+ /**
+ * Find all paired patterns in the stream
+ * @param {ByteStream} leftPattern Left pattern to search for
+ * @param {ByteStream} rightPattern Right pattern to search for
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @returns {Array}
+ */
+ findPairedPatterns(leftPattern, rightPattern, start = null, length = null) {
+ //region Initial variables
+ const result = [];
+
+ // noinspection NonBlockStatementBodyJS
+ if (leftPattern.isEqual(rightPattern)) return result;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = 0;
+ }
+
+ // noinspection NonBlockStatementBodyJS
+ if (start > this.buffer.byteLength - 1) return result;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ if (length > this.buffer.byteLength - start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ let currentPositionLeft = 0;
+ //endregion
+
+ //region Find all "left patterns" as sorted array
+ const leftPatterns = this.findAllPatternIn(leftPattern, start, length);
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (leftPatterns.length == 0) return result;
+ //endregion
+
+ //region Find all "right patterns" as sorted array
+ const rightPatterns = this.findAllPatternIn(rightPattern, start, length);
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (rightPatterns.length == 0) return result;
+ //endregion
+
+ //region Combine patterns
+ while (currentPositionLeft < leftPatterns.length) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, EqualityComparisonWithCoercionJS
+ if (rightPatterns.length == 0) {
+ // noinspection BreakStatementJS
+ break;
+ }
+
+ // noinspection EqualityComparisonWithCoercionJS
+ if (leftPatterns[0] == rightPatterns[0]) {
+ // Possible situation when one pattern is a part of another
+ // For example "stream" and "endstream"
+ // In case when we have only "endstream" in fact "stream" will be also found at the same position
+ // (position of the pattern is an index AFTER the pattern)
+
+ result.push({
+ left: leftPatterns[0],
+ right: rightPatterns[0]
+ });
+
+ leftPatterns.splice(0, 1);
+ rightPatterns.splice(0, 1);
+
+ // noinspection ContinueStatementJS
+ continue;
+ }
+
+ if (leftPatterns[currentPositionLeft] > rightPatterns[0]) {
+ // noinspection BreakStatementJS
+ break;
+ }
+
+ while (leftPatterns[currentPositionLeft] < rightPatterns[0]) {
+ currentPositionLeft++;
+
+ if (currentPositionLeft >= leftPatterns.length) {
+ // noinspection BreakStatementJS
+ break;
+ }
+ }
+
+ result.push({
+ left: leftPatterns[currentPositionLeft - 1],
+ right: rightPatterns[0]
+ });
+
+ leftPatterns.splice(currentPositionLeft - 1, 1);
+ rightPatterns.splice(0, 1);
+
+ currentPositionLeft = 0;
+ }
+ //endregion
+
+ //region Sort result
+ result.sort((a, b) => a.left - b.left);
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleLoopsJS, FunctionWithMultipleReturnPointsJS, OverlyComplexFunctionJS, FunctionTooLongJS
+ /**
+ * Find all paired patterns in the stream
+ * @param {Array.<ByteStream>} inputLeftPatterns Array of left patterns to search for
+ * @param {Array.<ByteStream>} inputRightPatterns Array of right patterns to search for
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @returns {Array}
+ */
+ findPairedArrays(inputLeftPatterns, inputRightPatterns, start = null, length = null) {
+ //region Initial variables
+ const result = [];
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = 0;
+ }
+
+ // noinspection NonBlockStatementBodyJS
+ if (start > this.buffer.byteLength - 1) return result;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ if (length > this.buffer.byteLength - start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ let currentPositionLeft = 0;
+ //endregion
+
+ //region Find all "left patterns" as sorted array
+ const leftPatterns = this.findAllIn(inputLeftPatterns, start, length);
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (leftPatterns.length == 0) return result;
+ //endregion
+
+ //region Find all "right patterns" as sorted array
+ const rightPatterns = this.findAllIn(inputRightPatterns, start, length);
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (rightPatterns.length == 0) return result;
+ //endregion
+
+ //region Combine patterns
+ while (currentPositionLeft < leftPatterns.length) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, EqualityComparisonWithCoercionJS
+ if (rightPatterns.length == 0) {
+ // noinspection BreakStatementJS
+ break;
+ }
+
+ // noinspection EqualityComparisonWithCoercionJS
+ if (leftPatterns[0].position == rightPatterns[0].position) {
+ // Possible situation when one pattern is a part of another
+ // For example "stream" and "endstream"
+ // In case when we have only "endstream" in fact "stream" will be also found at the same position
+ // (position of the pattern is an index AFTER the pattern)
+
+ result.push({
+ left: leftPatterns[0],
+ right: rightPatterns[0]
+ });
+
+ leftPatterns.splice(0, 1);
+ rightPatterns.splice(0, 1);
+
+ // noinspection ContinueStatementJS
+ continue;
+ }
+
+ if (leftPatterns[currentPositionLeft].position > rightPatterns[0].position) {
+ // noinspection BreakStatementJS
+ break;
+ }
+
+ while (leftPatterns[currentPositionLeft].position < rightPatterns[0].position) {
+ currentPositionLeft++;
+
+ if (currentPositionLeft >= leftPatterns.length) {
+ // noinspection BreakStatementJS
+ break;
+ }
+ }
+
+ result.push({
+ left: leftPatterns[currentPositionLeft - 1],
+ right: rightPatterns[0]
+ });
+
+ leftPatterns.splice(currentPositionLeft - 1, 1);
+ rightPatterns.splice(0, 1);
+
+ currentPositionLeft = 0;
+ }
+ //endregion
+
+ //region Sort result
+ result.sort((a, b) => a.left.position - b.left.position);
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleReturnPointsJS, FunctionTooLongJS
+ /**
+ * Replace one patter with other
+ * @param {ByteStream} searchPattern The pattern to search for
+ * @param {ByteStream} replacePattern The pattern to replace initial pattern
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @param {Array|null} [findAllResult=null] Pre-calculated results of "findAllIn"
+ * @returns {*}
+ */
+ replacePattern(searchPattern, replacePattern, start = null, length = null, findAllResult = null) {
+ //region Initial variables
+ let result;
+
+ let i;
+ const output = {
+ status: -1,
+ searchPatternPositions: [],
+ replacePatternPositions: []
+ };
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = 0;
+ }
+
+ // noinspection NonBlockStatementBodyJS
+ if (start > this.buffer.byteLength - 1) return false;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ if (length > this.buffer.byteLength - start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+ //endregion
+
+ //region Find a pattern to search for
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (findAllResult == null) {
+ result = this.findAllIn([searchPattern], start, length);
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (result.length == 0) return output;
+ } else result = findAllResult;
+
+ // noinspection NestedFunctionCallJS
+ output.searchPatternPositions.push(...Array.from(result, element => element.position));
+ //endregion
+
+ //region Variables for new buffer initialization
+ const patternDifference = searchPattern.buffer.byteLength - replacePattern.buffer.byteLength;
+
+ const changedBuffer = new ArrayBuffer(this.view.length - result.length * patternDifference);
+ const changedView = new Uint8Array(changedBuffer);
+ //endregion
+
+ //region Copy data from 0 to start
+ // noinspection NestedFunctionCallJS
+ changedView.set(new Uint8Array(this.buffer, 0, start));
+ //endregion
+
+ //region Replace pattern
+ for (i = 0; i < result.length; i++) {
+ //region Initial variables
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, ConditionalExpressionJS, EqualityComparisonWithCoercionJS
+ const currentPosition = i == 0 ? start : result[i - 1].position;
+ //endregion
+
+ //region Copy bytes other then search pattern
+ // noinspection NestedFunctionCallJS
+ changedView.set(new Uint8Array(this.buffer, currentPosition, result[i].position - searchPattern.buffer.byteLength - currentPosition), currentPosition - i * patternDifference);
+ //endregion
+
+ //region Put replace pattern in a new buffer
+ changedView.set(replacePattern.view, result[i].position - searchPattern.buffer.byteLength - i * patternDifference);
+
+ output.replacePatternPositions.push(result[i].position - searchPattern.buffer.byteLength - i * patternDifference);
+ //endregion
+ }
+ //endregion
+
+ //region Copy data from the end of old buffer
+ i--;
+ // noinspection NestedFunctionCallJS
+ changedView.set(new Uint8Array(this.buffer, result[i].position, this.buffer.byteLength - result[i].position), result[i].position - searchPattern.buffer.byteLength + replacePattern.buffer.byteLength - i * patternDifference);
+ //endregion
+
+ //region Re-initialize existing buffer
+ this.buffer = changedBuffer;
+ this.view = new Uint8Array(this.buffer);
+ //endregion
+
+ output.status = 1;
+
+ return output;
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleLoopsJS, FunctionWithMultipleReturnPointsJS, OverlyComplexFunctionJS, FunctionTooLongJS
+ /**
+ * Skip any pattern from input array
+ * @param {Array.<ByteStream>} patterns Array with patterns which should be ommited
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @param {boolean} [backward=false] Flag to search in backward order
+ * @returns {*}
+ */
+ skipPatterns(patterns, start = null, length = null, backward = false) {
+ //region Initial variables
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start == null) {
+ // noinspection AssignmentToFunctionParameterJS, ConditionalExpressionJS
+ start = backward ? this.buffer.byteLength : 0;
+ }
+
+ if (start > this.buffer.byteLength) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = this.buffer.byteLength;
+ }
+
+ if (backward) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = start;
+ }
+
+ if (length > start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = start;
+ }
+ } else {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ if (length > this.buffer.byteLength - start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+ }
+
+ let result = start;
+ //endregion
+
+ //region Search for pattern
+ for (let k = 0; k < patterns.length; k++) {
+ const patternLength = patterns[k].buffer.byteLength;
+ // noinspection ConditionalExpressionJS
+ const equalStart = backward ? result - patternLength : result;
+ let equal = true;
+
+ for (let j = 0; j < patternLength; j++) {
+ // noinspection EqualityComparisonWithCoercionJS
+ if (this.view[j + equalStart] != patterns[k].view[j]) {
+ equal = false;
+ // noinspection BreakStatementJS
+ break;
+ }
+ }
+
+ if (equal) {
+ k = -1;
+
+ if (backward) {
+ result -= patternLength;
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (result <= 0) return result;
+ } else {
+ result += patternLength;
+ // noinspection NonBlockStatementBodyJS
+ if (result >= start + length) return result;
+ }
+ }
+ }
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleLoopsJS, OverlyComplexFunctionJS, FunctionTooLongJS
+ /**
+ * Skip any pattern not from input array
+ * @param {Array.<ByteStream>} patterns Array with patterns which should not be ommited
+ * @param start
+ * @param length
+ * @param backward
+ * @returns {number}
+ */
+ skipNotPatterns(patterns, start = null, length = null, backward = false) {
+ //region Initial variables
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start == null) {
+ // noinspection AssignmentToFunctionParameterJS, ConditionalExpressionJS
+ start = backward ? this.buffer.byteLength : 0;
+ }
+
+ if (start > this.buffer.byteLength) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = this.buffer.byteLength;
+ }
+
+ if (backward) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = start;
+ }
+
+ if (length > start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = start;
+ }
+ } else {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+
+ if (length > this.buffer.byteLength - start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.buffer.byteLength - start;
+ }
+ }
+
+ let result = -1;
+ //endregion
+
+ //region Search for pattern
+ for (let i = 0; i < length; i++) {
+ for (let k = 0; k < patterns.length; k++) {
+ const patternLength = patterns[k].buffer.byteLength;
+ // noinspection ConditionalExpressionJS
+ const equalStart = backward ? start - i - patternLength : start + i;
+ let equal = true;
+
+ for (let j = 0; j < patternLength; j++) {
+ // noinspection EqualityComparisonWithCoercionJS
+ if (this.view[j + equalStart] != patterns[k].view[j]) {
+ equal = false;
+ // noinspection BreakStatementJS
+ break;
+ }
+ }
+
+ if (equal) {
+ // noinspection ConditionalExpressionJS
+ result = backward ? start - i : start + i; // Exact position of pattern found
+ // noinspection BreakStatementJS
+ break;
+ }
+ }
+
+ // noinspection EqualityComparisonWithCoercionJS
+ if (result != -1) {
+ // noinspection BreakStatementJS
+ break;
+ }
+ }
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+}
+exports.ByteStream = ByteStream; //**************************************************************************************
+
+class SeqStream {
+ //**********************************************************************************
+ /**
+ * Constructor for "SeqStream" class
+ * @param {{[stream]: ByteStream, [length]: number, [backward]: boolean, [start]: number, [appendBlock]: number}} parameters
+ */
+ constructor(parameters = {}) {
+ /**
+ * Major stream
+ * @type {ByteStream}
+ */
+ this.stream = new ByteStream();
+ /**
+ * Length of the major stream
+ * @type {number}
+ */
+ this._length = 0;
+ /**
+ * Flag to search in backward direction
+ * @type {boolean}
+ */
+ this.backward = false;
+ /**
+ * Start position to search
+ * @type {number}
+ */
+ this._start = 0;
+ /**
+ * Length of a block when append information to major stream
+ * @type {number}
+ */
+ this.appendBlock = 0;
+
+ this.prevLength = 0;
+ this.prevStart = 0;
+
+ var _iteratorNormalCompletion2 = true;
+ var _didIteratorError2 = false;
+ var _iteratorError2 = undefined;
+
+ try {
+ for (var _iterator2 = Object.keys(parameters)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+ const key = _step2.value;
+
+ switch (key) {
+ case "stream":
+ this.stream = parameters.stream;
+ break;
+ case "backward":
+ this.backward = parameters.backward;
+ // noinspection JSUnusedGlobalSymbols
+ this._start = this.stream.buffer.byteLength;
+ break;
+ case "length":
+ // noinspection JSUnusedGlobalSymbols
+ this._length = parameters.length;
+ break;
+ case "start":
+ // noinspection JSUnusedGlobalSymbols
+ this._start = parameters.start;
+ break;
+ case "appendBlock":
+ this.appendBlock = parameters.appendBlock;
+ break;
+ case "view":
+ this.stream = new ByteStream({ view: parameters.view });
+ break;
+ case "buffer":
+ this.stream = new ByteStream({ buffer: parameters.buffer });
+ break;
+ case "string":
+ this.stream = new ByteStream({ string: parameters.string });
+ break;
+ case "hexstring":
+ this.stream = new ByteStream({ hexstring: parameters.hexstring });
+ break;
+ default:
+ }
+ }
+ } catch (err) {
+ _didIteratorError2 = true;
+ _iteratorError2 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion2 && _iterator2.return) {
+ _iterator2.return();
+ }
+ } finally {
+ if (_didIteratorError2) {
+ throw _iteratorError2;
+ }
+ }
+ }
+ }
+ //**********************************************************************************
+ /**
+ * Setter for "stream" property
+ * @param {ByteStream} value
+ */
+ set stream(value) {
+ this._stream = value;
+
+ this.prevLength = this._length;
+ // noinspection JSUnusedGlobalSymbols
+ this._length = value._buffer.byteLength;
+
+ this.prevStart = this._start;
+ // noinspection JSUnusedGlobalSymbols
+ this._start = 0;
+ }
+ //**********************************************************************************
+ /**
+ * Getter for "stream" property
+ * @returns {ByteStream}
+ */
+ get stream() {
+ return this._stream;
+ }
+ //**********************************************************************************
+ /**
+ * Setter for "length" property
+ * @param {number} value
+ */
+ set length(value) {
+ this.prevLength = this._length;
+ // noinspection JSUnusedGlobalSymbols
+ this._length = value;
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleReturnPointsJS
+ /**
+ * Getter for "length" property
+ * @returns {number}
+ */
+ get length() {
+ // noinspection NonBlockStatementBodyJS
+ if (this.appendBlock) return this.start;
+
+ return this._length;
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleReturnPointsJS
+ /**
+ * Setter for "start" property
+ * @param {number} value
+ */
+ set start(value) {
+ // noinspection NonBlockStatementBodyJS
+ if (value > this.stream.buffer.byteLength) return;
+
+ //region Initialization of "prev" internal variables
+ this.prevStart = this._start;
+ this.prevLength = this._length;
+ //endregion
+
+ // noinspection JSUnusedGlobalSymbols, ConditionalExpressionJS
+ this._length -= this.backward ? this._start - value : value - this._start;
+ // noinspection JSUnusedGlobalSymbols
+ this._start = value;
+ }
+ //**********************************************************************************
+ /**
+ * Getter for "start" property
+ * @returns {number}
+ */
+ get start() {
+ return this._start;
+ }
+ //**********************************************************************************
+ /**
+ * Return ArrayBuffer with having value of existing SeqStream length
+ * @return {ArrayBuffer}
+ */
+ get buffer() {
+ return this._stream._buffer.slice(0, this._length);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Reset current position of the "SeqStream"
+ */
+ resetPosition() {
+ // noinspection JSUnusedGlobalSymbols
+ this._start = this.prevStart;
+ // noinspection JSUnusedGlobalSymbols
+ this._length = this.prevLength;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS
+ /**
+ * Find any byte pattern in "ByteStream"
+ * @param {ByteStream} pattern Stream having pattern value
+ * @param {?number} [gap] Maximum gap between start position and position of nearest object
+ * @returns {number}
+ */
+ findPattern(pattern, gap = null) {
+ //region Initial variables
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (gap == null || gap > this.length) {
+ // noinspection AssignmentToFunctionParameterJS
+ gap = this.length;
+ }
+ //endregion
+
+ //region Find pattern
+ const result = this.stream.findPattern(pattern, this.start, this.length, this.backward);
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (result == -1) return result;
+
+ if (this.backward) {
+ // noinspection NonBlockStatementBodyJS
+ if (result < this.start - pattern.buffer.byteLength - gap) return -1;
+ } else {
+ // noinspection NonBlockStatementBodyJS
+ if (result > this.start + pattern.buffer.byteLength + gap) return -1;
+ }
+ //endregion
+
+ //region Create new values
+ this.start = result;
+ //endregion ;
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS
+ /**
+ * Find first position of any pattern from input array
+ * @param {Array.<ByteStream>} patterns Array with patterns which should be found
+ * @param {?number} [gap] Maximum gap between start position and position of nearest object
+ * @returns {{id: number, position: number}}
+ */
+ findFirstIn(patterns, gap = null) {
+ //region Initial variables
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (gap == null || gap > this.length) {
+ // noinspection AssignmentToFunctionParameterJS
+ gap = this.length;
+ }
+ //endregion
+
+ //region Search for patterns
+ const result = this.stream.findFirstIn(patterns, this.start, this.length, this.backward);
+ // noinspection NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (result.id == -1) return result;
+
+ if (this.backward) {
+ if (result.position < this.start - patterns[result.id].buffer.byteLength - gap) {
+ // noinspection ConditionalExpressionJS
+ return {
+ id: -1,
+ position: this.backward ? 0 : this.start + this.length
+ };
+ }
+ } else {
+ if (result.position > this.start + patterns[result.id].buffer.byteLength + gap) {
+ // noinspection ConditionalExpressionJS
+ return {
+ id: -1,
+ position: this.backward ? 0 : this.start + this.length
+ };
+ }
+ }
+ //endregion
+
+ //region Create new values
+ this.start = result.position;
+ //endregion ;
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Find all positions of any pattern from input array
+ * @param {Array.<ByteStream>} patterns Array with patterns which should be found
+ * @returns {Array}
+ */
+ findAllIn(patterns) {
+ // In case of "backward order" the start position is at the end on stream.
+ // In case of "normal order" the start position is at the begging of the stream.
+ // But in fact for search for all patterns we need to have start position in "normal order".
+ // noinspection ConditionalExpressionJS
+ const start = this.backward ? this.start - this.length : this.start;
+
+ return this.stream.findAllIn(patterns, start, this.length);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS, OverlyComplexFunctionJS
+ /**
+ * Find first position of data, not included in patterns from input array
+ * @param {Array.<ByteStream>} patterns Array with patterns which should be ommited
+ * @param {?number} gap Maximum gap between start position and position of nearest object
+ * @returns {*}
+ */
+ findFirstNotIn(patterns, gap = null) {
+ //region Initial variables
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (gap == null || gap > this._length) {
+ // noinspection AssignmentToFunctionParameterJS
+ gap = this._length;
+ }
+ //endregion
+
+ //region Search for patterns
+ const result = this._stream.findFirstNotIn(patterns, this._start, this._length, this.backward);
+ // noinspection NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (result.left.id == -1 && result.right.id == -1) return result;
+
+ if (this.backward) {
+ // noinspection EqualityComparisonWithCoercionJS
+ if (result.right.id != -1) {
+ if (result.right.position < this._start - patterns[result.right.id]._buffer.byteLength - gap) {
+ return {
+ left: {
+ id: -1,
+ position: this._start
+ },
+ right: {
+ id: -1,
+ position: 0
+ },
+ value: new ByteStream()
+ };
+ }
+ }
+ } else {
+ // noinspection EqualityComparisonWithCoercionJS
+ if (result.left.id != -1) {
+ if (result.left.position > this._start + patterns[result.left.id]._buffer.byteLength + gap) {
+ return {
+ left: {
+ id: -1,
+ position: this._start
+ },
+ right: {
+ id: -1,
+ position: 0
+ },
+ value: new ByteStream()
+ };
+ }
+ }
+ }
+ //endregion
+
+ //region Create new values
+ if (this.backward) {
+ // noinspection NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (result.left.id == -1) this.start = 0;else this.start = result.left.position;
+ } else {
+ // noinspection NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (result.right.id == -1) this.start = this._start + this._length;else this.start = result.right.position;
+ }
+ //endregion ;
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Find all positions of data, not included in patterns from input array
+ * @param {Array.<ByteStream>} patterns Array with patterns which should be ommited
+ * @returns {Array}
+ */
+ findAllNotIn(patterns) {
+ // In case of "backward order" the start position is at the end on stream.
+ // In case of "normal order" the start position is at the begging of the stream.
+ // But in fact for search for all patterns we need to have start position in "normal order".
+ // noinspection ConditionalExpressionJS
+ const start = this.backward ? this._start - this._length : this._start;
+
+ return this._stream.findAllNotIn(patterns, start, this._length);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS
+ /**
+ * Find position of a sequence of any patterns from input array
+ * @param {Array.<ByteStream>} patterns Array with patterns which should be ommited
+ * @param {?number} [length] Length to search sequence for
+ * @param {?number} [gap] Maximum gap between start position and position of nearest object
+ * @returns {*}
+ */
+ findFirstSequence(patterns, length = null, gap = null) {
+ //region Initial variables
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null || length > this._length) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this._length;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (gap == null || gap > length) {
+ // noinspection AssignmentToFunctionParameterJS
+ gap = length;
+ }
+ //endregion
+
+ //region Search for sequence
+ const result = this._stream.findFirstSequence(patterns, this._start, length, this.backward);
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (result.value.buffer.byteLength == 0) return result;
+
+ if (this.backward) {
+ if (result.position < this._start - result.value._buffer.byteLength - gap) {
+ return {
+ position: -1,
+ value: new ByteStream()
+ };
+ }
+ } else {
+ if (result.position > this._start + result.value._buffer.byteLength + gap) {
+ return {
+ position: -1,
+ value: new ByteStream()
+ };
+ }
+ }
+ //endregion
+
+ //region Create new values
+ this.start = result.position;
+ //endregion ;
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Find position of a sequence of any patterns from input array
+ * @param {Array.<ByteStream>} patterns Array with patterns which should be found
+ * @returns {Array}
+ */
+ findAllSequences(patterns) {
+ // In case of "backward order" the start position is at the end on stream.
+ // In case of "normal order" the start position is at the begging of the stream.
+ // But in fact for search for all patterns we need to have start position in "normal order".
+ // noinspection ConditionalExpressionJS
+ const start = this.backward ? this.start - this.length : this.start;
+
+ return this.stream.findAllSequences(patterns, start, this.length);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS
+ /**
+ * Find all paired patterns in the stream
+ * @param {ByteStream} leftPattern Left pattern to search for
+ * @param {ByteStream} rightPattern Right pattern to search for
+ * @param {?number} [gap] Maximum gap between start position and position of nearest object
+ * @returns {Array}
+ */
+ findPairedPatterns(leftPattern, rightPattern, gap = null) {
+ //region Initial variables
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (gap == null || gap > this.length) {
+ // noinspection AssignmentToFunctionParameterJS
+ gap = this.length;
+ }
+ //endregion
+
+ // In case of "backward order" the start position is at the end on stream.
+ // In case of "normal order" the start position is at the begging of the stream.
+ // But in fact for search for all patterns we need to have start position in "normal order".
+ // noinspection ConditionalExpressionJS
+ const start = this.backward ? this.start - this.length : this.start;
+
+ //region Search for patterns
+ const result = this.stream.findPairedPatterns(leftPattern, rightPattern, start, this.length);
+ if (result.length) {
+ if (this.backward) {
+ // noinspection NonBlockStatementBodyJS
+ if (result[0].right < this.start - rightPattern.buffer.byteLength - gap) return [];
+ } else {
+ // noinspection NonBlockStatementBodyJS
+ if (result[0].left > this.start + leftPattern.buffer.byteLength + gap) return [];
+ }
+ }
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS
+ /**
+ * Find all paired patterns in the stream
+ * @param {Array.<ByteStream>} leftPatterns Array of left patterns to search for
+ * @param {Array.<ByteStream>} rightPatterns Array of right patterns to search for
+ * @param {?number} [gap] Maximum gap between start position and position of nearest object
+ * @returns {Array}
+ */
+ findPairedArrays(leftPatterns, rightPatterns, gap = null) {
+ //region Initial variables
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (gap == null || gap > this.length) {
+ // noinspection AssignmentToFunctionParameterJS
+ gap = this.length;
+ }
+ //endregion
+
+ // In case of "backward order" the start position is at the end on stream.
+ // In case of "normal order" the start position is at the begging of the stream.
+ // But in fact for search for all patterns we need to have start position in "normal order".
+ // noinspection ConditionalExpressionJS
+ const start = this.backward ? this.start - this.length : this.start;
+
+ //region Search for patterns
+ const result = this.stream.findPairedArrays(leftPatterns, rightPatterns, start, this.length);
+ if (result.length) {
+ if (this.backward) {
+ // noinspection NonBlockStatementBodyJS
+ if (result[0].right.position < this.start - rightPatterns[result[0].right.id].buffer.byteLength - gap) return [];
+ } else {
+ // noinspection NonBlockStatementBodyJS
+ if (result[0].left.position > this.start + leftPatterns[result[0].left.id].buffer.byteLength + gap) return [];
+ }
+ }
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Replace one patter with other
+ * @param {ByteStream} searchPattern The pattern to search for
+ * @param {ByteStream} replacePattern The pattern to replace initial pattern
+ * @returns {*}
+ */
+ replacePattern(searchPattern, replacePattern) {
+ // In case of "backward order" the start position is at the end on stream.
+ // In case of "normal order" the start position is at the begging of the stream.
+ // But in fact for search for all patterns we need to have start position in "normal order".
+ // noinspection ConditionalExpressionJS
+ const start = this.backward ? this.start - this.length : this.start;
+
+ return this.stream.replacePattern(searchPattern, replacePattern, start, this.length);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Skip of any pattern from input array
+ * @param {Array.<ByteStream>} patterns Array with patterns which should be ommited
+ * @returns {*}
+ */
+ skipPatterns(patterns) {
+ const result = this.stream.skipPatterns(patterns, this.start, this.length, this.backward);
+
+ //region Create new values
+ this.start = result;
+ //endregion ;
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS
+ /**
+ * Skip of any pattern from input array
+ * @param {Array.<ByteStream>} patterns Array with patterns which should be ommited
+ * @returns {number}
+ */
+ skipNotPatterns(patterns) {
+ const result = this.stream.skipNotPatterns(patterns, this.start, this.length, this.backward);
+ // noinspection NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (result == -1) return -1;
+
+ //region Create new values
+ this.start = result;
+ //endregion ;
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Append a new "Stream" content to the current "Stream"
+ * @param {ByteStream} stream A new "stream" to append to current "stream"
+ */
+ append(stream) {
+ if (this._start + stream._buffer.byteLength > this._stream._buffer.byteLength) {
+ if (stream._buffer.byteLength > this.appendBlock) {
+ // noinspection MagicNumberJS
+ this.appendBlock = stream._buffer.byteLength + 1000;
+ }
+
+ this._stream.realloc(this._stream._buffer.byteLength + this.appendBlock);
+ }
+
+ this._stream._view.set(stream._view, this._start);
+
+ this._length += stream._buffer.byteLength * 2;
+ this.start = this._start + stream._buffer.byteLength;
+ this.prevLength -= stream._buffer.byteLength * 2;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Append a "view" content to the current "Stream"
+ * @param {Uint8Array} view A new "view" to append to current "stream"
+ */
+ appendView(view) {
+ if (this._start + view.length > this._stream._buffer.byteLength) {
+ if (view.length > this.appendBlock) {
+ // noinspection MagicNumberJS
+ this.appendBlock = view.length + 1000;
+ }
+
+ this._stream.realloc(this._stream._buffer.byteLength + this.appendBlock);
+ }
+
+ this._stream._view.set(view, this._start);
+
+ this._length += view.length * 2;
+ this.start = this._start + view.length;
+ this.prevLength -= view.length * 2;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Append a new char to the current "Stream"
+ * @param {number} char A new char to append to current "stream"
+ */
+ appendChar(char) {
+ if (this._start + 1 > this._stream._buffer.byteLength) {
+ // noinspection ConstantOnLefSideOfComparisonJS
+ if (1 > this.appendBlock) {
+ // noinspection MagicNumberJS
+ this.appendBlock = 1000;
+ }
+
+ this._stream.realloc(this._stream._buffer.byteLength + this.appendBlock);
+ }
+
+ this._stream._view[this._start] = char;
+
+ this._length += 2;
+ this.start = this._start + 1;
+ this.prevLength -= 2;
+ }
+ //**********************************************************************************
+ // noinspection FunctionNamingConventionJS
+ /**
+ * Append a new number to the current "Stream"
+ * @param {number} number A new unsigned 16-bit integer to append to current "stream"
+ */
+ appendUint16(number) {
+ if (this._start + 2 > this._stream._buffer.byteLength) {
+ // noinspection ConstantOnLefSideOfComparisonJS
+ if (2 > this.appendBlock) {
+ // noinspection MagicNumberJS
+ this.appendBlock = 1000;
+ }
+
+ this._stream.realloc(this._stream._buffer.byteLength + this.appendBlock);
+ }
+
+ const value = new Uint16Array([number]);
+ const view = new Uint8Array(value.buffer);
+
+ this._stream._view[this._start] = view[1];
+ this._stream._view[this._start + 1] = view[0];
+
+ this._length += 4;
+ this.start = this._start + 2;
+ this.prevLength -= 4;
+ }
+ //**********************************************************************************
+ // noinspection FunctionNamingConventionJS
+ /**
+ * Append a new number to the current "Stream"
+ * @param {number} number A new unsigned 24-bit integer to append to current "stream"
+ */
+ appendUint24(number) {
+ if (this._start + 3 > this._stream._buffer.byteLength) {
+ // noinspection ConstantOnLefSideOfComparisonJS
+ if (3 > this.appendBlock) {
+ // noinspection MagicNumberJS
+ this.appendBlock = 1000;
+ }
+
+ this._stream.realloc(this._stream._buffer.byteLength + this.appendBlock);
+ }
+
+ const value = new Uint32Array([number]);
+ const view = new Uint8Array(value.buffer);
+
+ this._stream._view[this._start] = view[2];
+ this._stream._view[this._start + 1] = view[1];
+ this._stream._view[this._start + 2] = view[0];
+
+ this._length += 6;
+ this.start = this._start + 3;
+ this.prevLength -= 6;
+ }
+ //**********************************************************************************
+ // noinspection FunctionNamingConventionJS
+ /**
+ * Append a new number to the current "Stream"
+ * @param {number} number A new unsigned 32-bit integer to append to current "stream"
+ */
+ appendUint32(number) {
+ if (this._start + 4 > this._stream._buffer.byteLength) {
+ // noinspection ConstantOnLefSideOfComparisonJS
+ if (4 > this.appendBlock) {
+ // noinspection MagicNumberJS
+ this.appendBlock = 1000;
+ }
+
+ this._stream.realloc(this._stream._buffer.byteLength + this.appendBlock);
+ }
+
+ const value = new Uint32Array([number]);
+ const view = new Uint8Array(value.buffer);
+
+ this._stream._view[this._start] = view[3];
+ this._stream._view[this._start + 1] = view[2];
+ this._stream._view[this._start + 2] = view[1];
+ this._stream._view[this._start + 3] = view[0];
+
+ this._length += 8;
+ this.start = this._start + 4;
+ this.prevLength -= 8;
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleReturnPointsJS
+ /**
+ * Get a block of data
+ * @param {number} size Size of the data block to get
+ * @param {boolean} [changeLength=true] Should we change "length" and "start" value after reading the data block
+ * @returns {Array}
+ */
+ getBlock(size, changeLength = true) {
+ //region Check input parameters
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (this._length <= 0) return [];
+
+ if (this._length < size) {
+ // noinspection AssignmentToFunctionParameterJS
+ size = this._length;
+ }
+ //endregion
+
+ //region Initial variables
+ let result;
+ //endregion
+
+ //region Getting result depends on "backward" flag
+ if (this.backward) {
+ const buffer = this._stream._buffer.slice(this._length - size, this._length);
+ const view = new Uint8Array(buffer);
+
+ result = new Array(size);
+
+ // noinspection NonBlockStatementBodyJS
+ for (let i = 0; i < size; i++) result[size - 1 - i] = view[i];
+ } else {
+ const buffer = this._stream._buffer.slice(this._start, this._start + size);
+
+ // noinspection NestedFunctionCallJS
+ result = Array.from(new Uint8Array(buffer));
+ }
+ //endregion
+
+ //region Change "length" value if needed
+ if (changeLength) {
+ // noinspection ConditionalExpressionJS
+ this.start += this.backward ? -1 * size : size;
+ }
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS, FunctionNamingConventionJS
+ /**
+ * Get 2-byte unsigned integer value
+ * @param {boolean} [changeLength=true] Should we change "length" and "start" value after reading the data block
+ * @returns {number}
+ */
+ getUint16(changeLength = true) {
+ const block = this.getBlock(2, changeLength);
+
+ //region Check posibility for convertion
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (block.length < 2) return 0;
+ //endregion
+
+ //region Convert byte array to "Uint16Array" value
+ const value = new Uint16Array(1);
+ const view = new Uint8Array(value.buffer);
+
+ view[0] = block[1];
+ view[1] = block[0];
+ //endregion
+
+ return value[0];
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS, FunctionNamingConventionJS
+ /**
+ * Get 2-byte signed integer value
+ * @param {boolean} [changeLength=true] Should we change "length" and "start" value after reading the data block
+ * @returns {number}
+ */
+ getInt16(changeLength = true) {
+ const block = this.getBlock(2, changeLength);
+
+ //region Check posibility for convertion
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (block.length < 2) return 0;
+ //endregion
+
+ //region Convert byte array to "Int16Array" value
+ const value = new Int16Array(1);
+ const view = new Uint8Array(value.buffer);
+
+ view[0] = block[1];
+ view[1] = block[0];
+ //endregion
+
+ return value[0];
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS, FunctionNamingConventionJS
+ /**
+ * Get 3-byte unsigned integer value
+ * @param {boolean} [changeLength=true] Should we change "length" and "start" value after reading the data block
+ * @returns {number}
+ */
+ getUint24(changeLength = true) {
+ const block = this.getBlock(3, changeLength);
+
+ //region Check posibility for convertion
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (block.length < 3) return 0;
+ //endregion
+
+ //region Convert byte array to "Uint32Array" value
+ const value = new Uint32Array(1);
+ const view = new Uint8Array(value.buffer);
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ for (let i = 3; i >= 1; i--) view[3 - i] = block[i - 1];
+ //endregion
+
+ return value[0];
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS, FunctionNamingConventionJS
+ /**
+ * Get 4-byte unsigned integer value
+ * @param {boolean} [changeLength=true] Should we change "length" and "start" value after reading the data block
+ * @returns {number}
+ */
+ getUint32(changeLength = true) {
+ const block = this.getBlock(4, changeLength);
+
+ //region Check posibility for convertion
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (block.length < 4) return 0;
+ //endregion
+
+ //region Convert byte array to "Uint32Array" value
+ const value = new Uint32Array(1);
+ const view = new Uint8Array(value.buffer);
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ for (let i = 3; i >= 0; i--) view[3 - i] = block[i];
+ //endregion
+
+ return value[0];
+ }
+ //**********************************************************************************
+ /**
+ * Get 4-byte signed integer value
+ * @param {boolean} [changeLength=true] Should we change "length" and "start" value after reading the data block
+ * @returns {number}
+ */
+ getInt32(changeLength = true) {
+ const block = this.getBlock(4, changeLength);
+
+ //region Check posibility for convertion
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (block.length < 4) return 0;
+ //endregion
+
+ //region Convert byte array to "Int32Array" value
+ const value = new Int32Array(1);
+ const view = new Uint8Array(value.buffer);
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ for (let i = 3; i >= 0; i--) view[3 - i] = block[i];
+ //endregion
+
+ return value[0];
+ }
+ //**********************************************************************************
+}
+exports.SeqStream = SeqStream; //**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS, FunctionWithMultipleReturnPointsJS, OverlyComplexFunctionJS, FunctionTooLongJS
+/**
+ * Get parsed values from "byte map"
+ * @param {ByteStream} stream Stream to parse data from
+ * @param {Object} map Object with information how to parse "byte map"
+ * @param {number} elements Number of elements in parsing byte map
+ * @param {?number} [start=null] Start position to parse from
+ * @param {?number} [length=null] Length of byte block to parse from
+ * @returns {*}
+ */
+
+function parseByteMap(stream, map, elements, start = null, length = null) {
+ /*
+ Map example:
+
+ let map = [
+ {
+ type: "string",
+ name: "type",
+ minlength: 1,
+ maxlength: 1,
+ func: function(array)
+ {
+ let result = {
+ status: (-1),
+ length: 1
+ };
+
+ switch(array[0])
+ {
+ case 0x6E: // "n"
+ result.value = "n";
+ break;
+ case 0x66: // "f"
+ result.value = "f";
+ break;
+ default:
+ return result;
+ }
+
+ result.status = 1;
+
+ return result;
+ }
+ },
+ {
+ type: "check",
+ minlength: 1,
+ maxlength: 2,
+ func: function(array)
+ {
+ let position = (-1);
+
+ if(array[0] == 0x0A)
+ position = 1;
+ if(array[1] == 0x0A)
+ position = 2;
+
+ return {
+ status: (position > 0) ? 1 : (-1),
+ length: position
+ };
+ }
+ }
+ ];
+ */
+
+ //region Initial variables
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start === null) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = 0;
+ }
+
+ // noinspection NonBlockStatementBodyJS
+ if (start > stream.buffer.byteLength - 1) return false;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length === null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = stream.buffer.byteLength - start;
+ }
+
+ if (length > stream.buffer.byteLength - start) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = stream.buffer.byteLength - start;
+ }
+
+ let dataView;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, EqualityComparisonWithCoercionJS, NonBlockStatementBodyJS
+ if (start == 0 && length == stream.buffer.byteLength) dataView = stream.view;else dataView = new Uint8Array(stream.buffer, start, length);
+
+ const resultArray = new Array(elements);
+ let elementsCount = 0;
+
+ let count = 0;
+ const mapLength = map.length;
+ //endregion
+
+ //region Parse all byte, structure by structure
+ while (count < length) {
+ let structureLength = 0;
+
+ resultArray[elementsCount] = {};
+
+ for (let i = 0; i < mapLength; i++) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, JSUnresolvedVariable, EqualityComparisonWithCoercionJS
+ if (map[i].maxlength == 0) {
+ // noinspection NonBlockStatementBodyJS
+ if ("defaultValue" in map[i]) resultArray[elementsCount][map[i].name] = map[i].defaultValue;
+
+ // noinspection ContinueStatementJS
+ continue;
+ }
+
+ // noinspection JSUnresolvedVariable
+ const array = new Array(map[i].maxlength);
+
+ // noinspection JSUnresolvedVariable
+ for (let j = 0; j < map[i].maxlength; j++) {
+ // noinspection IncrementDecrementResultUsedJS
+ array[j] = dataView[count++];
+ }
+
+ // noinspection JSUnresolvedVariable
+ const result = map[i].func(array);
+ // noinspection EqualityComparisonWithCoercionJS, NonBlockStatementBodyJS
+ if (result.status == -1) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS, EqualityComparisonWithCoercionJS
+ if (resultArray.length == 1) return [];
+
+ return resultArray.slice(0, resultArray.length - 1);
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, EqualityComparisonWithCoercionJS, NonBlockStatementBodyJS
+ if (map[i].type != "check") resultArray[elementsCount][map[i].name] = result.value;
+
+ // noinspection JSUnresolvedVariable
+ count -= map[i].maxlength - result.length;
+ structureLength += result.length;
+ }
+
+ // noinspection IncrementDecrementResultUsedJS
+ resultArray[elementsCount++].structureLength = structureLength;
+ }
+ //endregion
+
+ return resultArray;
+}
+//**************************************************************************************
+//region "Bits-to-string" array
+const bitsToStringArray = ["00000000", "00000001", "00000010", "00000011", "00000100", "00000101", "00000110", "00000111", "00001000", "00001001", "00001010", "00001011", "00001100", "00001101", "00001110", "00001111", "00010000", "00010001", "00010010", "00010011", "00010100", "00010101", "00010110", "00010111", "00011000", "00011001", "00011010", "00011011", "00011100", "00011101", "00011110", "00011111", "00100000", "00100001", "00100010", "00100011", "00100100", "00100101", "00100110", "00100111", "00101000", "00101001", "00101010", "00101011", "00101100", "00101101", "00101110", "00101111", "00110000", "00110001", "00110010", "00110011", "00110100", "00110101", "00110110", "00110111", "00111000", "00111001", "00111010", "00111011", "00111100", "00111101", "00111110", "00111111", "01000000", "01000001", "01000010", "01000011", "01000100", "01000101", "01000110", "01000111", "01001000", "01001001", "01001010", "01001011", "01001100", "01001101", "01001110", "01001111", "01010000", "01010001", "01010010", "01010011", "01010100", "01010101", "01010110", "01010111", "01011000", "01011001", "01011010", "01011011", "01011100", "01011101", "01011110", "01011111", "01100000", "01100001", "01100010", "01100011", "01100100", "01100101", "01100110", "01100111", "01101000", "01101001", "01101010", "01101011", "01101100", "01101101", "01101110", "01101111", "01110000", "01110001", "01110010", "01110011", "01110100", "01110101", "01110110", "01110111", "01111000", "01111001", "01111010", "01111011", "01111100", "01111101", "01111110", "01111111", "10000000", "10000001", "10000010", "10000011", "10000100", "10000101", "10000110", "10000111", "10001000", "10001001", "10001010", "10001011", "10001100", "10001101", "10001110", "10001111", "10010000", "10010001", "10010010", "10010011", "10010100", "10010101", "10010110", "10010111", "10011000", "10011001", "10011010", "10011011", "10011100", "10011101", "10011110", "10011111", "10100000", "10100001", "10100010", "10100011", "10100100", "10100101", "10100110", "10100111", "10101000", "10101001", "10101010", "10101011", "10101100", "10101101", "10101110", "10101111", "10110000", "10110001", "10110010", "10110011", "10110100", "10110101", "10110110", "10110111", "10111000", "10111001", "10111010", "10111011", "10111100", "10111101", "10111110", "10111111", "11000000", "11000001", "11000010", "11000011", "11000100", "11000101", "11000110", "11000111", "11001000", "11001001", "11001010", "11001011", "11001100", "11001101", "11001110", "11001111", "11010000", "11010001", "11010010", "11010011", "11010100", "11010101", "11010110", "11010111", "11011000", "11011001", "11011010", "11011011", "11011100", "11011101", "11011110", "11011111", "11100000", "11100001", "11100010", "11100011", "11100100", "11100101", "11100110", "11100111", "11101000", "11101001", "11101010", "11101011", "11101100", "11101101", "11101110", "11101111", "11110000", "11110001", "11110010", "11110011", "11110100", "11110101", "11110110", "11110111", "11111000", "11111001", "11111010", "11111011", "11111100", "11111101", "11111110", "11111111"];
+//endregion
+//**************************************************************************************
+class BitStream {
+ //**********************************************************************************
+ /**
+ * Constructor for "BitStream" class
+ * @param {{[byteStream]: ByteStream, [view]: Uint8Array, [buffer]: ArrayBuffer, [string]: string, [bitsCount]: number}} parameters
+ */
+ constructor(parameters = {}) {
+ this.buffer = new ArrayBuffer(0);
+ this.view = new Uint8Array(this.buffer);
+
+ this.bitsCount = 0; // Number of bits stored in current "BitStream"
+
+ var _iteratorNormalCompletion3 = true;
+ var _didIteratorError3 = false;
+ var _iteratorError3 = undefined;
+
+ try {
+ for (var _iterator3 = Object.keys(parameters)[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
+ const key = _step3.value;
+
+ switch (key) {
+ case "byteStream":
+ this.fromByteStream(parameters.byteStream);
+ break;
+ case "view":
+ this.fromUint8Array(parameters.view);
+ break;
+ case "buffer":
+ this.fromArrayBuffer(parameters.buffer);
+ break;
+ case "string":
+ this.fromString(parameters.string);
+ break;
+ case "uint32":
+ this.fromUint32(parameters.uint32);
+ break;
+ case "bitsCount":
+ this.bitsCount = parameters.bitsCount;
+ break;
+ default:
+ }
+ }
+ } catch (err) {
+ _didIteratorError3 = true;
+ _iteratorError3 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion3 && _iterator3.return) {
+ _iterator3.return();
+ }
+ } finally {
+ if (_didIteratorError3) {
+ throw _iteratorError3;
+ }
+ }
+ }
+ }
+ //**********************************************************************************
+ /**
+ * Clear existing stream
+ */
+ clear() {
+ this.buffer = new ArrayBuffer(0);
+ this.view = new Uint8Array(this.buffer);
+
+ this.bitsCount = 0;
+ }
+ //**********************************************************************************
+ /**
+ * Initialize "BitStream" by data from existing "ByteStream"
+ * @param {ByteStream} stream
+ */
+ fromByteStream(stream) {
+ this.buffer = stream.buffer.slice(0);
+ this.view = new Uint8Array(this.buffer);
+
+ this.bitsCount = this.view.length << 3;
+ }
+ //**********************************************************************************
+ /**
+ * Initialize "BitStream" object from existing "ArrayBuffer"
+ * @param {ArrayBuffer} array The ArrayBuffer to copy from
+ */
+ fromArrayBuffer(array) {
+ this.buffer = array.slice(0);
+ this.view = new Uint8Array(this.buffer);
+
+ this.bitsCount = this.view.length << 3;
+ }
+ //**********************************************************************************
+ // noinspection FunctionNamingConventionJS
+ /**
+ * Initialize "BitStream" object from existing "Uint8Array"
+ * @param {Uint8Array} array The Uint8Array to copy from
+ */
+ fromUint8Array(array) {
+ this.buffer = new ArrayBuffer(array.length);
+ this.view = new Uint8Array(this.buffer);
+
+ this.view.set(array);
+
+ this.bitsCount = this.view.length << 3;
+ }
+ //**********************************************************************************
+ /**
+ * Initialize "BitStream" object from existing bit string
+ * @param {string} string The string to initialize from
+ */
+ fromString(string) {
+ //region Initial variables
+ const stringLength = string.length;
+
+ // noinspection ConditionalExpressionJS
+ this.buffer = new ArrayBuffer((stringLength >> 3) + (stringLength % 8 ? 1 : 0));
+ this.view = new Uint8Array(this.buffer);
+
+ this.bitsCount = (stringLength >> 3) + 1 << 3; // In order to handle correct shifting
+
+ let byteIndex = 0;
+ //endregion
+
+ //region Convert from "bit string" to bytes
+ for (let i = 0; i < stringLength; i++) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, EqualityComparisonWithCoercionJS, NonBlockStatementBodyJS
+ if (string[i] == "1") this.view[byteIndex] |= 1 << 7 - i % 8;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, EqualityComparisonWithCoercionJS, NonBlockStatementBodyJS
+ if (i && (i + 1) % 8 == 0) byteIndex++;
+ }
+ //endregion
+
+ //region Shift "BitStream" into correct position
+ // noinspection NonBlockStatementBodyJS
+ if (stringLength % 8) this.shiftRight(8 - stringLength % 8);
+ //endregion
+
+ //region Change "bitsCount"
+ this.bitsCount = stringLength;
+ //endregion
+ }
+ //**********************************************************************************
+ /**
+ * Initialize "BitStream" object from existing uint32 number
+ * @param {Number} number The string to initialize from
+ */
+ fromUint32(uint32) {
+ this.buffer = new ArrayBuffer(4);
+ this.view = new Uint8Array(this.buffer);
+
+ const value = new Uint32Array([uint32]);
+ const view = new Uint8Array(value.buffer);
+
+ for (let i = 3; i >= 0; i--) this.view[i] = view[3 - i];
+
+ this.bitsCount = 32;
+ }
+ //**********************************************************************************
+ /**
+ * Represent "BitStream" object content as a string
+ * @param {?number} [start=null] Start number to convert to string from
+ * @param {?number} [length=null] Length of BitStream to convert to string
+ * @returns {string}
+ */
+ toString(start = null, length = null) {
+ //region Check input parameters
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = 0;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start >= this.view.length || start < 0) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = 0;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.view.length - start;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length >= this.view.length || length < 0) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.view.length - start;
+ }
+ //endregion
+
+ //region Initial variables
+ const result = [];
+ //endregion
+
+ //region Convert from bytes to "bit string"
+ // noinspection NonBlockStatementBodyJS
+ for (let i = start; i < start + length; i++) result.push(bitsToStringArray[this.view[i]]);
+ //endregion
+
+ // noinspection ChainedFunctionCallJS
+ return result.join("").slice((this.view.length << 3) - this.bitsCount);
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleReturnPointsJS
+ /**
+ * Shift entire "BitStream" value right to number of bits
+ * @param {number} shift Number of bits to shift value
+ * @param {boolean} [needShrink=true] Need to shrink result or not
+ */
+ shiftRight(shift, needShrink = true) {
+ //region Check parameters
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, EqualityComparisonWithCoercionJS, NonBlockStatementBodyJS
+ if (this.view.length == 0) return;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (shift < 0 || shift > 8) throw new Error("The \"shift\" parameter must be in range 0-8");
+
+ // noinspection NonBlockStatementBodyJS
+ if (shift > this.bitsCount) throw new Error("The \"shift\" parameter can not be bigger than \"this.bitsCount\"");
+ //endregion
+
+ //region Initial variables
+ // noinspection MagicNumberJS
+ const shiftMask = 0xFF >> 8 - shift;
+ this.view[this.view.length - 1] >>= shift;
+ //endregion
+
+ //region Shift value
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ for (let i = this.view.length - 2; i >= 0; i--) {
+ // noinspection NonShortCircuitBooleanExpressionJS
+ this.view[i + 1] |= (this.view[i] & shiftMask) << 8 - shift;
+ this.view[i] >>= shift;
+ }
+ //endregion
+
+ //region Decrease number of bits stored into value
+ this.bitsCount -= shift;
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, EqualityComparisonWithCoercionJS, NonBlockStatementBodyJS
+ if (this.bitsCount == 0) this.clear();
+ //endregion
+
+ //region Change stream size if needed
+ // noinspection NonBlockStatementBodyJS
+ if (needShrink) this.shrink();
+ //endregion
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS
+ /**
+ * Shift entire "BitStream" value left to number of bits
+ * @param {number} shift Number of bits to shift value
+ */
+ shiftLeft(shift) {
+ /*
+ NOTE: We do not really shift value because of internal structure of "BitStream":
+ all bytes inside "BitStream" are aligned to right position. So, even if we will
+ really shift value to left after that we will need again shift it right to the
+ same number of bits. Thus all that we do here is hiding of left bits and descresing
+ the "bitsCount" number.
+ */
+
+ //region Check parameters
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, EqualityComparisonWithCoercionJS, NonBlockStatementBodyJS
+ if (this.view.length == 0) return;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (shift < 0 || shift > 8) throw new Error("The \"shift\" parameter must be in range 0-8");
+
+ // noinspection NonBlockStatementBodyJS
+ if (shift > this.bitsCount) throw new Error("The \"shift\" parameter can not be bigger than \"this.bitsCount\"");
+ //endregion
+
+ //region Remove shifted bits
+ // noinspection MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const bitsOffset = this.bitsCount & 0x07;
+ if (bitsOffset > shift) {
+ // noinspection MagicNumberJS
+ this.view[0] &= 0xFF >> bitsOffset + shift;
+ } else {
+ //region Change size of buffer
+ const buffer = new ArrayBuffer(this.buffer.byteLength - 1);
+ const view = new Uint8Array(buffer);
+
+ // noinspection NestedFunctionCallJS
+ view.set(new Uint8Array(this.buffer, 1, this.buffer.byteLength - 1));
+ //endregion
+
+ //region Mask item with index 0
+ // noinspection MagicNumberJS
+ view[0] &= 0xFF >> shift - bitsOffset;
+ //endregion
+
+ //region Store final array into current stream
+ this.buffer = buffer.slice(0);
+ this.view = new Uint8Array(this.buffer);
+ //endregion
+ }
+ //endregion
+
+ //region Decrease number of bits stored into value
+ this.bitsCount -= shift;
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, EqualityComparisonWithCoercionJS, NonBlockStatementBodyJS
+ if (this.bitsCount == 0) this.clear();
+ //endregion
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleReturnPointsJS, FunctionTooLongJS
+ /**
+ * Return slice of existing "BitStream"
+ * @param {?number} [start=null] Start position of the slice (in bits)
+ * @param {?number} [end=null] End position of the slice (in bits)
+ * @returns {BitStream}
+ */
+ slice(start = null, end = null) {
+ //region Make ability to pass non-value bits
+ let valueShift = 0;
+ // noinspection NonBlockStatementBodyJS
+ if (this.bitsCount % 8) valueShift = 8 - this.bitsCount % 8;
+
+ // noinspection AssignmentToFunctionParameterJS
+ start += valueShift;
+ // noinspection AssignmentToFunctionParameterJS
+ end += valueShift;
+ //endregion
+
+ //region Initial variables
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (start == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ start = 0;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (start < 0 || start > (this.view.length << 3) - 1) return new BitStream(); //("Wrong start position: " + start);
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (end == null) {
+ // noinspection AssignmentToFunctionParameterJS
+ end = (this.view.length << 3) - 1;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (end < 0 || end > (this.view.length << 3) - 1) return new BitStream(); //("Wrong end position: " + end);
+
+ // noinspection NonBlockStatementBodyJS
+ if (end - start + 1 > this.bitsCount) return new BitStream(); //("Maximum length is " + this.bitsCount);
+
+ const startIndex = start >> 3;
+ // noinspection MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const startOffset = start & 0x07;
+
+ const endIndex = end >> 3;
+ // noinspection MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const endOffset = end & 0x07;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, ConditionalExpressionJS, EqualityComparisonWithCoercionJS
+ const bitsLength = endIndex - startIndex == 0 ? 1 : endIndex - startIndex + 1;
+
+ const result = new BitStream();
+ //endregion
+
+ //region Store "primary bytes"
+ result.buffer = new ArrayBuffer(bitsLength);
+ result.view = new Uint8Array(result.buffer);
+ result.bitsCount = bitsLength << 3;
+
+ // noinspection NestedFunctionCallJS
+ result.view.set(new Uint8Array(this.buffer, startIndex, bitsLength));
+ //endregion
+
+ //region Change "start byte"
+ // noinspection MagicNumberJS
+ result.view[0] &= 0xFF >> startOffset;
+ //endregion
+
+ //region Change "end byte"
+ // noinspection MagicNumberJS
+ result.view[bitsLength] &= 0xFF << 7 - endOffset;
+ //endregion
+
+ //region Shift result array to right
+ // noinspection NonBlockStatementBodyJS
+ if (7 - endOffset) result.shiftRight(7 - endOffset, false);
+ //endregion
+
+ //region Set final number of bits
+ result.bitsCount = end - start + 1;
+ //endregion
+
+ //region Cut unnecessary bytes from result
+ result.shrink();
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleReturnPointsJS
+ /**
+ * Return copy of existing "BitStream"
+ * @param {?number} [start=null] Start position of the copy (in bits)
+ * @param {?number} [length=null] Length of the copy (in bits)
+ * @returns {BitStream}
+ */
+ copy(start = null, length = null) {
+ //region Check input parameters
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (start < 0 || start > (this.view.length << 3) - 1) return new BitStream(); //("Wrong start position: " + start);
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS
+ if (length === null) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = (this.view.length << 3) - start - 1;
+ }
+
+ // noinspection NonBlockStatementBodyJS
+ if (length > this.bitsCount) return new BitStream(); //("Maximum length is " + this.bitsCount);
+ //endregion
+
+ return this.slice(start, start + length - 1);
+ }
+ //**********************************************************************************
+ /**
+ * Shrink unnecessary bytes in current stream accordingly to "bitsCount" value
+ */
+ shrink() {
+ // noinspection ConditionalExpressionJS
+ const currentLength = (this.bitsCount >> 3) + (this.bitsCount % 8 ? 1 : 0);
+ if (currentLength < this.buffer.byteLength) {
+ //region Change size of buffer
+ const buffer = new ArrayBuffer(currentLength);
+ const view = new Uint8Array(buffer);
+
+ // noinspection NestedFunctionCallJS
+ view.set(new Uint8Array(this.buffer, this.buffer.byteLength - currentLength, currentLength));
+ //endregion
+
+ //region Store final array into current stream
+ this.buffer = buffer.slice(0);
+ this.view = new Uint8Array(this.buffer);
+ //endregion
+ }
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Reverse bits order in each byte in the stream
+ * Got it from here: http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits
+ */
+ reverseBytes() {
+ //region Reverse bits order in each byte in the stream
+ for (let i = 0; i < this.view.length; i++) {
+ // noinspection MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ this.view[i] = (this.view[i] * 0x0802 & 0x22110 | this.view[i] * 0x8020 & 0x88440) * 0x10101 >> 16;
+ }
+ //endregion
+
+ //region Shift "most significant" byte
+ if (this.bitsCount % 8) {
+ // noinspection ConditionalExpressionJS
+ const currentLength = (this.bitsCount >> 3) + (this.bitsCount % 8 ? 1 : 0);
+ // noinspection MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ this.view[this.view.length - currentLength] >>= 8 - (this.bitsCount & 0x07);
+ }
+ //endregion
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Reverse all bits in entire "BitStream"
+ */
+ reverseValue() {
+ const initialValue = this.toString();
+ const initialValueLength = initialValue.length;
+
+ const reversedValue = new Array(initialValueLength);
+
+ // noinspection NonBlockStatementBodyJS
+ for (let i = 0; i < initialValueLength; i++) reversedValue[initialValueLength - 1 - i] = initialValue[i];
+
+ // noinspection NestedFunctionCallJS
+ this.fromString(reversedValue.join(""));
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS
+ /**
+ * Trying to represent entire "BitStream" as an unsigned integer.
+ * @return {number}
+ */
+ getNumberValue() {
+ //region Initial variables
+ const byteLength = this.buffer.byteLength - 1;
+ //endregion
+
+ //region Check posibility for convertion
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ if (byteLength > 3) return -1;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, EqualityComparisonWithCoercionJS, NonBlockStatementBodyJS
+ if (byteLength == -1) return 0;
+ //endregion
+
+ //region Convert byte array to "Uint32Array" value
+ const value = new Uint32Array(1);
+ const view = new Uint8Array(value.buffer);
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, NonBlockStatementBodyJS
+ for (let i = byteLength; i >= 0; i--) view[byteLength - i] = this.view[i];
+ //endregion
+
+ return value[0];
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Find any bit pattern in "BitStream"
+ * @param {BitStream} pattern Stream having pattern value
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @param {boolean} [backward=false] Flag to search in backward order
+ * @returns {number}
+ */
+ findPattern(pattern, start = null, length = null, backward = false) {
+ //region Convert "BitStream" values to "ByteStream"
+ const stringStream = new ByteStream({
+ string: this.toString()
+ });
+ const stringPattern = new ByteStream({
+ string: pattern.toString()
+ });
+ //endregion
+
+ return stringStream.findPattern(stringPattern, start, length, backward);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Find first position of any pattern from input array
+ * @param {Array.<BitStream>} patterns Array with patterns which should be found
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @param {boolean} [backward=false] Flag to search in backward order
+ * @returns {{id: number, position: number}}
+ */
+ findFirstIn(patterns, start = null, length = null, backward = false) {
+ //region Convert "BitStream" values to "ByteStream"
+ const stringStream = new ByteStream({
+ string: this.toString()
+ });
+
+ const stringPatterns = new Array(patterns.length);
+
+ for (let i = 0; i < patterns.length; i++) {
+ stringPatterns[i] = new ByteStream({
+ string: patterns[i].toString()
+ });
+ }
+ //endregion
+
+ return stringStream.findFirstIn(stringPatterns, start, length, backward);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Find all positions of any pattern from input array
+ * @param {Array.<BitStream>} patterns Array with patterns which should be found
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @returns {Array}
+ */
+ findAllIn(patterns, start = null, length = null) {
+ //region Convert "BitStream" values to "ByteStream"
+ const stringStream = new ByteStream({
+ string: this.toString()
+ });
+
+ const stringPatterns = new Array(patterns.length);
+
+ for (let i = 0; i < patterns.length; i++) {
+ stringPatterns[i] = new ByteStream({
+ string: patterns[i].toString()
+ });
+ }
+ //endregion
+
+ return stringStream.findAllIn(stringPatterns, start, length);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Find all positions of a pattern
+ * @param {BitStream} pattern Stream having pattern value
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @returns {Array|number}
+ */
+ findAllPatternIn(pattern, start = null, length = null) {
+ //region Convert "BitStream" values to "ByteStream"
+ const stringStream = new ByteStream({
+ string: this.toString()
+ });
+ const stringPattern = new ByteStream({
+ string: pattern.toString()
+ });
+ //endregion
+
+ return stringStream.findAllPatternIn(stringPattern, start, length);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Find first position of data, not included in patterns from input array
+ * @param {Array.<BitStream>} patterns Array with patterns which should be found
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @param {boolean} [backward=false] Flag to search in backward order
+ * @returns {{left: {id: number, position: *}, right: {id: number, position: number}, value: ByteStream}}
+ */
+ findFirstNotIn(patterns, start = null, length = null, backward = false) {
+ //region Convert "BitStream" values to "ByteStream"
+ const stringStream = new ByteStream({
+ string: this.toString()
+ });
+
+ const stringPatterns = new Array(patterns.length);
+
+ for (let i = 0; i < patterns.length; i++) {
+ stringPatterns[i] = new ByteStream({
+ string: patterns[i].toString()
+ });
+ }
+ //endregion
+
+ return stringStream.findFirstNotIn(stringPatterns, start, length, backward);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Find all positions of data, not included in patterns from input array
+ * @param {Array.<BitStream>} patterns Array with patterns which should be found
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @returns {Array}
+ */
+ findAllNotIn(patterns, start = null, length = null) {
+ //region Convert "BitStream" values to "ByteStream"
+ const stringStream = new ByteStream({
+ string: this.toString()
+ });
+
+ const stringPatterns = new Array(patterns.length);
+
+ for (let i = 0; i < patterns.length; i++) {
+ stringPatterns[i] = new ByteStream({
+ string: patterns[i].toString()
+ });
+ }
+ //endregion
+
+ return stringStream.findAllNotIn(stringPatterns, start, length);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Find position of a sequence of any patterns from input array
+ * @param {Array.<BitStream>} patterns Array with patterns which should be found
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @param {boolean} [backward=false] Flag to search in backward order
+ * @returns {{position, value}|*}
+ */
+ findFirstSequence(patterns, start = null, length = null, backward = false) {
+ //region Convert "BitStream" values to "ByteStream"
+ const stringStream = new ByteStream({
+ string: this.toString()
+ });
+
+ const stringPatterns = new Array(patterns.length);
+
+ for (let i = 0; i < patterns.length; i++) {
+ stringPatterns[i] = new ByteStream({
+ string: patterns[i].toString()
+ });
+ }
+ //endregion
+
+ return stringStream.findFirstSequence(stringPatterns, start, length, backward);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Find position of a sequence of any patterns from input array
+ * @param {Array.<BitStream>} patterns Array with patterns which should be found
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @returns {Array}
+ */
+ findAllSequences(patterns, start, length) {
+ //region Convert "BitStream" values to "ByteStream"
+ const stringStream = new ByteStream({
+ string: this.toString()
+ });
+
+ const stringPatterns = new Array(patterns.length);
+
+ for (let i = 0; i < patterns.length; i++) {
+ stringPatterns[i] = new ByteStream({
+ string: patterns[i].toString()
+ });
+ }
+ //endregion
+
+ return stringStream.findAllSequences(stringPatterns, start, length);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Find all paired patterns in the stream
+ * @param {BitStream} leftPattern Left pattern to search for
+ * @param {BitStream} rightPattern Right pattern to search for
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @returns {Array}
+ */
+ findPairedPatterns(leftPattern, rightPattern, start = null, length = null) {
+ //region Convert "BitStream" values to "ByteStream"
+ const stringStream = new ByteStream({
+ string: this.toString()
+ });
+ const stringLeftPattern = new ByteStream({
+ string: leftPattern.toString()
+ });
+ const stringRightPattern = new ByteStream({
+ string: rightPattern.toString()
+ });
+ //endregion
+
+ return stringStream.findPairedPatterns(stringLeftPattern, stringRightPattern, start, length);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleLoopsJS
+ /**
+ * Find all paired patterns in the stream
+ * @param {Array.<BitStream>} inputLeftPatterns Array of left patterns to search for
+ * @param {Array.<BitStream>} inputRightPatterns Array of right patterns to search for
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @returns {Array}
+ */
+ findPairedArrays(inputLeftPatterns, inputRightPatterns, start = null, length = null) {
+ //region Convert "BitStream" values to "ByteStream"
+ const stringStream = new ByteStream({
+ string: this.toString()
+ });
+
+ const stringLeftPatterns = new Array(inputLeftPatterns.length);
+
+ for (let i = 0; i < inputLeftPatterns.length; i++) {
+ stringLeftPatterns[i] = new ByteStream({
+ string: inputLeftPatterns[i].toString()
+ });
+ }
+
+ const stringRightPatterns = new Array(inputRightPatterns.length);
+
+ for (let i = 0; i < inputRightPatterns.length; i++) {
+ stringRightPatterns[i] = new ByteStream({
+ string: inputRightPatterns[i].toString()
+ });
+ }
+ //endregion
+
+ return stringStream.findPairedArrays(stringLeftPatterns, stringRightPatterns, start, length);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleReturnPointsJS
+ /**
+ * Replace one pattern with other
+ * @param {BitStream} searchPattern The pattern to search for
+ * @param {BitStream} replacePattern The pattern to replace initial pattern
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @returns {boolean}
+ */
+ replacePattern(searchPattern, replacePattern, start = null, length = null) {
+ //region Convert "BitStream" values to "ByteStream"
+ const stringStream = new ByteStream({
+ string: this.toString()
+ });
+ const stringSearchPattern = new ByteStream({
+ string: searchPattern.toString()
+ });
+ const stringReplacePattern = new ByteStream({
+ string: replacePattern.toString()
+ });
+ //endregion
+
+ //region Re-initialize existing data
+ if (stringStream.findPairedPatterns(stringSearchPattern, stringReplacePattern, start, length)) {
+ // noinspection NestedFunctionCallJS
+ this.fromString(stringStream.toString());
+ return true;
+ }
+ //endregion
+
+ return false;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Skip any pattern from input array
+ * @param {Array.<BitStream>} patterns Array with patterns which should be ommited
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @param {boolean} [backward=false] Flag to search in backward order
+ * @returns {*}
+ */
+ skipPatterns(patterns, start, length, backward) {
+ //region Convert "BitStream" values to "ByteStream"
+ const stringStream = new ByteStream({
+ string: this.toString()
+ });
+
+ const stringPatterns = new Array(patterns.length);
+
+ for (let i = 0; i < patterns.length; i++) {
+ stringPatterns[i] = new ByteStream({
+ string: patterns[i].toString()
+ });
+ }
+ //endregion
+
+ return stringStream.skipPatterns(stringPatterns, start, length, backward);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Skip any pattern not from input array
+ * @param {Array.<BitStream>} patterns Array with patterns which should be ommited
+ * @param {?number} [start=null] Start position to search from
+ * @param {?number} [length=null] Length of byte block to search at
+ * @param {boolean} [backward=false] Flag to search in backward order
+ * @returns {number}
+ */
+ skipNotPatterns(patterns, start, length, backward) {
+ //region Convert "BitStream" values to "ByteStream"
+ const stringStream = new ByteStream({
+ string: this.toString()
+ });
+
+ const stringPatterns = new Array(patterns.length);
+
+ for (let i = 0; i < patterns.length; i++) {
+ stringPatterns[i] = new ByteStream({
+ string: patterns[i].toString()
+ });
+ }
+ //endregion
+
+ return stringStream.skipNotPatterns(stringPatterns, start, length, backward);
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Append a new "BitStream" content to the current "BitStream"
+ * @param {BitStream} stream A new "stream" to append to current "stream"
+ */
+ append(stream) {
+ //region Initialize current stream with new data
+ // noinspection NestedFunctionCallJS
+ this.fromString([this.toString(), stream.toString()].join(""));
+ //endregion
+ }
+ //**********************************************************************************
+}
+exports.BitStream = BitStream; //**************************************************************************************
+
+class SeqBitStream {
+ //**********************************************************************************
+ constructor(parameters = {}) {
+ //region Internal variables
+ this.stream = new BitStream();
+
+ this._start = 0;
+ this._length = this.stream.bitsCount;
+
+ this.backward = false;
+
+ this.appendBlock = 0;
+ //endregion
+
+ var _iteratorNormalCompletion4 = true;
+ var _didIteratorError4 = false;
+ var _iteratorError4 = undefined;
+
+ try {
+ for (var _iterator4 = Object.keys(parameters)[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
+ const key = _step4.value;
+
+ switch (key) {
+ case "stream":
+ case "start":
+ case "length":
+ case "backward":
+ case "appendBlock":
+ this[key] = parameters[key];
+ break;
+ default:
+ }
+ }
+ } catch (err) {
+ _didIteratorError4 = true;
+ _iteratorError4 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion4 && _iterator4.return) {
+ _iterator4.return();
+ }
+ } finally {
+ if (_didIteratorError4) {
+ throw _iteratorError4;
+ }
+ }
+ }
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleReturnPointsJS
+ set start(value) {
+ // noinspection NonBlockStatementBodyJS
+ if (value > this.stream.bitsCount) return;
+
+ // noinspection ConditionalExpressionJS
+ this._length -= this.backward ? this._start - value : value - this._start;
+ this._start = value;
+
+ //region Initialization of "prev" internal variables
+ // noinspection JSUnusedGlobalSymbols
+ this.prevStart = this._start;
+ // noinspection JSUnusedGlobalSymbols
+ this.prevLength = this._length;
+ //endregion
+ }
+ //**********************************************************************************
+ get start() {
+ return this._start;
+ }
+ //**********************************************************************************
+ // noinspection FunctionWithMultipleReturnPointsJS
+ set length(value) {
+ // noinspection NonBlockStatementBodyJS
+ if (value > this.stream.bitsCount) return;
+
+ // noinspection JSUnusedGlobalSymbols
+ this.prevLength = this._length;
+ this._length = value;
+ }
+ //**********************************************************************************
+ get length() {
+ return this._length;
+ }
+ //**********************************************************************************
+ set stream(value) {
+ this._stream = value;
+
+ // noinspection JSUnusedGlobalSymbols
+ this.prevLength = this._length;
+ this._length = value.bitsCount;
+
+ // noinspection JSUnusedGlobalSymbols
+ this.prevStart = this._start;
+ // noinspection ConditionalExpressionJS
+ this._start = this.backward ? this.length : 0;
+ }
+ //**********************************************************************************
+ get stream() {
+ return this._stream;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols
+ /**
+ * Get next "length" bits from the stream
+ * @param {number} length Number of bits to read
+ * @returns {*}
+ */
+ getBits(length) {
+ //region Check input parameters
+ if (this.start + length > this.stream.bitsCount) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.stream.bitsCount - this.start;
+ }
+ //endregion
+
+ //region Initial variables
+ let result;
+ //endregion
+
+ //region Copy necessary length of bits
+ if (this.backward) {
+ result = this.stream.copy(this.start - length, length);
+ this.start -= result.bitsCount;
+ } else {
+ result = this.stream.copy(this.start, length);
+ this.start += result.bitsCount;
+ }
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection FunctionTooLongJS
+ /**
+ * Get string representation for the next "length" bits from the stream
+ * @param {number} length Number of bits to read
+ * @returns {string}
+ */
+ getBitsString(length) {
+ //region Check input parameters
+ if (this.start + length > this.stream.bitsCount) {
+ // noinspection AssignmentToFunctionParameterJS
+ length = this.stream.bitsCount - this.start;
+ }
+ //endregion
+
+ //region Initial variables
+ let result = [];
+
+ let start;
+
+ // noinspection NonBlockStatementBodyJS
+ if (this.backward) start = this.start - length;else start = this.start;
+
+ let end = this.start + length - 1;
+
+ //region Make ability to pass non-value bits
+ let valueShift = 0;
+ // noinspection NonBlockStatementBodyJS
+ if (this.stream.bitsCount % 8) valueShift = 8 - this.stream.bitsCount % 8;
+
+ start += valueShift;
+ end += valueShift;
+ //endregion
+
+ const startIndex = start >> 3;
+ // noinspection MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const startOffset = start & 0x07;
+
+ const endIndex = end >> 3;
+ // noinspection MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const endOffset = end & 0x07;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, ConditionalExpressionJS, EqualityComparisonWithCoercionJS
+ const bitsLengthIndex = startIndex + (endIndex - startIndex == 0 ? 1 : endIndex - startIndex + 1);
+ //endregion
+
+ //region Get string representation of bits
+ for (let i = startIndex; i < bitsLengthIndex; i++) {
+ let value = bitsToStringArray[this.stream.view[i]];
+
+ // noinspection EqualityComparisonWithCoercionJS, NonBlockStatementBodyJS
+ if (i == startIndex) value = value.slice(startOffset);
+
+ // noinspection EqualityComparisonWithCoercionJS, NonBlockStatementBodyJS
+ if (i == bitsLengthIndex - 1) value = value.slice(0, endOffset - 7 + value.length);
+
+ result.push(value);
+ }
+
+ result = result.join("");
+ //endregion
+
+ //region Change internal values
+ // noinspection NonBlockStatementBodyJS
+ if (this.backward) this.start -= result.length;else this.start += result.length;
+ //endregion
+
+ return result;
+ }
+ //**********************************************************************************
+ // noinspection JSUnusedGlobalSymbols, FunctionWithMultipleLoopsJS, FunctionWithMultipleReturnPointsJS
+ /**
+ * Get number value representation of the next "length" bits from the stream, preliminary reversed
+ * @param {number} length Number of bits to read
+ * @returns {*}
+ */
+ getBitsReversedValue(length) {
+ //region Initial variables
+ const initialValue = this.getBitsString(length);
+ const initialValueLength = initialValue.length;
+
+ let byteIndex;
+
+ const initialOffset = 8 - initialValueLength % 8;
+
+ const reversedValue = new Array(initialValueLength);
+
+ const value = new Uint32Array(1);
+ const valueView = new Uint8Array(value.buffer, 0, 4);
+
+ let i;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, MagicNumberJS, NonBlockStatementBodyJS
+ if (initialValueLength > 32) return -1;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, MagicNumberJS, EqualityComparisonWithCoercionJS, NonBlockStatementBodyJS
+ if (length == 32) byteIndex = 3;else byteIndex = initialValueLength - 1 >> 3;
+ //endregion
+
+ //region Reverse value
+ // noinspection NonBlockStatementBodyJS
+ for (i = 0; i < initialValueLength; i++) reversedValue[initialValueLength - 1 - i] = initialValue[i];
+ //endregion
+
+ //region Convert byte array to "Uint32Array" value
+ for (i = initialOffset; i < initialOffset + initialValueLength; i++) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, EqualityComparisonWithCoercionJS
+ if (reversedValue[i - initialOffset] == "1") {
+ // noinspection MagicNumberJS
+ valueView[byteIndex] |= 0x01 << 7 - i % 8;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS, ConstantOnLeftSideOfComparisonJS, EqualityComparisonWithCoercionJS, NonBlockStatementBodyJS
+ if (i && (i + 1) % 8 == 0) byteIndex--;
+ }
+ //endregion
+
+ return value[0];
+ }
+ //**********************************************************************************
+ /**
+ * Represent remaining bits in "BitStream" as a string
+ * @return {string}
+ */
+ toString() {
+ const streamToDisplay = this.stream.copy(this.start, this.length);
+ return streamToDisplay.toString();
+ }
+ //**********************************************************************************
+}
+exports.SeqBitStream = SeqBitStream; //**************************************************************************************
+
+},{}],2:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _GeneralName = _interopRequireDefault(require("./GeneralName.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class AccessDescription {
+ //**********************************************************************************
+
+ /**
+ * Constructor for AccessDescription class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc The type and format of the information are specified by the accessMethod field. This profile defines two accessMethod OIDs: id-ad-caIssuers and id-ad-ocsp
+ */
+ this.accessMethod = (0, _pvutils.getParametersValue)(parameters, "accessMethod", AccessDescription.defaultValues("accessMethod"));
+ /**
+ * @type {GeneralName}
+ * @desc The accessLocation field specifies the location of the information
+ */
+
+ this.accessLocation = (0, _pvutils.getParametersValue)(parameters, "accessLocation", AccessDescription.defaultValues("accessLocation")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "accessMethod":
+ return "";
+
+ case "accessLocation":
+ return new _GeneralName.default();
+
+ default:
+ throw new Error(`Invalid member name for AccessDescription class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * AccessDescription ::= SEQUENCE {
+ * accessMethod OBJECT IDENTIFIER,
+ * accessLocation GeneralName }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [accessMethod]
+ * @property {string} [accessLocation]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.accessMethod || ""
+ }), _GeneralName.default.schema(names.accessLocation || {})]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["accessMethod", "accessLocation"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, AccessDescription.schema({
+ names: {
+ accessMethod: "accessMethod",
+ accessLocation: {
+ names: {
+ blockName: "accessLocation"
+ }
+ }
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for AccessDescription"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.accessMethod = asn1.result.accessMethod.valueBlock.toString();
+ this.accessLocation = new _GeneralName.default({
+ schema: asn1.result.accessLocation
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [new asn1js.ObjectIdentifier({
+ value: this.accessMethod
+ }), this.accessLocation.toSchema()]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ accessMethod: this.accessMethod,
+ accessLocation: this.accessLocation.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = AccessDescription;
+
+},{"./GeneralName.js":40,"asn1js":112,"pvutils":113}],3:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC3161. Accuracy represents the time deviation around the UTC time contained in GeneralizedTime.
+ */
+class Accuracy {
+ //**********************************************************************************
+
+ /**
+ * Constructor for Accuracy class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+ if ("seconds" in parameters)
+ /**
+ * @type {number}
+ * @desc seconds
+ */
+ this.seconds = (0, _pvutils.getParametersValue)(parameters, "seconds", Accuracy.defaultValues("seconds"));
+ if ("millis" in parameters)
+ /**
+ * @type {number}
+ * @desc millis
+ */
+ this.millis = (0, _pvutils.getParametersValue)(parameters, "millis", Accuracy.defaultValues("millis"));
+ if ("micros" in parameters)
+ /**
+ * @type {number}
+ * @desc micros
+ */
+ this.micros = (0, _pvutils.getParametersValue)(parameters, "micros", Accuracy.defaultValues("micros")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "seconds":
+ case "millis":
+ case "micros":
+ return 0;
+
+ default:
+ throw new Error(`Invalid member name for Accuracy class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "seconds":
+ case "millis":
+ case "micros":
+ return memberValue === Accuracy.defaultValues(memberName);
+
+ default:
+ throw new Error(`Invalid member name for Accuracy class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * Accuracy ::= SEQUENCE {
+ * seconds INTEGER OPTIONAL,
+ * millis [0] INTEGER (1..999) OPTIONAL,
+ * micros [1] INTEGER (1..999) OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [seconds]
+ * @property {string} [millis]
+ * @property {string} [micros]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ optional: true,
+ value: [new asn1js.Integer({
+ optional: true,
+ name: names.seconds || ""
+ }), new asn1js.Primitive({
+ name: names.millis || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ }
+ }), new asn1js.Primitive({
+ name: names.micros || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ }
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["seconds", "millis", "micros"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, Accuracy.schema({
+ names: {
+ seconds: "seconds",
+ millis: "millis",
+ micros: "micros"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for Accuracy"); //endregion
+ //region Get internal properties from parsed schema
+
+ if ("seconds" in asn1.result) this.seconds = asn1.result.seconds.valueBlock.valueDec;
+
+ if ("millis" in asn1.result) {
+ const intMillis = new asn1js.Integer({
+ valueHex: asn1.result.millis.valueBlock.valueHex
+ });
+ this.millis = intMillis.valueBlock.valueDec;
+ }
+
+ if ("micros" in asn1.result) {
+ const intMicros = new asn1js.Integer({
+ valueHex: asn1.result.micros.valueBlock.valueHex
+ });
+ this.micros = intMicros.valueBlock.valueDec;
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array of output sequence
+ const outputArray = [];
+ if ("seconds" in this) outputArray.push(new asn1js.Integer({
+ value: this.seconds
+ }));
+
+ if ("millis" in this) {
+ const intMillis = new asn1js.Integer({
+ value: this.millis
+ });
+ outputArray.push(new asn1js.Primitive({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ valueHex: intMillis.valueBlock.valueHex
+ }));
+ }
+
+ if ("micros" in this) {
+ const intMicros = new asn1js.Integer({
+ value: this.micros
+ });
+ outputArray.push(new asn1js.Primitive({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ valueHex: intMicros.valueBlock.valueHex
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {};
+ if ("seconds" in this) _object.seconds = this.seconds;
+ if ("millis" in this) _object.millis = this.millis;
+ if ("micros" in this) _object.micros = this.micros;
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = Accuracy;
+
+},{"asn1js":112,"pvutils":113}],4:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class AlgorithmIdentifier {
+ //**********************************************************************************
+
+ /**
+ * Constructor for AlgorithmIdentifier class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ * @property {string} [algorithmId] ObjectIdentifier for algorithm (string representation)
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc ObjectIdentifier for algorithm (string representation)
+ */
+ this.algorithmId = (0, _pvutils.getParametersValue)(parameters, "algorithmId", AlgorithmIdentifier.defaultValues("algorithmId"));
+ if ("algorithmParams" in parameters)
+ /**
+ * @type {Object}
+ * @desc Any algorithm parameters
+ */
+ this.algorithmParams = (0, _pvutils.getParametersValue)(parameters, "algorithmParams", AlgorithmIdentifier.defaultValues("algorithmParams")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "algorithmId":
+ return "";
+
+ case "algorithmParams":
+ return new asn1js.Any();
+
+ default:
+ throw new Error(`Invalid member name for AlgorithmIdentifier class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "algorithmId":
+ return memberValue === "";
+
+ case "algorithmParams":
+ return memberValue instanceof asn1js.Any;
+
+ default:
+ throw new Error(`Invalid member name for AlgorithmIdentifier class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * AlgorithmIdentifier ::= Sequence {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} algorithmIdentifier ObjectIdentifier for the algorithm
+ * @property {string} algorithmParams Any algorithm parameters
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ optional: names.optional || false,
+ value: [new asn1js.ObjectIdentifier({
+ name: names.algorithmIdentifier || ""
+ }), new asn1js.Any({
+ name: names.algorithmParams || "",
+ optional: true
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["algorithm", "params"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, AlgorithmIdentifier.schema({
+ names: {
+ algorithmIdentifier: "algorithm",
+ algorithmParams: "params"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for AlgorithmIdentifier"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.algorithmId = asn1.result.algorithm.valueBlock.toString();
+ if ("params" in asn1.result) this.algorithmParams = asn1.result.params; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(new asn1js.ObjectIdentifier({
+ value: this.algorithmId
+ }));
+ if ("algorithmParams" in this && this.algorithmParams instanceof asn1js.Any === false) outputArray.push(this.algorithmParams); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {
+ algorithmId: this.algorithmId
+ };
+ if ("algorithmParams" in this && this.algorithmParams instanceof asn1js.Any === false) object.algorithmParams = this.algorithmParams.toJSON();
+ return object;
+ } //**********************************************************************************
+
+ /**
+ * Check that two "AlgorithmIdentifiers" are equal
+ * @param {AlgorithmIdentifier} algorithmIdentifier
+ * @returns {boolean}
+ */
+
+
+ isEqual(algorithmIdentifier) {
+ //region Check input type
+ if (algorithmIdentifier instanceof AlgorithmIdentifier === false) return false; //endregion
+ //region Check "algorithm_id"
+
+ if (this.algorithmId !== algorithmIdentifier.algorithmId) return false; //endregion
+ //region Check "algorithm_params"
+
+ if ("algorithmParams" in this) {
+ if ("algorithmParams" in algorithmIdentifier) return JSON.stringify(this.algorithmParams) === JSON.stringify(algorithmIdentifier.algorithmParams);
+ return false;
+ }
+
+ if ("algorithmParams" in algorithmIdentifier) return false; //endregion
+
+ return true;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = AlgorithmIdentifier;
+
+},{"asn1js":112,"pvutils":113}],5:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _GeneralName = _interopRequireDefault(require("./GeneralName.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class AltName {
+ //**********************************************************************************
+
+ /**
+ * Constructor for AltName class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array.<GeneralName>}
+ * @desc Array of alternative names in GeneralName type
+ */
+ this.altNames = (0, _pvutils.getParametersValue)(parameters, "altNames", AltName.defaultValues("altNames")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "altNames":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for AltName class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * AltName ::= GeneralNames
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [altNames]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Repeated({
+ name: names.altNames || "",
+ value: _GeneralName.default.schema()
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["altNames"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, AltName.schema({
+ names: {
+ altNames: "altNames"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for AltName"); //endregion
+ //region Get internal properties from parsed schema
+
+ if ("altNames" in asn1.result) this.altNames = Array.from(asn1.result.altNames, element => new _GeneralName.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: Array.from(this.altNames, element => element.toSchema())
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ altNames: Array.from(this.altNames, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = AltName;
+
+},{"./GeneralName.js":40,"asn1js":112,"pvutils":113}],6:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC2986
+ */
+class Attribute {
+ //**********************************************************************************
+
+ /**
+ * Constructor for Attribute class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc ObjectIdentifier for attribute (string representation)
+ */
+ this.type = (0, _pvutils.getParametersValue)(parameters, "type", Attribute.defaultValues("type"));
+ /**
+ * @type {Array}
+ * @desc Any attribute values
+ */
+
+ this.values = (0, _pvutils.getParametersValue)(parameters, "values", Attribute.defaultValues("values")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "type":
+ return "";
+
+ case "values":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for Attribute class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "type":
+ return memberValue === "";
+
+ case "values":
+ return memberValue.length === 0;
+
+ default:
+ throw new Error(`Invalid member name for Attribute class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
+ * type ATTRIBUTE.&id({IOSet}),
+ * values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type})
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [type]
+ * @property {string} [setName]
+ * @property {string} [values]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.type || ""
+ }), new asn1js.Set({
+ name: names.setName || "",
+ value: [new asn1js.Repeated({
+ name: names.values || "",
+ value: new asn1js.Any()
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["type", "values"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, Attribute.schema({
+ names: {
+ type: "type",
+ values: "values"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for Attribute"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.type = asn1.result.type.valueBlock.toString();
+ this.values = asn1.result.values; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [new asn1js.ObjectIdentifier({
+ value: this.type
+ }), new asn1js.Set({
+ value: this.values
+ })]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ type: this.type,
+ values: Array.from(this.values, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = Attribute;
+
+},{"asn1js":112,"pvutils":113}],7:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = exports.AttributeCertificateInfoV1 = exports.IssuerSerial = exports.AttCertValidityPeriod = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _GeneralNames = _interopRequireDefault(require("./GeneralNames.js"));
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _Attribute = _interopRequireDefault(require("./Attribute.js"));
+
+var _Extensions = _interopRequireDefault(require("./Extensions.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5755
+ */
+class AttCertValidityPeriod {
+ //**********************************************************************************
+
+ /**
+ * Constructor for AttCertValidityPeriod class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {GeneralizedTime}
+ * @desc notBeforeTime
+ */
+ this.notBeforeTime = (0, _pvutils.getParametersValue)(parameters, "notBeforeTime", AttCertValidityPeriod.defaultValues("notBeforeTime"));
+ /**
+ * @type {GeneralizedTime}
+ * @desc notAfterTime
+ */
+
+ this.notAfterTime = (0, _pvutils.getParametersValue)(parameters, "notAfterTime", AttCertValidityPeriod.defaultValues("notAfterTime")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "notBeforeTime":
+ case "notAfterTime":
+ return new Date(0, 0, 0);
+
+ default:
+ throw new Error(`Invalid member name for AttCertValidityPeriod class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * AttCertValidityPeriod ::= SEQUENCE {
+ * notBeforeTime GeneralizedTime,
+ * notAfterTime GeneralizedTime
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [notBeforeTime]
+ * @property {string} [notAfterTime]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.GeneralizedTime({
+ name: names.notBeforeTime || ""
+ }), new asn1js.GeneralizedTime({
+ name: names.notAfterTime || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["notBeforeTime", "notAfterTime"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, AttCertValidityPeriod.schema({
+ names: {
+ notBeforeTime: "notBeforeTime",
+ notAfterTime: "notAfterTime"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for AttCertValidityPeriod"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.notBeforeTime = asn1.result.notBeforeTime.toDate();
+ this.notAfterTime = asn1.result.notAfterTime.toDate(); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [new asn1js.GeneralizedTime({
+ valueDate: this.notBeforeTime
+ }), new asn1js.GeneralizedTime({
+ valueDate: this.notAfterTime
+ })]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ notBeforeTime: this.notBeforeTime,
+ notAfterTime: this.notAfterTime
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * Class from RFC5755
+ */
+
+
+exports.AttCertValidityPeriod = AttCertValidityPeriod;
+
+class IssuerSerial {
+ //**********************************************************************************
+
+ /**
+ * Constructor for IssuerSerial class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {RelativeDistinguishedNames}
+ * @desc issuer
+ */
+ this.issuer = (0, _pvutils.getParametersValue)(parameters, "issuer", IssuerSerial.defaultValues("issuer"));
+ /**
+ * @type {Integer}
+ * @desc serialNumber
+ */
+
+ this.serialNumber = (0, _pvutils.getParametersValue)(parameters, "serialNumber", IssuerSerial.defaultValues("serialNumber"));
+ if ("issuerUID" in parameters)
+ /**
+ * @type {BitString}
+ * @desc issuerUID
+ */
+ this.issuerUID = (0, _pvutils.getParametersValue)(parameters, "issuerUID", IssuerSerial.defaultValues("issuerUID")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "issuer":
+ return new _GeneralNames.default();
+
+ case "serialNumber":
+ return new asn1js.Integer();
+
+ case "issuerUID":
+ return new asn1js.BitString();
+
+ default:
+ throw new Error(`Invalid member name for IssuerSerial class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * IssuerSerial ::= SEQUENCE {
+ * issuer GeneralNames,
+ * serial CertificateSerialNumber,
+ * issuerUID UniqueIdentifier OPTIONAL
+ * }
+ *
+ * CertificateSerialNumber ::= INTEGER
+ * UniqueIdentifier ::= BIT STRING
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [issuer]
+ * @property {string} [serialNumber]
+ * @property {string} [issuerUID]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [_GeneralNames.default.schema(names.issuer || {}), new asn1js.Integer({
+ name: names.serialNumber || ""
+ }), new asn1js.BitString({
+ optional: true,
+ name: names.issuerUID || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["issuer", "serialNumber", "issuerUID"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, IssuerSerial.schema({
+ names: {
+ issuer: {
+ names: {
+ blockName: "issuer"
+ }
+ },
+ serialNumber: "serialNumber",
+ issuerUID: "issuerUID"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for IssuerSerial"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.issuer = new _GeneralNames.default({
+ schema: asn1.result.issuer
+ });
+ this.serialNumber = asn1.result.serialNumber;
+ if ("issuerUID" in asn1.result) this.issuerUID = asn1.result.issuerUID; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ const result = new asn1js.Sequence({
+ value: [this.issuer.toSchema(), this.serialNumber]
+ });
+ if ("issuerUID" in this) result.valueBlock.value.push(this.issuerUID); //region Construct and return new ASN.1 schema for this object
+
+ return result; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const result = {
+ issuer: this.issuer.toJSON(),
+ serialNumber: this.serialNumber.toJSON()
+ };
+ if ("issuerUID" in this) result.issuerUID = this.issuerUID.toJSON();
+ return result;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * Class from RFC5755
+ */
+
+
+exports.IssuerSerial = IssuerSerial;
+
+class AttributeCertificateInfoV1 {
+ //**********************************************************************************
+
+ /**
+ * Constructor for AttributeCertificateInfoV1 class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", AttributeCertificateInfoV1.defaultValues("version"));
+ if ("baseCertificateID" in parameters)
+ /**
+ * @type {IssuerSerial}
+ * @desc baseCertificateID
+ */
+ this.baseCertificateID = (0, _pvutils.getParametersValue)(parameters, "baseCertificateID", AttributeCertificateInfoV1.defaultValues("baseCertificateID"));
+ if ("subjectName" in parameters)
+ /**
+ * @type {GeneralNames}
+ * @desc subjectName
+ */
+ this.subjectName = (0, _pvutils.getParametersValue)(parameters, "subjectName", AttributeCertificateInfoV1.defaultValues("subjectName"));
+ /**
+ * @type {GeneralNames}
+ * @desc issuer
+ */
+
+ this.issuer = (0, _pvutils.getParametersValue)(parameters, "issuer", AttributeCertificateInfoV1.defaultValues("issuer"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc signature
+ */
+
+ this.signature = (0, _pvutils.getParametersValue)(parameters, "signature", AttributeCertificateInfoV1.defaultValues("signature"));
+ /**
+ * @type {Integer}
+ * @desc serialNumber
+ */
+
+ this.serialNumber = (0, _pvutils.getParametersValue)(parameters, "serialNumber", AttributeCertificateInfoV1.defaultValues("serialNumber"));
+ /**
+ * @type {AttCertValidityPeriod}
+ * @desc attrCertValidityPeriod
+ */
+
+ this.attrCertValidityPeriod = (0, _pvutils.getParametersValue)(parameters, "attrCertValidityPeriod", AttributeCertificateInfoV1.defaultValues("attrCertValidityPeriod"));
+ /**
+ * @type {Array.<Attribute>}
+ * @desc attributes
+ */
+
+ this.attributes = (0, _pvutils.getParametersValue)(parameters, "attributes", AttributeCertificateInfoV1.defaultValues("attributes"));
+ if ("issuerUniqueID" in parameters)
+ /**
+ * @type {BitString}
+ * @desc issuerUniqueID
+ */
+ this.issuerUniqueID = (0, _pvutils.getParametersValue)(parameters, "issuerUniqueID", AttributeCertificateInfoV1.defaultValues("issuerUniqueID"));
+ if ("extensions" in parameters)
+ /**
+ * @type {Extensions}
+ * @desc extensions
+ */
+ this.extensions = (0, _pvutils.getParametersValue)(parameters, "extensions", AttributeCertificateInfoV1.defaultValues("extensions")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return 0;
+
+ case "baseCertificateID":
+ return new IssuerSerial();
+
+ case "subjectName":
+ return new _GeneralNames.default();
+
+ case "issuer":
+ return {};
+
+ case "signature":
+ return new _AlgorithmIdentifier.default();
+
+ case "serialNumber":
+ return new asn1js.Integer();
+
+ case "attrCertValidityPeriod":
+ return new AttCertValidityPeriod();
+
+ case "attributes":
+ return [];
+
+ case "issuerUniqueID":
+ return new asn1js.BitString();
+
+ case "extensions":
+ return new _Extensions.default();
+
+ default:
+ throw new Error(`Invalid member name for AttributeCertificateInfoV1 class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * AttributeCertificateInfo ::= SEQUENCE {
+ * version Version DEFAULT v1,
+ * subject CHOICE {
+ * baseCertificateID [0] IssuerSerial, -- associated with a Public Key Certificate
+ * subjectName [1] GeneralNames }, -- associated with a name
+ * issuer GeneralNames, -- CA issuing the attribute certificate
+ * signature AlgorithmIdentifier,
+ * serialNumber CertificateSerialNumber,
+ * attrCertValidityPeriod AttCertValidityPeriod,
+ * attributes SEQUENCE OF Attribute,
+ * issuerUniqueID UniqueIdentifier OPTIONAL,
+ * extensions Extensions OPTIONAL
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [issuer]
+ * @property {string} [serialNumber]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Integer({
+ name: names.version || ""
+ }), new asn1js.Choice({
+ value: [new asn1js.Constructed({
+ name: names.baseCertificateID || "",
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 0 // [0]
+
+ },
+ value: IssuerSerial.schema().valueBlock.value
+ }), new asn1js.Constructed({
+ name: names.subjectName || "",
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 1 // [2]
+
+ },
+ value: _GeneralNames.default.schema().valueBlock.value
+ })]
+ }), _GeneralNames.default.schema({
+ names: {
+ blockName: names.issuer || ""
+ }
+ }), _AlgorithmIdentifier.default.schema(names.signature || {}), new asn1js.Integer({
+ name: names.serialNumber || ""
+ }), AttCertValidityPeriod.schema(names.attrCertValidityPeriod || {}), new asn1js.Sequence({
+ name: names.attributes || "",
+ value: [new asn1js.Repeated({
+ value: _Attribute.default.schema()
+ })]
+ }), new asn1js.BitString({
+ optional: true,
+ name: names.issuerUniqueID || ""
+ }), _Extensions.default.schema(names.extensions || {}, true)]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["version", "baseCertificateID", "subjectName", "issuer", "signature", "serialNumber", "attrCertValidityPeriod", "attributes", "issuerUniqueID", "extensions"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, AttributeCertificateInfoV1.schema({
+ names: {
+ version: "version",
+ baseCertificateID: "baseCertificateID",
+ subjectName: "subjectName",
+ issuer: "issuer",
+ signature: {
+ names: {
+ blockName: "signature"
+ }
+ },
+ serialNumber: "serialNumber",
+ attrCertValidityPeriod: {
+ names: {
+ blockName: "attrCertValidityPeriod"
+ }
+ },
+ attributes: "attributes",
+ issuerUniqueID: "issuerUniqueID",
+ extensions: {
+ names: {
+ blockName: "extensions"
+ }
+ }
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for AttributeCertificateInfoV1"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.version = asn1.result.version.valueBlock.valueDec;
+
+ if ("baseCertificateID" in asn1.result) {
+ this.baseCertificateID = new IssuerSerial({
+ schema: new asn1js.Sequence({
+ value: asn1.result.baseCertificateID.valueBlock.value
+ })
+ });
+ }
+
+ if ("subjectName" in asn1.result) {
+ this.subjectName = new _GeneralNames.default({
+ schema: new asn1js.Sequence({
+ value: asn1.result.subjectName.valueBlock.value
+ })
+ });
+ }
+
+ this.issuer = asn1.result.issuer;
+ this.signature = new _AlgorithmIdentifier.default({
+ schema: asn1.result.signature
+ });
+ this.serialNumber = asn1.result.serialNumber;
+ this.attrCertValidityPeriod = new AttCertValidityPeriod({
+ schema: asn1.result.attrCertValidityPeriod
+ });
+ this.attributes = Array.from(asn1.result.attributes.valueBlock.value, element => new _Attribute.default({
+ schema: element
+ }));
+ if ("issuerUniqueID" in asn1.result) this.issuerUniqueID = asn1.result.issuerUniqueID;
+ if ("extensions" in asn1.result) this.extensions = new _Extensions.default({
+ schema: asn1.result.extensions
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ const result = new asn1js.Sequence({
+ value: [new asn1js.Integer({
+ value: this.version
+ })]
+ });
+
+ if ("baseCertificateID" in this) {
+ result.valueBlock.value.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 0 // [0]
+
+ },
+ value: this.baseCertificateID.toSchema().valueBlock.value
+ }));
+ }
+
+ if ("subjectName" in this) {
+ result.valueBlock.value.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 1 // [1]
+
+ },
+ value: this.subjectName.toSchema().valueBlock.value
+ }));
+ }
+
+ result.valueBlock.value.push(this.issuer.toSchema());
+ result.valueBlock.value.push(this.signature.toSchema());
+ result.valueBlock.value.push(this.serialNumber);
+ result.valueBlock.value.push(this.attrCertValidityPeriod.toSchema());
+ result.valueBlock.value.push(new asn1js.Sequence({
+ value: Array.from(this.attributes, element => element.toSchema())
+ }));
+ if ("issuerUniqueID" in this) result.valueBlock.value.push(this.issuerUniqueID);
+ if ("extensions" in this) result.valueBlock.value.push(this.extensions.toSchema());
+ return result;
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const result = {
+ version: this.version
+ };
+ if ("baseCertificateID" in this) result.baseCertificateID = this.baseCertificateID.toJSON();
+ if ("subjectName" in this) result.subjectName = this.subjectName.toJSON();
+ result.issuer = this.issuer.toJSON();
+ result.signature = this.signature.toJSON();
+ result.serialNumber = this.serialNumber.toJSON();
+ result.attrCertValidityPeriod = this.attrCertValidityPeriod.toJSON();
+ result.attributes = Array.from(this.attributes, element => element.toJSON());
+ if ("issuerUniqueID" in this) result.issuerUniqueID = this.issuerUniqueID.toJSON();
+ if ("extensions" in this) result.extensions = this.extensions.toJSON();
+ return result;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * Class from X.509:1997
+ */
+
+
+exports.AttributeCertificateInfoV1 = AttributeCertificateInfoV1;
+
+class AttributeCertificateV1 {
+ //**********************************************************************************
+
+ /**
+ * Constructor for AttributeCertificateV1 class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {AttributeCertificateInfoV1}
+ * @desc acinfo
+ */
+ this.acinfo = (0, _pvutils.getParametersValue)(parameters, "acinfo", AttributeCertificateV1.defaultValues("acinfo"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc signatureAlgorithm
+ */
+
+ this.signatureAlgorithm = (0, _pvutils.getParametersValue)(parameters, "signatureAlgorithm", AttributeCertificateV1.defaultValues("signatureAlgorithm"));
+ /**
+ * @type {BitString}
+ * @desc signatureValue
+ */
+
+ this.signatureValue = (0, _pvutils.getParametersValue)(parameters, "signatureValue", AttributeCertificateV1.defaultValues("signatureValue")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "acinfo":
+ return new AttributeCertificateInfoV1();
+
+ case "signatureAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "signatureValue":
+ return new asn1js.BitString();
+
+ default:
+ throw new Error(`Invalid member name for AttributeCertificateV1 class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * AttributeCertificate ::= SEQUENCE {
+ * acinfo AttributeCertificateInfoV1,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {Object} [acinfo]
+ * @property {Object} [signatureAlgorithm]
+ * @property {string} [signatureValue]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [AttributeCertificateInfoV1.schema(names.acinfo || {}), _AlgorithmIdentifier.default.schema(names.signatureAlgorithm || {}), new asn1js.BitString({
+ name: names.signatureValue || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["acinfo", "signatureValue", "signatureAlgorithm"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, AttributeCertificateV1.schema({
+ names: {
+ acinfo: {
+ names: {
+ blockName: "acinfo"
+ }
+ },
+ signatureAlgorithm: {
+ names: {
+ blockName: "signatureAlgorithm"
+ }
+ },
+ signatureValue: "signatureValue"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for AttributeCertificateV1"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.acinfo = new AttributeCertificateInfoV1({
+ schema: asn1.result.acinfo
+ });
+ this.signatureAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.signatureAlgorithm
+ });
+ this.signatureValue = asn1.result.signatureValue; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ return new asn1js.Sequence({
+ value: [this.acinfo.toSchema(), this.signatureAlgorithm.toSchema(), this.signatureValue]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ acinfo: this.acinfo.toJSON(),
+ signatureAlgorithm: this.signatureAlgorithm.toJSON(),
+ signatureValue: this.signatureValue.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = AttributeCertificateV1;
+
+},{"./AlgorithmIdentifier.js":4,"./Attribute.js":6,"./Extensions.js":39,"./GeneralNames.js":41,"asn1js":112,"pvutils":113}],8:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = exports.AttributeCertificateInfoV2 = exports.Holder = exports.V2Form = exports.ObjectDigestInfo = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _GeneralNames = _interopRequireDefault(require("./GeneralNames.js"));
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _Attribute = _interopRequireDefault(require("./Attribute.js"));
+
+var _Extensions = _interopRequireDefault(require("./Extensions.js"));
+
+var _AttributeCertificateV = require("./AttributeCertificateV1.js");
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5755
+ */
+class ObjectDigestInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for ObjectDigestInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Enumerated}
+ * @desc digestedObjectType
+ */
+ this.digestedObjectType = (0, _pvutils.getParametersValue)(parameters, "digestedObjectType", ObjectDigestInfo.defaultValues("digestedObjectType"));
+ if ("otherObjectTypeID" in parameters)
+ /**
+ * @type {ObjectIdentifier}
+ * @desc otherObjectTypeID
+ */
+ this.otherObjectTypeID = (0, _pvutils.getParametersValue)(parameters, "otherObjectTypeID", ObjectDigestInfo.defaultValues("otherObjectTypeID"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc digestAlgorithm
+ */
+
+ this.digestAlgorithm = (0, _pvutils.getParametersValue)(parameters, "digestAlgorithm", ObjectDigestInfo.defaultValues("digestAlgorithm"));
+ /**
+ * @type {BitString}
+ * @desc objectDigest
+ */
+
+ this.objectDigest = (0, _pvutils.getParametersValue)(parameters, "objectDigest", ObjectDigestInfo.defaultValues("objectDigest")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "digestedObjectType":
+ return new asn1js.Enumerated();
+
+ case "otherObjectTypeID":
+ return new asn1js.ObjectIdentifier();
+
+ case "digestAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "objectDigest":
+ return new asn1js.BitString();
+
+ default:
+ throw new Error(`Invalid member name for ObjectDigestInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * ObjectDigestInfo ::= SEQUENCE {
+ * digestedObjectType ENUMERATED {
+ * publicKey (0),
+ * publicKeyCert (1),
+ * otherObjectTypes (2) },
+ * -- otherObjectTypes MUST NOT
+ * -- be used in this profile
+ * otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
+ * digestAlgorithm AlgorithmIdentifier,
+ * objectDigest BIT STRING
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [digestedObjectType]
+ * @property {string} [otherObjectTypeID]
+ * @property {string} [digestAlgorithm]
+ * @property {string} [objectDigest]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Enumerated({
+ name: names.digestedObjectType || ""
+ }), new asn1js.ObjectIdentifier({
+ optional: true,
+ name: names.otherObjectTypeID || ""
+ }), _AlgorithmIdentifier.default.schema(names.digestAlgorithm || {}), new asn1js.BitString({
+ name: names.objectDigest || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["digestedObjectType", "otherObjectTypeID", "digestAlgorithm", "objectDigest"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, ObjectDigestInfo.schema({
+ names: {
+ digestedObjectType: "digestedObjectType",
+ otherObjectTypeID: "otherObjectTypeID",
+ digestAlgorithm: {
+ names: {
+ blockName: "digestAlgorithm"
+ }
+ },
+ objectDigest: "objectDigest"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for ObjectDigestInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.digestedObjectType = asn1.result.digestedObjectType;
+ if ("otherObjectTypeID" in asn1.result) this.otherObjectTypeID = asn1.result.otherObjectTypeID;
+ this.digestAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.digestAlgorithm
+ });
+ this.objectDigest = asn1.result.objectDigest; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ const result = new asn1js.Sequence({
+ value: [this.digestedObjectType]
+ });
+ if ("otherObjectTypeID" in this) result.value.push(this.otherObjectTypeID);
+ result.value.push(this.digestAlgorithm.toSchema());
+ result.value.push(this.objectDigest);
+ return result;
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const result = {
+ digestedObjectType: this.digestedObjectType.toJSON()
+ };
+ if ("otherObjectTypeID" in this) result.otherObjectTypeID = this.otherObjectTypeID.toJSON();
+ result.digestAlgorithm = this.digestAlgorithm.toJSON();
+ result.objectDigest = this.objectDigest.toJSON();
+ return result;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * Class from RFC5755
+ */
+
+
+exports.ObjectDigestInfo = ObjectDigestInfo;
+
+class V2Form {
+ //**********************************************************************************
+
+ /**
+ * Constructor for V2Form class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+ if ("issuerName" in parameters)
+ /**
+ * @type {GeneralNames}
+ * @desc issuerName
+ */
+ this.issuerName = (0, _pvutils.getParametersValue)(parameters, "issuerName", V2Form.defaultValues("issuerName"));
+ if ("baseCertificateID" in parameters)
+ /**
+ * @type {IssuerSerial}
+ * @desc baseCertificateID
+ */
+ this.baseCertificateID = (0, _pvutils.getParametersValue)(parameters, "baseCertificateID", V2Form.defaultValues("baseCertificateID"));
+ if ("objectDigestInfo" in parameters)
+ /**
+ * @type {ObjectDigestInfo}
+ * @desc objectDigestInfo
+ */
+ this.objectDigestInfo = (0, _pvutils.getParametersValue)(parameters, "objectDigestInfo", V2Form.defaultValues("objectDigestInfo")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "issuerName":
+ return new _GeneralNames.default();
+
+ case "baseCertificateID":
+ return new _AttributeCertificateV.IssuerSerial();
+
+ case "objectDigestInfo":
+ return new ObjectDigestInfo();
+
+ default:
+ throw new Error(`Invalid member name for V2Form class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * V2Form ::= SEQUENCE {
+ * issuerName GeneralNames OPTIONAL,
+ * baseCertificateID [0] IssuerSerial OPTIONAL,
+ * objectDigestInfo [1] ObjectDigestInfo OPTIONAL
+ * -- issuerName MUST be present in this profile
+ * -- baseCertificateID and objectDigestInfo MUST NOT
+ * -- be present in this profile
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [issuerName]
+ * @property {string} [baseCertificateID]
+ * @property {string} [objectDigestInfo]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [_GeneralNames.default.schema({
+ names: {
+ blockName: names.issuerName
+ }
+ }, true), new asn1js.Constructed({
+ optional: true,
+ name: names.baseCertificateID || "",
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 0 // [0]
+
+ },
+ value: _AttributeCertificateV.IssuerSerial.schema().valueBlock.value
+ }), new asn1js.Constructed({
+ optional: true,
+ name: names.objectDigestInfo || "",
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 1 // [1]
+
+ },
+ value: ObjectDigestInfo.schema().valueBlock.value
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["issuerName", "baseCertificateID", "objectDigestInfo"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, V2Form.schema({
+ names: {
+ issuerName: "issuerName",
+ baseCertificateID: "baseCertificateID",
+ objectDigestInfo: "objectDigestInfo"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for V2Form"); //endregion
+ //region Get internal properties from parsed schema
+
+ if ("issuerName" in asn1.result) this.issuerName = new _GeneralNames.default({
+ schema: asn1.result.issuerName
+ });
+
+ if ("baseCertificateID" in asn1.result) {
+ this.baseCertificateID = new _AttributeCertificateV.IssuerSerial({
+ schema: new asn1js.Sequence({
+ value: asn1.result.baseCertificateID.valueBlock.value
+ })
+ });
+ }
+
+ if ("objectDigestInfo" in asn1.result) {
+ this.objectDigestInfo = new ObjectDigestInfo({
+ schema: new asn1js.Sequence({
+ value: asn1.result.objectDigestInfo.valueBlock.value
+ })
+ });
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ const result = new asn1js.Sequence();
+ if ("issuerName" in this) result.valueBlock.value.push(this.issuerName.toSchema());
+
+ if ("baseCertificateID" in this) {
+ result.valueBlock.value.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 0 // [0]
+
+ },
+ value: this.baseCertificateID.toSchema().valueBlock.value
+ }));
+ }
+
+ if ("objectDigestInfo" in this) {
+ result.valueBlock.value.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 1 // [1]
+
+ },
+ value: this.objectDigestInfo.toSchema().valueBlock.value
+ }));
+ } //region Construct and return new ASN.1 schema for this object
+
+
+ return result; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const result = {};
+ if ("issuerName" in this) result.issuerName = this.issuerName.toJSON();
+ if ("baseCertificateID" in this) result.baseCertificateID = this.baseCertificateID.toJSON();
+ if ("objectDigestInfo" in this) result.objectDigestInfo = this.objectDigestInfo.toJSON();
+ return result;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * Class from RFC5755
+ */
+
+
+exports.V2Form = V2Form;
+
+class Holder {
+ //**********************************************************************************
+
+ /**
+ * Constructor for Holder class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+ if ("baseCertificateID" in parameters)
+ /**
+ * @type {IssuerSerial}
+ * @desc baseCertificateID
+ */
+ this.baseCertificateID = (0, _pvutils.getParametersValue)(parameters, "baseCertificateID", Holder.defaultValues("baseCertificateID"));
+ if ("entityName" in parameters)
+ /**
+ * @type {GeneralNames}
+ * @desc entityName
+ */
+ this.entityName = (0, _pvutils.getParametersValue)(parameters, "entityName", Holder.defaultValues("entityName"));
+ if ("objectDigestInfo" in parameters)
+ /**
+ * @type {ObjectDigestInfo}
+ * @desc objectDigestInfo
+ */
+ this.objectDigestInfo = (0, _pvutils.getParametersValue)(parameters, "objectDigestInfo", Holder.defaultValues("objectDigestInfo")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "baseCertificateID":
+ return new _AttributeCertificateV.IssuerSerial();
+
+ case "entityName":
+ return new _GeneralNames.default();
+
+ case "objectDigestInfo":
+ return new ObjectDigestInfo();
+
+ default:
+ throw new Error(`Invalid member name for Holder class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * Holder ::= SEQUENCE {
+ * baseCertificateID [0] IssuerSerial OPTIONAL,
+ * -- the issuer and serial number of
+ * -- the holder's Public Key Certificate
+ * entityName [1] GeneralNames OPTIONAL,
+ * -- the name of the claimant or role
+ * objectDigestInfo [2] ObjectDigestInfo OPTIONAL
+ * -- used to directly authenticate the holder,
+ * -- for example, an executable
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [baseCertificateID]
+ * @property {string} [entityName]
+ * @property {string} [objectDigestInfo]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Constructed({
+ optional: true,
+ name: names.baseCertificateID || "",
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 0 // [0]
+
+ },
+ value: _AttributeCertificateV.IssuerSerial.schema().valueBlock.value
+ }), new asn1js.Constructed({
+ optional: true,
+ name: names.entityName || "",
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 1 // [2]
+
+ },
+ value: _GeneralNames.default.schema().valueBlock.value
+ }), new asn1js.Constructed({
+ optional: true,
+ name: names.objectDigestInfo || "",
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 2 // [2]
+
+ },
+ value: ObjectDigestInfo.schema().valueBlock.value
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["baseCertificateID", "entityName", "objectDigestInfo"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, Holder.schema({
+ names: {
+ baseCertificateID: "baseCertificateID",
+ entityName: "entityName",
+ objectDigestInfo: "objectDigestInfo"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for Holder"); //endregion
+ //region Get internal properties from parsed schema
+
+ if ("baseCertificateID" in asn1.result) {
+ this.baseCertificateID = new _AttributeCertificateV.IssuerSerial({
+ schema: new asn1js.Sequence({
+ value: asn1.result.baseCertificateID.valueBlock.value
+ })
+ });
+ }
+
+ if ("entityName" in asn1.result) {
+ this.entityName = new _GeneralNames.default({
+ schema: new asn1js.Sequence({
+ value: asn1.result.entityName.valueBlock.value
+ })
+ });
+ }
+
+ if ("objectDigestInfo" in asn1.result) {
+ this.objectDigestInfo = new ObjectDigestInfo({
+ schema: new asn1js.Sequence({
+ value: asn1.result.objectDigestInfo.valueBlock.value
+ })
+ });
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ const result = new asn1js.Sequence();
+
+ if ("baseCertificateID" in this) {
+ result.valueBlock.value.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 0 // [0]
+
+ },
+ value: this.baseCertificateID.toSchema().valueBlock.value
+ }));
+ }
+
+ if ("entityName" in this) {
+ result.valueBlock.value.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 1 // [1]
+
+ },
+ value: this.entityName.toSchema().valueBlock.value
+ }));
+ }
+
+ if ("objectDigestInfo" in this) {
+ result.valueBlock.value.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 2 // [2]
+
+ },
+ value: this.objectDigestInfo.toSchema().valueBlock.value
+ }));
+ }
+
+ return result;
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const result = {};
+ if ("baseCertificateID" in this) result.baseCertificateID = this.baseCertificateID.toJSON();
+ if ("entityName" in this) result.entityName = this.entityName.toJSON();
+ if ("objectDigestInfo" in this) result.objectDigestInfo = this.objectDigestInfo.toJSON();
+ return result;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * Class from RFC5755
+ */
+
+
+exports.Holder = Holder;
+
+class AttributeCertificateInfoV2 {
+ //**********************************************************************************
+
+ /**
+ * Constructor for AttributeCertificateInfoV2 class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", AttributeCertificateInfoV2.defaultValues("version"));
+ /**
+ * @type {Holder}
+ * @desc holder
+ */
+
+ this.holder = (0, _pvutils.getParametersValue)(parameters, "holder", AttributeCertificateInfoV2.defaultValues("holder"));
+ /**
+ * @type {GeneralNames|V2Form}
+ * @desc issuer
+ */
+
+ this.issuer = (0, _pvutils.getParametersValue)(parameters, "issuer", AttributeCertificateInfoV2.defaultValues("issuer"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc signature
+ */
+
+ this.signature = (0, _pvutils.getParametersValue)(parameters, "signature", AttributeCertificateInfoV2.defaultValues("signature"));
+ /**
+ * @type {Integer}
+ * @desc serialNumber
+ */
+
+ this.serialNumber = (0, _pvutils.getParametersValue)(parameters, "serialNumber", AttributeCertificateInfoV2.defaultValues("serialNumber"));
+ /**
+ * @type {AttCertValidityPeriod}
+ * @desc attrCertValidityPeriod
+ */
+
+ this.attrCertValidityPeriod = (0, _pvutils.getParametersValue)(parameters, "attrCertValidityPeriod", AttributeCertificateInfoV2.defaultValues("attrCertValidityPeriod"));
+ /**
+ * @type {Array.<Attribute>}
+ * @desc attributes
+ */
+
+ this.attributes = (0, _pvutils.getParametersValue)(parameters, "attributes", AttributeCertificateInfoV2.defaultValues("attributes"));
+ if ("issuerUniqueID" in parameters)
+ /**
+ * @type {BitString}
+ * @desc issuerUniqueID
+ */
+ this.issuerUniqueID = (0, _pvutils.getParametersValue)(parameters, "issuerUniqueID", AttributeCertificateInfoV2.defaultValues("issuerUniqueID"));
+ if ("extensions" in parameters)
+ /**
+ * @type {Extensions}
+ * @desc extensions
+ */
+ this.extensions = (0, _pvutils.getParametersValue)(parameters, "extensions", AttributeCertificateInfoV2.defaultValues("extensions")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return 1;
+
+ case "holder":
+ return new Holder();
+
+ case "issuer":
+ return {};
+
+ case "signature":
+ return new _AlgorithmIdentifier.default();
+
+ case "serialNumber":
+ return new asn1js.Integer();
+
+ case "attrCertValidityPeriod":
+ return new _AttributeCertificateV.AttCertValidityPeriod();
+
+ case "attributes":
+ return [];
+
+ case "issuerUniqueID":
+ return new asn1js.BitString();
+
+ case "extensions":
+ return new _Extensions.default();
+
+ default:
+ throw new Error(`Invalid member name for AttributeCertificateInfoV2 class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * AttributeCertificateInfoV2 ::= SEQUENCE {
+ * version AttCertVersion, -- version is v2
+ * holder Holder,
+ * issuer AttCertIssuer,
+ * signature AlgorithmIdentifier,
+ * serialNumber CertificateSerialNumber,
+ * attrCertValidityPeriod AttCertValidityPeriod,
+ * attributes SEQUENCE OF Attribute,
+ * issuerUniqueID UniqueIdentifier OPTIONAL,
+ * extensions Extensions OPTIONAL
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [issuer]
+ * @property {string} [serialNumber]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Integer({
+ name: names.version || ""
+ }), Holder.schema(names.holder || {}), new asn1js.Choice({
+ value: [_GeneralNames.default.schema({
+ names: {
+ blockName: names.issuer || ""
+ }
+ }), new asn1js.Constructed({
+ name: names.issuer || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: V2Form.schema().valueBlock.value
+ })]
+ }), _AlgorithmIdentifier.default.schema(names.signature || {}), new asn1js.Integer({
+ name: names.serialNumber || ""
+ }), _AttributeCertificateV.AttCertValidityPeriod.schema(names.attrCertValidityPeriod || {}), new asn1js.Sequence({
+ name: names.attributes || "",
+ value: [new asn1js.Repeated({
+ value: _Attribute.default.schema()
+ })]
+ }), new asn1js.BitString({
+ optional: true,
+ name: names.issuerUniqueID || ""
+ }), _Extensions.default.schema(names.extensions || {}, true)]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["version", "holder", "issuer", "signature", "serialNumber", "attrCertValidityPeriod", "attributes", "issuerUniqueID", "extensions"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, AttributeCertificateInfoV2.schema({
+ names: {
+ version: "version",
+ holder: {
+ names: {
+ blockName: "holder"
+ }
+ },
+ issuer: "issuer",
+ signature: {
+ names: {
+ blockName: "signature"
+ }
+ },
+ serialNumber: "serialNumber",
+ attrCertValidityPeriod: {
+ names: {
+ blockName: "attrCertValidityPeriod"
+ }
+ },
+ attributes: "attributes",
+ issuerUniqueID: "issuerUniqueID",
+ extensions: {
+ names: {
+ blockName: "extensions"
+ }
+ }
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for AttributeCertificateInfoV2"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.version = asn1.result.version.valueBlock.valueDec;
+ this.holder = new Holder({
+ schema: asn1.result.holder
+ });
+
+ switch (asn1.result.issuer.idBlock.tagClass) {
+ case 3:
+ // V2Form
+ this.issuer = new V2Form({
+ schema: new asn1js.Sequence({
+ value: asn1.result.issuer.valueBlock.value
+ })
+ });
+ break;
+
+ case 1: // GeneralNames (should not be used)
+
+ default:
+ throw new Error("Incorect value for 'issuer' in AttributeCertificateInfoV2");
+ }
+
+ this.signature = new _AlgorithmIdentifier.default({
+ schema: asn1.result.signature
+ });
+ this.serialNumber = asn1.result.serialNumber;
+ this.attrCertValidityPeriod = new _AttributeCertificateV.AttCertValidityPeriod({
+ schema: asn1.result.attrCertValidityPeriod
+ });
+ this.attributes = Array.from(asn1.result.attributes.valueBlock.value, element => new _Attribute.default({
+ schema: element
+ }));
+ if ("issuerUniqueID" in asn1.result) this.issuerUniqueID = asn1.result.issuerUniqueID;
+ if ("extensions" in asn1.result) this.extensions = new _Extensions.default({
+ schema: asn1.result.extensions
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ const result = new asn1js.Sequence({
+ value: [new asn1js.Integer({
+ value: this.version
+ }), this.holder.toSchema(), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: this.issuer.toSchema().valueBlock.value
+ }), this.signature.toSchema(), this.serialNumber, this.attrCertValidityPeriod.toSchema(), new asn1js.Sequence({
+ value: Array.from(this.attributes, element => element.toSchema())
+ })]
+ });
+ if ("issuerUniqueID" in this) result.valueBlock.value.push(this.issuerUniqueID);
+ if ("extensions" in this) result.valueBlock.value.push(this.extensions.toSchema());
+ return result;
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const result = {
+ version: this.version,
+ holder: this.holder.toJSON(),
+ issuer: this.issuer.toJSON(),
+ signature: this.signature.toJSON(),
+ serialNumber: this.serialNumber.toJSON(),
+ attrCertValidityPeriod: this.attrCertValidityPeriod.toJSON(),
+ attributes: Array.from(this.attributes, element => element.toJSON())
+ };
+ if ("issuerUniqueID" in this) result.issuerUniqueID = this.issuerUniqueID.toJSON();
+ if ("extensions" in this) result.extensions = this.extensions.toJSON();
+ return result;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * Class from RFC5755
+ */
+
+
+exports.AttributeCertificateInfoV2 = AttributeCertificateInfoV2;
+
+class AttributeCertificateV2 {
+ //**********************************************************************************
+
+ /**
+ * Constructor for AttributeCertificateV2 class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {AttributeCertificateInfoV2}
+ * @desc acinfo
+ */
+ this.acinfo = (0, _pvutils.getParametersValue)(parameters, "acinfo", AttributeCertificateV2.defaultValues("acinfo"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc signatureAlgorithm
+ */
+
+ this.signatureAlgorithm = (0, _pvutils.getParametersValue)(parameters, "signatureAlgorithm", AttributeCertificateV2.defaultValues("signatureAlgorithm"));
+ /**
+ * @type {BitString}
+ * @desc signatureValue
+ */
+
+ this.signatureValue = (0, _pvutils.getParametersValue)(parameters, "signatureValue", AttributeCertificateV2.defaultValues("signatureValue")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "acinfo":
+ return new AttributeCertificateInfoV2();
+
+ case "signatureAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "signatureValue":
+ return new asn1js.BitString();
+
+ default:
+ throw new Error(`Invalid member name for AttributeCertificateV2 class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * AttributeCertificate ::= SEQUENCE {
+ * acinfo AttributeCertificateInfoV2,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {Object} [acinfo]
+ * @property {Object} [signatureAlgorithm]
+ * @property {string} [signatureValue]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [AttributeCertificateInfoV2.schema(names.acinfo || {}), _AlgorithmIdentifier.default.schema(names.signatureAlgorithm || {}), new asn1js.BitString({
+ name: names.signatureValue || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["acinfo", "signatureAlgorithm", "signatureValue"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, AttributeCertificateV2.schema({
+ names: {
+ acinfo: {
+ names: {
+ blockName: "acinfo"
+ }
+ },
+ signatureAlgorithm: {
+ names: {
+ blockName: "signatureAlgorithm"
+ }
+ },
+ signatureValue: "signatureValue"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for AttributeCertificateV2"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.acinfo = new AttributeCertificateInfoV2({
+ schema: asn1.result.acinfo
+ });
+ this.signatureAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.signatureAlgorithm
+ });
+ this.signatureValue = asn1.result.signatureValue; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ return new asn1js.Sequence({
+ value: [this.acinfo.toSchema(), this.signatureAlgorithm.toSchema(), this.signatureValue]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ acinfo: this.acinfo.toJSON(),
+ signatureAlgorithm: this.signatureAlgorithm.toJSON(),
+ signatureValue: this.signatureValue.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = AttributeCertificateV2;
+
+},{"./AlgorithmIdentifier.js":4,"./Attribute.js":6,"./AttributeCertificateV1.js":7,"./Extensions.js":39,"./GeneralNames.js":41,"asn1js":112,"pvutils":113}],9:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _common = require("./common.js");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class AttributeTypeAndValue {
+ //**********************************************************************************
+
+ /**
+ * Constructor for AttributeTypeAndValue class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc type
+ */
+ this.type = (0, _pvutils.getParametersValue)(parameters, "type", AttributeTypeAndValue.defaultValues("type"));
+ /**
+ * @type {Object}
+ * @desc Value of the AttributeTypeAndValue class
+ */
+
+ this.value = (0, _pvutils.getParametersValue)(parameters, "value", AttributeTypeAndValue.defaultValues("value")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "type":
+ return "";
+
+ case "value":
+ return {};
+
+ default:
+ throw new Error(`Invalid member name for AttributeTypeAndValue class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * AttributeTypeAndValue ::= Sequence {
+ * type AttributeType,
+ * value AttributeValue }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ *
+ * AttributeValue ::= ANY -- DEFINED BY AttributeType
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName] Name for entire block
+ * @property {string} [type] Name for "type" element
+ * @property {string} [value] Name for "value" element
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.type || ""
+ }), new asn1js.Any({
+ name: names.value || ""
+ })]
+ });
+ } //**********************************************************************************
+
+
+ static blockName() {
+ return "AttributeTypeAndValue";
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["type", "typeValue"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, AttributeTypeAndValue.schema({
+ names: {
+ type: "type",
+ value: "typeValue"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for AttributeTypeAndValue"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.type = asn1.result.type.valueBlock.toString(); // noinspection JSUnresolvedVariable
+
+ this.value = asn1.result.typeValue; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [new asn1js.ObjectIdentifier({
+ value: this.type
+ }), this.value]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ type: this.type
+ };
+ if (Object.keys(this.value).length !== 0) _object.value = this.value.toJSON();else _object.value = this.value;
+ return _object;
+ } //**********************************************************************************
+
+ /**
+ * Compare two AttributeTypeAndValue values, or AttributeTypeAndValue with ArrayBuffer value
+ * @param {(AttributeTypeAndValue|ArrayBuffer)} compareTo The value compare to current
+ * @returns {boolean}
+ */
+
+
+ isEqual(compareTo) {
+ const stringBlockNames = [asn1js.Utf8String.blockName(), asn1js.BmpString.blockName(), asn1js.UniversalString.blockName(), asn1js.NumericString.blockName(), asn1js.PrintableString.blockName(), asn1js.TeletexString.blockName(), asn1js.VideotexString.blockName(), asn1js.IA5String.blockName(), asn1js.GraphicString.blockName(), asn1js.VisibleString.blockName(), asn1js.GeneralString.blockName(), asn1js.CharacterString.blockName()];
+
+ if (compareTo.constructor.blockName() === AttributeTypeAndValue.blockName()) {
+ if (this.type !== compareTo.type) return false; //region Check we do have both strings
+
+ let isString = false;
+ const thisName = this.value.constructor.blockName();
+
+ if (thisName === compareTo.value.constructor.blockName()) {
+ for (var _i = 0, _stringBlockNames = stringBlockNames; _i < _stringBlockNames.length; _i++) {
+ const name = _stringBlockNames[_i];
+
+ if (thisName === name) {
+ isString = true;
+ break;
+ }
+ }
+ } //endregion
+
+
+ if (isString) {
+ const value1 = (0, _common.stringPrep)(this.value.valueBlock.value);
+ const value2 = (0, _common.stringPrep)(compareTo.value.valueBlock.value);
+ if (value1.localeCompare(value2) !== 0) return false;
+ } else // Comparing as two ArrayBuffers
+ {
+ if ((0, _pvutils.isEqualBuffer)(this.value.valueBeforeDecode, compareTo.value.valueBeforeDecode) === false) return false;
+ }
+
+ return true;
+ }
+
+ if (compareTo instanceof ArrayBuffer) return (0, _pvutils.isEqualBuffer)(this.value.valueBeforeDecode, compareTo);
+ return false;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = AttributeTypeAndValue;
+
+},{"./common.js":110,"asn1js":112,"pvutils":113}],10:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _ContentInfo = _interopRequireDefault(require("./ContentInfo.js"));
+
+var _SafeContents = _interopRequireDefault(require("./SafeContents.js"));
+
+var _EnvelopedData = _interopRequireDefault(require("./EnvelopedData.js"));
+
+var _EncryptedData = _interopRequireDefault(require("./EncryptedData.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
+
+function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
+
+function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
+
+function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC7292
+ */
+class AuthenticatedSafe {
+ //**********************************************************************************
+
+ /**
+ * Constructor for AuthenticatedSafe class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array.<ContentInfo>}
+ * @desc safeContents
+ */
+ this.safeContents = (0, _pvutils.getParametersValue)(parameters, "safeContents", AuthenticatedSafe.defaultValues("safeContents"));
+ if ("parsedValue" in parameters)
+ /**
+ * @type {*}
+ * @desc parsedValue
+ */
+ this.parsedValue = (0, _pvutils.getParametersValue)(parameters, "parsedValue", AuthenticatedSafe.defaultValues("parsedValue")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "safeContents":
+ return [];
+
+ case "parsedValue":
+ return {};
+
+ default:
+ throw new Error(`Invalid member name for AuthenticatedSafe class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "safeContents":
+ return memberValue.length === 0;
+
+ case "parsedValue":
+ return memberValue instanceof Object && Object.keys(memberValue).length === 0;
+
+ default:
+ throw new Error(`Invalid member name for AuthenticatedSafe class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * AuthenticatedSafe ::= SEQUENCE OF ContentInfo
+ * -- Data if unencrypted
+ * -- EncryptedData if password-encrypted
+ * -- EnvelopedData if public key-encrypted
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [contentInfos]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Repeated({
+ name: names.contentInfos || "",
+ value: _ContentInfo.default.schema()
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["contentInfos"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, AuthenticatedSafe.schema({
+ names: {
+ contentInfos: "contentInfos"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for AuthenticatedSafe"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.safeContents = Array.from(asn1.result.contentInfos, element => new _ContentInfo.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: Array.from(this.safeContents, element => element.toSchema())
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ safeContents: Array.from(this.safeContents, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+ parseInternalValues(parameters) {
+ //region Check input data from "parameters"
+ if (parameters instanceof Object === false) return Promise.reject("The \"parameters\" must has \"Object\" type");
+ if ("safeContents" in parameters === false) return Promise.reject("Absent mandatory parameter \"safeContents\"");
+ if (parameters.safeContents instanceof Array === false) return Promise.reject("The \"parameters.safeContents\" must has \"Array\" type");
+ if (parameters.safeContents.length !== this.safeContents.length) return Promise.reject("Length of \"parameters.safeContents\" must be equal to \"this.safeContents.length\""); //endregion
+ //region Initial variables
+
+ let sequence = Promise.resolve(); //endregion
+ //region Create value for "this.parsedValue.authenticatedSafe"
+
+ this.parsedValue = {
+ safeContents: []
+ };
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = this.safeContents.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ const _step$value = _slicedToArray(_step.value, 2),
+ index = _step$value[0],
+ content = _step$value[1];
+
+ switch (content.contentType) {
+ //region data
+ case "1.2.840.113549.1.7.1":
+ {
+ //region Check that we do have OCTETSTRING as "content"
+ if (content.content instanceof asn1js.OctetString === false) return Promise.reject("Wrong type of \"this.safeContents[j].content\""); //endregion
+ //region Check we have "constructive encoding" for AuthSafe content
+
+ let authSafeContent = new ArrayBuffer(0);
+
+ if (content.content.valueBlock.isConstructed) {
+ var _iteratorNormalCompletion2 = true;
+ var _didIteratorError2 = false;
+ var _iteratorError2 = undefined;
+
+ try {
+ for (var _iterator2 = content.content.valueBlock.value[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+ const contentValue = _step2.value;
+ authSafeContent = (0, _pvutils.utilConcatBuf)(authSafeContent, contentValue.valueBlock.valueHex);
+ }
+ } catch (err) {
+ _didIteratorError2 = true;
+ _iteratorError2 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
+ _iterator2.return();
+ }
+ } finally {
+ if (_didIteratorError2) {
+ throw _iteratorError2;
+ }
+ }
+ }
+ } else authSafeContent = content.content.valueBlock.valueHex; //endregion
+ //region Parse internal ASN.1 data
+
+
+ const asn1 = asn1js.fromBER(authSafeContent);
+ if (asn1.offset === -1) return Promise.reject("Error during parsing of ASN.1 data inside \"content.content\""); //endregion
+ //region Finilly initialize initial values of "SafeContents" type
+
+ this.parsedValue.safeContents.push({
+ privacyMode: 0,
+ // No privacy, clear data
+ value: new _SafeContents.default({
+ schema: asn1.result
+ })
+ }); //endregion
+ }
+ break;
+ //endregion
+ //region envelopedData
+
+ case "1.2.840.113549.1.7.3":
+ {
+ //region Initial variables
+ const cmsEnveloped = new _EnvelopedData.default({
+ schema: content.content
+ }); //endregion
+ //region Check mandatory parameters
+
+ if ("recipientCertificate" in parameters.safeContents[index] === false) return Promise.reject("Absent mandatory parameter \"recipientCertificate\" in \"parameters.safeContents[j]\"");
+ const recipientCertificate = parameters.safeContents[index].recipientCertificate;
+ if ("recipientKey" in parameters.safeContents[index] === false) return Promise.reject("Absent mandatory parameter \"recipientKey\" in \"parameters.safeContents[j]\""); // noinspection JSUnresolvedVariable
+
+ const recipientKey = parameters.safeContents[index].recipientKey; //endregion
+ //region Decrypt CMS EnvelopedData using first recipient information
+
+ sequence = sequence.then(() => cmsEnveloped.decrypt(0, {
+ recipientCertificate,
+ recipientPrivateKey: recipientKey
+ }));
+ sequence = sequence.then(
+ /**
+ * @param {ArrayBuffer} result
+ */
+ result => {
+ const asn1 = asn1js.fromBER(result);
+ if (asn1.offset === -1) return Promise.reject("Error during parsing of decrypted data");
+ this.parsedValue.safeContents.push({
+ privacyMode: 2,
+ // Public-key privacy mode
+ value: new _SafeContents.default({
+ schema: asn1.result
+ })
+ });
+ return Promise.resolve();
+ }); //endregion
+ }
+ break;
+ //endregion
+ //region encryptedData
+
+ case "1.2.840.113549.1.7.6":
+ {
+ //region Initial variables
+ const cmsEncrypted = new _EncryptedData.default({
+ schema: content.content
+ }); //endregion
+ //region Check mandatory parameters
+
+ if ("password" in parameters.safeContents[index] === false) return Promise.reject("Absent mandatory parameter \"password\" in \"parameters.safeContents[j]\"");
+ const password = parameters.safeContents[index].password; //endregion
+ //region Decrypt CMS EncryptedData using password
+
+ sequence = sequence.then(() => cmsEncrypted.decrypt({
+ password
+ }), error => Promise.reject(error)); //endregion
+ //region Initialize internal data
+
+ sequence = sequence.then(
+ /**
+ * @param {ArrayBuffer} result
+ */
+ result => {
+ const asn1 = asn1js.fromBER(result);
+ if (asn1.offset === -1) return Promise.reject("Error during parsing of decrypted data");
+ this.parsedValue.safeContents.push({
+ privacyMode: 1,
+ // Password-based privacy mode
+ value: new _SafeContents.default({
+ schema: asn1.result
+ })
+ });
+ return Promise.resolve();
+ }, error => Promise.reject(error)); //endregion
+ }
+ break;
+ //endregion
+ //region default
+
+ default:
+ throw new Error(`Unknown "contentType" for AuthenticatedSafe: " ${content.contentType}`);
+ //endregion
+ }
+ } //endregion
+
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+
+ return sequence;
+ } //**********************************************************************************
+
+
+ makeInternalValues(parameters) {
+ //region Check data in "parsedValue"
+ if ("parsedValue" in this === false) return Promise.reject("Please run \"parseValues\" first or add \"parsedValue\" manually");
+ if (this.parsedValue instanceof Object === false) return Promise.reject("The \"this.parsedValue\" must has \"Object\" type");
+ if (this.parsedValue.safeContents instanceof Array === false) return Promise.reject("The \"this.parsedValue.safeContents\" must has \"Array\" type"); //endregion
+ //region Check input data from "parameters"
+
+ if (parameters instanceof Object === false) return Promise.reject("The \"parameters\" must has \"Object\" type");
+ if ("safeContents" in parameters === false) return Promise.reject("Absent mandatory parameter \"safeContents\"");
+ if (parameters.safeContents instanceof Array === false) return Promise.reject("The \"parameters.safeContents\" must has \"Array\" type");
+ if (parameters.safeContents.length !== this.parsedValue.safeContents.length) return Promise.reject("Length of \"parameters.safeContents\" must be equal to \"this.parsedValue.safeContents\""); //endregion
+ //region Initial variables
+
+ let sequence = Promise.resolve(); //endregion
+ //region Create internal values from already parsed values
+
+ this.safeContents = [];
+ var _iteratorNormalCompletion3 = true;
+ var _didIteratorError3 = false;
+ var _iteratorError3 = undefined;
+
+ try {
+ for (var _iterator3 = this.parsedValue.safeContents.entries()[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
+ const _step3$value = _slicedToArray(_step3.value, 2),
+ index = _step3$value[0],
+ content = _step3$value[1];
+
+ //region Check current "content" value
+ if ("privacyMode" in content === false) return Promise.reject("The \"privacyMode\" is a mandatory parameter for \"content\"");
+ if ("value" in content === false) return Promise.reject("The \"value\" is a mandatory parameter for \"content\"");
+ if (content.value instanceof _SafeContents.default === false) return Promise.reject("The \"content.value\" must has \"SafeContents\" type"); //endregion
+
+ switch (content.privacyMode) {
+ //region No privacy
+ case 0:
+ {
+ const contentBuffer = content.value.toSchema().toBER(false);
+ sequence = sequence.then(() => {
+ this.safeContents.push(new _ContentInfo.default({
+ contentType: "1.2.840.113549.1.7.1",
+ content: new asn1js.OctetString({
+ valueHex: contentBuffer
+ })
+ }));
+ });
+ }
+ break;
+ //endregion
+ //region Privacy with password
+
+ case 1:
+ {
+ //region Initial variables
+ const cmsEncrypted = new _EncryptedData.default();
+ const currentParameters = parameters.safeContents[index];
+ currentParameters.contentToEncrypt = content.value.toSchema().toBER(false); //endregion
+ //region Encrypt CMS EncryptedData using password
+
+ sequence = sequence.then(() => cmsEncrypted.encrypt(currentParameters), error => Promise.reject(error)); //endregion
+ //region Store result content in CMS_CONTENT_INFO type
+
+ sequence = sequence.then(() => {
+ this.safeContents.push(new _ContentInfo.default({
+ contentType: "1.2.840.113549.1.7.6",
+ content: cmsEncrypted.toSchema()
+ }));
+ }, error => Promise.reject(error)); //endregion
+ }
+ break;
+ //endregion
+ //region Privacy with public key
+
+ case 2:
+ {
+ //region Initial variables
+ const cmsEnveloped = new _EnvelopedData.default();
+ const contentToEncrypt = content.value.toSchema().toBER(false); //endregion
+ //region Check mandatory parameters
+
+ if ("encryptingCertificate" in parameters.safeContents[index] === false) return Promise.reject("Absent mandatory parameter \"encryptingCertificate\" in \"parameters.safeContents[i]\"");
+ if ("encryptionAlgorithm" in parameters.safeContents[index] === false) return Promise.reject("Absent mandatory parameter \"encryptionAlgorithm\" in \"parameters.safeContents[i]\"");
+
+ switch (true) {
+ case parameters.safeContents[index].encryptionAlgorithm.name.toLowerCase() === "aes-cbc":
+ case parameters.safeContents[index].encryptionAlgorithm.name.toLowerCase() === "aes-gcm":
+ break;
+
+ default:
+ return Promise.reject(`Incorrect parameter "encryptionAlgorithm" in "parameters.safeContents[i]": ${parameters.safeContents[index].encryptionAlgorithm}`);
+ }
+
+ switch (true) {
+ case parameters.safeContents[index].encryptionAlgorithm.length === 128:
+ case parameters.safeContents[index].encryptionAlgorithm.length === 192:
+ case parameters.safeContents[index].encryptionAlgorithm.length === 256:
+ break;
+
+ default:
+ return Promise.reject(`Incorrect parameter "encryptionAlgorithm.length" in "parameters.safeContents[i]": ${parameters.safeContents[index].encryptionAlgorithm.length}`);
+ } //endregion
+ //region Making correct "encryptionAlgorithm" variable
+
+
+ const encryptionAlgorithm = parameters.safeContents[index].encryptionAlgorithm; //endregion
+ //region Append recipient for enveloped data
+
+ cmsEnveloped.addRecipientByCertificate(parameters.safeContents[index].encryptingCertificate); //endregion
+ //region Making encryption
+
+ sequence = sequence.then(() => cmsEnveloped.encrypt(encryptionAlgorithm, contentToEncrypt));
+ sequence = sequence.then(() => {
+ this.safeContents.push(new _ContentInfo.default({
+ contentType: "1.2.840.113549.1.7.3",
+ content: cmsEnveloped.toSchema()
+ }));
+ }); //endregion
+ }
+ break;
+ //endregion
+ //region default
+
+ default:
+ return Promise.reject(`Incorrect value for "content.privacyMode": ${content.privacyMode}`);
+ //endregion
+ }
+ } //endregion
+ //region Return result of the function
+
+ } catch (err) {
+ _didIteratorError3 = true;
+ _iteratorError3 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
+ _iterator3.return();
+ }
+ } finally {
+ if (_didIteratorError3) {
+ throw _iteratorError3;
+ }
+ }
+ }
+
+ return sequence.then(() => this, error => Promise.reject(`Error during parsing: ${error}`)); //endregion
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = AuthenticatedSafe;
+
+},{"./ContentInfo.js":26,"./EncryptedData.js":35,"./EnvelopedData.js":36,"./SafeContents.js":96,"asn1js":112,"pvutils":113}],11:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _GeneralName = _interopRequireDefault(require("./GeneralName.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class AuthorityKeyIdentifier {
+ //**********************************************************************************
+
+ /**
+ * Constructor for AuthorityKeyIdentifier class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+ if ("keyIdentifier" in parameters)
+ /**
+ * @type {OctetString}
+ * @desc keyIdentifier
+ */
+ this.keyIdentifier = (0, _pvutils.getParametersValue)(parameters, "keyIdentifier", AuthorityKeyIdentifier.defaultValues("keyIdentifier"));
+ if ("authorityCertIssuer" in parameters)
+ /**
+ * @type {Array.<GeneralName>}
+ * @desc authorityCertIssuer
+ */
+ this.authorityCertIssuer = (0, _pvutils.getParametersValue)(parameters, "authorityCertIssuer", AuthorityKeyIdentifier.defaultValues("authorityCertIssuer"));
+ if ("authorityCertSerialNumber" in parameters)
+ /**
+ * @type {Integer}
+ * @desc authorityCertIssuer
+ */
+ this.authorityCertSerialNumber = (0, _pvutils.getParametersValue)(parameters, "authorityCertSerialNumber", AuthorityKeyIdentifier.defaultValues("authorityCertSerialNumber")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "keyIdentifier":
+ return new asn1js.OctetString();
+
+ case "authorityCertIssuer":
+ return [];
+
+ case "authorityCertSerialNumber":
+ return new asn1js.Integer();
+
+ default:
+ throw new Error(`Invalid member name for AuthorityKeyIdentifier class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * AuthorityKeyIdentifier OID ::= 2.5.29.35
+ *
+ * AuthorityKeyIdentifier ::= SEQUENCE {
+ * keyIdentifier [0] KeyIdentifier OPTIONAL,
+ * authorityCertIssuer [1] GeneralNames OPTIONAL,
+ * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
+ *
+ * KeyIdentifier ::= OCTET STRING
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [keyIdentifier]
+ * @property {string} [authorityCertIssuer]
+ * @property {string} [authorityCertSerialNumber]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Primitive({
+ name: names.keyIdentifier || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ }
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [new asn1js.Repeated({
+ name: names.authorityCertIssuer || "",
+ value: _GeneralName.default.schema()
+ })]
+ }), new asn1js.Primitive({
+ name: names.authorityCertSerialNumber || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ }
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["keyIdentifier", "authorityCertIssuer", "authorityCertSerialNumber"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, AuthorityKeyIdentifier.schema({
+ names: {
+ keyIdentifier: "keyIdentifier",
+ authorityCertIssuer: "authorityCertIssuer",
+ authorityCertSerialNumber: "authorityCertSerialNumber"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for AuthorityKeyIdentifier"); //endregion
+ //region Get internal properties from parsed schema
+
+ if ("keyIdentifier" in asn1.result) this.keyIdentifier = new asn1js.OctetString({
+ valueHex: asn1.result.keyIdentifier.valueBlock.valueHex
+ });
+ if ("authorityCertIssuer" in asn1.result) this.authorityCertIssuer = Array.from(asn1.result.authorityCertIssuer, element => new _GeneralName.default({
+ schema: element
+ }));
+ if ("authorityCertSerialNumber" in asn1.result) this.authorityCertSerialNumber = new asn1js.Integer({
+ valueHex: asn1.result.authorityCertSerialNumber.valueBlock.valueHex
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+
+ if ("keyIdentifier" in this) {
+ outputArray.push(new asn1js.Primitive({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ valueHex: this.keyIdentifier.valueBlock.valueHex
+ }));
+ }
+
+ if ("authorityCertIssuer" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: Array.from(this.authorityCertIssuer, element => element.toSchema())
+ }));
+ }
+
+ if ("authorityCertSerialNumber" in this) {
+ outputArray.push(new asn1js.Primitive({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ valueHex: this.authorityCertSerialNumber.valueBlock.valueHex
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {};
+ if ("keyIdentifier" in this) object.keyIdentifier = this.keyIdentifier.toJSON();
+ if ("authorityCertIssuer" in this) object.authorityCertIssuer = Array.from(this.authorityCertIssuer, element => element.toJSON());
+ if ("authorityCertSerialNumber" in this) object.authorityCertSerialNumber = this.authorityCertSerialNumber.toJSON();
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = AuthorityKeyIdentifier;
+
+},{"./GeneralName.js":40,"asn1js":112,"pvutils":113}],12:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class BasicConstraints {
+ //**********************************************************************************
+
+ /**
+ * Constructor for BasicConstraints class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ * @property {Object} [cA]
+ * @property {Object} [pathLenConstraint]
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {boolean}
+ * @desc cA
+ */
+ this.cA = (0, _pvutils.getParametersValue)(parameters, "cA", false);
+ if ("pathLenConstraint" in parameters)
+ /**
+ * @type {number|Integer}
+ * @desc pathLenConstraint
+ */
+ this.pathLenConstraint = (0, _pvutils.getParametersValue)(parameters, "pathLenConstraint", 0); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "cA":
+ return false;
+
+ default:
+ throw new Error(`Invalid member name for BasicConstraints class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * BasicConstraints ::= SEQUENCE {
+ * cA BOOLEAN DEFAULT FALSE,
+ * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [cA]
+ * @property {string} [pathLenConstraint]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Boolean({
+ optional: true,
+ name: names.cA || ""
+ }), new asn1js.Integer({
+ optional: true,
+ name: names.pathLenConstraint || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["cA", "pathLenConstraint"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, BasicConstraints.schema({
+ names: {
+ cA: "cA",
+ pathLenConstraint: "pathLenConstraint"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for BasicConstraints"); //endregion
+ //region Get internal properties from parsed schema
+
+ if ("cA" in asn1.result) this.cA = asn1.result.cA.valueBlock.value;
+
+ if ("pathLenConstraint" in asn1.result) {
+ if (asn1.result.pathLenConstraint.valueBlock.isHexOnly) this.pathLenConstraint = asn1.result.pathLenConstraint;else this.pathLenConstraint = asn1.result.pathLenConstraint.valueBlock.valueDec;
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ if (this.cA !== BasicConstraints.defaultValues("cA")) outputArray.push(new asn1js.Boolean({
+ value: this.cA
+ }));
+
+ if ("pathLenConstraint" in this) {
+ if (this.pathLenConstraint instanceof asn1js.Integer) outputArray.push(this.pathLenConstraint);else outputArray.push(new asn1js.Integer({
+ value: this.pathLenConstraint
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {};
+ if (this.cA !== BasicConstraints.defaultValues("cA")) object.cA = this.cA;
+
+ if ("pathLenConstraint" in this) {
+ if (this.pathLenConstraint instanceof asn1js.Integer) object.pathLenConstraint = this.pathLenConstraint.toJSON();else object.pathLenConstraint = this.pathLenConstraint;
+ }
+
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = BasicConstraints;
+
+},{"asn1js":112,"pvutils":113}],13:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _common = require("./common.js");
+
+var _ResponseData = _interopRequireDefault(require("./ResponseData.js"));
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _Certificate = _interopRequireDefault(require("./Certificate.js"));
+
+var _CertID = _interopRequireDefault(require("./CertID.js"));
+
+var _RelativeDistinguishedNames = _interopRequireDefault(require("./RelativeDistinguishedNames.js"));
+
+var _CertificateChainValidationEngine = _interopRequireDefault(require("./CertificateChainValidationEngine.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
+
+function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
+
+function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
+
+function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC6960
+ */
+class BasicOCSPResponse {
+ //**********************************************************************************
+
+ /**
+ * Constructor for BasicOCSPResponse class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {ResponseData}
+ * @desc tbsResponseData
+ */
+ this.tbsResponseData = (0, _pvutils.getParametersValue)(parameters, "tbsResponseData", BasicOCSPResponse.defaultValues("tbsResponseData"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc signatureAlgorithm
+ */
+
+ this.signatureAlgorithm = (0, _pvutils.getParametersValue)(parameters, "signatureAlgorithm", BasicOCSPResponse.defaultValues("signatureAlgorithm"));
+ /**
+ * @type {BitString}
+ * @desc signature
+ */
+
+ this.signature = (0, _pvutils.getParametersValue)(parameters, "signature", BasicOCSPResponse.defaultValues("signature"));
+ if ("certs" in parameters)
+ /**
+ * @type {Array.<Certificate>}
+ * @desc certs
+ */
+ this.certs = (0, _pvutils.getParametersValue)(parameters, "certs", BasicOCSPResponse.defaultValues("certs")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "tbsResponseData":
+ return new _ResponseData.default();
+
+ case "signatureAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "signature":
+ return new asn1js.BitString();
+
+ case "certs":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for BasicOCSPResponse class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "type":
+ {
+ // noinspection OverlyComplexBooleanExpressionJS
+ let comparisonResult = _ResponseData.default.compareWithDefault("tbs", memberValue.tbs) && _ResponseData.default.compareWithDefault("responderID", memberValue.responderID) && _ResponseData.default.compareWithDefault("producedAt", memberValue.producedAt) && _ResponseData.default.compareWithDefault("responses", memberValue.responses);
+
+ if ("responseExtensions" in memberValue) comparisonResult = comparisonResult && _ResponseData.default.compareWithDefault("responseExtensions", memberValue.responseExtensions);
+ return comparisonResult;
+ }
+
+ case "signatureAlgorithm":
+ return memberValue.algorithmId === "" && "algorithmParams" in memberValue === false;
+
+ case "signature":
+ return memberValue.isEqual(BasicOCSPResponse.defaultValues(memberName));
+
+ case "certs":
+ return memberValue.length === 0;
+
+ default:
+ throw new Error(`Invalid member name for BasicOCSPResponse class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * BasicOCSPResponse ::= SEQUENCE {
+ * tbsResponseData ResponseData,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING,
+ * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [tbsResponseData]
+ * @property {string} [signatureAlgorithm]
+ * @property {string} [signature]
+ * @property {string} [certs]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "BasicOCSPResponse",
+ value: [_ResponseData.default.schema(names.tbsResponseData || {
+ names: {
+ blockName: "BasicOCSPResponse.tbsResponseData"
+ }
+ }), _AlgorithmIdentifier.default.schema(names.signatureAlgorithm || {
+ names: {
+ blockName: "BasicOCSPResponse.signatureAlgorithm"
+ }
+ }), new asn1js.BitString({
+ name: names.signature || "BasicOCSPResponse.signature"
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Sequence({
+ value: [new asn1js.Repeated({
+ name: "BasicOCSPResponse.certs",
+ value: _Certificate.default.schema(names.certs || {})
+ })]
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["BasicOCSPResponse.tbsResponseData", "BasicOCSPResponse.signatureAlgorithm", "BasicOCSPResponse.signature", "BasicOCSPResponse.certs"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, BasicOCSPResponse.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for BasicOCSPResponse"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.tbsResponseData = new _ResponseData.default({
+ schema: asn1.result["BasicOCSPResponse.tbsResponseData"]
+ });
+ this.signatureAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result["BasicOCSPResponse.signatureAlgorithm"]
+ });
+ this.signature = asn1.result["BasicOCSPResponse.signature"];
+ if ("BasicOCSPResponse.certs" in asn1.result) this.certs = Array.from(asn1.result["BasicOCSPResponse.certs"], element => new _Certificate.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(this.tbsResponseData.toSchema());
+ outputArray.push(this.signatureAlgorithm.toSchema());
+ outputArray.push(this.signature); //region Create array of certificates
+
+ if ("certs" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Sequence({
+ value: Array.from(this.certs, element => element.toSchema())
+ })]
+ }));
+ } //endregion
+ //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ tbsResponseData: this.tbsResponseData.toJSON(),
+ signatureAlgorithm: this.signatureAlgorithm.toJSON(),
+ signature: this.signature.toJSON()
+ };
+ if ("certs" in this) _object.certs = Array.from(this.certs, element => element.toJSON());
+ return _object;
+ } //**********************************************************************************
+
+ /**
+ * Get OCSP response status for specific certificate
+ * @param {Certificate} certificate Certificate to be checked
+ * @param {Certificate} issuerCertificate Certificate of issuer for certificate to be checked
+ * @returns {Promise}
+ */
+
+
+ getCertificateStatus(certificate, issuerCertificate) {
+ //region Initial variables
+ let sequence = Promise.resolve();
+ const result = {
+ isForCertificate: false,
+ status: 2 // 0 = good, 1 = revoked, 2 = unknown
+
+ };
+ const hashesObject = {};
+ const certIDs = [];
+ const certIDPromises = []; //endregion
+ //region Create all "certIDs" for input certificates
+
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = this.tbsResponseData.responses[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ const response = _step.value;
+ const hashAlgorithm = (0, _common.getAlgorithmByOID)(response.certID.hashAlgorithm.algorithmId);
+ if ("name" in hashAlgorithm === false) return Promise.reject(`Wrong CertID hashing algorithm: ${response.certID.hashAlgorithm.algorithmId}`);
+
+ if (hashAlgorithm.name in hashesObject === false) {
+ hashesObject[hashAlgorithm.name] = 1;
+ const certID = new _CertID.default();
+ certIDs.push(certID);
+ certIDPromises.push(certID.createForCertificate(certificate, {
+ hashAlgorithm: hashAlgorithm.name,
+ issuerCertificate
+ }));
+ }
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+
+ sequence = sequence.then(() => Promise.all(certIDPromises)); //endregion
+ //region Compare all response's "certIDs" with identifiers for input certificate
+
+ sequence = sequence.then(() => {
+ var _iteratorNormalCompletion2 = true;
+ var _didIteratorError2 = false;
+ var _iteratorError2 = undefined;
+
+ try {
+ for (var _iterator2 = this.tbsResponseData.responses[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+ const response = _step2.value;
+
+ for (var _i = 0, _certIDs = certIDs; _i < _certIDs.length; _i++) {
+ const id = _certIDs[_i];
+
+ if (response.certID.isEqual(id)) {
+ result.isForCertificate = true;
+
+ try {
+ switch (response.certStatus.idBlock.isConstructed) {
+ case true:
+ if (response.certStatus.idBlock.tagNumber === 1) result.status = 1; // revoked
+
+ break;
+
+ case false:
+ switch (response.certStatus.idBlock.tagNumber) {
+ case 0:
+ // good
+ result.status = 0;
+ break;
+
+ case 2:
+ // unknown
+ result.status = 2;
+ break;
+
+ default:
+ }
+
+ break;
+
+ default:
+ }
+ } catch (ex) {}
+
+ return result;
+ }
+ }
+ }
+ } catch (err) {
+ _didIteratorError2 = true;
+ _iteratorError2 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
+ _iterator2.return();
+ }
+ } finally {
+ if (_didIteratorError2) {
+ throw _iteratorError2;
+ }
+ }
+ }
+
+ return result;
+ }); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+ /**
+ * Make signature for current OCSP Basic Response
+ * @param {Object} privateKey Private key for "subjectPublicKeyInfo" structure
+ * @param {string} [hashAlgorithm="SHA-1"] Hashing algorithm. Default SHA-1
+ * @returns {Promise}
+ */
+
+
+ sign(privateKey, hashAlgorithm = "SHA-1") {
+ //region Initial checking
+ //region Get a private key from function parameter
+ if (typeof privateKey === "undefined") return Promise.reject("Need to provide a private key for signing"); //endregion
+ //endregion
+ //region Initial variables
+
+ let sequence = Promise.resolve();
+ let parameters;
+ const engine = (0, _common.getEngine)(); //endregion
+ //region Get a "default parameters" for current algorithm and set correct signature algorithm
+
+ sequence = sequence.then(() => engine.subtle.getSignatureParameters(privateKey, hashAlgorithm));
+ sequence = sequence.then(result => {
+ parameters = result.parameters;
+ this.signatureAlgorithm = result.signatureAlgorithm;
+ }); //endregion
+ //region Create TBS data for signing
+
+ sequence = sequence.then(() => {
+ this.tbsResponseData.tbs = this.tbsResponseData.toSchema(true).toBER(false);
+ }); //endregion
+ //region Signing TBS data on provided private key
+
+ sequence = sequence.then(() => engine.subtle.signWithPrivateKey(this.tbsResponseData.tbs, privateKey, parameters));
+ sequence = sequence.then(result => {
+ this.signature = new asn1js.BitString({
+ valueHex: result
+ });
+ }); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+ /**
+ * Verify existing OCSP Basic Response
+ * @param {Object} parameters Additional parameters
+ * @returns {Promise}
+ */
+
+
+ verify(parameters = {}) {
+ //region Initial variables
+ let signerCert = null;
+ let certIndex = -1;
+ let sequence = Promise.resolve();
+ let trustedCerts = [];
+
+ const _this = this;
+
+ const engine = (0, _common.getEngine)(); //endregion
+ //region Check amount of certificates
+
+ if ("certs" in this === false) return Promise.reject("No certificates attached to the BasicOCSPResponce"); //endregion
+ //region Get input values
+
+ if ("trustedCerts" in parameters) trustedCerts = parameters.trustedCerts; //endregion
+ //region Aux functions
+
+ /**
+ * Check CA flag for the certificate
+ * @param {Certificate} cert Certificate to find CA flag for
+ * @returns {*}
+ */
+
+ function checkCA(cert) {
+ //region Do not include signer's certificate
+ if (cert.issuer.isEqual(signerCert.issuer) === true && cert.serialNumber.isEqual(signerCert.serialNumber) === true) return null; //endregion
+
+ let isCA = false;
+ var _iteratorNormalCompletion3 = true;
+ var _didIteratorError3 = false;
+ var _iteratorError3 = undefined;
+
+ try {
+ for (var _iterator3 = cert.extensions[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
+ const extension = _step3.value;
+
+ if (extension.extnID === "2.5.29.19") // BasicConstraints
+ {
+ if ("cA" in extension.parsedValue) {
+ if (extension.parsedValue.cA === true) isCA = true;
+ }
+ }
+ }
+ } catch (err) {
+ _didIteratorError3 = true;
+ _iteratorError3 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
+ _iterator3.return();
+ }
+ } finally {
+ if (_didIteratorError3) {
+ throw _iteratorError3;
+ }
+ }
+ }
+
+ if (isCA) return cert;
+ return null;
+ } //endregion
+ //region Get a "crypto" extension
+
+
+ const crypto = (0, _common.getCrypto)();
+ if (typeof crypto === "undefined") return Promise.reject("Unable to create WebCrypto object"); //endregion
+ //region Find correct value for "responderID"
+
+ switch (true) {
+ case this.tbsResponseData.responderID instanceof _RelativeDistinguishedNames.default:
+ // [1] Name
+ sequence = sequence.then(() => {
+ var _iteratorNormalCompletion4 = true;
+ var _didIteratorError4 = false;
+ var _iteratorError4 = undefined;
+
+ try {
+ for (var _iterator4 = _this.certs.entries()[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
+ const _step4$value = _slicedToArray(_step4.value, 2),
+ index = _step4$value[0],
+ certificate = _step4$value[1];
+
+ if (certificate.subject.isEqual(_this.tbsResponseData.responderID)) {
+ certIndex = index;
+ break;
+ }
+ }
+ } catch (err) {
+ _didIteratorError4 = true;
+ _iteratorError4 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion4 && _iterator4.return != null) {
+ _iterator4.return();
+ }
+ } finally {
+ if (_didIteratorError4) {
+ throw _iteratorError4;
+ }
+ }
+ }
+ });
+ break;
+
+ case this.tbsResponseData.responderID instanceof asn1js.OctetString:
+ // [2] KeyHash
+ sequence = sequence.then(() => Promise.all(Array.from(_this.certs, element => crypto.digest({
+ name: "sha-1"
+ }, new Uint8Array(element.subjectPublicKeyInfo.subjectPublicKey.valueBlock.valueHex)))).then(results => {
+ var _iteratorNormalCompletion5 = true;
+ var _didIteratorError5 = false;
+ var _iteratorError5 = undefined;
+
+ try {
+ for (var _iterator5 = _this.certs.entries()[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
+ const _step5$value = _slicedToArray(_step5.value, 1),
+ index = _step5$value[0];
+
+ if ((0, _pvutils.isEqualBuffer)(results[index], _this.tbsResponseData.responderID.valueBlock.valueHex)) {
+ certIndex = index;
+ break;
+ }
+ }
+ } catch (err) {
+ _didIteratorError5 = true;
+ _iteratorError5 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion5 && _iterator5.return != null) {
+ _iterator5.return();
+ }
+ } finally {
+ if (_didIteratorError5) {
+ throw _iteratorError5;
+ }
+ }
+ }
+ }));
+ break;
+
+ default:
+ return Promise.reject("Wrong value for responderID");
+ } //endregion
+ //region Make additional verification for signer's certificate
+
+
+ sequence = sequence.then(() => {
+ if (certIndex === -1) return Promise.reject("Correct certificate was not found in OCSP response");
+ signerCert = this.certs[certIndex];
+ return Promise.all(Array.from(_this.certs, element => checkCA(element))).then(promiseResults => {
+ const additionalCerts = [];
+ additionalCerts.push(signerCert);
+ var _iteratorNormalCompletion6 = true;
+ var _didIteratorError6 = false;
+ var _iteratorError6 = undefined;
+
+ try {
+ for (var _iterator6 = promiseResults[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
+ const promiseResult = _step6.value;
+ if (promiseResult !== null) additionalCerts.push(promiseResult);
+ }
+ } catch (err) {
+ _didIteratorError6 = true;
+ _iteratorError6 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion6 && _iterator6.return != null) {
+ _iterator6.return();
+ }
+ } finally {
+ if (_didIteratorError6) {
+ throw _iteratorError6;
+ }
+ }
+ }
+
+ const certChain = new _CertificateChainValidationEngine.default({
+ certs: additionalCerts,
+ trustedCerts
+ });
+ return certChain.verify().then(verificationResult => {
+ if (verificationResult.result === true) return Promise.resolve();
+ return Promise.reject("Validation of signer's certificate failed");
+ }, error => Promise.reject(`Validation of signer's certificate failed with error: ${error instanceof Object ? error.resultMessage : error}`));
+ }, promiseError => Promise.reject(`Error during checking certificates for CA flag: ${promiseError}`));
+ }); //endregion
+
+ sequence = sequence.then(() => engine.subtle.verifyWithPublicKey(this.tbsResponseData.tbs, this.signature, this.certs[certIndex].subjectPublicKeyInfo, this.signatureAlgorithm));
+ return sequence;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = BasicOCSPResponse;
+
+},{"./AlgorithmIdentifier.js":4,"./CertID.js":18,"./Certificate.js":19,"./CertificateChainValidationEngine.js":20,"./RelativeDistinguishedNames.js":89,"./ResponseData.js":92,"./common.js":110,"asn1js":112,"pvutils":113}],14:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from https://docs.microsoft.com/en-us/windows/desktop/seccrypto/certification-authority-renewal
+ */
+class CAVersion {
+ //**********************************************************************************
+
+ /**
+ * Constructor for CAVersion class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc certificateIndex
+ */
+ this.certificateIndex = (0, _pvutils.getParametersValue)(parameters, "certificateIndex", CAVersion.defaultValues("certificateIndex"));
+ /**
+ * @type {number}
+ * @desc keyIndex
+ */
+
+ this.keyIndex = (0, _pvutils.getParametersValue)(parameters, "keyIndex", CAVersion.defaultValues("keyIndex")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "certificateIndex":
+ case "keyIndex":
+ return 0;
+
+ default:
+ throw new Error(`Invalid member name for CAVersion class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * CAVersion ::= INTEGER
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ return new asn1js.Integer();
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Check the schema is valid
+ if (schema.constructor.blockName() !== asn1js.Integer.blockName()) throw new Error("Object's schema was not verified against input data for CAVersion"); //endregion
+ //region Check length of the input value and correct it if needed
+
+ let value = schema.valueBlock.valueHex.slice(0);
+ const valueView = new Uint8Array(value);
+
+ switch (true) {
+ case value.byteLength < 4:
+ {
+ const tempValue = new ArrayBuffer(4);
+ const tempValueView = new Uint8Array(tempValue);
+ tempValueView.set(valueView, 4 - value.byteLength);
+ value = tempValue.slice(0);
+ }
+ break;
+
+ case value.byteLength > 4:
+ {
+ const tempValue = new ArrayBuffer(4);
+ const tempValueView = new Uint8Array(tempValue);
+ tempValueView.set(valueView.slice(0, 4));
+ value = tempValue.slice(0);
+ }
+ break;
+
+ default:
+ } //endregion
+ //region Get internal properties from parsed schema
+
+
+ const keyIndexBuffer = value.slice(0, 2);
+ const keyIndexView8 = new Uint8Array(keyIndexBuffer);
+ let temp = keyIndexView8[0];
+ keyIndexView8[0] = keyIndexView8[1];
+ keyIndexView8[1] = temp;
+ const keyIndexView16 = new Uint16Array(keyIndexBuffer);
+ this.keyIndex = keyIndexView16[0];
+ const certificateIndexBuffer = value.slice(2);
+ const certificateIndexView8 = new Uint8Array(certificateIndexBuffer);
+ temp = certificateIndexView8[0];
+ certificateIndexView8[0] = certificateIndexView8[1];
+ certificateIndexView8[1] = temp;
+ const certificateIndexView16 = new Uint16Array(certificateIndexBuffer);
+ this.certificateIndex = certificateIndexView16[0]; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create raw values
+ const certificateIndexBuffer = new ArrayBuffer(2);
+ const certificateIndexView = new Uint16Array(certificateIndexBuffer);
+ certificateIndexView[0] = this.certificateIndex;
+ const certificateIndexView8 = new Uint8Array(certificateIndexBuffer);
+ let temp = certificateIndexView8[0];
+ certificateIndexView8[0] = certificateIndexView8[1];
+ certificateIndexView8[1] = temp;
+ const keyIndexBuffer = new ArrayBuffer(2);
+ const keyIndexView = new Uint16Array(keyIndexBuffer);
+ keyIndexView[0] = this.keyIndex;
+ const keyIndexView8 = new Uint8Array(keyIndexBuffer);
+ temp = keyIndexView8[0];
+ keyIndexView8[0] = keyIndexView8[1];
+ keyIndexView8[1] = temp; //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Integer({
+ valueHex: (0, _pvutils.utilConcatBuf)(keyIndexBuffer, certificateIndexBuffer)
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ certificateIndex: this.certificateIndex,
+ keyIndex: this.keyIndex
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = CAVersion;
+
+},{"asn1js":112,"pvutils":113}],15:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _CertificateRevocationList = _interopRequireDefault(require("./CertificateRevocationList.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC7292
+ */
+class CRLBag {
+ //**********************************************************************************
+
+ /**
+ * Constructor for CRLBag class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc crlId
+ */
+ this.crlId = (0, _pvutils.getParametersValue)(parameters, "crlId", CRLBag.defaultValues("crlId"));
+ /**
+ * @type {*}
+ * @desc crlValue
+ */
+
+ this.crlValue = (0, _pvutils.getParametersValue)(parameters, "crlValue", CRLBag.defaultValues("crlValue"));
+ if ("parsedValue" in parameters)
+ /**
+ * @type {*}
+ * @desc parsedValue
+ */
+ this.parsedValue = (0, _pvutils.getParametersValue)(parameters, "parsedValue", CRLBag.defaultValues("parsedValue")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "crlId":
+ return "";
+
+ case "crlValue":
+ return new asn1js.Any();
+
+ case "parsedValue":
+ return {};
+
+ default:
+ throw new Error(`Invalid member name for CRLBag class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "crlId":
+ return memberValue === "";
+
+ case "crlValue":
+ return memberValue instanceof asn1js.Any;
+
+ case "parsedValue":
+ return memberValue instanceof Object && Object.keys(memberValue).length === 0;
+
+ default:
+ throw new Error(`Invalid member name for CRLBag class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * CRLBag ::= SEQUENCE {
+ * crlId BAG-TYPE.&id ({CRLTypes}),
+ * crlValue [0] EXPLICIT BAG-TYPE.&Type ({CRLTypes}{@crlId})
+ *}
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [id]
+ * @property {string} [value]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.id || "id"
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Any({
+ name: names.value || "value"
+ })] // EXPLICIT ANY value
+
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["crlId", "crlValue"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, CRLBag.schema({
+ names: {
+ id: "crlId",
+ value: "crlValue"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for CRLBag"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.crlId = asn1.result.crlId.valueBlock.toString();
+ this.crlValue = asn1.result.crlValue;
+
+ switch (this.crlId) {
+ case "1.2.840.113549.1.9.23.1":
+ // x509CRL
+ {
+ const asn1Inner = asn1js.fromBER(this.certValue.valueBlock.valueHex);
+ this.parsedValue = new _CertificateRevocationList.default({
+ schema: asn1Inner.result
+ });
+ }
+ break;
+
+ default:
+ throw new Error(`Incorrect "crlId" value in CRLBag: ${this.crlId}`);
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ if ("parsedValue" in this) {
+ this.certId = "1.2.840.113549.1.9.23.1";
+ this.certValue = new asn1js.OctetString({
+ valueHex: this.parsedValue.toSchema().toBER(false)
+ });
+ }
+
+ return new asn1js.Sequence({
+ value: [new asn1js.ObjectIdentifier({
+ value: this.crlId
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [this.crlValue.toSchema()]
+ })]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ crlId: this.crlId,
+ crlValue: this.crlValue.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = CRLBag;
+
+},{"./CertificateRevocationList.js":22,"asn1js":112,"pvutils":113}],16:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _DistributionPoint = _interopRequireDefault(require("./DistributionPoint.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class CRLDistributionPoints {
+ //**********************************************************************************
+
+ /**
+ * Constructor for CRLDistributionPoints class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array.<DistributionPoint>}
+ * @desc distributionPoints
+ */
+ this.distributionPoints = (0, _pvutils.getParametersValue)(parameters, "distributionPoints", CRLDistributionPoints.defaultValues("distributionPoints")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "distributionPoints":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for CRLDistributionPoints class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [distributionPoints]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Repeated({
+ name: names.distributionPoints || "",
+ value: _DistributionPoint.default.schema()
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["distributionPoints"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, CRLDistributionPoints.schema({
+ names: {
+ distributionPoints: "distributionPoints"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for CRLDistributionPoints"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.distributionPoints = Array.from(asn1.result.distributionPoints, element => new _DistributionPoint.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: Array.from(this.distributionPoints, element => element.toSchema())
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ distributionPoints: Array.from(this.distributionPoints, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = CRLDistributionPoints;
+
+},{"./DistributionPoint.js":29,"asn1js":112,"pvutils":113}],17:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _Certificate = _interopRequireDefault(require("./Certificate.js"));
+
+var _AttributeCertificateV = _interopRequireDefault(require("./AttributeCertificateV2.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC7292
+ */
+class CertBag {
+ //**********************************************************************************
+
+ /**
+ * Constructor for CertBag class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc certId
+ */
+ this.certId = (0, _pvutils.getParametersValue)(parameters, "certId", CertBag.defaultValues("certId"));
+ /**
+ * @type {*}
+ * @desc certValue
+ */
+
+ this.certValue = (0, _pvutils.getParametersValue)(parameters, "certValue", CertBag.defaultValues("certValue"));
+ if ("parsedValue" in parameters)
+ /**
+ * @type {*}
+ * @desc parsedValue
+ */
+ this.parsedValue = (0, _pvutils.getParametersValue)(parameters, "parsedValue", CertBag.defaultValues("parsedValue")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "certId":
+ return "";
+
+ case "certValue":
+ return new asn1js.Any();
+
+ case "parsedValue":
+ return {};
+
+ default:
+ throw new Error(`Invalid member name for CertBag class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "certId":
+ return memberValue === "";
+
+ case "certValue":
+ return memberValue instanceof asn1js.Any;
+
+ case "parsedValue":
+ return memberValue instanceof Object && Object.keys(memberValue).length === 0;
+
+ default:
+ throw new Error(`Invalid member name for CertBag class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * CertBag ::= SEQUENCE {
+ * certId BAG-TYPE.&id ({CertTypes}),
+ * certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId})
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [id]
+ * @property {string} [value]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.id || "id"
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Any({
+ name: names.value || "value"
+ })] // EXPLICIT ANY value
+
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["certId", "certValue"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, CertBag.schema({
+ names: {
+ id: "certId",
+ value: "certValue"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for CertBag"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.certId = asn1.result.certId.valueBlock.toString();
+ this.certValue = asn1.result.certValue;
+
+ switch (this.certId) {
+ case "1.2.840.113549.1.9.22.1":
+ // x509Certificate
+ {
+ const asn1Inner = asn1js.fromBER(this.certValue.valueBlock.valueHex);
+
+ try {
+ this.parsedValue = new _Certificate.default({
+ schema: asn1Inner.result
+ });
+ } catch (ex) // In some realizations the same OID used for attribute certificates
+ {
+ this.parsedValue = new _AttributeCertificateV.default({
+ schema: asn1Inner.result
+ });
+ }
+ }
+ break;
+
+ case "1.2.840.113549.1.9.22.3":
+ // attributeCertificate - (!!!) THIS OID IS SUBJECT FOR CHANGE IN FUTURE (!!!)
+ {
+ const asn1Inner = asn1js.fromBER(this.certValue.valueBlock.valueHex);
+ this.parsedValue = new _AttributeCertificateV.default({
+ schema: asn1Inner.result
+ });
+ }
+ break;
+
+ case "1.2.840.113549.1.9.22.2": // sdsiCertificate
+
+ default:
+ throw new Error(`Incorrect "certId" value in CertBag: ${this.certId}`);
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ if ("parsedValue" in this) {
+ if ("acinfo" in this.parsedValue) // attributeCertificate
+ this.certId = "1.2.840.113549.1.9.22.3";else // x509Certificate
+ this.certId = "1.2.840.113549.1.9.22.1";
+ this.certValue = new asn1js.OctetString({
+ valueHex: this.parsedValue.toSchema().toBER(false)
+ });
+ }
+
+ return new asn1js.Sequence({
+ value: [new asn1js.ObjectIdentifier({
+ value: this.certId
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: ["toSchema" in this.certValue ? this.certValue.toSchema() : this.certValue]
+ })]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ certId: this.certId,
+ certValue: this.certValue.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = CertBag;
+
+},{"./AttributeCertificateV2.js":8,"./Certificate.js":19,"asn1js":112,"pvutils":113}],18:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _common = require("./common.js");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC6960
+ */
+class CertID {
+ //**********************************************************************************
+
+ /**
+ * Constructor for CertID class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc hashAlgorithm
+ */
+ this.hashAlgorithm = (0, _pvutils.getParametersValue)(parameters, "hashAlgorithm", CertID.defaultValues("hashAlgorithm"));
+ /**
+ * @type {OctetString}
+ * @desc issuerNameHash
+ */
+
+ this.issuerNameHash = (0, _pvutils.getParametersValue)(parameters, "issuerNameHash", CertID.defaultValues("issuerNameHash"));
+ /**
+ * @type {OctetString}
+ * @desc issuerKeyHash
+ */
+
+ this.issuerKeyHash = (0, _pvutils.getParametersValue)(parameters, "issuerKeyHash", CertID.defaultValues("issuerKeyHash"));
+ /**
+ * @type {Integer}
+ * @desc serialNumber
+ */
+
+ this.serialNumber = (0, _pvutils.getParametersValue)(parameters, "serialNumber", CertID.defaultValues("serialNumber")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "hashAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "issuerNameHash":
+ case "issuerKeyHash":
+ return new asn1js.OctetString();
+
+ case "serialNumber":
+ return new asn1js.Integer();
+
+ default:
+ throw new Error(`Invalid member name for CertID class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "hashAlgorithm":
+ return memberValue.algorithmId === "" && "algorithmParams" in memberValue === false;
+
+ case "issuerNameHash":
+ case "issuerKeyHash":
+ case "serialNumber":
+ return memberValue.isEqual(CertID.defaultValues(memberName));
+
+ default:
+ throw new Error(`Invalid member name for CertID class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * CertID ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * issuerNameHash OCTET STRING, -- Hash of issuer's DN
+ * issuerKeyHash OCTET STRING, -- Hash of issuer's public key
+ * serialNumber CertificateSerialNumber }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [hashAlgorithm]
+ * @property {string} [hashAlgorithmObject]
+ * @property {string} [issuerNameHash]
+ * @property {string} [issuerKeyHash]
+ * @property {string} [serialNumber]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [_AlgorithmIdentifier.default.schema(names.hashAlgorithmObject || {
+ names: {
+ blockName: names.hashAlgorithm || ""
+ }
+ }), new asn1js.OctetString({
+ name: names.issuerNameHash || ""
+ }), new asn1js.OctetString({
+ name: names.issuerKeyHash || ""
+ }), new asn1js.Integer({
+ name: names.serialNumber || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["hashAlgorithm", "issuerNameHash", "issuerKeyHash", "serialNumber"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, CertID.schema({
+ names: {
+ hashAlgorithm: "hashAlgorithm",
+ issuerNameHash: "issuerNameHash",
+ issuerKeyHash: "issuerKeyHash",
+ serialNumber: "serialNumber"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for CertID"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.hashAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.hashAlgorithm
+ });
+ this.issuerNameHash = asn1.result.issuerNameHash;
+ this.issuerKeyHash = asn1.result.issuerKeyHash;
+ this.serialNumber = asn1.result.serialNumber; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [this.hashAlgorithm.toSchema(), this.issuerNameHash, this.issuerKeyHash, this.serialNumber]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ hashAlgorithm: this.hashAlgorithm.toJSON(),
+ issuerNameHash: this.issuerNameHash.toJSON(),
+ issuerKeyHash: this.issuerKeyHash.toJSON(),
+ serialNumber: this.serialNumber.toJSON()
+ };
+ } //**********************************************************************************
+
+ /**
+ * Check that two "CertIDs" are equal
+ * @param {CertID} certificateID Identifier of the certificate to be checked
+ * @returns {boolean}
+ */
+
+
+ isEqual(certificateID) {
+ //region Check "hashAlgorithm"
+ if (!this.hashAlgorithm.algorithmId === certificateID.hashAlgorithm.algorithmId) return false; //endregion
+ //region Check "issuerNameHash"
+
+ if ((0, _pvutils.isEqualBuffer)(this.issuerNameHash.valueBlock.valueHex, certificateID.issuerNameHash.valueBlock.valueHex) === false) return false; //endregion
+ //region Check "issuerKeyHash"
+
+ if ((0, _pvutils.isEqualBuffer)(this.issuerKeyHash.valueBlock.valueHex, certificateID.issuerKeyHash.valueBlock.valueHex) === false) return false; //endregion
+ //region Check "serialNumber"
+
+ if (!this.serialNumber.isEqual(certificateID.serialNumber)) return false; //endregion
+
+ return true;
+ } //**********************************************************************************
+
+ /**
+ * Making OCSP certificate identifier for specific certificate
+ * @param {Certificate} certificate Certificate making OCSP Request for
+ * @param {Object} parameters Additional parameters
+ * @returns {Promise}
+ */
+
+
+ createForCertificate(certificate, parameters) {
+ //region Initial variables
+ let sequence = Promise.resolve();
+ let issuerCertificate; //endregion
+ //region Get a "crypto" extension
+
+ const crypto = (0, _common.getCrypto)();
+ if (typeof crypto === "undefined") return Promise.reject("Unable to create WebCrypto object"); //endregion
+ //region Check input parameters
+
+ if ("hashAlgorithm" in parameters === false) return Promise.reject("Parameter \"hashAlgorithm\" is mandatory for \"OCSP_REQUEST.createForCertificate\"");
+ const hashOID = (0, _common.getOIDByAlgorithm)({
+ name: parameters.hashAlgorithm
+ });
+ if (hashOID === "") return Promise.reject(`Incorrect "hashAlgorithm": ${this.hashAlgorithm}`);
+ this.hashAlgorithm = new _AlgorithmIdentifier.default({
+ algorithmId: hashOID,
+ algorithmParams: new asn1js.Null()
+ });
+ if ("issuerCertificate" in parameters) issuerCertificate = parameters.issuerCertificate;else return Promise.reject("Parameter \"issuerCertificate\" is mandatory for \"OCSP_REQUEST.createForCertificate\""); //endregion
+ //region Initialize "serialNumber" field
+
+ this.serialNumber = certificate.serialNumber; //endregion
+ //region Create "issuerNameHash"
+
+ sequence = sequence.then(() => crypto.digest({
+ name: parameters.hashAlgorithm
+ }, issuerCertificate.subject.toSchema().toBER(false)), error => Promise.reject(error)); //endregion
+ //region Create "issuerKeyHash"
+
+ sequence = sequence.then(result => {
+ this.issuerNameHash = new asn1js.OctetString({
+ valueHex: result
+ });
+ const issuerKeyBuffer = issuerCertificate.subjectPublicKeyInfo.subjectPublicKey.valueBlock.valueHex;
+ return crypto.digest({
+ name: parameters.hashAlgorithm
+ }, issuerKeyBuffer);
+ }, error => Promise.reject(error)).then(result => {
+ this.issuerKeyHash = new asn1js.OctetString({
+ valueHex: result
+ });
+ }, error => Promise.reject(error)); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = CertID;
+
+},{"./AlgorithmIdentifier.js":4,"./common.js":110,"asn1js":112,"pvutils":113}],19:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _common = require("./common.js");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _RelativeDistinguishedNames = _interopRequireDefault(require("./RelativeDistinguishedNames.js"));
+
+var _Time = _interopRequireDefault(require("./Time.js"));
+
+var _PublicKeyInfo = _interopRequireDefault(require("./PublicKeyInfo.js"));
+
+var _Extension = _interopRequireDefault(require("./Extension.js"));
+
+var _Extensions = _interopRequireDefault(require("./Extensions.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+function tbsCertificate(parameters = {}) {
+ //TBSCertificate ::= SEQUENCE {
+ // version [0] EXPLICIT Version DEFAULT v1,
+ // serialNumber CertificateSerialNumber,
+ // signature AlgorithmIdentifier,
+ // issuer Name,
+ // validity Validity,
+ // subject Name,
+ // subjectPublicKeyInfo SubjectPublicKeyInfo,
+ // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
+ // -- If present, version MUST be v2 or v3
+ // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
+ // -- If present, version MUST be v2 or v3
+ // extensions [3] EXPLICIT Extensions OPTIONAL
+ // -- If present, version MUST be v3
+ //}
+
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [tbsCertificateVersion]
+ * @property {string} [tbsCertificateSerialNumber]
+ * @property {string} [signature]
+ * @property {string} [issuer]
+ * @property {string} [tbsCertificateValidity]
+ * @property {string} [notBefore]
+ * @property {string} [notAfter]
+ * @property {string} [subject]
+ * @property {string} [subjectPublicKeyInfo]
+ * @property {string} [tbsCertificateIssuerUniqueID]
+ * @property {string} [tbsCertificateSubjectUniqueID]
+ * @property {string} [extensions]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "tbsCertificate",
+ value: [new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Integer({
+ name: names.tbsCertificateVersion || "tbsCertificate.version"
+ }) // EXPLICIT integer value
+ ]
+ }), new asn1js.Integer({
+ name: names.tbsCertificateSerialNumber || "tbsCertificate.serialNumber"
+ }), _AlgorithmIdentifier.default.schema(names.signature || {
+ names: {
+ blockName: "tbsCertificate.signature"
+ }
+ }), _RelativeDistinguishedNames.default.schema(names.issuer || {
+ names: {
+ blockName: "tbsCertificate.issuer"
+ }
+ }), new asn1js.Sequence({
+ name: names.tbsCertificateValidity || "tbsCertificate.validity",
+ value: [_Time.default.schema(names.notBefore || {
+ names: {
+ utcTimeName: "tbsCertificate.notBefore",
+ generalTimeName: "tbsCertificate.notBefore"
+ }
+ }), _Time.default.schema(names.notAfter || {
+ names: {
+ utcTimeName: "tbsCertificate.notAfter",
+ generalTimeName: "tbsCertificate.notAfter"
+ }
+ })]
+ }), _RelativeDistinguishedNames.default.schema(names.subject || {
+ names: {
+ blockName: "tbsCertificate.subject"
+ }
+ }), _PublicKeyInfo.default.schema(names.subjectPublicKeyInfo || {
+ names: {
+ blockName: "tbsCertificate.subjectPublicKeyInfo"
+ }
+ }), new asn1js.Primitive({
+ name: names.tbsCertificateIssuerUniqueID || "tbsCertificate.issuerUniqueID",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ }
+ }), // IMPLICIT bistring value
+ new asn1js.Primitive({
+ name: names.tbsCertificateSubjectUniqueID || "tbsCertificate.subjectUniqueID",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ }
+ }), // IMPLICIT bistring value
+ new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 3 // [3]
+
+ },
+ value: [_Extensions.default.schema(names.extensions || {
+ names: {
+ blockName: "tbsCertificate.extensions"
+ }
+ })]
+ }) // EXPLICIT SEQUENCE value
+ ]
+ });
+} //**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+
+
+class Certificate {
+ //**********************************************************************************
+
+ /**
+ * Constructor for Certificate class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {ArrayBuffer}
+ * @desc ToBeSigned (TBS) part of the certificate
+ */
+ this.tbs = (0, _pvutils.getParametersValue)(parameters, "tbs", Certificate.defaultValues("tbs"));
+ /**
+ * @type {number}
+ * @desc Version number
+ */
+
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", Certificate.defaultValues("version"));
+ /**
+ * @type {Integer}
+ * @desc Serial number of the certificate
+ */
+
+ this.serialNumber = (0, _pvutils.getParametersValue)(parameters, "serialNumber", Certificate.defaultValues("serialNumber"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc This field contains the algorithm identifier for the algorithm used by the CA to sign the certificate
+ */
+
+ this.signature = (0, _pvutils.getParametersValue)(parameters, "signature", Certificate.defaultValues("signature"));
+ /**
+ * @type {RelativeDistinguishedNames}
+ * @desc The issuer field identifies the entity that has signed and issued the certificate
+ */
+
+ this.issuer = (0, _pvutils.getParametersValue)(parameters, "issuer", Certificate.defaultValues("issuer"));
+ /**
+ * @type {Time}
+ * @desc The date on which the certificate validity period begins
+ */
+
+ this.notBefore = (0, _pvutils.getParametersValue)(parameters, "notBefore", Certificate.defaultValues("notBefore"));
+ /**
+ * @type {Time}
+ * @desc The date on which the certificate validity period ends
+ */
+
+ this.notAfter = (0, _pvutils.getParametersValue)(parameters, "notAfter", Certificate.defaultValues("notAfter"));
+ /**
+ * @type {RelativeDistinguishedNames}
+ * @desc The subject field identifies the entity associated with the public key stored in the subject public key field
+ */
+
+ this.subject = (0, _pvutils.getParametersValue)(parameters, "subject", Certificate.defaultValues("subject"));
+ /**
+ * @type {PublicKeyInfo}
+ * @desc This field is used to carry the public key and identify the algorithm with which the key is used
+ */
+
+ this.subjectPublicKeyInfo = (0, _pvutils.getParametersValue)(parameters, "subjectPublicKeyInfo", Certificate.defaultValues("subjectPublicKeyInfo"));
+ if ("issuerUniqueID" in parameters)
+ /**
+ * @type {ArrayBuffer}
+ * @desc The subject and issuer unique identifiers are present in the certificate to handle the possibility of reuse of subject and/or issuer names over time
+ */
+ this.issuerUniqueID = (0, _pvutils.getParametersValue)(parameters, "issuerUniqueID", Certificate.defaultValues("issuerUniqueID"));
+ if ("subjectUniqueID" in parameters)
+ /**
+ * @type {ArrayBuffer}
+ * @desc The subject and issuer unique identifiers are present in the certificate to handle the possibility of reuse of subject and/or issuer names over time
+ */
+ this.subjectUniqueID = (0, _pvutils.getParametersValue)(parameters, "subjectUniqueID", Certificate.defaultValues("subjectUniqueID"));
+ if ("extensions" in parameters)
+ /**
+ * @type {Array}
+ * @desc If present, this field is a SEQUENCE of one or more certificate extensions
+ */
+ this.extensions = (0, _pvutils.getParametersValue)(parameters, "extensions", Certificate.defaultValues("extensions"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc The signatureAlgorithm field contains the identifier for the cryptographic algorithm used by the CA to sign this certificate
+ */
+
+ this.signatureAlgorithm = (0, _pvutils.getParametersValue)(parameters, "signatureAlgorithm", Certificate.defaultValues("signatureAlgorithm"));
+ /**
+ * @type {BitString}
+ * @desc The signatureValue field contains a digital signature computed upon the ASN.1 DER encoded tbsCertificate
+ */
+
+ this.signatureValue = (0, _pvutils.getParametersValue)(parameters, "signatureValue", Certificate.defaultValues("signatureValue")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "tbs":
+ return new ArrayBuffer(0);
+
+ case "version":
+ return 0;
+
+ case "serialNumber":
+ return new asn1js.Integer();
+
+ case "signature":
+ return new _AlgorithmIdentifier.default();
+
+ case "issuer":
+ return new _RelativeDistinguishedNames.default();
+
+ case "notBefore":
+ return new _Time.default();
+
+ case "notAfter":
+ return new _Time.default();
+
+ case "subject":
+ return new _RelativeDistinguishedNames.default();
+
+ case "subjectPublicKeyInfo":
+ return new _PublicKeyInfo.default();
+
+ case "issuerUniqueID":
+ return new ArrayBuffer(0);
+
+ case "subjectUniqueID":
+ return new ArrayBuffer(0);
+
+ case "extensions":
+ return [];
+
+ case "signatureAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "signatureValue":
+ return new asn1js.BitString();
+
+ default:
+ throw new Error(`Invalid member name for Certificate class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * Certificate ::= SEQUENCE {
+ * tbsCertificate TBSCertificate,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [tbsCertificate]
+ * @property {string} [signatureAlgorithm]
+ * @property {string} [signatureValue]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [tbsCertificate(names.tbsCertificate), _AlgorithmIdentifier.default.schema(names.signatureAlgorithm || {
+ names: {
+ blockName: "signatureAlgorithm"
+ }
+ }), new asn1js.BitString({
+ name: names.signatureValue || "signatureValue"
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["tbsCertificate", "tbsCertificate.extensions", "tbsCertificate.version", "tbsCertificate.serialNumber", "tbsCertificate.signature", "tbsCertificate.issuer", "tbsCertificate.notBefore", "tbsCertificate.notAfter", "tbsCertificate.subject", "tbsCertificate.subjectPublicKeyInfo", "tbsCertificate.issuerUniqueID", "tbsCertificate.subjectUniqueID", "signatureAlgorithm", "signatureValue"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, Certificate.schema({
+ names: {
+ tbsCertificate: {
+ names: {
+ extensions: {
+ names: {
+ extensions: "tbsCertificate.extensions"
+ }
+ }
+ }
+ }
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for Certificate"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.tbs = asn1.result.tbsCertificate.valueBeforeDecode;
+ if ("tbsCertificate.version" in asn1.result) this.version = asn1.result["tbsCertificate.version"].valueBlock.valueDec;
+ this.serialNumber = asn1.result["tbsCertificate.serialNumber"];
+ this.signature = new _AlgorithmIdentifier.default({
+ schema: asn1.result["tbsCertificate.signature"]
+ });
+ this.issuer = new _RelativeDistinguishedNames.default({
+ schema: asn1.result["tbsCertificate.issuer"]
+ });
+ this.notBefore = new _Time.default({
+ schema: asn1.result["tbsCertificate.notBefore"]
+ });
+ this.notAfter = new _Time.default({
+ schema: asn1.result["tbsCertificate.notAfter"]
+ });
+ this.subject = new _RelativeDistinguishedNames.default({
+ schema: asn1.result["tbsCertificate.subject"]
+ });
+ this.subjectPublicKeyInfo = new _PublicKeyInfo.default({
+ schema: asn1.result["tbsCertificate.subjectPublicKeyInfo"]
+ });
+ if ("tbsCertificate.issuerUniqueID" in asn1.result) this.issuerUniqueID = asn1.result["tbsCertificate.issuerUniqueID"].valueBlock.valueHex;
+ if ("tbsCertificate.subjectUniqueID" in asn1.result) this.subjectUniqueID = asn1.result["tbsCertificate.subjectUniqueID"].valueBlock.valueHex;
+ if ("tbsCertificate.extensions" in asn1.result) this.extensions = Array.from(asn1.result["tbsCertificate.extensions"], element => new _Extension.default({
+ schema: element
+ }));
+ this.signatureAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.signatureAlgorithm
+ });
+ this.signatureValue = asn1.result.signatureValue; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Create ASN.1 schema for existing values of TBS part for the certificate
+ */
+
+
+ encodeTBS() {
+ //region Create array for output sequence
+ const outputArray = [];
+
+ if ("version" in this && this.version !== Certificate.defaultValues("version")) {
+ outputArray.push(new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Integer({
+ value: this.version
+ }) // EXPLICIT integer value
+ ]
+ }));
+ }
+
+ outputArray.push(this.serialNumber);
+ outputArray.push(this.signature.toSchema());
+ outputArray.push(this.issuer.toSchema());
+ outputArray.push(new asn1js.Sequence({
+ value: [this.notBefore.toSchema(), this.notAfter.toSchema()]
+ }));
+ outputArray.push(this.subject.toSchema());
+ outputArray.push(this.subjectPublicKeyInfo.toSchema());
+
+ if ("issuerUniqueID" in this) {
+ outputArray.push(new asn1js.Primitive({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ valueHex: this.issuerUniqueID
+ }));
+ }
+
+ if ("subjectUniqueID" in this) {
+ outputArray.push(new asn1js.Primitive({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ valueHex: this.subjectUniqueID
+ }));
+ }
+
+ if ("extensions" in this) {
+ outputArray.push(new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 3 // [3]
+
+ },
+ value: [new asn1js.Sequence({
+ value: Array.from(this.extensions, element => element.toSchema())
+ })]
+ }));
+ } //endregion
+ //region Create and return output sequence
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema(encodeFlag = false) {
+ let tbsSchema = {}; //region Decode stored TBS value
+
+ if (encodeFlag === false) {
+ if (this.tbs.length === 0) // No stored certificate TBS part
+ return Certificate.schema().value[0];
+ tbsSchema = asn1js.fromBER(this.tbs).result;
+ } //endregion
+ //region Create TBS schema via assembling from TBS parts
+ else tbsSchema = this.encodeTBS(); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: [tbsSchema, this.signatureAlgorithm.toSchema(), this.signatureValue]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {
+ tbs: (0, _pvutils.bufferToHexCodes)(this.tbs, 0, this.tbs.byteLength),
+ serialNumber: this.serialNumber.toJSON(),
+ signature: this.signature.toJSON(),
+ issuer: this.issuer.toJSON(),
+ notBefore: this.notBefore.toJSON(),
+ notAfter: this.notAfter.toJSON(),
+ subject: this.subject.toJSON(),
+ subjectPublicKeyInfo: this.subjectPublicKeyInfo.toJSON(),
+ signatureAlgorithm: this.signatureAlgorithm.toJSON(),
+ signatureValue: this.signatureValue.toJSON()
+ };
+ if ("version" in this && this.version !== Certificate.defaultValues("version")) object.version = this.version;
+ if ("issuerUniqueID" in this) object.issuerUniqueID = (0, _pvutils.bufferToHexCodes)(this.issuerUniqueID, 0, this.issuerUniqueID.byteLength);
+ if ("subjectUniqueID" in this) object.subjectUniqueID = (0, _pvutils.bufferToHexCodes)(this.subjectUniqueID, 0, this.subjectUniqueID.byteLength);
+ if ("extensions" in this) object.extensions = Array.from(this.extensions, element => element.toJSON());
+ return object;
+ } //**********************************************************************************
+
+ /**
+ * Importing public key for current certificate
+ */
+
+
+ getPublicKey(parameters = null) {
+ return (0, _common.getEngine)().subtle.getPublicKey(this.subjectPublicKeyInfo, this.signatureAlgorithm, parameters);
+ } //**********************************************************************************
+
+ /**
+ * Get hash value for subject public key (default SHA-1)
+ * @param {String} [hashAlgorithm=SHA-1] Hashing algorithm name
+ */
+
+
+ getKeyHash(hashAlgorithm = "SHA-1") {
+ //region Get a "crypto" extension
+ const crypto = (0, _common.getCrypto)();
+ if (typeof crypto === "undefined") return Promise.reject("Unable to create WebCrypto object"); //endregion
+
+ return crypto.digest({
+ name: hashAlgorithm
+ }, new Uint8Array(this.subjectPublicKeyInfo.subjectPublicKey.valueBlock.valueHex));
+ } //**********************************************************************************
+
+ /**
+ * Make a signature for current value from TBS section
+ * @param {Object} privateKey Private key for "subjectPublicKeyInfo" structure
+ * @param {string} [hashAlgorithm="SHA-1"] Hashing algorithm
+ */
+
+
+ sign(privateKey, hashAlgorithm = "SHA-1") {
+ //region Initial checking
+ //region Check private key
+ if (typeof privateKey === "undefined") return Promise.reject("Need to provide a private key for signing"); //endregion
+ //endregion
+ //region Initial variables
+
+ let sequence = Promise.resolve();
+ let parameters;
+ const engine = (0, _common.getEngine)(); //endregion
+ //region Get a "default parameters" for current algorithm and set correct signature algorithm
+
+ sequence = sequence.then(() => engine.subtle.getSignatureParameters(privateKey, hashAlgorithm));
+ sequence = sequence.then(result => {
+ parameters = result.parameters;
+ this.signature = result.signatureAlgorithm;
+ this.signatureAlgorithm = result.signatureAlgorithm;
+ }); //endregion
+ //region Create TBS data for signing
+
+ sequence = sequence.then(() => {
+ this.tbs = this.encodeTBS().toBER(false);
+ }); //endregion
+ //region Signing TBS data on provided private key
+
+ sequence = sequence.then(() => engine.subtle.signWithPrivateKey(this.tbs, privateKey, parameters));
+ sequence = sequence.then(result => {
+ this.signatureValue = new asn1js.BitString({
+ valueHex: result
+ });
+ }); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+
+ verify(issuerCertificate = null) {
+ //region Global variables
+ let subjectPublicKeyInfo = {}; //endregion
+ //region Set correct "subjectPublicKeyInfo" value
+
+ if (issuerCertificate !== null) subjectPublicKeyInfo = issuerCertificate.subjectPublicKeyInfo;else {
+ if (this.issuer.isEqual(this.subject)) // Self-signed certificate
+ subjectPublicKeyInfo = this.subjectPublicKeyInfo;
+ }
+ if (subjectPublicKeyInfo instanceof _PublicKeyInfo.default === false) return Promise.reject("Please provide issuer certificate as a parameter"); //endregion
+
+ return (0, _common.getEngine)().subtle.verifyWithPublicKey(this.tbs, this.signatureValue, subjectPublicKeyInfo, this.signatureAlgorithm);
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = Certificate;
+
+},{"./AlgorithmIdentifier.js":4,"./Extension.js":38,"./Extensions.js":39,"./PublicKeyInfo.js":78,"./RelativeDistinguishedNames.js":89,"./Time.js":107,"./common.js":110,"asn1js":112,"pvutils":113}],20:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var _pvutils = require("pvutils");
+
+var _common = require("./common.js");
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+
+//**************************************************************************************
+class CertificateChainValidationEngine {
+ //**********************************************************************************
+
+ /**
+ * Constructor for CertificateChainValidationEngine class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array.<Certificate>}
+ * @desc Array of pre-defined trusted (by user) certificates
+ */
+ this.trustedCerts = (0, _pvutils.getParametersValue)(parameters, "trustedCerts", this.defaultValues("trustedCerts"));
+ /**
+ * @type {Array.<Certificate>}
+ * @desc Array with certificate chain. Could be only one end-user certificate in there!
+ */
+
+ this.certs = (0, _pvutils.getParametersValue)(parameters, "certs", this.defaultValues("certs"));
+ /**
+ * @type {Array.<CertificateRevocationList>}
+ * @desc Array of all CRLs for all certificates from certificate chain
+ */
+
+ this.crls = (0, _pvutils.getParametersValue)(parameters, "crls", this.defaultValues("crls"));
+ /**
+ * @type {Array}
+ * @desc Array of all OCSP responses
+ */
+
+ this.ocsps = (0, _pvutils.getParametersValue)(parameters, "ocsps", this.defaultValues("ocsps"));
+ /**
+ * @type {Date}
+ * @desc The date at which the check would be
+ */
+
+ this.checkDate = (0, _pvutils.getParametersValue)(parameters, "checkDate", this.defaultValues("checkDate"));
+ /**
+ * @type {Function}
+ * @desc The date at which the check would be
+ */
+
+ this.findOrigin = (0, _pvutils.getParametersValue)(parameters, "findOrigin", this.defaultValues("findOrigin"));
+ /**
+ * @type {Function}
+ * @desc The date at which the check would be
+ */
+
+ this.findIssuer = (0, _pvutils.getParametersValue)(parameters, "findIssuer", this.defaultValues("findIssuer")); //endregion
+ } //**********************************************************************************
+
+
+ static defaultFindOrigin(certificate, validationEngine) {
+ //region Firstly encode TBS for certificate
+ if (certificate.tbs.byteLength === 0) certificate.tbs = certificate.encodeTBS(); //endregion
+ //region Search in Intermediate Certificates
+
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = validationEngine.certs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ const localCert = _step.value;
+ //region Firstly encode TBS for certificate
+ if (localCert.tbs.byteLength === 0) localCert.tbs = localCert.encodeTBS(); //endregion
+
+ if ((0, _pvutils.isEqualBuffer)(certificate.tbs, localCert.tbs)) return "Intermediate Certificates";
+ } //endregion
+ //region Search in Trusted Certificates
+
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+
+ var _iteratorNormalCompletion2 = true;
+ var _didIteratorError2 = false;
+ var _iteratorError2 = undefined;
+
+ try {
+ for (var _iterator2 = validationEngine.trustedCerts[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+ const trustedCert = _step2.value;
+ //region Firstly encode TBS for certificate
+ if (trustedCert.tbs.byteLength === 0) trustedCert.tbs = trustedCert.encodeTBS(); //endregion
+
+ if ((0, _pvutils.isEqualBuffer)(certificate.tbs, trustedCert.tbs)) return "Trusted Certificates";
+ } //endregion
+
+ } catch (err) {
+ _didIteratorError2 = true;
+ _iteratorError2 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
+ _iterator2.return();
+ }
+ } finally {
+ if (_didIteratorError2) {
+ throw _iteratorError2;
+ }
+ }
+ }
+
+ return "Unknown";
+ } //**********************************************************************************
+
+
+ defaultFindIssuer(certificate, validationEngine) {
+ return _asyncToGenerator(function* () {
+ //region Initial variables
+ let result = [];
+ let keyIdentifier = null;
+ let authorityCertIssuer = null;
+ let authorityCertSerialNumber = null; //endregion
+ //region Speed-up searching in case of self-signed certificates
+
+ if (certificate.subject.isEqual(certificate.issuer)) {
+ try {
+ const verificationResult = yield certificate.verify();
+ if (verificationResult === true) return [certificate];
+ } catch (ex) {}
+ } //endregion
+ //region Find values to speed-up search
+
+
+ if ("extensions" in certificate) {
+ var _iteratorNormalCompletion3 = true;
+ var _didIteratorError3 = false;
+ var _iteratorError3 = undefined;
+
+ try {
+ for (var _iterator3 = certificate.extensions[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
+ const extension = _step3.value;
+
+ if (extension.extnID === "2.5.29.35") // AuthorityKeyIdentifier
+ {
+ if ("keyIdentifier" in extension.parsedValue) keyIdentifier = extension.parsedValue.keyIdentifier;else {
+ if ("authorityCertIssuer" in extension.parsedValue) authorityCertIssuer = extension.parsedValue.authorityCertIssuer;
+ if ("authorityCertSerialNumber" in extension.parsedValue) authorityCertSerialNumber = extension.parsedValue.authorityCertSerialNumber;
+ }
+ break;
+ }
+ }
+ } catch (err) {
+ _didIteratorError3 = true;
+ _iteratorError3 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
+ _iterator3.return();
+ }
+ } finally {
+ if (_didIteratorError3) {
+ throw _iteratorError3;
+ }
+ }
+ }
+ } //endregion
+ //region Aux function
+
+
+ function checkCertificate(possibleIssuer) {
+ //region Firstly search for appropriate extensions
+ if (keyIdentifier !== null) {
+ if ("extensions" in possibleIssuer) {
+ let extensionFound = false;
+ var _iteratorNormalCompletion4 = true;
+ var _didIteratorError4 = false;
+ var _iteratorError4 = undefined;
+
+ try {
+ for (var _iterator4 = possibleIssuer.extensions[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
+ const extension = _step4.value;
+
+ if (extension.extnID === "2.5.29.14") // SubjectKeyIdentifier
+ {
+ extensionFound = true;
+ if ((0, _pvutils.isEqualBuffer)(extension.parsedValue.valueBlock.valueHex, keyIdentifier.valueBlock.valueHex)) result.push(possibleIssuer);
+ break;
+ }
+ }
+ } catch (err) {
+ _didIteratorError4 = true;
+ _iteratorError4 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion4 && _iterator4.return != null) {
+ _iterator4.return();
+ }
+ } finally {
+ if (_didIteratorError4) {
+ throw _iteratorError4;
+ }
+ }
+ }
+
+ if (extensionFound) return;
+ }
+ } //endregion
+ //region Now search for authorityCertSerialNumber
+
+
+ let authorityCertSerialNumberEqual = false;
+ if (authorityCertSerialNumber !== null) authorityCertSerialNumberEqual = possibleIssuer.serialNumber.isEqual(authorityCertSerialNumber); //endregion
+ //region And at least search for Issuer data
+
+ if (authorityCertIssuer !== null) {
+ if (possibleIssuer.subject.isEqual(authorityCertIssuer)) {
+ if (authorityCertSerialNumberEqual) result.push(possibleIssuer);
+ }
+ } else {
+ if (certificate.issuer.isEqual(possibleIssuer.subject)) result.push(possibleIssuer);
+ } //endregion
+
+ } //endregion
+ //region Search in Trusted Certificates
+
+
+ var _iteratorNormalCompletion5 = true;
+ var _didIteratorError5 = false;
+ var _iteratorError5 = undefined;
+
+ try {
+ for (var _iterator5 = validationEngine.trustedCerts[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
+ const trustedCert = _step5.value;
+ checkCertificate(trustedCert);
+ } //endregion
+ //region Search in Intermediate Certificates
+
+ } catch (err) {
+ _didIteratorError5 = true;
+ _iteratorError5 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion5 && _iterator5.return != null) {
+ _iterator5.return();
+ }
+ } finally {
+ if (_didIteratorError5) {
+ throw _iteratorError5;
+ }
+ }
+ }
+
+ var _iteratorNormalCompletion6 = true;
+ var _didIteratorError6 = false;
+ var _iteratorError6 = undefined;
+
+ try {
+ for (var _iterator6 = validationEngine.certs[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
+ const intermediateCert = _step6.value;
+ checkCertificate(intermediateCert);
+ } //endregion
+ //region Now perform certificate verification checking
+
+ } catch (err) {
+ _didIteratorError6 = true;
+ _iteratorError6 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion6 && _iterator6.return != null) {
+ _iterator6.return();
+ }
+ } finally {
+ if (_didIteratorError6) {
+ throw _iteratorError6;
+ }
+ }
+ }
+
+ for (let i = 0; i < result.length; i++) {
+ try {
+ const verificationResult = yield certificate.verify(result[i]);
+ if (verificationResult === false) result.splice(i, 1);
+ } catch (ex) {
+ result.splice(i, 1); // Something wrong, remove the certificate
+ }
+ } //endregion
+
+
+ return result;
+ })();
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ defaultValues(memberName) {
+ switch (memberName) {
+ case "trustedCerts":
+ return [];
+
+ case "certs":
+ return [];
+
+ case "crls":
+ return [];
+
+ case "ocsps":
+ return [];
+
+ case "checkDate":
+ return new Date();
+
+ case "findOrigin":
+ return CertificateChainValidationEngine.defaultFindOrigin;
+
+ case "findIssuer":
+ return this.defaultFindIssuer;
+
+ default:
+ throw new Error(`Invalid member name for CertificateChainValidationEngine class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+
+ sort(passedWhenNotRevValues = false) {
+ var _this2 = this;
+
+ return _asyncToGenerator(function* () {
+ //region Initial variables
+ const localCerts = [];
+ const _this = _this2; //endregion
+ //region Building certificate path
+
+ function buildPath(_x) {
+ return _buildPath.apply(this, arguments);
+ } //endregion
+ //region Find CRL for specific certificate
+
+
+ function _buildPath() {
+ _buildPath = _asyncToGenerator(function* (certificate) {
+ const result = []; //region Aux function checking array for unique elements
+
+ function checkUnique(array) {
+ let unique = true;
+
+ for (let i = 0; i < array.length; i++) {
+ for (let j = 0; j < array.length; j++) {
+ if (j === i) continue;
+
+ if (array[i] === array[j]) {
+ unique = false;
+ break;
+ }
+ }
+
+ if (!unique) break;
+ }
+
+ return unique;
+ } //endregion
+
+
+ const findIssuerResult = yield _this.findIssuer(certificate, _this);
+ if (findIssuerResult.length === 0) throw new Error("No valid certificate paths found");
+
+ for (let i = 0; i < findIssuerResult.length; i++) {
+ if ((0, _pvutils.isEqualBuffer)(findIssuerResult[i].tbs, certificate.tbs)) {
+ result.push([findIssuerResult[i]]);
+ continue;
+ }
+
+ const buildPathResult = yield buildPath(findIssuerResult[i]);
+
+ for (let j = 0; j < buildPathResult.length; j++) {
+ const copy = buildPathResult[j].slice();
+ copy.splice(0, 0, findIssuerResult[i]);
+ if (checkUnique(copy)) result.push(copy);else result.push(buildPathResult[j]);
+ }
+ }
+
+ return result;
+ });
+ return _buildPath.apply(this, arguments);
+ }
+
+ function findCRL(_x2) {
+ return _findCRL.apply(this, arguments);
+ } //endregion
+ //region Find OCSP for specific certificate
+
+
+ function _findCRL() {
+ _findCRL = _asyncToGenerator(function* (certificate) {
+ //region Initial variables
+ const issuerCertificates = [];
+ const crls = [];
+ const crlsAndCertificates = []; //endregion
+ //region Find all possible CRL issuers
+
+ issuerCertificates.push(...localCerts.filter(element => certificate.issuer.isEqual(element.subject)));
+
+ if (issuerCertificates.length === 0) {
+ return {
+ status: 1,
+ statusMessage: "No certificate's issuers"
+ };
+ } //endregion
+ //region Find all CRLs for certificate's issuer
+
+
+ crls.push(..._this.crls.filter(element => element.issuer.isEqual(certificate.issuer)));
+
+ if (crls.length === 0) {
+ return {
+ status: 2,
+ statusMessage: "No CRLs for specific certificate issuer"
+ };
+ } //endregion
+ //region Find specific certificate of issuer for each CRL
+
+
+ for (let i = 0; i < crls.length; i++) {
+ //region Check "nextUpdate" for the CRL
+ // The "nextUpdate" is older than "checkDate".
+ // Thus we should do have another, updated CRL.
+ // Thus the CRL assumed to be invalid.
+ if (crls[i].nextUpdate.value < _this.checkDate) continue; //endregion
+
+ for (let j = 0; j < issuerCertificates.length; j++) {
+ try {
+ const result = yield crls[i].verify({
+ issuerCertificate: issuerCertificates[j]
+ });
+
+ if (result) {
+ crlsAndCertificates.push({
+ crl: crls[i],
+ certificate: issuerCertificates[j]
+ });
+ break;
+ }
+ } catch (ex) {}
+ }
+ } //endregion
+
+
+ if (crlsAndCertificates.length) {
+ return {
+ status: 0,
+ statusMessage: "",
+ result: crlsAndCertificates
+ };
+ }
+
+ return {
+ status: 3,
+ statusMessage: "No valid CRLs found"
+ };
+ });
+ return _findCRL.apply(this, arguments);
+ }
+
+ function findOCSP(_x3, _x4) {
+ return _findOCSP.apply(this, arguments);
+ } //endregion
+ //region Check for certificate to be CA
+
+
+ function _findOCSP() {
+ _findOCSP = _asyncToGenerator(function* (certificate, issuerCertificate) {
+ //region Get hash algorithm from certificate
+ const hashAlgorithm = (0, _common.getAlgorithmByOID)(certificate.signatureAlgorithm.algorithmId);
+ if ("name" in hashAlgorithm === false) return 1;
+ if ("hash" in hashAlgorithm === false) return 1; //endregion
+ //region Search for OCSP response for the certificate
+
+ for (let i = 0; i < _this.ocsps.length; i++) {
+ const result = yield _this.ocsps[i].getCertificateStatus(certificate, issuerCertificate);
+
+ if (result.isForCertificate) {
+ if (result.status === 0) return 0;
+ return 1;
+ }
+ } //endregion
+
+
+ return 2;
+ });
+ return _findOCSP.apply(this, arguments);
+ }
+
+ function checkForCA(_x5) {
+ return _checkForCA.apply(this, arguments);
+ } //endregion
+ //region Basic check for certificate path
+
+
+ function _checkForCA() {
+ _checkForCA = _asyncToGenerator(function* (certificate, needToCheckCRL = false) {
+ //region Initial variables
+ let isCA = false;
+ let mustBeCA = false;
+ let keyUsagePresent = false;
+ let cRLSign = false; //endregion
+
+ if ("extensions" in certificate) {
+ for (let j = 0; j < certificate.extensions.length; j++) {
+ if (certificate.extensions[j].critical === true && "parsedValue" in certificate.extensions[j] === false) {
+ return {
+ result: false,
+ resultCode: 6,
+ resultMessage: `Unable to parse critical certificate extension: ${certificate.extensions[j].extnID}`
+ };
+ }
+
+ if (certificate.extensions[j].extnID === "2.5.29.15") // KeyUsage
+ {
+ keyUsagePresent = true;
+ const view = new Uint8Array(certificate.extensions[j].parsedValue.valueBlock.valueHex);
+ if ((view[0] & 0x04) === 0x04) // Set flag "keyCertSign"
+ mustBeCA = true;
+ if ((view[0] & 0x02) === 0x02) // Set flag "cRLSign"
+ cRLSign = true;
+ }
+
+ if (certificate.extensions[j].extnID === "2.5.29.19") // BasicConstraints
+ {
+ if ("cA" in certificate.extensions[j].parsedValue) {
+ if (certificate.extensions[j].parsedValue.cA === true) isCA = true;
+ }
+ }
+ }
+
+ if (mustBeCA === true && isCA === false) {
+ return {
+ result: false,
+ resultCode: 3,
+ resultMessage: "Unable to build certificate chain - using \"keyCertSign\" flag set without BasicConstaints"
+ };
+ }
+
+ if (keyUsagePresent === true && isCA === true && mustBeCA === false) {
+ return {
+ result: false,
+ resultCode: 4,
+ resultMessage: "Unable to build certificate chain - \"keyCertSign\" flag was not set"
+ };
+ } // noinspection OverlyComplexBooleanExpressionJS
+
+
+ if (isCA === true && keyUsagePresent === true && needToCheckCRL && cRLSign === false) {
+ return {
+ result: false,
+ resultCode: 5,
+ resultMessage: "Unable to build certificate chain - intermediate certificate must have \"cRLSign\" key usage flag"
+ };
+ }
+ }
+
+ if (isCA === false) {
+ return {
+ result: false,
+ resultCode: 7,
+ resultMessage: "Unable to build certificate chain - more than one possible end-user certificate"
+ };
+ }
+
+ return {
+ result: true,
+ resultCode: 0,
+ resultMessage: ""
+ };
+ });
+ return _checkForCA.apply(this, arguments);
+ }
+
+ function basicCheck(_x6, _x7) {
+ return _basicCheck.apply(this, arguments);
+ } //endregion
+ //region Do main work
+ //region Initialize "localCerts" by value of "_this.certs" + "_this.trustedCerts" arrays
+
+
+ function _basicCheck() {
+ _basicCheck = _asyncToGenerator(function* (path, checkDate) {
+ //region Check that all dates are valid
+ for (let i = 0; i < path.length; i++) {
+ if (path[i].notBefore.value > checkDate || path[i].notAfter.value < checkDate) {
+ return {
+ result: false,
+ resultCode: 8,
+ resultMessage: "The certificate is either not yet valid or expired"
+ };
+ }
+ } //endregion
+ //region Check certificate name chain
+ // We should have at least two certificates: end entity and trusted root
+
+
+ if (path.length < 2) {
+ return {
+ result: false,
+ resultCode: 9,
+ resultMessage: "Too short certificate path"
+ };
+ }
+
+ for (let i = path.length - 2; i >= 0; i--) {
+ //region Check that we do not have a "self-signed" certificate
+ if (path[i].issuer.isEqual(path[i].subject) === false) {
+ if (path[i].issuer.isEqual(path[i + 1].subject) === false) {
+ return {
+ result: false,
+ resultCode: 10,
+ resultMessage: "Incorrect name chaining"
+ };
+ }
+ } //endregion
+
+ } //endregion
+ //region Check each certificate (except "trusted root") to be non-revoked
+
+
+ if (_this.crls.length !== 0 || _this.ocsps.length !== 0) // If CRLs and OCSPs are empty then we consider all certificates to be valid
+ {
+ for (let i = 0; i < path.length - 1; i++) {
+ //region Initial variables
+ let ocspResult = 2;
+ let crlResult = {
+ status: 0,
+ statusMessage: ""
+ }; //endregion
+ //region Check OCSPs first
+
+ if (_this.ocsps.length !== 0) {
+ ocspResult = yield findOCSP(path[i], path[i + 1]);
+
+ switch (ocspResult) {
+ case 0:
+ continue;
+
+ case 1:
+ return {
+ result: false,
+ resultCode: 12,
+ resultMessage: "One of certificates was revoked via OCSP response"
+ };
+
+ case 2:
+ // continue to check the certificate with CRL
+ break;
+
+ default:
+ }
+ } //endregion
+ //region Check CRLs
+
+
+ if (_this.crls.length !== 0) {
+ crlResult = yield findCRL(path[i]);
+
+ if (crlResult.status === 0) {
+ for (let j = 0; j < crlResult.result.length; j++) {
+ //region Check that the CRL issuer certificate have not been revoked
+ const isCertificateRevoked = crlResult.result[j].crl.isCertificateRevoked(path[i]);
+
+ if (isCertificateRevoked) {
+ return {
+ result: false,
+ resultCode: 12,
+ resultMessage: "One of certificates had been revoked"
+ };
+ } //endregion
+ //region Check that the CRL issuer certificate is a CA certificate
+
+
+ const isCertificateCA = yield checkForCA(crlResult.result[j].certificate, true);
+
+ if (isCertificateCA.result === false) {
+ return {
+ result: false,
+ resultCode: 13,
+ resultMessage: "CRL issuer certificate is not a CA certificate or does not have crlSign flag"
+ };
+ } //endregion
+
+ }
+ } else {
+ if (passedWhenNotRevValues === false) {
+ throw {
+ result: false,
+ resultCode: 11,
+ resultMessage: `No revocation values found for one of certificates: ${crlResult.statusMessage}`
+ };
+ }
+ }
+ } else {
+ if (ocspResult === 2) {
+ return {
+ result: false,
+ resultCode: 11,
+ resultMessage: "No revocation values found for one of certificates"
+ };
+ }
+ } //endregion
+ //region Check we do have links to revocation values inside issuer's certificate
+
+
+ if (ocspResult === 2 && crlResult.status === 2 && passedWhenNotRevValues) {
+ const issuerCertificate = path[i + 1];
+ let extensionFound = false;
+
+ if ("extensions" in issuerCertificate) {
+ var _iteratorNormalCompletion7 = true;
+ var _didIteratorError7 = false;
+ var _iteratorError7 = undefined;
+
+ try {
+ for (var _iterator7 = issuerCertificate.extensions[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
+ const extension = _step7.value;
+
+ switch (extension.extnID) {
+ case "2.5.29.31": // CRLDistributionPoints
+
+ case "2.5.29.46": // FreshestCRL
+
+ case "1.3.6.1.5.5.7.1.1":
+ // AuthorityInfoAccess
+ extensionFound = true;
+ break;
+
+ default:
+ }
+ }
+ } catch (err) {
+ _didIteratorError7 = true;
+ _iteratorError7 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion7 && _iterator7.return != null) {
+ _iterator7.return();
+ }
+ } finally {
+ if (_didIteratorError7) {
+ throw _iteratorError7;
+ }
+ }
+ }
+ }
+
+ if (extensionFound) {
+ throw {
+ result: false,
+ resultCode: 11,
+ resultMessage: `No revocation values found for one of certificates: ${crlResult.statusMessage}`
+ };
+ }
+ } //endregion
+
+ }
+ } //endregion
+ //region Check each certificate (except "end entity") in the path to be a CA certificate
+
+
+ for (let i = 1; i < path.length; i++) {
+ const result = yield checkForCA(path[i]);
+
+ if (result.result === false) {
+ return {
+ result: false,
+ resultCode: 14,
+ resultMessage: "One of intermediate certificates is not a CA certificate"
+ };
+ }
+ } //endregion
+
+
+ return {
+ result: true
+ };
+ });
+ return _basicCheck.apply(this, arguments);
+ }
+
+ localCerts.push(..._this.trustedCerts);
+ localCerts.push(..._this.certs); //endregion
+ //region Check all certificates for been unique
+
+ for (let i = 0; i < localCerts.length; i++) {
+ for (let j = 0; j < localCerts.length; j++) {
+ if (i === j) continue;
+
+ if ((0, _pvutils.isEqualBuffer)(localCerts[i].tbs, localCerts[j].tbs)) {
+ localCerts.splice(j, 1);
+ i = 0;
+ break;
+ }
+ }
+ } //endregion
+ //region Initial variables
+
+
+ let result;
+ const certificatePath = [localCerts[localCerts.length - 1]]; // The "end entity" certificate must be the least in "certs" array
+ //endregion
+ //region Build path for "end entity" certificate
+
+ result = yield buildPath(localCerts[localCerts.length - 1]);
+
+ if (result.length === 0) {
+ return {
+ result: false,
+ resultCode: 60,
+ resultMessage: "Unable to find certificate path"
+ };
+ } //endregion
+ //region Exclude certificate paths not ended with "trusted roots"
+
+
+ for (let i = 0; i < result.length; i++) {
+ let found = false;
+
+ for (let j = 0; j < result[i].length; j++) {
+ const certificate = result[i][j];
+
+ for (let k = 0; k < _this.trustedCerts.length; k++) {
+ if ((0, _pvutils.isEqualBuffer)(certificate.tbs, _this.trustedCerts[k].tbs)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) break;
+ }
+
+ if (!found) {
+ result.splice(i, 1);
+ i = 0;
+ }
+ }
+
+ if (result.length === 0) {
+ throw {
+ result: false,
+ resultCode: 97,
+ resultMessage: "No valid certificate paths found"
+ };
+ } //endregion
+ //region Find shortest certificate path (for the moment it is the only criteria)
+
+
+ let shortestLength = result[0].length;
+ let shortestIndex = 0;
+
+ for (let i = 0; i < result.length; i++) {
+ if (result[i].length < shortestLength) {
+ shortestLength = result[i].length;
+ shortestIndex = i;
+ }
+ } //endregion
+ //region Create certificate path for basic check
+
+
+ for (let i = 0; i < result[shortestIndex].length; i++) certificatePath.push(result[shortestIndex][i]); //endregion
+ //region Perform basic checking for all certificates in the path
+
+
+ result = yield basicCheck(certificatePath, _this.checkDate);
+ if (result.result === false) throw result; //endregion
+
+ return certificatePath; //endregion
+ })();
+ } //**********************************************************************************
+
+ /**
+ * Major verification function for certificate chain.
+ * @param {{initialPolicySet, initialExplicitPolicy, initialPolicyMappingInhibit, initialInhibitPolicy, initialPermittedSubtreesSet, initialExcludedSubtreesSet, initialRequiredNameForms}} [parameters]
+ * @returns {Promise}
+ */
+
+
+ verify(parameters = {}) {
+ var _this3 = this;
+
+ return _asyncToGenerator(function* () {
+ //region Auxiliary functions for name constraints checking
+ function compareDNSName(name, constraint) {
+ /// <summary>Compare two dNSName values</summary>
+ /// <param name="name" type="String">DNS from name</param>
+ /// <param name="constraint" type="String">Constraint for DNS from name</param>
+ /// <returns type="Boolean">Boolean result - valid or invalid the "name" against the "constraint"</returns>
+ //region Make a "string preparation" for both name and constrain
+ const namePrepared = (0, _common.stringPrep)(name);
+ const constraintPrepared = (0, _common.stringPrep)(constraint); //endregion
+ //region Make a "splitted" versions of "constraint" and "name"
+
+ const nameSplitted = namePrepared.split(".");
+ const constraintSplitted = constraintPrepared.split("."); //endregion
+ //region Length calculation and additional check
+
+ const nameLen = nameSplitted.length;
+ const constrLen = constraintSplitted.length;
+ if (nameLen === 0 || constrLen === 0 || nameLen < constrLen) return false; //endregion
+ //region Check that no part of "name" has zero length
+
+ for (let i = 0; i < nameLen; i++) {
+ if (nameSplitted[i].length === 0) return false;
+ } //endregion
+ //region Check that no part of "constraint" has zero length
+
+
+ for (let i = 0; i < constrLen; i++) {
+ if (constraintSplitted[i].length === 0) {
+ if (i === 0) {
+ if (constrLen === 1) return false;
+ continue;
+ }
+
+ return false;
+ }
+ } //endregion
+ //region Check that "name" has a tail as "constraint"
+
+
+ for (let i = 0; i < constrLen; i++) {
+ if (constraintSplitted[constrLen - 1 - i].length === 0) continue;
+ if (nameSplitted[nameLen - 1 - i].localeCompare(constraintSplitted[constrLen - 1 - i]) !== 0) return false;
+ } //endregion
+
+
+ return true;
+ }
+
+ function compareRFC822Name(name, constraint) {
+ /// <summary>Compare two rfc822Name values</summary>
+ /// <param name="name" type="String">E-mail address from name</param>
+ /// <param name="constraint" type="String">Constraint for e-mail address from name</param>
+ /// <returns type="Boolean">Boolean result - valid or invalid the "name" against the "constraint"</returns>
+ //region Make a "string preparation" for both name and constrain
+ const namePrepared = (0, _common.stringPrep)(name);
+ const constraintPrepared = (0, _common.stringPrep)(constraint); //endregion
+ //region Make a "splitted" versions of "constraint" and "name"
+
+ const nameSplitted = namePrepared.split("@");
+ const constraintSplitted = constraintPrepared.split("@"); //endregion
+ //region Splitted array length checking
+
+ if (nameSplitted.length === 0 || constraintSplitted.length === 0 || nameSplitted.length < constraintSplitted.length) return false; //endregion
+
+ if (constraintSplitted.length === 1) {
+ const result = compareDNSName(nameSplitted[1], constraintSplitted[0]);
+
+ if (result) {
+ //region Make a "splitted" versions of domain name from "constraint" and "name"
+ const ns = nameSplitted[1].split(".");
+ const cs = constraintSplitted[0].split("."); //endregion
+
+ if (cs[0].length === 0) return true;
+ return ns.length === cs.length;
+ }
+
+ return false;
+ }
+
+ return namePrepared.localeCompare(constraintPrepared) === 0;
+ }
+
+ function compareUniformResourceIdentifier(name, constraint) {
+ /// <summary>Compare two uniformResourceIdentifier values</summary>
+ /// <param name="name" type="String">uniformResourceIdentifier from name</param>
+ /// <param name="constraint" type="String">Constraint for uniformResourceIdentifier from name</param>
+ /// <returns type="Boolean">Boolean result - valid or invalid the "name" against the "constraint"</returns>
+ //region Make a "string preparation" for both name and constrain
+ let namePrepared = (0, _common.stringPrep)(name);
+ const constraintPrepared = (0, _common.stringPrep)(constraint); //endregion
+ //region Find out a major URI part to compare with
+
+ const ns = namePrepared.split("/");
+ const cs = constraintPrepared.split("/");
+ if (cs.length > 1) // Malformed constraint
+ return false;
+
+ if (ns.length > 1) // Full URI string
+ {
+ for (let i = 0; i < ns.length; i++) {
+ if (ns[i].length > 0 && ns[i].charAt(ns[i].length - 1) !== ":") {
+ const nsPort = ns[i].split(":");
+ namePrepared = nsPort[0];
+ break;
+ }
+ }
+ } //endregion
+
+
+ const result = compareDNSName(namePrepared, constraintPrepared);
+
+ if (result) {
+ //region Make a "splitted" versions of "constraint" and "name"
+ const nameSplitted = namePrepared.split(".");
+ const constraintSplitted = constraintPrepared.split("."); //endregion
+
+ if (constraintSplitted[0].length === 0) return true;
+ return nameSplitted.length === constraintSplitted.length;
+ }
+
+ return false;
+ }
+
+ function compareIPAddress(name, constraint) {
+ /// <summary>Compare two iPAddress values</summary>
+ /// <param name="name" type="in_window.org.pkijs.asn1.OCTETSTRING">iPAddress from name</param>
+ /// <param name="constraint" type="in_window.org.pkijs.asn1.OCTETSTRING">Constraint for iPAddress from name</param>
+ /// <returns type="Boolean">Boolean result - valid or invalid the "name" against the "constraint"</returns>
+ //region Common variables
+ const nameView = new Uint8Array(name.valueBlock.valueHex);
+ const constraintView = new Uint8Array(constraint.valueBlock.valueHex); //endregion
+ //region Work with IPv4 addresses
+
+ if (nameView.length === 4 && constraintView.length === 8) {
+ for (let i = 0; i < 4; i++) {
+ if ((nameView[i] ^ constraintView[i]) & constraintView[i + 4]) return false;
+ }
+
+ return true;
+ } //endregion
+ //region Work with IPv6 addresses
+
+
+ if (nameView.length === 16 && constraintView.length === 32) {
+ for (let i = 0; i < 16; i++) {
+ if ((nameView[i] ^ constraintView[i]) & constraintView[i + 16]) return false;
+ }
+
+ return true;
+ } //endregion
+
+
+ return false;
+ }
+
+ function compareDirectoryName(name, constraint) {
+ /// <summary>Compare two directoryName values</summary>
+ /// <param name="name" type="in_window.org.pkijs.simpl.RDN">directoryName from name</param>
+ /// <param name="constraint" type="in_window.org.pkijs.simpl.RDN">Constraint for directoryName from name</param>
+ /// <param name="any" type="Boolean">Boolean flag - should be comparision interrupted after first match or we need to match all "constraints" parts</param>
+ /// <returns type="Boolean">Boolean result - valid or invalid the "name" against the "constraint"</returns>
+ //region Initial check
+ if (name.typesAndValues.length === 0 || constraint.typesAndValues.length === 0) return true;
+ if (name.typesAndValues.length < constraint.typesAndValues.length) return false; //endregion
+ //region Initial variables
+
+ let result = true;
+ let nameStart = 0; //endregion
+
+ for (let i = 0; i < constraint.typesAndValues.length; i++) {
+ let localResult = false;
+
+ for (let j = nameStart; j < name.typesAndValues.length; j++) {
+ localResult = name.typesAndValues[j].isEqual(constraint.typesAndValues[i]);
+ if (name.typesAndValues[j].type === constraint.typesAndValues[i].type) result = result && localResult;
+
+ if (localResult === true) {
+ if (nameStart === 0 || nameStart === j) {
+ nameStart = j + 1;
+ break;
+ } else // Structure of "name" must be the same with "constraint"
+ return false;
+ }
+ }
+
+ if (localResult === false) return false;
+ }
+
+ return nameStart === 0 ? false : result;
+ } //endregion
+
+
+ try {
+ //region Initial checks
+ if (_this3.certs.length === 0) throw "Empty certificate array"; //endregion
+ //region Get input variables
+
+ let passedWhenNotRevValues = false;
+ if ("passedWhenNotRevValues" in parameters) passedWhenNotRevValues = parameters.passedWhenNotRevValues;
+ let initialPolicySet = [];
+ initialPolicySet.push("2.5.29.32.0"); // "anyPolicy"
+
+ let initialExplicitPolicy = false;
+ let initialPolicyMappingInhibit = false;
+ let initialInhibitPolicy = false;
+ let initialPermittedSubtreesSet = []; // Array of "simpl.x509.GeneralSubtree"
+
+ let initialExcludedSubtreesSet = []; // Array of "simpl.x509.GeneralSubtree"
+
+ let initialRequiredNameForms = []; // Array of "simpl.x509.GeneralSubtree"
+
+ if ("initialPolicySet" in parameters) initialPolicySet = parameters.initialPolicySet;
+ if ("initialExplicitPolicy" in parameters) initialExplicitPolicy = parameters.initialExplicitPolicy;
+ if ("initialPolicyMappingInhibit" in parameters) initialPolicyMappingInhibit = parameters.initialPolicyMappingInhibit;
+ if ("initialInhibitPolicy" in parameters) initialInhibitPolicy = parameters.initialInhibitPolicy;
+ if ("initialPermittedSubtreesSet" in parameters) initialPermittedSubtreesSet = parameters.initialPermittedSubtreesSet;
+ if ("initialExcludedSubtreesSet" in parameters) initialExcludedSubtreesSet = parameters.initialExcludedSubtreesSet;
+ if ("initialRequiredNameForms" in parameters) initialRequiredNameForms = parameters.initialRequiredNameForms;
+ let explicitPolicyIndicator = initialExplicitPolicy;
+ let policyMappingInhibitIndicator = initialPolicyMappingInhibit;
+ let inhibitAnyPolicyIndicator = initialInhibitPolicy;
+ const pendingConstraints = new Array(3);
+ pendingConstraints[0] = false; // For "explicitPolicyPending"
+
+ pendingConstraints[1] = false; // For "policyMappingInhibitPending"
+
+ pendingConstraints[2] = false; // For "inhibitAnyPolicyPending"
+
+ let explicitPolicyPending = 0;
+ let policyMappingInhibitPending = 0;
+ let inhibitAnyPolicyPending = 0;
+ let permittedSubtrees = initialPermittedSubtreesSet;
+ let excludedSubtrees = initialExcludedSubtreesSet;
+ const requiredNameForms = initialRequiredNameForms;
+ let pathDepth = 1; //endregion
+ //region Sorting certificates in the chain array
+
+ _this3.certs = yield _this3.sort(passedWhenNotRevValues); //endregion
+ //region Work with policies
+ //region Support variables
+
+ const allPolicies = []; // Array of all policies (string values)
+
+ allPolicies.push("2.5.29.32.0"); // Put "anyPolicy" at first place
+
+ const policiesAndCerts = []; // In fact "array of array" where rows are for each specific policy, column for each certificate and value is "true/false"
+
+ const anyPolicyArray = new Array(_this3.certs.length - 1); // Minus "trusted anchor"
+
+ for (let ii = 0; ii < _this3.certs.length - 1; ii++) anyPolicyArray[ii] = true;
+
+ policiesAndCerts.push(anyPolicyArray);
+ const policyMappings = new Array(_this3.certs.length - 1); // Array of "PolicyMappings" for each certificate
+
+ const certPolicies = new Array(_this3.certs.length - 1); // Array of "CertificatePolicies" for each certificate
+
+ let explicitPolicyStart = explicitPolicyIndicator ? _this3.certs.length - 1 : -1; //endregion
+ //region Gather all neccessary information from certificate chain
+
+ for (let i = _this3.certs.length - 2; i >= 0; i--, pathDepth++) {
+ if ("extensions" in _this3.certs[i]) {
+ //region Get information about certificate extensions
+ for (let j = 0; j < _this3.certs[i].extensions.length; j++) {
+ //region CertificatePolicies
+ if (_this3.certs[i].extensions[j].extnID === "2.5.29.32") {
+ certPolicies[i] = _this3.certs[i].extensions[j].parsedValue; //region Remove entry from "anyPolicies" for the certificate
+
+ for (let s = 0; s < allPolicies.length; s++) {
+ if (allPolicies[s] === "2.5.29.32.0") {
+ delete policiesAndCerts[s][i];
+ break;
+ }
+ } //endregion
+
+
+ for (let k = 0; k < _this3.certs[i].extensions[j].parsedValue.certificatePolicies.length; k++) {
+ let policyIndex = -1; //region Try to find extension in "allPolicies" array
+
+ for (let s = 0; s < allPolicies.length; s++) {
+ if (_this3.certs[i].extensions[j].parsedValue.certificatePolicies[k].policyIdentifier === allPolicies[s]) {
+ policyIndex = s;
+ break;
+ }
+ } //endregion
+
+
+ if (policyIndex === -1) {
+ allPolicies.push(_this3.certs[i].extensions[j].parsedValue.certificatePolicies[k].policyIdentifier);
+ const certArray = new Array(_this3.certs.length - 1);
+ certArray[i] = true;
+ policiesAndCerts.push(certArray);
+ } else policiesAndCerts[policyIndex][i] = true;
+ }
+ } //endregion
+ //region PolicyMappings
+
+
+ if (_this3.certs[i].extensions[j].extnID === "2.5.29.33") {
+ if (policyMappingInhibitIndicator) {
+ return {
+ result: false,
+ resultCode: 98,
+ resultMessage: "Policy mapping prohibited"
+ };
+ }
+
+ policyMappings[i] = _this3.certs[i].extensions[j].parsedValue;
+ } //endregion
+ //region PolicyConstraints
+
+
+ if (_this3.certs[i].extensions[j].extnID === "2.5.29.36") {
+ if (explicitPolicyIndicator === false) {
+ //region requireExplicitPolicy
+ if (_this3.certs[i].extensions[j].parsedValue.requireExplicitPolicy === 0) {
+ explicitPolicyIndicator = true;
+ explicitPolicyStart = i;
+ } else {
+ if (pendingConstraints[0] === false) {
+ pendingConstraints[0] = true;
+ explicitPolicyPending = _this3.certs[i].extensions[j].parsedValue.requireExplicitPolicy;
+ } else explicitPolicyPending = explicitPolicyPending > _this3.certs[i].extensions[j].parsedValue.requireExplicitPolicy ? _this3.certs[i].extensions[j].parsedValue.requireExplicitPolicy : explicitPolicyPending;
+ } //endregion
+ //region inhibitPolicyMapping
+
+
+ if (_this3.certs[i].extensions[j].parsedValue.inhibitPolicyMapping === 0) policyMappingInhibitIndicator = true;else {
+ if (pendingConstraints[1] === false) {
+ pendingConstraints[1] = true;
+ policyMappingInhibitPending = _this3.certs[i].extensions[j].parsedValue.inhibitPolicyMapping + 1;
+ } else policyMappingInhibitPending = policyMappingInhibitPending > _this3.certs[i].extensions[j].parsedValue.inhibitPolicyMapping + 1 ? _this3.certs[i].extensions[j].parsedValue.inhibitPolicyMapping + 1 : policyMappingInhibitPending;
+ } //endregion
+ }
+ } //endregion
+ //region InhibitAnyPolicy
+
+
+ if (_this3.certs[i].extensions[j].extnID === "2.5.29.54") {
+ if (inhibitAnyPolicyIndicator === false) {
+ if (_this3.certs[i].extensions[j].parsedValue.valueBlock.valueDec === 0) inhibitAnyPolicyIndicator = true;else {
+ if (pendingConstraints[2] === false) {
+ pendingConstraints[2] = true;
+ inhibitAnyPolicyPending = _this3.certs[i].extensions[j].parsedValue.valueBlock.valueDec;
+ } else inhibitAnyPolicyPending = inhibitAnyPolicyPending > _this3.certs[i].extensions[j].parsedValue.valueBlock.valueDec ? _this3.certs[i].extensions[j].parsedValue.valueBlock.valueDec : inhibitAnyPolicyPending;
+ }
+ }
+ } //endregion
+
+ } //endregion
+ //region Check "inhibitAnyPolicyIndicator"
+
+
+ if (inhibitAnyPolicyIndicator === true) {
+ let policyIndex = -1; //region Find "anyPolicy" index
+
+ for (let searchAnyPolicy = 0; searchAnyPolicy < allPolicies.length; searchAnyPolicy++) {
+ if (allPolicies[searchAnyPolicy] === "2.5.29.32.0") {
+ policyIndex = searchAnyPolicy;
+ break;
+ }
+ } //endregion
+
+
+ if (policyIndex !== -1) delete policiesAndCerts[0][i]; // Unset value to "undefined" for "anyPolicies" value for current certificate
+ } //endregion
+ //region Process with "pending constraints"
+
+
+ if (explicitPolicyIndicator === false) {
+ if (pendingConstraints[0] === true) {
+ explicitPolicyPending--;
+
+ if (explicitPolicyPending === 0) {
+ explicitPolicyIndicator = true;
+ explicitPolicyStart = i;
+ pendingConstraints[0] = false;
+ }
+ }
+ }
+
+ if (policyMappingInhibitIndicator === false) {
+ if (pendingConstraints[1] === true) {
+ policyMappingInhibitPending--;
+
+ if (policyMappingInhibitPending === 0) {
+ policyMappingInhibitIndicator = true;
+ pendingConstraints[1] = false;
+ }
+ }
+ }
+
+ if (inhibitAnyPolicyIndicator === false) {
+ if (pendingConstraints[2] === true) {
+ inhibitAnyPolicyPending--;
+
+ if (inhibitAnyPolicyPending === 0) {
+ inhibitAnyPolicyIndicator = true;
+ pendingConstraints[2] = false;
+ }
+ }
+ } //endregion
+
+ }
+ } //endregion
+ //region Working with policy mappings
+
+
+ for (let i = 0; i < _this3.certs.length - 1; i++) {
+ //region Check that there is "policy mapping" for level "i + 1"
+ if (i < _this3.certs.length - 2 && typeof policyMappings[i + 1] !== "undefined") {
+ for (let k = 0; k < policyMappings[i + 1].mappings.length; k++) {
+ //region Check that we do not have "anyPolicy" in current mapping
+ if (policyMappings[i + 1].mappings[k].issuerDomainPolicy === "2.5.29.32.0" || policyMappings[i + 1].mappings[k].subjectDomainPolicy === "2.5.29.32.0") {
+ return {
+ result: false,
+ resultCode: 99,
+ resultMessage: "The \"anyPolicy\" should not be a part of policy mapping scheme"
+ };
+ } //endregion
+ //region Initial variables
+
+
+ let issuerDomainPolicyIndex = -1;
+ let subjectDomainPolicyIndex = -1; //endregion
+ //region Search for index of policies indedes
+
+ for (let n = 0; n < allPolicies.length; n++) {
+ if (allPolicies[n] === policyMappings[i + 1].mappings[k].issuerDomainPolicy) issuerDomainPolicyIndex = n;
+ if (allPolicies[n] === policyMappings[i + 1].mappings[k].subjectDomainPolicy) subjectDomainPolicyIndex = n;
+ } //endregion
+ //region Delete existing "issuerDomainPolicy" because on the level we mapped the policy to another one
+
+
+ if (typeof policiesAndCerts[issuerDomainPolicyIndex][i] !== "undefined") delete policiesAndCerts[issuerDomainPolicyIndex][i]; //endregion
+ //region Check all policies for the certificate
+
+ for (let j = 0; j < certPolicies[i].certificatePolicies.length; j++) {
+ if (policyMappings[i + 1].mappings[k].subjectDomainPolicy === certPolicies[i].certificatePolicies[j].policyIdentifier) {
+ //region Set mapped policy for current certificate
+ if (issuerDomainPolicyIndex !== -1 && subjectDomainPolicyIndex !== -1) {
+ for (let m = 0; m <= i; m++) {
+ if (typeof policiesAndCerts[subjectDomainPolicyIndex][m] !== "undefined") {
+ policiesAndCerts[issuerDomainPolicyIndex][m] = true;
+ delete policiesAndCerts[subjectDomainPolicyIndex][m];
+ }
+ }
+ } //endregion
+
+ }
+ } //endregion
+
+ }
+ } //endregion
+
+ } //endregion
+ //region Working with "explicitPolicyIndicator" and "anyPolicy"
+
+
+ for (let i = 0; i < allPolicies.length; i++) {
+ if (allPolicies[i] === "2.5.29.32.0") {
+ for (let j = 0; j < explicitPolicyStart; j++) delete policiesAndCerts[i][j];
+ }
+ } //endregion
+ //region Create "set of authorities-constrained policies"
+
+
+ const authConstrPolicies = [];
+
+ for (let i = 0; i < policiesAndCerts.length; i++) {
+ let found = true;
+
+ for (let j = 0; j < _this3.certs.length - 1; j++) {
+ let anyPolicyFound = false;
+
+ if (j < explicitPolicyStart && allPolicies[i] === "2.5.29.32.0" && allPolicies.length > 1) {
+ found = false;
+ break;
+ }
+
+ if (typeof policiesAndCerts[i][j] === "undefined") {
+ if (j >= explicitPolicyStart) {
+ //region Search for "anyPolicy" in the policy set
+ for (let k = 0; k < allPolicies.length; k++) {
+ if (allPolicies[k] === "2.5.29.32.0") {
+ if (policiesAndCerts[k][j] === true) anyPolicyFound = true;
+ break;
+ }
+ } //endregion
+
+ }
+
+ if (!anyPolicyFound) {
+ found = false;
+ break;
+ }
+ }
+ }
+
+ if (found === true) authConstrPolicies.push(allPolicies[i]);
+ } //endregion
+ //region Create "set of user-constrained policies"
+
+
+ let userConstrPolicies = [];
+ if (initialPolicySet.length === 1 && initialPolicySet[0] === "2.5.29.32.0" && explicitPolicyIndicator === false) userConstrPolicies = initialPolicySet;else {
+ if (authConstrPolicies.length === 1 && authConstrPolicies[0] === "2.5.29.32.0") userConstrPolicies = initialPolicySet;else {
+ for (let i = 0; i < authConstrPolicies.length; i++) {
+ for (let j = 0; j < initialPolicySet.length; j++) {
+ if (initialPolicySet[j] === authConstrPolicies[i] || initialPolicySet[j] === "2.5.29.32.0") {
+ userConstrPolicies.push(authConstrPolicies[i]);
+ break;
+ }
+ }
+ }
+ }
+ } //endregion
+ //region Combine output object
+
+ const policyResult = {
+ result: userConstrPolicies.length > 0,
+ resultCode: 0,
+ resultMessage: userConstrPolicies.length > 0 ? "" : "Zero \"userConstrPolicies\" array, no intersections with \"authConstrPolicies\"",
+ authConstrPolicies,
+ userConstrPolicies,
+ explicitPolicyIndicator,
+ policyMappings,
+ certificatePath: _this3.certs
+ };
+ if (userConstrPolicies.length === 0) return policyResult; //endregion
+ //endregion
+ //region Work with name constraints
+ //region Check a result from "policy checking" part
+
+ if (policyResult.result === false) return policyResult; //endregion
+ //region Check all certificates, excluding "trust anchor"
+
+ pathDepth = 1;
+
+ for (let i = _this3.certs.length - 2; i >= 0; i--, pathDepth++) {
+ //region Support variables
+ let subjectAltNames = [];
+ let certPermittedSubtrees = [];
+ let certExcludedSubtrees = []; //endregion
+
+ if ("extensions" in _this3.certs[i]) {
+ for (let j = 0; j < _this3.certs[i].extensions.length; j++) {
+ //region NameConstraints
+ if (_this3.certs[i].extensions[j].extnID === "2.5.29.30") {
+ if ("permittedSubtrees" in _this3.certs[i].extensions[j].parsedValue) certPermittedSubtrees = certPermittedSubtrees.concat(_this3.certs[i].extensions[j].parsedValue.permittedSubtrees);
+ if ("excludedSubtrees" in _this3.certs[i].extensions[j].parsedValue) certExcludedSubtrees = certExcludedSubtrees.concat(_this3.certs[i].extensions[j].parsedValue.excludedSubtrees);
+ } //endregion
+ //region SubjectAltName
+
+
+ if (_this3.certs[i].extensions[j].extnID === "2.5.29.17") subjectAltNames = subjectAltNames.concat(_this3.certs[i].extensions[j].parsedValue.altNames); //endregion
+ }
+ } //region Checking for "required name forms"
+
+
+ let formFound = requiredNameForms.length <= 0;
+
+ for (let j = 0; j < requiredNameForms.length; j++) {
+ switch (requiredNameForms[j].base.type) {
+ case 4:
+ // directoryName
+ {
+ if (requiredNameForms[j].base.value.typesAndValues.length !== _this3.certs[i].subject.typesAndValues.length) continue;
+ formFound = true;
+
+ for (let k = 0; k < _this3.certs[i].subject.typesAndValues.length; k++) {
+ if (_this3.certs[i].subject.typesAndValues[k].type !== requiredNameForms[j].base.value.typesAndValues[k].type) {
+ formFound = false;
+ break;
+ }
+ }
+
+ if (formFound === true) break;
+ }
+ break;
+
+ default: // ??? Probably here we should reject the certificate ???
+
+ }
+ }
+
+ if (formFound === false) {
+ policyResult.result = false;
+ policyResult.resultCode = 21;
+ policyResult.resultMessage = "No neccessary name form found";
+ throw policyResult;
+ } //endregion
+ //region Checking for "permited sub-trees"
+ //region Make groups for all types of constraints
+
+
+ const constrGroups = []; // Array of array for groupped constraints
+
+ constrGroups[0] = []; // rfc822Name
+
+ constrGroups[1] = []; // dNSName
+
+ constrGroups[2] = []; // directoryName
+
+ constrGroups[3] = []; // uniformResourceIdentifier
+
+ constrGroups[4] = []; // iPAddress
+
+ for (let j = 0; j < permittedSubtrees.length; j++) {
+ switch (permittedSubtrees[j].base.type) {
+ //region rfc822Name
+ case 1:
+ constrGroups[0].push(permittedSubtrees[j]);
+ break;
+ //endregion
+ //region dNSName
+
+ case 2:
+ constrGroups[1].push(permittedSubtrees[j]);
+ break;
+ //endregion
+ //region directoryName
+
+ case 4:
+ constrGroups[2].push(permittedSubtrees[j]);
+ break;
+ //endregion
+ //region uniformResourceIdentifier
+
+ case 6:
+ constrGroups[3].push(permittedSubtrees[j]);
+ break;
+ //endregion
+ //region iPAddress
+
+ case 7:
+ constrGroups[4].push(permittedSubtrees[j]);
+ break;
+ //endregion
+ //region default
+
+ default: //endregion
+
+ }
+ } //endregion
+ //region Check name constraints groupped by type, one-by-one
+
+
+ for (let p = 0; p < 5; p++) {
+ let groupPermitted = false;
+ let valueExists = false;
+ const group = constrGroups[p];
+
+ for (let j = 0; j < group.length; j++) {
+ switch (p) {
+ //region rfc822Name
+ case 0:
+ if (subjectAltNames.length > 0) {
+ for (let k = 0; k < subjectAltNames.length; k++) {
+ if (subjectAltNames[k].type === 1) // rfc822Name
+ {
+ valueExists = true;
+ groupPermitted = groupPermitted || compareRFC822Name(subjectAltNames[k].value, group[j].base.value);
+ }
+ }
+ } else // Try to find out "emailAddress" inside "subject"
+ {
+ for (let k = 0; k < _this3.certs[i].subject.typesAndValues.length; k++) {
+ if (_this3.certs[i].subject.typesAndValues[k].type === "1.2.840.113549.1.9.1" || // PKCS#9 e-mail address
+ _this3.certs[i].subject.typesAndValues[k].type === "0.9.2342.19200300.100.1.3") // RFC1274 "rfc822Mailbox" e-mail address
+ {
+ valueExists = true;
+ groupPermitted = groupPermitted || compareRFC822Name(_this3.certs[i].subject.typesAndValues[k].value.valueBlock.value, group[j].base.value);
+ }
+ }
+ }
+
+ break;
+ //endregion
+ //region dNSName
+
+ case 1:
+ if (subjectAltNames.length > 0) {
+ for (let k = 0; k < subjectAltNames.length; k++) {
+ if (subjectAltNames[k].type === 2) // dNSName
+ {
+ valueExists = true;
+ groupPermitted = groupPermitted || compareDNSName(subjectAltNames[k].value, group[j].base.value);
+ }
+ }
+ }
+
+ break;
+ //endregion
+ //region directoryName
+
+ case 2:
+ valueExists = true;
+ groupPermitted = compareDirectoryName(_this3.certs[i].subject, group[j].base.value);
+ break;
+ //endregion
+ //region uniformResourceIdentifier
+
+ case 3:
+ if (subjectAltNames.length > 0) {
+ for (let k = 0; k < subjectAltNames.length; k++) {
+ if (subjectAltNames[k].type === 6) // uniformResourceIdentifier
+ {
+ valueExists = true;
+ groupPermitted = groupPermitted || compareUniformResourceIdentifier(subjectAltNames[k].value, group[j].base.value);
+ }
+ }
+ }
+
+ break;
+ //endregion
+ //region iPAddress
+
+ case 4:
+ if (subjectAltNames.length > 0) {
+ for (let k = 0; k < subjectAltNames.length; k++) {
+ if (subjectAltNames[k].type === 7) // iPAddress
+ {
+ valueExists = true;
+ groupPermitted = groupPermitted || compareIPAddress(subjectAltNames[k].value, group[j].base.value);
+ }
+ }
+ }
+
+ break;
+ //endregion
+ //region default
+
+ default: //endregion
+
+ }
+
+ if (groupPermitted) break;
+ }
+
+ if (groupPermitted === false && group.length > 0 && valueExists) {
+ policyResult.result = false;
+ policyResult.resultCode = 41;
+ policyResult.resultMessage = "Failed to meet \"permitted sub-trees\" name constraint";
+ throw policyResult;
+ }
+ } //endregion
+ //endregion
+ //region Checking for "excluded sub-trees"
+
+
+ let excluded = false;
+
+ for (let j = 0; j < excludedSubtrees.length; j++) {
+ switch (excludedSubtrees[j].base.type) {
+ //region rfc822Name
+ case 1:
+ if (subjectAltNames.length >= 0) {
+ for (let k = 0; k < subjectAltNames.length; k++) {
+ if (subjectAltNames[k].type === 1) // rfc822Name
+ excluded = excluded || compareRFC822Name(subjectAltNames[k].value, excludedSubtrees[j].base.value);
+ }
+ } else // Try to find out "emailAddress" inside "subject"
+ {
+ for (let k = 0; k < _this3.certs[i].subject.typesAndValues.length; k++) {
+ if (_this3.certs[i].subject.typesAndValues[k].type === "1.2.840.113549.1.9.1" || // PKCS#9 e-mail address
+ _this3.certs[i].subject.typesAndValues[k].type === "0.9.2342.19200300.100.1.3") // RFC1274 "rfc822Mailbox" e-mail address
+ excluded = excluded || compareRFC822Name(_this3.certs[i].subject.typesAndValues[k].value.valueBlock.value, excludedSubtrees[j].base.value);
+ }
+ }
+
+ break;
+ //endregion
+ //region dNSName
+
+ case 2:
+ if (subjectAltNames.length > 0) {
+ for (let k = 0; k < subjectAltNames.length; k++) {
+ if (subjectAltNames[k].type === 2) // dNSName
+ excluded = excluded || compareDNSName(subjectAltNames[k].value, excludedSubtrees[j].base.value);
+ }
+ }
+
+ break;
+ //endregion
+ //region directoryName
+
+ case 4:
+ excluded = excluded || compareDirectoryName(_this3.certs[i].subject, excludedSubtrees[j].base.value);
+ break;
+ //endregion
+ //region uniformResourceIdentifier
+
+ case 6:
+ if (subjectAltNames.length > 0) {
+ for (let k = 0; k < subjectAltNames.length; k++) {
+ if (subjectAltNames[k].type === 6) // uniformResourceIdentifier
+ excluded = excluded || compareUniformResourceIdentifier(subjectAltNames[k].value, excludedSubtrees[j].base.value);
+ }
+ }
+
+ break;
+ //endregion
+ //region iPAddress
+
+ case 7:
+ if (subjectAltNames.length > 0) {
+ for (let k = 0; k < subjectAltNames.length; k++) {
+ if (subjectAltNames[k].type === 7) // iPAddress
+ excluded = excluded || compareIPAddress(subjectAltNames[k].value, excludedSubtrees[j].base.value);
+ }
+ }
+
+ break;
+ //endregion
+ //region default
+
+ default: // No action, but probably here we need to create a warning for "malformed constraint"
+ //endregion
+
+ }
+
+ if (excluded) break;
+ }
+
+ if (excluded === true) {
+ policyResult.result = false;
+ policyResult.resultCode = 42;
+ policyResult.resultMessage = "Failed to meet \"excluded sub-trees\" name constraint";
+ throw policyResult;
+ } //endregion
+ //region Append "cert_..._subtrees" to "..._subtrees"
+
+
+ permittedSubtrees = permittedSubtrees.concat(certPermittedSubtrees);
+ excludedSubtrees = excludedSubtrees.concat(certExcludedSubtrees); //endregion
+ } //endregion
+
+
+ return policyResult; //endregion
+ } catch (error) {
+ if (error instanceof Object) {
+ if ("resultMessage" in error) return error;
+
+ if ("message" in error) {
+ return {
+ result: false,
+ resultCode: -1,
+ resultMessage: error.message
+ };
+ }
+ }
+
+ return {
+ result: false,
+ resultCode: -1,
+ resultMessage: error
+ };
+ }
+ })();
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = CertificateChainValidationEngine;
+
+},{"./common.js":110,"pvutils":113}],21:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _PolicyInformation = _interopRequireDefault(require("./PolicyInformation.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class CertificatePolicies {
+ //**********************************************************************************
+
+ /**
+ * Constructor for CertificatePolicies class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array.<PolicyInformation>}
+ * @desc certificatePolicies
+ */
+ this.certificatePolicies = (0, _pvutils.getParametersValue)(parameters, "certificatePolicies", CertificatePolicies.defaultValues("certificatePolicies")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "certificatePolicies":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for CertificatePolicies class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [certificatePolicies]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Repeated({
+ name: names.certificatePolicies || "",
+ value: _PolicyInformation.default.schema()
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["certificatePolicies"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, CertificatePolicies.schema({
+ names: {
+ certificatePolicies: "certificatePolicies"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for CertificatePolicies"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.certificatePolicies = Array.from(asn1.result.certificatePolicies, element => new _PolicyInformation.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: Array.from(this.certificatePolicies, element => element.toSchema())
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ certificatePolicies: Array.from(this.certificatePolicies, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = CertificatePolicies;
+
+},{"./PolicyInformation.js":72,"asn1js":112,"pvutils":113}],22:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _common = require("./common.js");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _RelativeDistinguishedNames = _interopRequireDefault(require("./RelativeDistinguishedNames.js"));
+
+var _Time = _interopRequireDefault(require("./Time.js"));
+
+var _RevokedCertificate = _interopRequireDefault(require("./RevokedCertificate.js"));
+
+var _Extensions = _interopRequireDefault(require("./Extensions.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+function tbsCertList(parameters = {}) {
+ //TBSCertList ::= SEQUENCE {
+ // version Version OPTIONAL,
+ // -- if present, MUST be v2
+ // signature AlgorithmIdentifier,
+ // issuer Name,
+ // thisUpdate Time,
+ // nextUpdate Time OPTIONAL,
+ // revokedCertificates SEQUENCE OF SEQUENCE {
+ // userCertificate CertificateSerialNumber,
+ // revocationDate Time,
+ // crlEntryExtensions Extensions OPTIONAL
+ // -- if present, version MUST be v2
+ // } OPTIONAL,
+ // crlExtensions [0] EXPLICIT Extensions OPTIONAL
+ // -- if present, version MUST be v2
+ //}
+
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [tbsCertListVersion]
+ * @property {string} [signature]
+ * @property {string} [issuer]
+ * @property {string} [tbsCertListThisUpdate]
+ * @property {string} [tbsCertListNextUpdate]
+ * @property {string} [tbsCertListRevokedCertificates]
+ * @property {string} [crlExtensions]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "tbsCertList",
+ value: [new asn1js.Integer({
+ optional: true,
+ name: names.tbsCertListVersion || "tbsCertList.version",
+ value: 2
+ }), // EXPLICIT integer value (v2)
+ _AlgorithmIdentifier.default.schema(names.signature || {
+ names: {
+ blockName: "tbsCertList.signature"
+ }
+ }), _RelativeDistinguishedNames.default.schema(names.issuer || {
+ names: {
+ blockName: "tbsCertList.issuer"
+ }
+ }), _Time.default.schema(names.tbsCertListThisUpdate || {
+ names: {
+ utcTimeName: "tbsCertList.thisUpdate",
+ generalTimeName: "tbsCertList.thisUpdate"
+ }
+ }), _Time.default.schema(names.tbsCertListNextUpdate || {
+ names: {
+ utcTimeName: "tbsCertList.nextUpdate",
+ generalTimeName: "tbsCertList.nextUpdate"
+ }
+ }, true), new asn1js.Sequence({
+ optional: true,
+ value: [new asn1js.Repeated({
+ name: names.tbsCertListRevokedCertificates || "tbsCertList.revokedCertificates",
+ value: new asn1js.Sequence({
+ value: [new asn1js.Integer(), _Time.default.schema(), _Extensions.default.schema({}, true)]
+ })
+ })]
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [_Extensions.default.schema(names.crlExtensions || {
+ names: {
+ blockName: "tbsCertList.extensions"
+ }
+ })]
+ }) // EXPLICIT SEQUENCE value
+ ]
+ });
+} //**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+
+
+class CertificateRevocationList {
+ //**********************************************************************************
+
+ /**
+ * Constructor for Attribute class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {ArrayBuffer}
+ * @desc tbs
+ */
+ this.tbs = (0, _pvutils.getParametersValue)(parameters, "tbs", CertificateRevocationList.defaultValues("tbs"));
+ /**
+ * @type {number}
+ * @desc version
+ */
+
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", CertificateRevocationList.defaultValues("version"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc signature
+ */
+
+ this.signature = (0, _pvutils.getParametersValue)(parameters, "signature", CertificateRevocationList.defaultValues("signature"));
+ /**
+ * @type {RelativeDistinguishedNames}
+ * @desc issuer
+ */
+
+ this.issuer = (0, _pvutils.getParametersValue)(parameters, "issuer", CertificateRevocationList.defaultValues("issuer"));
+ /**
+ * @type {Time}
+ * @desc thisUpdate
+ */
+
+ this.thisUpdate = (0, _pvutils.getParametersValue)(parameters, "thisUpdate", CertificateRevocationList.defaultValues("thisUpdate"));
+ if ("nextUpdate" in parameters)
+ /**
+ * @type {Time}
+ * @desc nextUpdate
+ */
+ this.nextUpdate = (0, _pvutils.getParametersValue)(parameters, "nextUpdate", CertificateRevocationList.defaultValues("nextUpdate"));
+ if ("revokedCertificates" in parameters)
+ /**
+ * @type {Array.<RevokedCertificate>}
+ * @desc revokedCertificates
+ */
+ this.revokedCertificates = (0, _pvutils.getParametersValue)(parameters, "revokedCertificates", CertificateRevocationList.defaultValues("revokedCertificates"));
+ if ("crlExtensions" in parameters)
+ /**
+ * @type {Extensions}
+ * @desc crlExtensions
+ */
+ this.crlExtensions = (0, _pvutils.getParametersValue)(parameters, "crlExtensions", CertificateRevocationList.defaultValues("crlExtensions"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc signatureAlgorithm
+ */
+
+ this.signatureAlgorithm = (0, _pvutils.getParametersValue)(parameters, "signatureAlgorithm", CertificateRevocationList.defaultValues("signatureAlgorithm"));
+ /**
+ * @type {BitString}
+ * @desc signatureValue
+ */
+
+ this.signatureValue = (0, _pvutils.getParametersValue)(parameters, "signatureValue", CertificateRevocationList.defaultValues("signatureValue")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "tbs":
+ return new ArrayBuffer(0);
+
+ case "version":
+ return 1;
+
+ case "signature":
+ return new _AlgorithmIdentifier.default();
+
+ case "issuer":
+ return new _RelativeDistinguishedNames.default();
+
+ case "thisUpdate":
+ return new _Time.default();
+
+ case "nextUpdate":
+ return new _Time.default();
+
+ case "revokedCertificates":
+ return [];
+
+ case "crlExtensions":
+ return new _Extensions.default();
+
+ case "signatureAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "signatureValue":
+ return new asn1js.BitString();
+
+ default:
+ throw new Error(`Invalid member name for CertificateRevocationList class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * CertificateList ::= SEQUENCE {
+ * tbsCertList TBSCertList,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [signatureAlgorithm]
+ * @property {string} [signatureValue]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "CertificateList",
+ value: [tbsCertList(parameters), _AlgorithmIdentifier.default.schema(names.signatureAlgorithm || {
+ names: {
+ blockName: "signatureAlgorithm"
+ }
+ }), new asn1js.BitString({
+ name: names.signatureValue || "signatureValue"
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["tbsCertList", "tbsCertList.version", "tbsCertList.signature", "tbsCertList.issuer", "tbsCertList.thisUpdate", "tbsCertList.nextUpdate", "tbsCertList.revokedCertificates", "tbsCertList.extensions", "signatureAlgorithm", "signatureValue"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, CertificateRevocationList.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for CertificateRevocationList"); //endregion
+ //region Get internal properties from parsed schema
+ // noinspection JSUnresolvedVariable
+
+ this.tbs = asn1.result.tbsCertList.valueBeforeDecode;
+ if ("tbsCertList.version" in asn1.result) this.version = asn1.result["tbsCertList.version"].valueBlock.valueDec;
+ this.signature = new _AlgorithmIdentifier.default({
+ schema: asn1.result["tbsCertList.signature"]
+ });
+ this.issuer = new _RelativeDistinguishedNames.default({
+ schema: asn1.result["tbsCertList.issuer"]
+ });
+ this.thisUpdate = new _Time.default({
+ schema: asn1.result["tbsCertList.thisUpdate"]
+ });
+ if ("tbsCertList.nextUpdate" in asn1.result) this.nextUpdate = new _Time.default({
+ schema: asn1.result["tbsCertList.nextUpdate"]
+ });
+ if ("tbsCertList.revokedCertificates" in asn1.result) this.revokedCertificates = Array.from(asn1.result["tbsCertList.revokedCertificates"], element => new _RevokedCertificate.default({
+ schema: element
+ }));
+ if ("tbsCertList.extensions" in asn1.result) this.crlExtensions = new _Extensions.default({
+ schema: asn1.result["tbsCertList.extensions"]
+ });
+ this.signatureAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.signatureAlgorithm
+ });
+ this.signatureValue = asn1.result.signatureValue; //endregion
+ } //**********************************************************************************
+
+
+ encodeTBS() {
+ //region Create array for output sequence
+ const outputArray = [];
+ if (this.version !== CertificateRevocationList.defaultValues("version")) outputArray.push(new asn1js.Integer({
+ value: this.version
+ }));
+ outputArray.push(this.signature.toSchema());
+ outputArray.push(this.issuer.toSchema());
+ outputArray.push(this.thisUpdate.toSchema());
+ if ("nextUpdate" in this) outputArray.push(this.nextUpdate.toSchema());
+
+ if ("revokedCertificates" in this) {
+ outputArray.push(new asn1js.Sequence({
+ value: Array.from(this.revokedCertificates, element => element.toSchema())
+ }));
+ }
+
+ if ("crlExtensions" in this) {
+ outputArray.push(new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [this.crlExtensions.toSchema()]
+ }));
+ } //endregion
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema(encodeFlag = false) {
+ //region Decode stored TBS value
+ let tbsSchema;
+
+ if (encodeFlag === false) {
+ if (this.tbs.length === 0) // No stored TBS part
+ return CertificateRevocationList.schema();
+ tbsSchema = asn1js.fromBER(this.tbs).result;
+ } //endregion
+ //region Create TBS schema via assembling from TBS parts
+ else tbsSchema = this.encodeTBS(); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: [tbsSchema, this.signatureAlgorithm.toSchema(), this.signatureValue]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {
+ tbs: (0, _pvutils.bufferToHexCodes)(this.tbs, 0, this.tbs.byteLength),
+ signature: this.signature.toJSON(),
+ issuer: this.issuer.toJSON(),
+ thisUpdate: this.thisUpdate.toJSON(),
+ signatureAlgorithm: this.signatureAlgorithm.toJSON(),
+ signatureValue: this.signatureValue.toJSON()
+ };
+ if (this.version !== CertificateRevocationList.defaultValues("version")) object.version = this.version;
+ if ("nextUpdate" in this) object.nextUpdate = this.nextUpdate.toJSON();
+ if ("revokedCertificates" in this) object.revokedCertificates = Array.from(this.revokedCertificates, element => element.toJSON());
+ if ("crlExtensions" in this) object.crlExtensions = this.crlExtensions.toJSON();
+ return object;
+ } //**********************************************************************************
+
+
+ isCertificateRevoked(certificate) {
+ //region Check that issuer of the input certificate is the same with issuer of this CRL
+ if (this.issuer.isEqual(certificate.issuer) === false) return false; //endregion
+ //region Check that there are revoked certificates in this CRL
+
+ if ("revokedCertificates" in this === false) return false; //endregion
+ //region Search for input certificate in revoked certificates array
+
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = this.revokedCertificates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ const revokedCertificate = _step.value;
+ if (revokedCertificate.userCertificate.isEqual(certificate.serialNumber)) return true;
+ } //endregion
+
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+
+ return false;
+ } //**********************************************************************************
+
+ /**
+ * Make a signature for existing CRL data
+ * @param {Object} privateKey Private key for "subjectPublicKeyInfo" structure
+ * @param {string} [hashAlgorithm] Hashing algorithm. Default SHA-1
+ */
+
+
+ sign(privateKey, hashAlgorithm = "SHA-1") {
+ //region Initial checking
+ //region Get a private key from function parameter
+ if (typeof privateKey === "undefined") return Promise.reject("Need to provide a private key for signing"); //endregion
+ //endregion
+ //region Initial variables
+
+ let sequence = Promise.resolve();
+ let parameters;
+ const engine = (0, _common.getEngine)(); //endregion
+ //region Get a "default parameters" for current algorithm and set correct signature algorithm
+
+ sequence = sequence.then(() => engine.subtle.getSignatureParameters(privateKey, hashAlgorithm));
+ sequence = sequence.then(result => {
+ parameters = result.parameters;
+ this.signature = result.signatureAlgorithm;
+ this.signatureAlgorithm = result.signatureAlgorithm;
+ }); //endregion
+ //region Create TBS data for signing
+
+ sequence = sequence.then(() => {
+ this.tbs = this.encodeTBS().toBER(false);
+ }); //endregion
+ //region Signing TBS data on provided private key
+
+ sequence = sequence.then(() => engine.subtle.signWithPrivateKey(this.tbs, privateKey, parameters));
+ sequence = sequence.then(result => {
+ this.signatureValue = new asn1js.BitString({
+ valueHex: result
+ });
+ }); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+ /**
+ * Verify existing signature
+ * @param {{[issuerCertificate]: Object, [publicKeyInfo]: Object}} parameters
+ * @returns {*}
+ */
+
+
+ verify(parameters = {}) {
+ //region Global variables
+ let sequence = Promise.resolve();
+ let subjectPublicKeyInfo = -1;
+ const engine = (0, _common.getEngine)(); //endregion
+ //region Get information about CRL issuer certificate
+
+ if ("issuerCertificate" in parameters) // "issuerCertificate" must be of type "Certificate"
+ {
+ subjectPublicKeyInfo = parameters.issuerCertificate.subjectPublicKeyInfo; // The CRL issuer name and "issuerCertificate" subject name are not equal
+
+ if (this.issuer.isEqual(parameters.issuerCertificate.subject) === false) return Promise.resolve(false);
+ } //region In case if there is only public key during verification
+
+
+ if ("publicKeyInfo" in parameters) subjectPublicKeyInfo = parameters.publicKeyInfo; // Must be of type "PublicKeyInfo"
+ //endregion
+
+ if ("subjectPublicKey" in subjectPublicKeyInfo === false) return Promise.reject("Issuer's certificate must be provided as an input parameter"); //endregion
+ //region Check the CRL for unknown critical extensions
+
+ if ("crlExtensions" in this) {
+ var _iteratorNormalCompletion2 = true;
+ var _didIteratorError2 = false;
+ var _iteratorError2 = undefined;
+
+ try {
+ for (var _iterator2 = this.crlExtensions.extensions[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+ const extension = _step2.value;
+
+ if (extension.critical) {
+ // We can not be sure that unknown extension has no value for CRL signature
+ if ("parsedValue" in extension === false) return Promise.resolve(false);
+ }
+ }
+ } catch (err) {
+ _didIteratorError2 = true;
+ _iteratorError2 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
+ _iterator2.return();
+ }
+ } finally {
+ if (_didIteratorError2) {
+ throw _iteratorError2;
+ }
+ }
+ }
+ } //endregion
+
+
+ sequence = sequence.then(() => engine.subtle.verifyWithPublicKey(this.tbs, this.signatureValue, subjectPublicKeyInfo, this.signatureAlgorithm));
+ return sequence;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = CertificateRevocationList;
+
+},{"./AlgorithmIdentifier.js":4,"./Extensions.js":39,"./RelativeDistinguishedNames.js":89,"./RevokedCertificate.js":94,"./Time.js":107,"./common.js":110,"asn1js":112,"pvutils":113}],23:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _Certificate = _interopRequireDefault(require("./Certificate.js"));
+
+var _AttributeCertificateV = _interopRequireDefault(require("./AttributeCertificateV1.js"));
+
+var _AttributeCertificateV2 = _interopRequireDefault(require("./AttributeCertificateV2.js"));
+
+var _OtherCertificateFormat = _interopRequireDefault(require("./OtherCertificateFormat.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class CertificateSet {
+ //**********************************************************************************
+
+ /**
+ * Constructor for CertificateSet class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array}
+ * @desc certificates
+ */
+ this.certificates = (0, _pvutils.getParametersValue)(parameters, "certificates", CertificateSet.defaultValues("certificates")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "certificates":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for Attribute class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * CertificateSet ::= SET OF CertificateChoices
+ *
+ * CertificateChoices ::= CHOICE {
+ * certificate Certificate,
+ * extendedCertificate [0] IMPLICIT ExtendedCertificate, -- Obsolete
+ * v1AttrCert [1] IMPLICIT AttributeCertificateV1, -- Obsolete
+ * v2AttrCert [2] IMPLICIT AttributeCertificateV2,
+ * other [3] IMPLICIT OtherCertificateFormat }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Set({
+ name: names.blockName || "",
+ value: [new asn1js.Repeated({
+ name: names.certificates || "certificates",
+ value: new asn1js.Choice({
+ value: [_Certificate.default.schema(), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Any()]
+ }), // JUST A STUB
+ new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: _AttributeCertificateV.default.schema().valueBlock.value
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ value: _AttributeCertificateV2.default.schema().valueBlock.value
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 3 // [3]
+
+ },
+ value: _OtherCertificateFormat.default.schema().valueBlock.value
+ })]
+ })
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["certificates"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, CertificateSet.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for CertificateSet"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.certificates = Array.from(asn1.result.certificates || [], element => {
+ const initialTagNumber = element.idBlock.tagNumber;
+ if (element.idBlock.tagClass === 1) return new _Certificate.default({
+ schema: element
+ }); //region Making "Sequence" from "Constructed" value
+
+ const elementSequence = new asn1js.Sequence({
+ value: element.valueBlock.value
+ }); //endregion
+
+ switch (initialTagNumber) {
+ case 1:
+ return new _AttributeCertificateV.default({
+ schema: elementSequence
+ });
+
+ case 2:
+ return new _AttributeCertificateV2.default({
+ schema: elementSequence
+ });
+
+ case 3:
+ return new _OtherCertificateFormat.default({
+ schema: elementSequence
+ });
+
+ case 0:
+ default:
+ }
+
+ return element;
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Set({
+ value: Array.from(this.certificates, element => {
+ switch (true) {
+ case element instanceof _Certificate.default:
+ return element.toSchema();
+
+ case element instanceof _AttributeCertificateV.default:
+ return new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 1 // [1]
+
+ },
+ value: element.toSchema().valueBlock.value
+ });
+
+ case element instanceof _AttributeCertificateV2.default:
+ return new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 2 // [2]
+
+ },
+ value: element.toSchema().valueBlock.value
+ });
+
+ case element instanceof _OtherCertificateFormat.default:
+ return new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 3 // [3]
+
+ },
+ value: element.toSchema().valueBlock.value
+ });
+
+ default:
+ }
+
+ return element;
+ })
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ certificates: Array.from(this.certificates, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = CertificateSet;
+
+},{"./AttributeCertificateV1.js":7,"./AttributeCertificateV2.js":8,"./Certificate.js":19,"./OtherCertificateFormat.js":60,"asn1js":112,"pvutils":113}],24:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from "[MS-WCCE]: Windows Client Certificate Enrollment Protocol"
+ */
+class CertificateTemplate {
+ //**********************************************************************************
+
+ /**
+ * Constructor for CertificateTemplate class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc templateID
+ */
+ this.templateID = (0, _pvutils.getParametersValue)(parameters, "templateID", CertificateTemplate.defaultValues("templateID"));
+ if ("templateMajorVersion" in parameters)
+ /**
+ * @type {number}
+ * @desc templateMajorVersion
+ */
+ this.templateMajorVersion = (0, _pvutils.getParametersValue)(parameters, "templateMajorVersion", CertificateTemplate.defaultValues("templateMajorVersion"));
+ if ("templateMinorVersion" in parameters)
+ /**
+ * @type {number}
+ * @desc templateMinorVersion
+ */
+ this.templateMinorVersion = (0, _pvutils.getParametersValue)(parameters, "templateMinorVersion", CertificateTemplate.defaultValues("templateMinorVersion")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "templateID":
+ return "";
+
+ case "templateMajorVersion":
+ case "templateMinorVersion":
+ return 0;
+
+ default:
+ throw new Error(`Invalid member name for CertificateTemplate class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * CertificateTemplateOID ::= SEQUENCE {
+ * templateID OBJECT IDENTIFIER,
+ * templateMajorVersion INTEGER (0..4294967295) OPTIONAL,
+ * templateMinorVersion INTEGER (0..4294967295) OPTIONAL
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [templateID]
+ * @property {string} [templateMajorVersion]
+ * @property {string} [templateMinorVersion]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.templateID || ""
+ }), new asn1js.Integer({
+ name: names.templateMajorVersion || "",
+ optional: true
+ }), new asn1js.Integer({
+ name: names.templateMinorVersion || "",
+ optional: true
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["templateID", "templateMajorVersion", "templateMinorVersion"]); //endregion
+ //region Check the schema is valid
+
+ let asn1 = asn1js.compareSchema(schema, schema, CertificateTemplate.schema({
+ names: {
+ templateID: "templateID",
+ templateMajorVersion: "templateMajorVersion",
+ templateMinorVersion: "templateMinorVersion"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for CertificateTemplate"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.templateID = asn1.result.templateID.valueBlock.toString();
+ if ("templateMajorVersion" in asn1.result) this.templateMajorVersion = asn1.result.templateMajorVersion.valueBlock.valueDec;
+ if ("templateMinorVersion" in asn1.result) this.templateMinorVersion = asn1.result.templateMinorVersion.valueBlock.valueDec; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(new asn1js.ObjectIdentifier({
+ value: this.templateID
+ }));
+ if ("templateMajorVersion" in this) outputArray.push(new asn1js.Integer({
+ value: this.templateMajorVersion
+ }));
+ if ("templateMinorVersion" in this) outputArray.push(new asn1js.Integer({
+ value: this.templateMinorVersion
+ })); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {
+ extnID: this.templateID
+ };
+ if ("templateMajorVersion" in this) object.templateMajorVersion = this.templateMajorVersion;
+ if ("templateMinorVersion" in this) object.templateMinorVersion = this.templateMinorVersion;
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = CertificateTemplate;
+
+},{"asn1js":112,"pvutils":113}],25:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _common = require("./common.js");
+
+var _PublicKeyInfo = _interopRequireDefault(require("./PublicKeyInfo.js"));
+
+var _RelativeDistinguishedNames = _interopRequireDefault(require("./RelativeDistinguishedNames.js"));
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _Attribute = _interopRequireDefault(require("./Attribute.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+function CertificationRequestInfo(parameters = {}) {
+ //CertificationRequestInfo ::= SEQUENCE {
+ // version INTEGER { v1(0) } (v1,...),
+ // subject Name,
+ // subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+ // attributes [0] Attributes{{ CRIAttributes }}
+ //}
+
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [CertificationRequestInfo]
+ * @property {string} [CertificationRequestInfoVersion]
+ * @property {string} [subject]
+ * @property {string} [CertificationRequestInfoAttributes]
+ * @property {string} [attributes]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.CertificationRequestInfo || "CertificationRequestInfo",
+ value: [new asn1js.Integer({
+ name: names.CertificationRequestInfoVersion || "CertificationRequestInfo.version"
+ }), _RelativeDistinguishedNames.default.schema(names.subject || {
+ names: {
+ blockName: "CertificationRequestInfo.subject"
+ }
+ }), _PublicKeyInfo.default.schema({
+ names: {
+ blockName: "CertificationRequestInfo.subjectPublicKeyInfo"
+ }
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Repeated({
+ optional: true,
+ // Because OpenSSL makes wrong "attributes" field
+ name: names.CertificationRequestInfoAttributes || "CertificationRequestInfo.attributes",
+ value: _Attribute.default.schema(names.attributes || {})
+ })]
+ })]
+ });
+} //**************************************************************************************
+
+/**
+ * Class from RFC2986
+ */
+
+
+class CertificationRequest {
+ //**********************************************************************************
+
+ /**
+ * Constructor for Attribute class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {ArrayBuffer}
+ * @desc tbs
+ */
+ this.tbs = (0, _pvutils.getParametersValue)(parameters, "tbs", CertificationRequest.defaultValues("tbs"));
+ /**
+ * @type {number}
+ * @desc version
+ */
+
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", CertificationRequest.defaultValues("version"));
+ /**
+ * @type {RelativeDistinguishedNames}
+ * @desc subject
+ */
+
+ this.subject = (0, _pvutils.getParametersValue)(parameters, "subject", CertificationRequest.defaultValues("subject"));
+ /**
+ * @type {PublicKeyInfo}
+ * @desc subjectPublicKeyInfo
+ */
+
+ this.subjectPublicKeyInfo = (0, _pvutils.getParametersValue)(parameters, "subjectPublicKeyInfo", CertificationRequest.defaultValues("subjectPublicKeyInfo"));
+ if ("attributes" in parameters)
+ /**
+ * @type {Array.<Attribute>}
+ * @desc attributes
+ */
+ this.attributes = (0, _pvutils.getParametersValue)(parameters, "attributes", CertificationRequest.defaultValues("attributes"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc signatureAlgorithm
+ */
+
+ this.signatureAlgorithm = (0, _pvutils.getParametersValue)(parameters, "signatureAlgorithm", CertificationRequest.defaultValues("signatureAlgorithm"));
+ /**
+ * @type {BitString}
+ * @desc signatureAlgorithm
+ */
+
+ this.signatureValue = (0, _pvutils.getParametersValue)(parameters, "signatureValue", CertificationRequest.defaultValues("signatureValue")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "tbs":
+ return new ArrayBuffer(0);
+
+ case "version":
+ return 0;
+
+ case "subject":
+ return new _RelativeDistinguishedNames.default();
+
+ case "subjectPublicKeyInfo":
+ return new _PublicKeyInfo.default();
+
+ case "attributes":
+ return [];
+
+ case "signatureAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "signatureValue":
+ return new asn1js.BitString();
+
+ default:
+ throw new Error(`Invalid member name for CertificationRequest class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * CertificationRequest ::= SEQUENCE {
+ * certificationRequestInfo CertificationRequestInfo,
+ * signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }},
+ * signature BIT STRING
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [certificationRequestInfo]
+ * @property {string} [signatureAlgorithm]
+ * @property {string} [signatureValue]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ value: [CertificationRequestInfo(names.certificationRequestInfo || {}), new asn1js.Sequence({
+ name: names.signatureAlgorithm || "signatureAlgorithm",
+ value: [new asn1js.ObjectIdentifier(), new asn1js.Any({
+ optional: true
+ })]
+ }), new asn1js.BitString({
+ name: names.signatureValue || "signatureValue"
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["CertificationRequestInfo", "CertificationRequestInfo.version", "CertificationRequestInfo.subject", "CertificationRequestInfo.subjectPublicKeyInfo", "CertificationRequestInfo.attributes", "signatureAlgorithm", "signatureValue"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, CertificationRequest.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for CertificationRequest"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.tbs = asn1.result.CertificationRequestInfo.valueBeforeDecode;
+ this.version = asn1.result["CertificationRequestInfo.version"].valueBlock.valueDec;
+ this.subject = new _RelativeDistinguishedNames.default({
+ schema: asn1.result["CertificationRequestInfo.subject"]
+ });
+ this.subjectPublicKeyInfo = new _PublicKeyInfo.default({
+ schema: asn1.result["CertificationRequestInfo.subjectPublicKeyInfo"]
+ });
+ if ("CertificationRequestInfo.attributes" in asn1.result) this.attributes = Array.from(asn1.result["CertificationRequestInfo.attributes"], element => new _Attribute.default({
+ schema: element
+ }));
+ this.signatureAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.signatureAlgorithm
+ });
+ this.signatureValue = asn1.result.signatureValue; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Aux function making ASN1js Sequence from current TBS
+ * @returns {Sequence}
+ */
+
+
+ encodeTBS() {
+ //region Create array for output sequence
+ const outputArray = [new asn1js.Integer({
+ value: this.version
+ }), this.subject.toSchema(), this.subjectPublicKeyInfo.toSchema()];
+
+ if ("attributes" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: Array.from(this.attributes, element => element.toSchema())
+ }));
+ } //endregion
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema(encodeFlag = false) {
+ //region Decode stored TBS value
+ let tbsSchema;
+
+ if (encodeFlag === false) {
+ if (this.tbs.byteLength === 0) // No stored TBS part
+ return CertificationRequest.schema();
+ tbsSchema = asn1js.fromBER(this.tbs).result;
+ } //endregion
+ //region Create TBS schema via assembling from TBS parts
+ else tbsSchema = this.encodeTBS(); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: [tbsSchema, this.signatureAlgorithm.toSchema(), this.signatureValue]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {
+ tbs: (0, _pvutils.bufferToHexCodes)(this.tbs, 0, this.tbs.byteLength),
+ version: this.version,
+ subject: this.subject.toJSON(),
+ subjectPublicKeyInfo: this.subjectPublicKeyInfo.toJSON(),
+ signatureAlgorithm: this.signatureAlgorithm.toJSON(),
+ signatureValue: this.signatureValue.toJSON()
+ };
+ if ("attributes" in this) object.attributes = Array.from(this.attributes, element => element.toJSON());
+ return object;
+ } //**********************************************************************************
+
+ /**
+ * Makes signature for currect certification request
+ * @param {Object} privateKey WebCrypto private key
+ * @param {string} [hashAlgorithm=SHA-1] String representing current hashing algorithm
+ */
+
+
+ sign(privateKey, hashAlgorithm = "SHA-1") {
+ //region Initial checking
+ //region Get a private key from function parameter
+ if (typeof privateKey === "undefined") return Promise.reject("Need to provide a private key for signing"); //endregion
+ //endregion
+ //region Initial variables
+
+ let sequence = Promise.resolve();
+ let parameters;
+ const engine = (0, _common.getEngine)(); //endregion
+ //region Get a "default parameters" for current algorithm and set correct signature algorithm
+
+ sequence = sequence.then(() => engine.subtle.getSignatureParameters(privateKey, hashAlgorithm));
+ sequence = sequence.then(result => {
+ parameters = result.parameters;
+ this.signatureAlgorithm = result.signatureAlgorithm;
+ }); //endregion
+ //region Create TBS data for signing
+
+ sequence = sequence.then(() => {
+ this.tbs = this.encodeTBS().toBER(false);
+ }); //endregion
+ //region Signing TBS data on provided private key
+
+ sequence = sequence.then(() => engine.subtle.signWithPrivateKey(this.tbs, privateKey, parameters));
+ sequence = sequence.then(result => {
+ this.signatureValue = new asn1js.BitString({
+ valueHex: result
+ });
+ }); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+ /**
+ * Verify existing certification request signature
+ * @returns {*}
+ */
+
+
+ verify() {
+ return (0, _common.getEngine)().subtle.verifyWithPublicKey(this.tbs, this.signatureValue, this.subjectPublicKeyInfo, this.signatureAlgorithm);
+ } //**********************************************************************************
+
+ /**
+ * Importing public key for current certificate request
+ */
+
+
+ getPublicKey(parameters = null) {
+ return (0, _common.getEngine)().getPublicKey(this.subjectPublicKeyInfo, this.signatureAlgorithm, parameters);
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = CertificationRequest;
+
+},{"./AlgorithmIdentifier.js":4,"./Attribute.js":6,"./PublicKeyInfo.js":78,"./RelativeDistinguishedNames.js":89,"./common.js":110,"asn1js":112,"pvutils":113}],26:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class ContentInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for ContentInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc contentType
+ */
+ this.contentType = (0, _pvutils.getParametersValue)(parameters, "contentType", ContentInfo.defaultValues("contentType"));
+ /**
+ * @type {Any}
+ * @desc content
+ */
+
+ this.content = (0, _pvutils.getParametersValue)(parameters, "content", ContentInfo.defaultValues("content")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "contentType":
+ return "";
+
+ case "content":
+ return new asn1js.Any();
+
+ default:
+ throw new Error(`Invalid member name for ContentInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "contentType":
+ return memberValue === "";
+
+ case "content":
+ return memberValue instanceof asn1js.Any;
+
+ default:
+ throw new Error(`Invalid member name for ContentInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * ContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * content [0] EXPLICIT ANY DEFINED BY contentType }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [contentType]
+ * @property {string} [content]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ if ("optional" in names === false) names.optional = false;
+ return new asn1js.Sequence({
+ name: names.blockName || "ContentInfo",
+ optional: names.optional,
+ value: [new asn1js.ObjectIdentifier({
+ name: names.contentType || "contentType"
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Any({
+ name: names.content || "content"
+ })] // EXPLICIT ANY value
+
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["contentType", "content"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, ContentInfo.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for ContentInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.contentType = asn1.result.contentType.valueBlock.toString();
+ this.content = asn1.result.content; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [new asn1js.ObjectIdentifier({
+ value: this.contentType
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [this.content] // EXPLICIT ANY value
+
+ })]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {
+ contentType: this.contentType
+ };
+ if (!(this.content instanceof asn1js.Any)) object.content = this.content.toJSON();
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = ContentInfo;
+
+},{"asn1js":112,"pvutils":113}],27:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _common = require("./common.js");
+
+var _PublicKeyInfo = _interopRequireDefault(require("./PublicKeyInfo.js"));
+
+var _PrivateKeyInfo = _interopRequireDefault(require("./PrivateKeyInfo.js"));
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _EncryptedContentInfo = _interopRequireDefault(require("./EncryptedContentInfo.js"));
+
+var _RSASSAPSSParams = _interopRequireDefault(require("./RSASSAPSSParams.js"));
+
+var _PBKDF2Params = _interopRequireDefault(require("./PBKDF2Params.js"));
+
+var _PBES2Params = _interopRequireDefault(require("./PBES2Params.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Making MAC key using algorithm described in B.2 of PKCS#12 standard.
+ */
+function makePKCS12B2Key(cryptoEngine, hashAlgorithm, keyLength, password, salt, iterationCount) {
+ //region Initial variables
+ let u;
+ let v;
+ const result = []; //endregion
+ //region Get "u" and "v" values
+
+ switch (hashAlgorithm.toUpperCase()) {
+ case "SHA-1":
+ u = 20; // 160
+
+ v = 64; // 512
+
+ break;
+
+ case "SHA-256":
+ u = 32; // 256
+
+ v = 64; // 512
+
+ break;
+
+ case "SHA-384":
+ u = 48; // 384
+
+ v = 128; // 1024
+
+ break;
+
+ case "SHA-512":
+ u = 64; // 512
+
+ v = 128; // 1024
+
+ break;
+
+ default:
+ throw new Error("Unsupported hashing algorithm");
+ } //endregion
+ //region Main algorithm making key
+ //region Transform password to UTF-8 like string
+
+
+ const passwordViewInitial = new Uint8Array(password);
+ const passwordTransformed = new ArrayBuffer(password.byteLength * 2 + 2);
+ const passwordTransformedView = new Uint8Array(passwordTransformed);
+
+ for (let i = 0; i < passwordViewInitial.length; i++) {
+ passwordTransformedView[i * 2] = 0x00;
+ passwordTransformedView[i * 2 + 1] = passwordViewInitial[i];
+ }
+
+ passwordTransformedView[passwordTransformedView.length - 2] = 0x00;
+ passwordTransformedView[passwordTransformedView.length - 1] = 0x00;
+ password = passwordTransformed.slice(0); //endregion
+ //region Construct a string D (the "diversifier") by concatenating v/8 copies of ID
+
+ const D = new ArrayBuffer(v);
+ const dView = new Uint8Array(D);
+
+ for (let i = 0; i < D.byteLength; i++) dView[i] = 3; // The ID value equal to "3" for MACing (see B.3 of standard)
+ //endregion
+ //region Concatenate copies of the salt together to create a string S of length v * ceil(s / v) bytes (the final copy of the salt may be trunacted to create S)
+
+
+ const saltLength = salt.byteLength;
+ const sLen = v * Math.ceil(saltLength / v);
+ const S = new ArrayBuffer(sLen);
+ const sView = new Uint8Array(S);
+ const saltView = new Uint8Array(salt);
+
+ for (let i = 0; i < sLen; i++) sView[i] = saltView[i % saltLength]; //endregion
+ //region Concatenate copies of the password together to create a string P of length v * ceil(p / v) bytes (the final copy of the password may be truncated to create P)
+
+
+ const passwordLength = password.byteLength;
+ const pLen = v * Math.ceil(passwordLength / v);
+ const P = new ArrayBuffer(pLen);
+ const pView = new Uint8Array(P);
+ const passwordView = new Uint8Array(password);
+
+ for (let i = 0; i < pLen; i++) pView[i] = passwordView[i % passwordLength]; //endregion
+ //region Set I=S||P to be the concatenation of S and P
+
+
+ const sPlusPLength = S.byteLength + P.byteLength;
+ let I = new ArrayBuffer(sPlusPLength);
+ let iView = new Uint8Array(I);
+ iView.set(sView);
+ iView.set(pView, sView.length); //endregion
+ //region Set c=ceil(n / u)
+
+ const c = Math.ceil((keyLength >> 3) / u); //endregion
+ //region Initial variables
+
+ let internalSequence = Promise.resolve(I); //endregion
+ //region For i=1, 2, ..., c, do the following:
+
+ for (let i = 0; i <= c; i++) {
+ internalSequence = internalSequence.then(_I => {
+ //region Create contecanetion of D and I
+ const dAndI = new ArrayBuffer(D.byteLength + _I.byteLength);
+ const dAndIView = new Uint8Array(dAndI);
+ dAndIView.set(dView);
+ dAndIView.set(iView, dView.length); //endregion
+
+ return dAndI;
+ }); //region Make "iterationCount" rounds of hashing
+
+ for (let j = 0; j < iterationCount; j++) internalSequence = internalSequence.then(roundBuffer => cryptoEngine.digest({
+ name: hashAlgorithm
+ }, new Uint8Array(roundBuffer))); //endregion
+
+
+ internalSequence = internalSequence.then(roundBuffer => {
+ //region Concatenate copies of Ai to create a string B of length v bits (the final copy of Ai may be truncated to create B)
+ const B = new ArrayBuffer(v);
+ const bView = new Uint8Array(B);
+
+ for (let j = 0; j < B.byteLength; j++) bView[j] = roundBuffer[j % roundBuffer.length]; //endregion
+ //region Make new I value
+
+
+ const k = Math.ceil(saltLength / v) + Math.ceil(passwordLength / v);
+ const iRound = [];
+ let sliceStart = 0;
+ let sliceLength = v;
+
+ for (let j = 0; j < k; j++) {
+ const chunk = Array.from(new Uint8Array(I.slice(sliceStart, sliceStart + sliceLength)));
+ sliceStart += v;
+ if (sliceStart + v > I.byteLength) sliceLength = I.byteLength - sliceStart;
+ let x = 0x1ff;
+
+ for (let l = B.byteLength - 1; l >= 0; l--) {
+ x >>= 8;
+ x += bView[l] + chunk[l];
+ chunk[l] = x & 0xff;
+ }
+
+ iRound.push(...chunk);
+ }
+
+ I = new ArrayBuffer(iRound.length);
+ iView = new Uint8Array(I);
+ iView.set(iRound); //endregion
+
+ result.push(...new Uint8Array(roundBuffer));
+ return I;
+ });
+ } //endregion
+ //region Initialize final key
+
+
+ internalSequence = internalSequence.then(() => {
+ const resultBuffer = new ArrayBuffer(keyLength >> 3);
+ const resultView = new Uint8Array(resultBuffer);
+ resultView.set(new Uint8Array(result).slice(0, keyLength >> 3));
+ return resultBuffer;
+ }); //endregion
+ //endregion
+
+ return internalSequence;
+} //**************************************************************************************
+
+/**
+ * Default cryptographic engine for Web Cryptography API
+ */
+
+
+class CryptoEngine {
+ //**********************************************************************************
+
+ /**
+ * Constructor for CryptoEngine class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Object}
+ * @desc Usually here we are expecting "window.crypto" or an equivalent from custom "crypto engine"
+ */
+ this.crypto = (0, _pvutils.getParametersValue)(parameters, "crypto", {});
+ /**
+ * @type {Object}
+ * @desc Usually here we are expecting "window.crypto.subtle" or an equivalent from custom "crypto engine"
+ */
+
+ this.subtle = (0, _pvutils.getParametersValue)(parameters, "subtle", {});
+ /**
+ * @type {string}
+ * @desc Name of the "crypto engine"
+ */
+
+ this.name = (0, _pvutils.getParametersValue)(parameters, "name", ""); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Import WebCrypto keys from different formats
+ * @param {string} format
+ * @param {ArrayBuffer|Uint8Array} keyData
+ * @param {Object} algorithm
+ * @param {boolean} extractable
+ * @param {Array} keyUsages
+ * @returns {Promise}
+ */
+
+
+ importKey(format, keyData, algorithm, extractable, keyUsages) {
+ //region Initial variables
+ let jwk = {}; //endregion
+ //region Change "keyData" type if needed
+
+ if (keyData instanceof Uint8Array) keyData = keyData.buffer; //endregion
+
+ switch (format.toLowerCase()) {
+ case "raw":
+ return this.subtle.importKey("raw", keyData, algorithm, extractable, keyUsages);
+
+ case "spki":
+ {
+ const asn1 = asn1js.fromBER(keyData);
+ if (asn1.offset === -1) return Promise.reject("Incorrect keyData");
+ const publicKeyInfo = new _PublicKeyInfo.default();
+
+ try {
+ publicKeyInfo.fromSchema(asn1.result);
+ } catch (ex) {
+ return Promise.reject("Incorrect keyData");
+ } // noinspection FallThroughInSwitchStatementJS
+
+
+ switch (algorithm.name.toUpperCase()) {
+ case "RSA-PSS":
+ {
+ //region Get information about used hash function
+ switch (algorithm.hash.name.toUpperCase()) {
+ case "SHA-1":
+ jwk.alg = "PS1";
+ break;
+
+ case "SHA-256":
+ jwk.alg = "PS256";
+ break;
+
+ case "SHA-384":
+ jwk.alg = "PS384";
+ break;
+
+ case "SHA-512":
+ jwk.alg = "PS512";
+ break;
+
+ default:
+ return Promise.reject(`Incorrect hash algorithm: ${algorithm.hash.name.toUpperCase()}`);
+ } //endregion
+
+ }
+ // break omitted
+
+ case "RSASSA-PKCS1-V1_5":
+ {
+ keyUsages = ["verify"]; // Override existing keyUsages value since the key is a public key
+
+ jwk.kty = "RSA";
+ jwk.ext = extractable;
+ jwk.key_ops = keyUsages;
+ if (publicKeyInfo.algorithm.algorithmId !== "1.2.840.113549.1.1.1") return Promise.reject(`Incorrect public key algorithm: ${publicKeyInfo.algorithm.algorithmId}`); //region Get information about used hash function
+
+ if ("alg" in jwk === false) {
+ switch (algorithm.hash.name.toUpperCase()) {
+ case "SHA-1":
+ jwk.alg = "RS1";
+ break;
+
+ case "SHA-256":
+ jwk.alg = "RS256";
+ break;
+
+ case "SHA-384":
+ jwk.alg = "RS384";
+ break;
+
+ case "SHA-512":
+ jwk.alg = "RS512";
+ break;
+
+ default:
+ return Promise.reject(`Incorrect public key algorithm: ${publicKeyInfo.algorithm.algorithmId}`);
+ }
+ } //endregion
+ //region Create RSA Public Key elements
+
+
+ const publicKeyJSON = publicKeyInfo.toJSON();
+
+ for (var _i = 0, _Object$keys = Object.keys(publicKeyJSON); _i < _Object$keys.length; _i++) {
+ const key = _Object$keys[_i];
+ jwk[key] = publicKeyJSON[key];
+ } //endregion
+
+ }
+ break;
+
+ case "ECDSA":
+ keyUsages = ["verify"];
+ // Override existing keyUsages value since the key is a public key
+ // break omitted
+
+ case "ECDH":
+ {
+ //region Initial variables
+ jwk = {
+ kty: "EC",
+ ext: extractable,
+ key_ops: keyUsages
+ }; //endregion
+ //region Get information about algorithm
+
+ if (publicKeyInfo.algorithm.algorithmId !== "1.2.840.10045.2.1") return Promise.reject(`Incorrect public key algorithm: ${publicKeyInfo.algorithm.algorithmId}`); //endregion
+ //region Create ECDSA Public Key elements
+
+ const publicKeyJSON = publicKeyInfo.toJSON();
+
+ for (var _i2 = 0, _Object$keys2 = Object.keys(publicKeyJSON); _i2 < _Object$keys2.length; _i2++) {
+ const key = _Object$keys2[_i2];
+ jwk[key] = publicKeyJSON[key];
+ } //endregion
+
+ }
+ break;
+
+ case "RSA-OAEP":
+ {
+ jwk.kty = "RSA";
+ jwk.ext = extractable;
+ jwk.key_ops = keyUsages;
+ if (this.name.toLowerCase() === "safari") jwk.alg = "RSA-OAEP";else {
+ switch (algorithm.hash.name.toUpperCase()) {
+ case "SHA-1":
+ jwk.alg = "RSA-OAEP";
+ break;
+
+ case "SHA-256":
+ jwk.alg = "RSA-OAEP-256";
+ break;
+
+ case "SHA-384":
+ jwk.alg = "RSA-OAEP-384";
+ break;
+
+ case "SHA-512":
+ jwk.alg = "RSA-OAEP-512";
+ break;
+
+ default:
+ return Promise.reject(`Incorrect public key algorithm: ${publicKeyInfo.algorithm.algorithmId}`);
+ }
+ } //region Create ECDSA Public Key elements
+
+ const publicKeyJSON = publicKeyInfo.toJSON();
+
+ for (var _i3 = 0, _Object$keys3 = Object.keys(publicKeyJSON); _i3 < _Object$keys3.length; _i3++) {
+ const key = _Object$keys3[_i3];
+ jwk[key] = publicKeyJSON[key];
+ } //endregion
+
+ }
+ break;
+
+ default:
+ return Promise.reject(`Incorrect algorithm name: ${algorithm.name.toUpperCase()}`);
+ }
+ }
+ break;
+
+ case "pkcs8":
+ {
+ const privateKeyInfo = new _PrivateKeyInfo.default(); //region Parse "PrivateKeyInfo" object
+
+ const asn1 = asn1js.fromBER(keyData);
+ if (asn1.offset === -1) return Promise.reject("Incorrect keyData");
+
+ try {
+ privateKeyInfo.fromSchema(asn1.result);
+ } catch (ex) {
+ return Promise.reject("Incorrect keyData");
+ }
+
+ if ("parsedKey" in privateKeyInfo === false) return Promise.reject("Incorrect keyData"); //endregion
+ // noinspection FallThroughInSwitchStatementJS
+ // noinspection FallThroughInSwitchStatementJS
+
+ switch (algorithm.name.toUpperCase()) {
+ case "RSA-PSS":
+ {
+ //region Get information about used hash function
+ switch (algorithm.hash.name.toUpperCase()) {
+ case "SHA-1":
+ jwk.alg = "PS1";
+ break;
+
+ case "SHA-256":
+ jwk.alg = "PS256";
+ break;
+
+ case "SHA-384":
+ jwk.alg = "PS384";
+ break;
+
+ case "SHA-512":
+ jwk.alg = "PS512";
+ break;
+
+ default:
+ return Promise.reject(`Incorrect hash algorithm: ${algorithm.hash.name.toUpperCase()}`);
+ } //endregion
+
+ }
+ // break omitted
+
+ case "RSASSA-PKCS1-V1_5":
+ {
+ keyUsages = ["sign"]; // Override existing keyUsages value since the key is a private key
+
+ jwk.kty = "RSA";
+ jwk.ext = extractable;
+ jwk.key_ops = keyUsages; //region Get information about used hash function
+
+ if (privateKeyInfo.privateKeyAlgorithm.algorithmId !== "1.2.840.113549.1.1.1") return Promise.reject(`Incorrect private key algorithm: ${privateKeyInfo.privateKeyAlgorithm.algorithmId}`); //endregion
+ //region Get information about used hash function
+
+ if ("alg" in jwk === false) {
+ switch (algorithm.hash.name.toUpperCase()) {
+ case "SHA-1":
+ jwk.alg = "RS1";
+ break;
+
+ case "SHA-256":
+ jwk.alg = "RS256";
+ break;
+
+ case "SHA-384":
+ jwk.alg = "RS384";
+ break;
+
+ case "SHA-512":
+ jwk.alg = "RS512";
+ break;
+
+ default:
+ return Promise.reject(`Incorrect hash algorithm: ${algorithm.hash.name.toUpperCase()}`);
+ }
+ } //endregion
+ //region Create RSA Private Key elements
+
+
+ const privateKeyJSON = privateKeyInfo.toJSON();
+
+ for (var _i4 = 0, _Object$keys4 = Object.keys(privateKeyJSON); _i4 < _Object$keys4.length; _i4++) {
+ const key = _Object$keys4[_i4];
+ jwk[key] = privateKeyJSON[key];
+ } //endregion
+
+ }
+ break;
+
+ case "ECDSA":
+ keyUsages = ["sign"];
+ // Override existing keyUsages value since the key is a private key
+ // break omitted
+
+ case "ECDH":
+ {
+ //region Initial variables
+ jwk = {
+ kty: "EC",
+ ext: extractable,
+ key_ops: keyUsages
+ }; //endregion
+ //region Get information about used hash function
+
+ if (privateKeyInfo.privateKeyAlgorithm.algorithmId !== "1.2.840.10045.2.1") return Promise.reject(`Incorrect algorithm: ${privateKeyInfo.privateKeyAlgorithm.algorithmId}`); //endregion
+ //region Create ECDSA Private Key elements
+
+ const privateKeyJSON = privateKeyInfo.toJSON();
+
+ for (var _i5 = 0, _Object$keys5 = Object.keys(privateKeyJSON); _i5 < _Object$keys5.length; _i5++) {
+ const key = _Object$keys5[_i5];
+ jwk[key] = privateKeyJSON[key];
+ } //endregion
+
+ }
+ break;
+
+ case "RSA-OAEP":
+ {
+ jwk.kty = "RSA";
+ jwk.ext = extractable;
+ jwk.key_ops = keyUsages; //region Get information about used hash function
+
+ if (this.name.toLowerCase() === "safari") jwk.alg = "RSA-OAEP";else {
+ switch (algorithm.hash.name.toUpperCase()) {
+ case "SHA-1":
+ jwk.alg = "RSA-OAEP";
+ break;
+
+ case "SHA-256":
+ jwk.alg = "RSA-OAEP-256";
+ break;
+
+ case "SHA-384":
+ jwk.alg = "RSA-OAEP-384";
+ break;
+
+ case "SHA-512":
+ jwk.alg = "RSA-OAEP-512";
+ break;
+
+ default:
+ return Promise.reject(`Incorrect hash algorithm: ${algorithm.hash.name.toUpperCase()}`);
+ }
+ } //endregion
+ //region Create RSA Private Key elements
+
+ const privateKeyJSON = privateKeyInfo.toJSON();
+
+ for (var _i6 = 0, _Object$keys6 = Object.keys(privateKeyJSON); _i6 < _Object$keys6.length; _i6++) {
+ const key = _Object$keys6[_i6];
+ jwk[key] = privateKeyJSON[key];
+ } //endregion
+
+ }
+ break;
+
+ default:
+ return Promise.reject(`Incorrect algorithm name: ${algorithm.name.toUpperCase()}`);
+ }
+ }
+ break;
+
+ case "jwk":
+ jwk = keyData;
+ break;
+
+ default:
+ return Promise.reject(`Incorrect format: ${format}`);
+ } //region Special case for Safari browser (since its acting not as WebCrypto standard describes)
+
+
+ if (this.name.toLowerCase() === "safari") {
+ // Try to use both ways - import using ArrayBuffer and pure JWK (for Safari Technology Preview)
+ return Promise.resolve().then(() => this.subtle.importKey("jwk", (0, _pvutils.stringToArrayBuffer)(JSON.stringify(jwk)), algorithm, extractable, keyUsages)).then(result => result, () => this.subtle.importKey("jwk", jwk, algorithm, extractable, keyUsages));
+ } //endregion
+
+
+ return this.subtle.importKey("jwk", jwk, algorithm, extractable, keyUsages);
+ } //**********************************************************************************
+
+ /**
+ * Export WebCrypto keys to different formats
+ * @param {string} format
+ * @param {Object} key
+ * @returns {Promise}
+ */
+
+
+ exportKey(format, key) {
+ let sequence = this.subtle.exportKey("jwk", key); //region Currently Safari returns ArrayBuffer as JWK thus we need an additional transformation
+
+ if (this.name.toLowerCase() === "safari") {
+ sequence = sequence.then(result => {
+ // Some additional checks for Safari Technology Preview
+ if (result instanceof ArrayBuffer) return JSON.parse((0, _pvutils.arrayBufferToString)(result));
+ return result;
+ });
+ } //endregion
+
+
+ switch (format.toLowerCase()) {
+ case "raw":
+ return this.subtle.exportKey("raw", key);
+
+ case "spki":
+ sequence = sequence.then(result => {
+ const publicKeyInfo = new _PublicKeyInfo.default();
+
+ try {
+ publicKeyInfo.fromJSON(result);
+ } catch (ex) {
+ return Promise.reject("Incorrect key data");
+ }
+
+ return publicKeyInfo.toSchema().toBER(false);
+ });
+ break;
+
+ case "pkcs8":
+ sequence = sequence.then(result => {
+ const privateKeyInfo = new _PrivateKeyInfo.default();
+
+ try {
+ privateKeyInfo.fromJSON(result);
+ } catch (ex) {
+ return Promise.reject("Incorrect key data");
+ }
+
+ return privateKeyInfo.toSchema().toBER(false);
+ });
+ break;
+
+ case "jwk":
+ break;
+
+ default:
+ return Promise.reject(`Incorrect format: ${format}`);
+ }
+
+ return sequence;
+ } //**********************************************************************************
+
+ /**
+ * Convert WebCrypto keys between different export formats
+ * @param {string} inputFormat
+ * @param {string} outputFormat
+ * @param {ArrayBuffer|Object} keyData
+ * @param {Object} algorithm
+ * @param {boolean} extractable
+ * @param {Array} keyUsages
+ * @returns {Promise}
+ */
+
+
+ convert(inputFormat, outputFormat, keyData, algorithm, extractable, keyUsages) {
+ switch (inputFormat.toLowerCase()) {
+ case "raw":
+ switch (outputFormat.toLowerCase()) {
+ case "raw":
+ return Promise.resolve(keyData);
+
+ case "spki":
+ return Promise.resolve().then(() => this.importKey("raw", keyData, algorithm, extractable, keyUsages)).then(result => this.exportKey("spki", result));
+
+ case "pkcs8":
+ return Promise.resolve().then(() => this.importKey("raw", keyData, algorithm, extractable, keyUsages)).then(result => this.exportKey("pkcs8", result));
+
+ case "jwk":
+ return Promise.resolve().then(() => this.importKey("raw", keyData, algorithm, extractable, keyUsages)).then(result => this.exportKey("jwk", result));
+
+ default:
+ return Promise.reject(`Incorrect outputFormat: ${outputFormat}`);
+ }
+
+ case "spki":
+ switch (outputFormat.toLowerCase()) {
+ case "raw":
+ return Promise.resolve().then(() => this.importKey("spki", keyData, algorithm, extractable, keyUsages)).then(result => this.exportKey("raw", result));
+
+ case "spki":
+ return Promise.resolve(keyData);
+
+ case "pkcs8":
+ return Promise.reject("Impossible to convert between SPKI/PKCS8");
+
+ case "jwk":
+ return Promise.resolve().then(() => this.importKey("spki", keyData, algorithm, extractable, keyUsages)).then(result => this.exportKey("jwk", result));
+
+ default:
+ return Promise.reject(`Incorrect outputFormat: ${outputFormat}`);
+ }
+
+ case "pkcs8":
+ switch (outputFormat.toLowerCase()) {
+ case "raw":
+ return Promise.resolve().then(() => this.importKey("pkcs8", keyData, algorithm, extractable, keyUsages)).then(result => this.exportKey("raw", result));
+
+ case "spki":
+ return Promise.reject("Impossible to convert between SPKI/PKCS8");
+
+ case "pkcs8":
+ return Promise.resolve(keyData);
+
+ case "jwk":
+ return Promise.resolve().then(() => this.importKey("pkcs8", keyData, algorithm, extractable, keyUsages)).then(result => this.exportKey("jwk", result));
+
+ default:
+ return Promise.reject(`Incorrect outputFormat: ${outputFormat}`);
+ }
+
+ case "jwk":
+ switch (outputFormat.toLowerCase()) {
+ case "raw":
+ return Promise.resolve().then(() => this.importKey("jwk", keyData, algorithm, extractable, keyUsages)).then(result => this.exportKey("raw", result));
+
+ case "spki":
+ return Promise.resolve().then(() => this.importKey("jwk", keyData, algorithm, extractable, keyUsages)).then(result => this.exportKey("spki", result));
+
+ case "pkcs8":
+ return Promise.resolve().then(() => this.importKey("jwk", keyData, algorithm, extractable, keyUsages)).then(result => this.exportKey("pkcs8", result));
+
+ case "jwk":
+ return Promise.resolve(keyData);
+
+ default:
+ return Promise.reject(`Incorrect outputFormat: ${outputFormat}`);
+ }
+
+ default:
+ return Promise.reject(`Incorrect inputFormat: ${inputFormat}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Wrapper for standard function "encrypt"
+ * @param args
+ * @returns {Promise}
+ */
+
+
+ encrypt(...args) {
+ return this.subtle.encrypt(...args);
+ } //**********************************************************************************
+
+ /**
+ * Wrapper for standard function "decrypt"
+ * @param args
+ * @returns {Promise}
+ */
+
+
+ decrypt(...args) {
+ return this.subtle.decrypt(...args);
+ } //**********************************************************************************
+
+ /**
+ * Wrapper for standard function "sign"
+ * @param args
+ * @returns {Promise}
+ */
+
+
+ sign(...args) {
+ return this.subtle.sign(...args);
+ } //**********************************************************************************
+
+ /**
+ * Wrapper for standard function "verify"
+ * @param args
+ * @returns {Promise}
+ */
+
+
+ verify(...args) {
+ return this.subtle.verify(...args);
+ } //**********************************************************************************
+
+ /**
+ * Wrapper for standard function "digest"
+ * @param args
+ * @returns {Promise}
+ */
+
+
+ digest(...args) {
+ return this.subtle.digest(...args);
+ } //**********************************************************************************
+
+ /**
+ * Wrapper for standard function "generateKey"
+ * @param args
+ * @returns {Promise}
+ */
+
+
+ generateKey(...args) {
+ return this.subtle.generateKey(...args);
+ } //**********************************************************************************
+
+ /**
+ * Wrapper for standard function "deriveKey"
+ * @param args
+ * @returns {Promise}
+ */
+
+
+ deriveKey(...args) {
+ return this.subtle.deriveKey(...args);
+ } //**********************************************************************************
+
+ /**
+ * Wrapper for standard function "deriveBits"
+ * @param args
+ * @returns {Promise}
+ */
+
+
+ deriveBits(...args) {
+ return this.subtle.deriveBits(...args);
+ } //**********************************************************************************
+
+ /**
+ * Wrapper for standard function "wrapKey"
+ * @param args
+ * @returns {Promise}
+ */
+
+
+ wrapKey(...args) {
+ return this.subtle.wrapKey(...args);
+ } //**********************************************************************************
+
+ /**
+ * Wrapper for standard function "unwrapKey"
+ * @param args
+ * @returns {Promise}
+ */
+
+
+ unwrapKey(...args) {
+ return this.subtle.unwrapKey(...args);
+ } //**********************************************************************************
+
+ /**
+ * Initialize input Uint8Array by random values (with help from current "crypto engine")
+ * @param {!Uint8Array} view
+ * @returns {*}
+ */
+
+
+ getRandomValues(view) {
+ if ("getRandomValues" in this.crypto === false) throw new Error("No support for getRandomValues");
+ return this.crypto.getRandomValues(view);
+ } //**********************************************************************************
+
+ /**
+ * Get WebCrypto algorithm by wel-known OID
+ * @param {string} oid well-known OID to search for
+ * @returns {Object}
+ */
+
+
+ getAlgorithmByOID(oid) {
+ switch (oid) {
+ case "1.2.840.113549.1.1.1":
+ case "1.2.840.113549.1.1.5":
+ return {
+ name: "RSASSA-PKCS1-v1_5",
+ hash: {
+ name: "SHA-1"
+ }
+ };
+
+ case "1.2.840.113549.1.1.11":
+ return {
+ name: "RSASSA-PKCS1-v1_5",
+ hash: {
+ name: "SHA-256"
+ }
+ };
+
+ case "1.2.840.113549.1.1.12":
+ return {
+ name: "RSASSA-PKCS1-v1_5",
+ hash: {
+ name: "SHA-384"
+ }
+ };
+
+ case "1.2.840.113549.1.1.13":
+ return {
+ name: "RSASSA-PKCS1-v1_5",
+ hash: {
+ name: "SHA-512"
+ }
+ };
+
+ case "1.2.840.113549.1.1.10":
+ return {
+ name: "RSA-PSS"
+ };
+
+ case "1.2.840.113549.1.1.7":
+ return {
+ name: "RSA-OAEP"
+ };
+
+ case "1.2.840.10045.2.1":
+ case "1.2.840.10045.4.1":
+ return {
+ name: "ECDSA",
+ hash: {
+ name: "SHA-1"
+ }
+ };
+
+ case "1.2.840.10045.4.3.2":
+ return {
+ name: "ECDSA",
+ hash: {
+ name: "SHA-256"
+ }
+ };
+
+ case "1.2.840.10045.4.3.3":
+ return {
+ name: "ECDSA",
+ hash: {
+ name: "SHA-384"
+ }
+ };
+
+ case "1.2.840.10045.4.3.4":
+ return {
+ name: "ECDSA",
+ hash: {
+ name: "SHA-512"
+ }
+ };
+
+ case "1.3.133.16.840.63.0.2":
+ return {
+ name: "ECDH",
+ kdf: "SHA-1"
+ };
+
+ case "1.3.132.1.11.1":
+ return {
+ name: "ECDH",
+ kdf: "SHA-256"
+ };
+
+ case "1.3.132.1.11.2":
+ return {
+ name: "ECDH",
+ kdf: "SHA-384"
+ };
+
+ case "1.3.132.1.11.3":
+ return {
+ name: "ECDH",
+ kdf: "SHA-512"
+ };
+
+ case "2.16.840.1.101.3.4.1.2":
+ return {
+ name: "AES-CBC",
+ length: 128
+ };
+
+ case "2.16.840.1.101.3.4.1.22":
+ return {
+ name: "AES-CBC",
+ length: 192
+ };
+
+ case "2.16.840.1.101.3.4.1.42":
+ return {
+ name: "AES-CBC",
+ length: 256
+ };
+
+ case "2.16.840.1.101.3.4.1.6":
+ return {
+ name: "AES-GCM",
+ length: 128
+ };
+
+ case "2.16.840.1.101.3.4.1.26":
+ return {
+ name: "AES-GCM",
+ length: 192
+ };
+
+ case "2.16.840.1.101.3.4.1.46":
+ return {
+ name: "AES-GCM",
+ length: 256
+ };
+
+ case "2.16.840.1.101.3.4.1.4":
+ return {
+ name: "AES-CFB",
+ length: 128
+ };
+
+ case "2.16.840.1.101.3.4.1.24":
+ return {
+ name: "AES-CFB",
+ length: 192
+ };
+
+ case "2.16.840.1.101.3.4.1.44":
+ return {
+ name: "AES-CFB",
+ length: 256
+ };
+
+ case "2.16.840.1.101.3.4.1.5":
+ return {
+ name: "AES-KW",
+ length: 128
+ };
+
+ case "2.16.840.1.101.3.4.1.25":
+ return {
+ name: "AES-KW",
+ length: 192
+ };
+
+ case "2.16.840.1.101.3.4.1.45":
+ return {
+ name: "AES-KW",
+ length: 256
+ };
+
+ case "1.2.840.113549.2.7":
+ return {
+ name: "HMAC",
+ hash: {
+ name: "SHA-1"
+ }
+ };
+
+ case "1.2.840.113549.2.9":
+ return {
+ name: "HMAC",
+ hash: {
+ name: "SHA-256"
+ }
+ };
+
+ case "1.2.840.113549.2.10":
+ return {
+ name: "HMAC",
+ hash: {
+ name: "SHA-384"
+ }
+ };
+
+ case "1.2.840.113549.2.11":
+ return {
+ name: "HMAC",
+ hash: {
+ name: "SHA-512"
+ }
+ };
+
+ case "1.2.840.113549.1.9.16.3.5":
+ return {
+ name: "DH"
+ };
+
+ case "1.3.14.3.2.26":
+ return {
+ name: "SHA-1"
+ };
+
+ case "2.16.840.1.101.3.4.2.1":
+ return {
+ name: "SHA-256"
+ };
+
+ case "2.16.840.1.101.3.4.2.2":
+ return {
+ name: "SHA-384"
+ };
+
+ case "2.16.840.1.101.3.4.2.3":
+ return {
+ name: "SHA-512"
+ };
+
+ case "1.2.840.113549.1.5.12":
+ return {
+ name: "PBKDF2"
+ };
+ //region Special case - OIDs for ECC curves
+
+ case "1.2.840.10045.3.1.7":
+ return {
+ name: "P-256"
+ };
+
+ case "1.3.132.0.34":
+ return {
+ name: "P-384"
+ };
+
+ case "1.3.132.0.35":
+ return {
+ name: "P-521"
+ };
+ //endregion
+
+ default:
+ }
+
+ return {};
+ } //**********************************************************************************
+
+ /**
+ * Get OID for each specific algorithm
+ * @param {Object} algorithm
+ * @returns {string}
+ */
+
+
+ getOIDByAlgorithm(algorithm) {
+ let result = "";
+
+ switch (algorithm.name.toUpperCase()) {
+ case "RSASSA-PKCS1-V1_5":
+ switch (algorithm.hash.name.toUpperCase()) {
+ case "SHA-1":
+ result = "1.2.840.113549.1.1.5";
+ break;
+
+ case "SHA-256":
+ result = "1.2.840.113549.1.1.11";
+ break;
+
+ case "SHA-384":
+ result = "1.2.840.113549.1.1.12";
+ break;
+
+ case "SHA-512":
+ result = "1.2.840.113549.1.1.13";
+ break;
+
+ default:
+ }
+
+ break;
+
+ case "RSA-PSS":
+ result = "1.2.840.113549.1.1.10";
+ break;
+
+ case "RSA-OAEP":
+ result = "1.2.840.113549.1.1.7";
+ break;
+
+ case "ECDSA":
+ switch (algorithm.hash.name.toUpperCase()) {
+ case "SHA-1":
+ result = "1.2.840.10045.4.1";
+ break;
+
+ case "SHA-256":
+ result = "1.2.840.10045.4.3.2";
+ break;
+
+ case "SHA-384":
+ result = "1.2.840.10045.4.3.3";
+ break;
+
+ case "SHA-512":
+ result = "1.2.840.10045.4.3.4";
+ break;
+
+ default:
+ }
+
+ break;
+
+ case "ECDH":
+ switch (algorithm.kdf.toUpperCase()) {
+ // Non-standard addition - hash algorithm of KDF function
+ case "SHA-1":
+ result = "1.3.133.16.840.63.0.2"; // dhSinglePass-stdDH-sha1kdf-scheme
+
+ break;
+
+ case "SHA-256":
+ result = "1.3.132.1.11.1"; // dhSinglePass-stdDH-sha256kdf-scheme
+
+ break;
+
+ case "SHA-384":
+ result = "1.3.132.1.11.2"; // dhSinglePass-stdDH-sha384kdf-scheme
+
+ break;
+
+ case "SHA-512":
+ result = "1.3.132.1.11.3"; // dhSinglePass-stdDH-sha512kdf-scheme
+
+ break;
+
+ default:
+ }
+
+ break;
+
+ case "AES-CTR":
+ break;
+
+ case "AES-CBC":
+ switch (algorithm.length) {
+ case 128:
+ result = "2.16.840.1.101.3.4.1.2";
+ break;
+
+ case 192:
+ result = "2.16.840.1.101.3.4.1.22";
+ break;
+
+ case 256:
+ result = "2.16.840.1.101.3.4.1.42";
+ break;
+
+ default:
+ }
+
+ break;
+
+ case "AES-CMAC":
+ break;
+
+ case "AES-GCM":
+ switch (algorithm.length) {
+ case 128:
+ result = "2.16.840.1.101.3.4.1.6";
+ break;
+
+ case 192:
+ result = "2.16.840.1.101.3.4.1.26";
+ break;
+
+ case 256:
+ result = "2.16.840.1.101.3.4.1.46";
+ break;
+
+ default:
+ }
+
+ break;
+
+ case "AES-CFB":
+ switch (algorithm.length) {
+ case 128:
+ result = "2.16.840.1.101.3.4.1.4";
+ break;
+
+ case 192:
+ result = "2.16.840.1.101.3.4.1.24";
+ break;
+
+ case 256:
+ result = "2.16.840.1.101.3.4.1.44";
+ break;
+
+ default:
+ }
+
+ break;
+
+ case "AES-KW":
+ switch (algorithm.length) {
+ case 128:
+ result = "2.16.840.1.101.3.4.1.5";
+ break;
+
+ case 192:
+ result = "2.16.840.1.101.3.4.1.25";
+ break;
+
+ case 256:
+ result = "2.16.840.1.101.3.4.1.45";
+ break;
+
+ default:
+ }
+
+ break;
+
+ case "HMAC":
+ switch (algorithm.hash.name.toUpperCase()) {
+ case "SHA-1":
+ result = "1.2.840.113549.2.7";
+ break;
+
+ case "SHA-256":
+ result = "1.2.840.113549.2.9";
+ break;
+
+ case "SHA-384":
+ result = "1.2.840.113549.2.10";
+ break;
+
+ case "SHA-512":
+ result = "1.2.840.113549.2.11";
+ break;
+
+ default:
+ }
+
+ break;
+
+ case "DH":
+ result = "1.2.840.113549.1.9.16.3.5";
+ break;
+
+ case "SHA-1":
+ result = "1.3.14.3.2.26";
+ break;
+
+ case "SHA-256":
+ result = "2.16.840.1.101.3.4.2.1";
+ break;
+
+ case "SHA-384":
+ result = "2.16.840.1.101.3.4.2.2";
+ break;
+
+ case "SHA-512":
+ result = "2.16.840.1.101.3.4.2.3";
+ break;
+
+ case "CONCAT":
+ break;
+
+ case "HKDF":
+ break;
+
+ case "PBKDF2":
+ result = "1.2.840.113549.1.5.12";
+ break;
+ //region Special case - OIDs for ECC curves
+
+ case "P-256":
+ result = "1.2.840.10045.3.1.7";
+ break;
+
+ case "P-384":
+ result = "1.3.132.0.34";
+ break;
+
+ case "P-521":
+ result = "1.3.132.0.35";
+ break;
+ //endregion
+
+ default:
+ }
+
+ return result;
+ } //**********************************************************************************
+
+ /**
+ * Get default algorithm parameters for each kind of operation
+ * @param {string} algorithmName Algorithm name to get common parameters for
+ * @param {string} operation Kind of operation: "sign", "encrypt", "generatekey", "importkey", "exportkey", "verify"
+ * @returns {*}
+ */
+
+
+ getAlgorithmParameters(algorithmName, operation) {
+ let result = {
+ algorithm: {},
+ usages: []
+ };
+
+ switch (algorithmName.toUpperCase()) {
+ case "RSASSA-PKCS1-V1_5":
+ switch (operation.toLowerCase()) {
+ case "generatekey":
+ result = {
+ algorithm: {
+ name: "RSASSA-PKCS1-v1_5",
+ modulusLength: 2048,
+ publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+ hash: {
+ name: "SHA-256"
+ }
+ },
+ usages: ["sign", "verify"]
+ };
+ break;
+
+ case "verify":
+ case "sign":
+ case "importkey":
+ result = {
+ algorithm: {
+ name: "RSASSA-PKCS1-v1_5",
+ hash: {
+ name: "SHA-256"
+ }
+ },
+ usages: ["verify"] // For importKey("pkcs8") usage must be "sign" only
+
+ };
+ break;
+
+ case "exportkey":
+ default:
+ return {
+ algorithm: {
+ name: "RSASSA-PKCS1-v1_5"
+ },
+ usages: []
+ };
+ }
+
+ break;
+
+ case "RSA-PSS":
+ switch (operation.toLowerCase()) {
+ case "sign":
+ case "verify":
+ result = {
+ algorithm: {
+ name: "RSA-PSS",
+ hash: {
+ name: "SHA-1"
+ },
+ saltLength: 20
+ },
+ usages: ["sign", "verify"]
+ };
+ break;
+
+ case "generatekey":
+ result = {
+ algorithm: {
+ name: "RSA-PSS",
+ modulusLength: 2048,
+ publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+ hash: {
+ name: "SHA-1"
+ }
+ },
+ usages: ["sign", "verify"]
+ };
+ break;
+
+ case "importkey":
+ result = {
+ algorithm: {
+ name: "RSA-PSS",
+ hash: {
+ name: "SHA-1"
+ }
+ },
+ usages: ["verify"] // For importKey("pkcs8") usage must be "sign" only
+
+ };
+ break;
+
+ case "exportkey":
+ default:
+ return {
+ algorithm: {
+ name: "RSA-PSS"
+ },
+ usages: []
+ };
+ }
+
+ break;
+
+ case "RSA-OAEP":
+ switch (operation.toLowerCase()) {
+ case "encrypt":
+ case "decrypt":
+ result = {
+ algorithm: {
+ name: "RSA-OAEP"
+ },
+ usages: ["encrypt", "decrypt"]
+ };
+ break;
+
+ case "generatekey":
+ result = {
+ algorithm: {
+ name: "RSA-OAEP",
+ modulusLength: 2048,
+ publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+ hash: {
+ name: "SHA-256"
+ }
+ },
+ usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+ };
+ break;
+
+ case "importkey":
+ result = {
+ algorithm: {
+ name: "RSA-OAEP",
+ hash: {
+ name: "SHA-256"
+ }
+ },
+ usages: ["encrypt"] // encrypt for "spki" and decrypt for "pkcs8"
+
+ };
+ break;
+
+ case "exportkey":
+ default:
+ return {
+ algorithm: {
+ name: "RSA-OAEP"
+ },
+ usages: []
+ };
+ }
+
+ break;
+
+ case "ECDSA":
+ switch (operation.toLowerCase()) {
+ case "generatekey":
+ result = {
+ algorithm: {
+ name: "ECDSA",
+ namedCurve: "P-256"
+ },
+ usages: ["sign", "verify"]
+ };
+ break;
+
+ case "importkey":
+ result = {
+ algorithm: {
+ name: "ECDSA",
+ namedCurve: "P-256"
+ },
+ usages: ["verify"] // "sign" for "pkcs8"
+
+ };
+ break;
+
+ case "verify":
+ case "sign":
+ result = {
+ algorithm: {
+ name: "ECDSA",
+ hash: {
+ name: "SHA-256"
+ }
+ },
+ usages: ["sign"]
+ };
+ break;
+
+ default:
+ return {
+ algorithm: {
+ name: "ECDSA"
+ },
+ usages: []
+ };
+ }
+
+ break;
+
+ case "ECDH":
+ switch (operation.toLowerCase()) {
+ case "exportkey":
+ case "importkey":
+ case "generatekey":
+ result = {
+ algorithm: {
+ name: "ECDH",
+ namedCurve: "P-256"
+ },
+ usages: ["deriveKey", "deriveBits"]
+ };
+ break;
+
+ case "derivekey":
+ case "derivebits":
+ result = {
+ algorithm: {
+ name: "ECDH",
+ namedCurve: "P-256",
+ public: [] // Must be a "publicKey"
+
+ },
+ usages: ["encrypt", "decrypt"]
+ };
+ break;
+
+ default:
+ return {
+ algorithm: {
+ name: "ECDH"
+ },
+ usages: []
+ };
+ }
+
+ break;
+
+ case "AES-CTR":
+ switch (operation.toLowerCase()) {
+ case "importkey":
+ case "exportkey":
+ case "generatekey":
+ result = {
+ algorithm: {
+ name: "AES-CTR",
+ length: 256
+ },
+ usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+ };
+ break;
+
+ case "decrypt":
+ case "encrypt":
+ result = {
+ algorithm: {
+ name: "AES-CTR",
+ counter: new Uint8Array(16),
+ length: 10
+ },
+ usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+ };
+ break;
+
+ default:
+ return {
+ algorithm: {
+ name: "AES-CTR"
+ },
+ usages: []
+ };
+ }
+
+ break;
+
+ case "AES-CBC":
+ switch (operation.toLowerCase()) {
+ case "importkey":
+ case "exportkey":
+ case "generatekey":
+ result = {
+ algorithm: {
+ name: "AES-CBC",
+ length: 256
+ },
+ usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+ };
+ break;
+
+ case "decrypt":
+ case "encrypt":
+ result = {
+ algorithm: {
+ name: "AES-CBC",
+ iv: this.getRandomValues(new Uint8Array(16)) // For "decrypt" the value should be replaced with value got on "encrypt" step
+
+ },
+ usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+ };
+ break;
+
+ default:
+ return {
+ algorithm: {
+ name: "AES-CBC"
+ },
+ usages: []
+ };
+ }
+
+ break;
+
+ case "AES-GCM":
+ switch (operation.toLowerCase()) {
+ case "importkey":
+ case "exportkey":
+ case "generatekey":
+ result = {
+ algorithm: {
+ name: "AES-GCM",
+ length: 256
+ },
+ usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+ };
+ break;
+
+ case "decrypt":
+ case "encrypt":
+ result = {
+ algorithm: {
+ name: "AES-GCM",
+ iv: this.getRandomValues(new Uint8Array(16)) // For "decrypt" the value should be replaced with value got on "encrypt" step
+
+ },
+ usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+ };
+ break;
+
+ default:
+ return {
+ algorithm: {
+ name: "AES-GCM"
+ },
+ usages: []
+ };
+ }
+
+ break;
+
+ case "AES-KW":
+ switch (operation.toLowerCase()) {
+ case "importkey":
+ case "exportkey":
+ case "generatekey":
+ case "wrapkey":
+ case "unwrapkey":
+ result = {
+ algorithm: {
+ name: "AES-KW",
+ length: 256
+ },
+ usages: ["wrapKey", "unwrapKey"]
+ };
+ break;
+
+ default:
+ return {
+ algorithm: {
+ name: "AES-KW"
+ },
+ usages: []
+ };
+ }
+
+ break;
+
+ case "HMAC":
+ switch (operation.toLowerCase()) {
+ case "sign":
+ case "verify":
+ result = {
+ algorithm: {
+ name: "HMAC"
+ },
+ usages: ["sign", "verify"]
+ };
+ break;
+
+ case "importkey":
+ case "exportkey":
+ case "generatekey":
+ result = {
+ algorithm: {
+ name: "HMAC",
+ length: 32,
+ hash: {
+ name: "SHA-256"
+ }
+ },
+ usages: ["sign", "verify"]
+ };
+ break;
+
+ default:
+ return {
+ algorithm: {
+ name: "HMAC"
+ },
+ usages: []
+ };
+ }
+
+ break;
+
+ case "HKDF":
+ switch (operation.toLowerCase()) {
+ case "derivekey":
+ result = {
+ algorithm: {
+ name: "HKDF",
+ hash: "SHA-256",
+ salt: new Uint8Array([]),
+ info: new Uint8Array([])
+ },
+ usages: ["encrypt", "decrypt"]
+ };
+ break;
+
+ default:
+ return {
+ algorithm: {
+ name: "HKDF"
+ },
+ usages: []
+ };
+ }
+
+ break;
+
+ case "PBKDF2":
+ switch (operation.toLowerCase()) {
+ case "derivekey":
+ result = {
+ algorithm: {
+ name: "PBKDF2",
+ hash: {
+ name: "SHA-256"
+ },
+ salt: new Uint8Array([]),
+ iterations: 10000
+ },
+ usages: ["encrypt", "decrypt"]
+ };
+ break;
+
+ default:
+ return {
+ algorithm: {
+ name: "PBKDF2"
+ },
+ usages: []
+ };
+ }
+
+ break;
+
+ default:
+ }
+
+ return result;
+ } //**********************************************************************************
+
+ /**
+ * Getting hash algorithm by signature algorithm
+ * @param {AlgorithmIdentifier} signatureAlgorithm Signature algorithm
+ * @returns {string}
+ */
+
+
+ getHashAlgorithm(signatureAlgorithm) {
+ let result = "";
+
+ switch (signatureAlgorithm.algorithmId) {
+ case "1.2.840.10045.4.1": // ecdsa-with-SHA1
+
+ case "1.2.840.113549.1.1.5":
+ result = "SHA-1";
+ break;
+
+ case "1.2.840.10045.4.3.2": // ecdsa-with-SHA256
+
+ case "1.2.840.113549.1.1.11":
+ result = "SHA-256";
+ break;
+
+ case "1.2.840.10045.4.3.3": // ecdsa-with-SHA384
+
+ case "1.2.840.113549.1.1.12":
+ result = "SHA-384";
+ break;
+
+ case "1.2.840.10045.4.3.4": // ecdsa-with-SHA512
+
+ case "1.2.840.113549.1.1.13":
+ result = "SHA-512";
+ break;
+
+ case "1.2.840.113549.1.1.10":
+ // RSA-PSS
+ {
+ try {
+ const params = new _RSASSAPSSParams.default({
+ schema: signatureAlgorithm.algorithmParams
+ });
+
+ if ("hashAlgorithm" in params) {
+ const algorithm = this.getAlgorithmByOID(params.hashAlgorithm.algorithmId);
+ if ("name" in algorithm === false) return "";
+ result = algorithm.name;
+ } else result = "SHA-1";
+ } catch (ex) {}
+ }
+ break;
+
+ default:
+ }
+
+ return result;
+ } //**********************************************************************************
+
+ /**
+ * Specialized function encrypting "EncryptedContentInfo" object using parameters
+ * @param {Object} parameters
+ * @returns {Promise}
+ */
+
+
+ encryptEncryptedContentInfo(parameters) {
+ //region Check for input parameters
+ if (parameters instanceof Object === false) return Promise.reject("Parameters must have type \"Object\"");
+ if ("password" in parameters === false) return Promise.reject("Absent mandatory parameter \"password\"");
+ if ("contentEncryptionAlgorithm" in parameters === false) return Promise.reject("Absent mandatory parameter \"contentEncryptionAlgorithm\"");
+ if ("hmacHashAlgorithm" in parameters === false) return Promise.reject("Absent mandatory parameter \"hmacHashAlgorithm\"");
+ if ("iterationCount" in parameters === false) return Promise.reject("Absent mandatory parameter \"iterationCount\"");
+ if ("contentToEncrypt" in parameters === false) return Promise.reject("Absent mandatory parameter \"contentToEncrypt\"");
+ if ("contentType" in parameters === false) return Promise.reject("Absent mandatory parameter \"contentType\"");
+ const contentEncryptionOID = this.getOIDByAlgorithm(parameters.contentEncryptionAlgorithm);
+ if (contentEncryptionOID === "") return Promise.reject("Wrong \"contentEncryptionAlgorithm\" value");
+ const pbkdf2OID = this.getOIDByAlgorithm({
+ name: "PBKDF2"
+ });
+ if (pbkdf2OID === "") return Promise.reject("Can not find OID for PBKDF2");
+ const hmacOID = this.getOIDByAlgorithm({
+ name: "HMAC",
+ hash: {
+ name: parameters.hmacHashAlgorithm
+ }
+ });
+ if (hmacOID === "") return Promise.reject(`Incorrect value for "hmacHashAlgorithm": ${parameters.hmacHashAlgorithm}`); //endregion
+ //region Initial variables
+
+ let sequence = Promise.resolve();
+ const ivBuffer = new ArrayBuffer(16); // For AES we need IV 16 bytes long
+
+ const ivView = new Uint8Array(ivBuffer);
+ this.getRandomValues(ivView);
+ const saltBuffer = new ArrayBuffer(64);
+ const saltView = new Uint8Array(saltBuffer);
+ this.getRandomValues(saltView);
+ const contentView = new Uint8Array(parameters.contentToEncrypt);
+ const pbkdf2Params = new _PBKDF2Params.default({
+ salt: new asn1js.OctetString({
+ valueHex: saltBuffer
+ }),
+ iterationCount: parameters.iterationCount,
+ prf: new _AlgorithmIdentifier.default({
+ algorithmId: hmacOID,
+ algorithmParams: new asn1js.Null()
+ })
+ }); //endregion
+ //region Derive PBKDF2 key from "password" buffer
+
+ sequence = sequence.then(() => {
+ const passwordView = new Uint8Array(parameters.password);
+ return this.importKey("raw", passwordView, "PBKDF2", false, ["deriveKey"]);
+ }, error => Promise.reject(error)); //endregion
+ //region Derive key for "contentEncryptionAlgorithm"
+
+ sequence = sequence.then(result => this.deriveKey({
+ name: "PBKDF2",
+ hash: {
+ name: parameters.hmacHashAlgorithm
+ },
+ salt: saltView,
+ iterations: parameters.iterationCount
+ }, result, parameters.contentEncryptionAlgorithm, false, ["encrypt"]), error => Promise.reject(error)); //endregion
+ //region Encrypt content
+
+ sequence = sequence.then(result => this.encrypt({
+ name: parameters.contentEncryptionAlgorithm.name,
+ iv: ivView
+ }, result, contentView), error => Promise.reject(error)); //endregion
+ //region Store all parameters in EncryptedData object
+
+ sequence = sequence.then(result => {
+ const pbes2Parameters = new _PBES2Params.default({
+ keyDerivationFunc: new _AlgorithmIdentifier.default({
+ algorithmId: pbkdf2OID,
+ algorithmParams: pbkdf2Params.toSchema()
+ }),
+ encryptionScheme: new _AlgorithmIdentifier.default({
+ algorithmId: contentEncryptionOID,
+ algorithmParams: new asn1js.OctetString({
+ valueHex: ivBuffer
+ })
+ })
+ });
+ return new _EncryptedContentInfo.default({
+ contentType: parameters.contentType,
+ contentEncryptionAlgorithm: new _AlgorithmIdentifier.default({
+ algorithmId: "1.2.840.113549.1.5.13",
+ // pkcs5PBES2
+ algorithmParams: pbes2Parameters.toSchema()
+ }),
+ encryptedContent: new asn1js.OctetString({
+ valueHex: result
+ })
+ });
+ }, error => Promise.reject(error)); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+ /**
+ * Decrypt data stored in "EncryptedContentInfo" object using parameters
+ * @param parameters
+ * @return {Promise}
+ */
+
+
+ decryptEncryptedContentInfo(parameters) {
+ //region Check for input parameters
+ if (parameters instanceof Object === false) return Promise.reject("Parameters must have type \"Object\"");
+ if ("password" in parameters === false) return Promise.reject("Absent mandatory parameter \"password\"");
+ if ("encryptedContentInfo" in parameters === false) return Promise.reject("Absent mandatory parameter \"encryptedContentInfo\"");
+ if (parameters.encryptedContentInfo.contentEncryptionAlgorithm.algorithmId !== "1.2.840.113549.1.5.13") // pkcs5PBES2
+ return Promise.reject(`Unknown "contentEncryptionAlgorithm": ${parameters.encryptedContentInfo.contentEncryptionAlgorithm.algorithmId}`); //endregion
+ //region Initial variables
+
+ let sequence = Promise.resolve();
+ let pbes2Parameters;
+
+ try {
+ pbes2Parameters = new _PBES2Params.default({
+ schema: parameters.encryptedContentInfo.contentEncryptionAlgorithm.algorithmParams
+ });
+ } catch (ex) {
+ return Promise.reject("Incorrectly encoded \"pbes2Parameters\"");
+ }
+
+ let pbkdf2Params;
+
+ try {
+ pbkdf2Params = new _PBKDF2Params.default({
+ schema: pbes2Parameters.keyDerivationFunc.algorithmParams
+ });
+ } catch (ex) {
+ return Promise.reject("Incorrectly encoded \"pbkdf2Params\"");
+ }
+
+ const contentEncryptionAlgorithm = this.getAlgorithmByOID(pbes2Parameters.encryptionScheme.algorithmId);
+ if ("name" in contentEncryptionAlgorithm === false) return Promise.reject(`Incorrect OID for "contentEncryptionAlgorithm": ${pbes2Parameters.encryptionScheme.algorithmId}`);
+ const ivBuffer = pbes2Parameters.encryptionScheme.algorithmParams.valueBlock.valueHex;
+ const ivView = new Uint8Array(ivBuffer);
+ const saltBuffer = pbkdf2Params.salt.valueBlock.valueHex;
+ const saltView = new Uint8Array(saltBuffer);
+ const iterationCount = pbkdf2Params.iterationCount;
+ let hmacHashAlgorithm = "SHA-1";
+
+ if ("prf" in pbkdf2Params) {
+ const algorithm = this.getAlgorithmByOID(pbkdf2Params.prf.algorithmId);
+ if ("name" in algorithm === false) return Promise.reject("Incorrect OID for HMAC hash algorithm");
+ hmacHashAlgorithm = algorithm.hash.name;
+ } //endregion
+ //region Derive PBKDF2 key from "password" buffer
+
+
+ sequence = sequence.then(() => this.importKey("raw", parameters.password, "PBKDF2", false, ["deriveKey"]), error => Promise.reject(error)); //endregion
+ //region Derive key for "contentEncryptionAlgorithm"
+
+ sequence = sequence.then(result => this.deriveKey({
+ name: "PBKDF2",
+ hash: {
+ name: hmacHashAlgorithm
+ },
+ salt: saltView,
+ iterations: iterationCount
+ }, result, contentEncryptionAlgorithm, false, ["decrypt"]), error => Promise.reject(error)); //endregion
+ //region Decrypt internal content using derived key
+
+ sequence = sequence.then(result => {
+ //region Create correct data block for decryption
+ let dataBuffer = new ArrayBuffer(0);
+ if (parameters.encryptedContentInfo.encryptedContent.idBlock.isConstructed === false) dataBuffer = parameters.encryptedContentInfo.encryptedContent.valueBlock.valueHex;else {
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = parameters.encryptedContentInfo.encryptedContent.valueBlock.value[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ const content = _step.value;
+ dataBuffer = (0, _pvutils.utilConcatBuf)(dataBuffer, content.valueBlock.valueHex);
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+ } //endregion
+
+ return this.decrypt({
+ name: contentEncryptionAlgorithm.name,
+ iv: ivView
+ }, result, dataBuffer);
+ }, error => Promise.reject(error)); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+ /**
+ * Stamping (signing) data using algorithm simular to HMAC
+ * @param {Object} parameters
+ * @return {Promise.<T>|Promise}
+ */
+
+
+ stampDataWithPassword(parameters) {
+ //region Check for input parameters
+ if (parameters instanceof Object === false) return Promise.reject("Parameters must have type \"Object\"");
+ if ("password" in parameters === false) return Promise.reject("Absent mandatory parameter \"password\"");
+ if ("hashAlgorithm" in parameters === false) return Promise.reject("Absent mandatory parameter \"hashAlgorithm\"");
+ if ("salt" in parameters === false) return Promise.reject("Absent mandatory parameter \"iterationCount\"");
+ if ("iterationCount" in parameters === false) return Promise.reject("Absent mandatory parameter \"salt\"");
+ if ("contentToStamp" in parameters === false) return Promise.reject("Absent mandatory parameter \"contentToStamp\""); //endregion
+ //region Choose correct length for HMAC key
+
+ let length;
+
+ switch (parameters.hashAlgorithm.toLowerCase()) {
+ case "sha-1":
+ length = 160;
+ break;
+
+ case "sha-256":
+ length = 256;
+ break;
+
+ case "sha-384":
+ length = 384;
+ break;
+
+ case "sha-512":
+ length = 512;
+ break;
+
+ default:
+ return Promise.reject(`Incorrect "parameters.hashAlgorithm" parameter: ${parameters.hashAlgorithm}`);
+ } //endregion
+ //region Initial variables
+
+
+ let sequence = Promise.resolve();
+ const hmacAlgorithm = {
+ name: "HMAC",
+ length,
+ hash: {
+ name: parameters.hashAlgorithm
+ }
+ }; //endregion
+ //region Create PKCS#12 key for integrity checking
+
+ sequence = sequence.then(() => makePKCS12B2Key(this, parameters.hashAlgorithm, length, parameters.password, parameters.salt, parameters.iterationCount)); //endregion
+ //region Import HMAC key
+ // noinspection JSCheckFunctionSignatures
+
+ sequence = sequence.then(result => this.importKey("raw", new Uint8Array(result), hmacAlgorithm, false, ["sign"])); //endregion
+ //region Make signed HMAC value
+
+ sequence = sequence.then(result => this.sign(hmacAlgorithm, result, new Uint8Array(parameters.contentToStamp)), error => Promise.reject(error)); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+
+ verifyDataStampedWithPassword(parameters) {
+ //region Check for input parameters
+ if (parameters instanceof Object === false) return Promise.reject("Parameters must have type \"Object\"");
+ if ("password" in parameters === false) return Promise.reject("Absent mandatory parameter \"password\"");
+ if ("hashAlgorithm" in parameters === false) return Promise.reject("Absent mandatory parameter \"hashAlgorithm\"");
+ if ("salt" in parameters === false) return Promise.reject("Absent mandatory parameter \"iterationCount\"");
+ if ("iterationCount" in parameters === false) return Promise.reject("Absent mandatory parameter \"salt\"");
+ if ("contentToVerify" in parameters === false) return Promise.reject("Absent mandatory parameter \"contentToVerify\"");
+ if ("signatureToVerify" in parameters === false) return Promise.reject("Absent mandatory parameter \"signatureToVerify\""); //endregion
+ //region Choose correct length for HMAC key
+
+ let length;
+
+ switch (parameters.hashAlgorithm.toLowerCase()) {
+ case "sha-1":
+ length = 160;
+ break;
+
+ case "sha-256":
+ length = 256;
+ break;
+
+ case "sha-384":
+ length = 384;
+ break;
+
+ case "sha-512":
+ length = 512;
+ break;
+
+ default:
+ return Promise.reject(`Incorrect "parameters.hashAlgorithm" parameter: ${parameters.hashAlgorithm}`);
+ } //endregion
+ //region Initial variables
+
+
+ let sequence = Promise.resolve();
+ const hmacAlgorithm = {
+ name: "HMAC",
+ length,
+ hash: {
+ name: parameters.hashAlgorithm
+ }
+ }; //endregion
+ //region Create PKCS#12 key for integrity checking
+
+ sequence = sequence.then(() => makePKCS12B2Key(this, parameters.hashAlgorithm, length, parameters.password, parameters.salt, parameters.iterationCount)); //endregion
+ //region Import HMAC key
+ // noinspection JSCheckFunctionSignatures
+
+ sequence = sequence.then(result => this.importKey("raw", new Uint8Array(result), hmacAlgorithm, false, ["verify"])); //endregion
+ //region Make signed HMAC value
+
+ sequence = sequence.then(result => this.verify(hmacAlgorithm, result, new Uint8Array(parameters.signatureToVerify), new Uint8Array(parameters.contentToVerify)), error => Promise.reject(error)); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+ /**
+ * Get signature parameters by analyzing private key algorithm
+ * @param {Object} privateKey The private key user would like to use
+ * @param {string} [hashAlgorithm="SHA-1"] Hash algorithm user would like to use
+ * @return {Promise.<T>|Promise}
+ */
+
+
+ getSignatureParameters(privateKey, hashAlgorithm = "SHA-1") {
+ //region Check hashing algorithm
+ const oid = this.getOIDByAlgorithm({
+ name: hashAlgorithm
+ });
+ if (oid === "") return Promise.reject(`Unsupported hash algorithm: ${hashAlgorithm}`); //endregion
+ //region Initial variables
+
+ const signatureAlgorithm = new _AlgorithmIdentifier.default(); //endregion
+ //region Get a "default parameters" for current algorithm
+
+ const parameters = this.getAlgorithmParameters(privateKey.algorithm.name, "sign");
+ parameters.algorithm.hash.name = hashAlgorithm; //endregion
+ //region Fill internal structures base on "privateKey" and "hashAlgorithm"
+
+ switch (privateKey.algorithm.name.toUpperCase()) {
+ case "RSASSA-PKCS1-V1_5":
+ case "ECDSA":
+ signatureAlgorithm.algorithmId = this.getOIDByAlgorithm(parameters.algorithm);
+ break;
+
+ case "RSA-PSS":
+ {
+ //region Set "saltLength" as a length (in octets) of hash function result
+ switch (hashAlgorithm.toUpperCase()) {
+ case "SHA-256":
+ parameters.algorithm.saltLength = 32;
+ break;
+
+ case "SHA-384":
+ parameters.algorithm.saltLength = 48;
+ break;
+
+ case "SHA-512":
+ parameters.algorithm.saltLength = 64;
+ break;
+
+ default:
+ } //endregion
+ //region Fill "RSASSA_PSS_params" object
+
+
+ const paramsObject = {};
+
+ if (hashAlgorithm.toUpperCase() !== "SHA-1") {
+ const hashAlgorithmOID = this.getOIDByAlgorithm({
+ name: hashAlgorithm
+ });
+ if (hashAlgorithmOID === "") return Promise.reject(`Unsupported hash algorithm: ${hashAlgorithm}`);
+ paramsObject.hashAlgorithm = new _AlgorithmIdentifier.default({
+ algorithmId: hashAlgorithmOID,
+ algorithmParams: new asn1js.Null()
+ });
+ paramsObject.maskGenAlgorithm = new _AlgorithmIdentifier.default({
+ algorithmId: "1.2.840.113549.1.1.8",
+ // MGF1
+ algorithmParams: paramsObject.hashAlgorithm.toSchema()
+ });
+ }
+
+ if (parameters.algorithm.saltLength !== 20) paramsObject.saltLength = parameters.algorithm.saltLength;
+ const pssParameters = new _RSASSAPSSParams.default(paramsObject); //endregion
+ //region Automatically set signature algorithm
+
+ signatureAlgorithm.algorithmId = "1.2.840.113549.1.1.10";
+ signatureAlgorithm.algorithmParams = pssParameters.toSchema(); //endregion
+ }
+ break;
+
+ default:
+ return Promise.reject(`Unsupported signature algorithm: ${privateKey.algorithm.name}`);
+ } //endregion
+
+
+ return Promise.resolve().then(() => ({
+ signatureAlgorithm,
+ parameters
+ }));
+ } //**********************************************************************************
+
+ /**
+ * Sign data with pre-defined private key
+ * @param {ArrayBuffer} data Data to be signed
+ * @param {Object} privateKey Private key to use
+ * @param {Object} parameters Parameters for used algorithm
+ * @return {Promise.<T>|Promise}
+ */
+
+
+ signWithPrivateKey(data, privateKey, parameters) {
+ return this.sign(parameters.algorithm, privateKey, new Uint8Array(data)).then(result => {
+ //region Special case for ECDSA algorithm
+ if (parameters.algorithm.name === "ECDSA") result = (0, _common.createCMSECDSASignature)(result); //endregion
+
+ return result;
+ }, error => Promise.reject(`Signing error: ${error}`));
+ } //**********************************************************************************
+
+
+ fillPublicKeyParameters(publicKeyInfo, signatureAlgorithm) {
+ const parameters = {}; //region Find signer's hashing algorithm
+
+ const shaAlgorithm = this.getHashAlgorithm(signatureAlgorithm);
+ if (shaAlgorithm === "") return Promise.reject(`Unsupported signature algorithm: ${signatureAlgorithm.algorithmId}`); //endregion
+ //region Get information about public key algorithm and default parameters for import
+
+ let algorithmId;
+ if (signatureAlgorithm.algorithmId === "1.2.840.113549.1.1.10") algorithmId = signatureAlgorithm.algorithmId;else algorithmId = publicKeyInfo.algorithm.algorithmId;
+ const algorithmObject = this.getAlgorithmByOID(algorithmId);
+ if ("name" in algorithmObject === "") return Promise.reject(`Unsupported public key algorithm: ${signatureAlgorithm.algorithmId}`);
+ parameters.algorithm = this.getAlgorithmParameters(algorithmObject.name, "importkey");
+ if ("hash" in parameters.algorithm.algorithm) parameters.algorithm.algorithm.hash.name = shaAlgorithm; //region Special case for ECDSA
+
+ if (algorithmObject.name === "ECDSA") {
+ //region Get information about named curve
+ let algorithmParamsChecked = false;
+
+ if ("algorithmParams" in publicKeyInfo.algorithm === true) {
+ if ("idBlock" in publicKeyInfo.algorithm.algorithmParams) {
+ if (publicKeyInfo.algorithm.algorithmParams.idBlock.tagClass === 1 && publicKeyInfo.algorithm.algorithmParams.idBlock.tagNumber === 6) algorithmParamsChecked = true;
+ }
+ }
+
+ if (algorithmParamsChecked === false) return Promise.reject("Incorrect type for ECDSA public key parameters");
+ const curveObject = this.getAlgorithmByOID(publicKeyInfo.algorithm.algorithmParams.valueBlock.toString());
+ if ("name" in curveObject === false) return Promise.reject(`Unsupported named curve algorithm: ${publicKeyInfo.algorithm.algorithmParams.valueBlock.toString()}`); //endregion
+
+ parameters.algorithm.algorithm.namedCurve = curveObject.name;
+ } //endregion
+ //endregion
+
+
+ return parameters;
+ } //**********************************************************************************
+
+
+ getPublicKey(publicKeyInfo, signatureAlgorithm, parameters = null) {
+ if (parameters === null) parameters = this.fillPublicKeyParameters(publicKeyInfo, signatureAlgorithm);
+ const publicKeyInfoSchema = publicKeyInfo.toSchema();
+ const publicKeyInfoBuffer = publicKeyInfoSchema.toBER(false);
+ const publicKeyInfoView = new Uint8Array(publicKeyInfoBuffer);
+ return this.importKey("spki", publicKeyInfoView, parameters.algorithm.algorithm, true, parameters.algorithm.usages);
+ } //**********************************************************************************
+
+
+ verifyWithPublicKey(data, signature, publicKeyInfo, signatureAlgorithm, shaAlgorithm = null) {
+ //region Initial variables
+ let sequence = Promise.resolve(); //endregion
+ //region Find signer's hashing algorithm
+
+ if (shaAlgorithm === null) {
+ shaAlgorithm = this.getHashAlgorithm(signatureAlgorithm);
+ if (shaAlgorithm === "") return Promise.reject(`Unsupported signature algorithm: ${signatureAlgorithm.algorithmId}`); //region Import public key
+
+ sequence = sequence.then(() => this.getPublicKey(publicKeyInfo, signatureAlgorithm)); //endregion
+ } else {
+ const parameters = {}; //region Get information about public key algorithm and default parameters for import
+
+ let algorithmId;
+ if (signatureAlgorithm.algorithmId === "1.2.840.113549.1.1.10") algorithmId = signatureAlgorithm.algorithmId;else algorithmId = publicKeyInfo.algorithm.algorithmId;
+ const algorithmObject = this.getAlgorithmByOID(algorithmId);
+ if ("name" in algorithmObject === "") return Promise.reject(`Unsupported public key algorithm: ${signatureAlgorithm.algorithmId}`);
+ parameters.algorithm = this.getAlgorithmParameters(algorithmObject.name, "importkey");
+ if ("hash" in parameters.algorithm.algorithm) parameters.algorithm.algorithm.hash.name = shaAlgorithm; //region Special case for ECDSA
+
+ if (algorithmObject.name === "ECDSA") {
+ //region Get information about named curve
+ let algorithmParamsChecked = false;
+
+ if ("algorithmParams" in publicKeyInfo.algorithm === true) {
+ if ("idBlock" in publicKeyInfo.algorithm.algorithmParams) {
+ if (publicKeyInfo.algorithm.algorithmParams.idBlock.tagClass === 1 && publicKeyInfo.algorithm.algorithmParams.idBlock.tagNumber === 6) algorithmParamsChecked = true;
+ }
+ }
+
+ if (algorithmParamsChecked === false) return Promise.reject("Incorrect type for ECDSA public key parameters");
+ const curveObject = this.getAlgorithmByOID(publicKeyInfo.algorithm.algorithmParams.valueBlock.toString());
+ if ("name" in curveObject === false) return Promise.reject(`Unsupported named curve algorithm: ${publicKeyInfo.algorithm.algorithmParams.valueBlock.toString()}`); //endregion
+
+ parameters.algorithm.algorithm.namedCurve = curveObject.name;
+ } //endregion
+ //endregion
+ //region Import public key
+
+
+ sequence = sequence.then(() => this.getPublicKey(publicKeyInfo, null, parameters)); //endregion
+ } //endregion
+ //region Verify signature
+
+
+ sequence = sequence.then(publicKey => {
+ //region Get default algorithm parameters for verification
+ const algorithm = this.getAlgorithmParameters(publicKey.algorithm.name, "verify");
+ if ("hash" in algorithm.algorithm) algorithm.algorithm.hash.name = shaAlgorithm; //endregion
+ //region Special case for ECDSA signatures
+
+ let signatureValue = signature.valueBlock.valueHex;
+
+ if (publicKey.algorithm.name === "ECDSA") {
+ const asn1 = asn1js.fromBER(signatureValue); // noinspection JSCheckFunctionSignatures
+
+ signatureValue = (0, _common.createECDSASignatureFromCMS)(asn1.result);
+ } //endregion
+ //region Special case for RSA-PSS
+
+
+ if (publicKey.algorithm.name === "RSA-PSS") {
+ let pssParameters;
+
+ try {
+ pssParameters = new _RSASSAPSSParams.default({
+ schema: signatureAlgorithm.algorithmParams
+ });
+ } catch (ex) {
+ return Promise.reject(ex);
+ }
+
+ if ("saltLength" in pssParameters) algorithm.algorithm.saltLength = pssParameters.saltLength;else algorithm.algorithm.saltLength = 20;
+ let hashAlgo = "SHA-1";
+
+ if ("hashAlgorithm" in pssParameters) {
+ const hashAlgorithm = this.getAlgorithmByOID(pssParameters.hashAlgorithm.algorithmId);
+ if ("name" in hashAlgorithm === false) return Promise.reject(`Unrecognized hash algorithm: ${pssParameters.hashAlgorithm.algorithmId}`);
+ hashAlgo = hashAlgorithm.name;
+ }
+
+ algorithm.algorithm.hash.name = hashAlgo;
+ } //endregion
+
+
+ return this.verify(algorithm.algorithm, publicKey, new Uint8Array(signatureValue), new Uint8Array(data));
+ }); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = CryptoEngine;
+
+},{"./AlgorithmIdentifier.js":4,"./EncryptedContentInfo.js":34,"./PBES2Params.js":65,"./PBKDF2Params.js":66,"./PrivateKeyInfo.js":76,"./PublicKeyInfo.js":78,"./RSASSAPSSParams.js":83,"./common.js":110,"asn1js":112,"pvutils":113}],28:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC3447
+ */
+class DigestInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for DigestInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc digestAlgorithm
+ */
+ this.digestAlgorithm = (0, _pvutils.getParametersValue)(parameters, "digestAlgorithm", DigestInfo.defaultValues("digestAlgorithm"));
+ /**
+ * @type {OctetString}
+ * @desc digest
+ */
+
+ this.digest = (0, _pvutils.getParametersValue)(parameters, "digest", DigestInfo.defaultValues("digest")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "digestAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "digest":
+ return new asn1js.OctetString();
+
+ default:
+ throw new Error(`Invalid member name for DigestInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "digestAlgorithm":
+ return _AlgorithmIdentifier.default.compareWithDefault("algorithmId", memberValue.algorithmId) && "algorithmParams" in memberValue === false;
+
+ case "digest":
+ return memberValue.isEqual(DigestInfo.defaultValues(memberName));
+
+ default:
+ throw new Error(`Invalid member name for DigestInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * digest Digest }
+ *
+ * Digest ::= OCTET STRING
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [type]
+ * @property {string} [setName]
+ * @property {string} [values]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [_AlgorithmIdentifier.default.schema(names.digestAlgorithm || {
+ names: {
+ blockName: "digestAlgorithm"
+ }
+ }), new asn1js.OctetString({
+ name: names.digest || "digest"
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["digestAlgorithm", "digest"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, DigestInfo.schema({
+ names: {
+ digestAlgorithm: {
+ names: {
+ blockName: "digestAlgorithm"
+ }
+ },
+ digest: "digest"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for DigestInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.digestAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.digestAlgorithm
+ });
+ this.digest = asn1.result.digest; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [this.digestAlgorithm.toSchema(), this.digest]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ digestAlgorithm: this.digestAlgorithm.toJSON(),
+ digest: this.digest.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = DigestInfo;
+
+},{"./AlgorithmIdentifier.js":4,"asn1js":112,"pvutils":113}],29:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _GeneralName = _interopRequireDefault(require("./GeneralName.js"));
+
+var _RelativeDistinguishedNames = _interopRequireDefault(require("./RelativeDistinguishedNames.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class DistributionPoint {
+ //**********************************************************************************
+
+ /**
+ * Constructor for DistributionPoint class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ * @property {Object} [distributionPoint]
+ * @property {Object} [reasons]
+ * @property {Object} [cRLIssuer]
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+ if ("distributionPoint" in parameters)
+ /**
+ * @type {Array.<GeneralName>}
+ * @desc distributionPoint
+ */
+ this.distributionPoint = (0, _pvutils.getParametersValue)(parameters, "distributionPoint", DistributionPoint.defaultValues("distributionPoint"));
+ if ("reasons" in parameters)
+ /**
+ * @type {BitString}
+ * @desc values
+ */
+ this.reasons = (0, _pvutils.getParametersValue)(parameters, "reasons", DistributionPoint.defaultValues("reasons"));
+ if ("cRLIssuer" in parameters)
+ /**
+ * @type {Array.<GeneralName>}
+ * @desc cRLIssuer
+ */
+ this.cRLIssuer = (0, _pvutils.getParametersValue)(parameters, "cRLIssuer", DistributionPoint.defaultValues("cRLIssuer")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "distributionPoint":
+ return [];
+
+ case "reasons":
+ return new asn1js.BitString();
+
+ case "cRLIssuer":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for DistributionPoint class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * DistributionPoint ::= SEQUENCE {
+ * distributionPoint [0] DistributionPointName OPTIONAL,
+ * reasons [1] ReasonFlags OPTIONAL,
+ * cRLIssuer [2] GeneralNames OPTIONAL }
+ *
+ * DistributionPointName ::= CHOICE {
+ * fullName [0] GeneralNames,
+ * nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
+ *
+ * ReasonFlags ::= BIT STRING {
+ * unused (0),
+ * keyCompromise (1),
+ * cACompromise (2),
+ * affiliationChanged (3),
+ * superseded (4),
+ * cessationOfOperation (5),
+ * certificateHold (6),
+ * privilegeWithdrawn (7),
+ * aACompromise (8) }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [distributionPoint]
+ * @property {string} [distributionPointNames]
+ * @property {string} [reasons]
+ * @property {string} [cRLIssuer]
+ * @property {string} [cRLIssuerNames]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Choice({
+ value: [new asn1js.Constructed({
+ name: names.distributionPoint || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Repeated({
+ name: names.distributionPointNames || "",
+ value: _GeneralName.default.schema()
+ })]
+ }), new asn1js.Constructed({
+ name: names.distributionPoint || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: _RelativeDistinguishedNames.default.schema().valueBlock.value
+ })]
+ })]
+ }), new asn1js.Primitive({
+ name: names.reasons || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ }
+ }), // IMPLICIT bitstring value
+ new asn1js.Constructed({
+ name: names.cRLIssuer || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ value: [new asn1js.Repeated({
+ name: names.cRLIssuerNames || "",
+ value: _GeneralName.default.schema()
+ })]
+ }) // IMPLICIT bitstring value
+ ]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["distributionPoint", "distributionPointNames", "reasons", "cRLIssuer", "cRLIssuerNames"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, DistributionPoint.schema({
+ names: {
+ distributionPoint: "distributionPoint",
+ distributionPointNames: "distributionPointNames",
+ reasons: "reasons",
+ cRLIssuer: "cRLIssuer",
+ cRLIssuerNames: "cRLIssuerNames"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for DistributionPoint"); //endregion
+ //region Get internal properties from parsed schema
+
+ if ("distributionPoint" in asn1.result) {
+ if (asn1.result.distributionPoint.idBlock.tagNumber === 0) // GENERAL_NAMES variant
+ this.distributionPoint = Array.from(asn1.result.distributionPointNames, element => new _GeneralName.default({
+ schema: element
+ }));
+
+ if (asn1.result.distributionPoint.idBlock.tagNumber === 1) // RDN variant
+ {
+ this.distributionPoint = new _RelativeDistinguishedNames.default({
+ schema: new asn1js.Sequence({
+ value: asn1.result.distributionPoint.valueBlock.value
+ })
+ });
+ }
+ }
+
+ if ("reasons" in asn1.result) this.reasons = new asn1js.BitString({
+ valueHex: asn1.result.reasons.valueBlock.valueHex
+ });
+ if ("cRLIssuer" in asn1.result) this.cRLIssuer = Array.from(asn1.result.cRLIssuerNames, element => new _GeneralName.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+
+ if ("distributionPoint" in this) {
+ let internalValue;
+
+ if (this.distributionPoint instanceof Array) {
+ internalValue = new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: Array.from(this.distributionPoint, element => element.toSchema())
+ });
+ } else {
+ internalValue = new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [this.distributionPoint.toSchema()]
+ });
+ }
+
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [internalValue]
+ }));
+ }
+
+ if ("reasons" in this) {
+ outputArray.push(new asn1js.Primitive({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ valueHex: this.reasons.valueBlock.valueHex
+ }));
+ }
+
+ if ("cRLIssuer" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ value: Array.from(this.cRLIssuer, element => element.toSchema())
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {};
+
+ if ("distributionPoint" in this) {
+ if (this.distributionPoint instanceof Array) object.distributionPoint = Array.from(this.distributionPoint, element => element.toJSON());else object.distributionPoint = this.distributionPoint.toJSON();
+ }
+
+ if ("reasons" in this) object.reasons = this.reasons.toJSON();
+ if ("cRLIssuer" in this) object.cRLIssuer = Array.from(this.cRLIssuer, element => element.toJSON());
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = DistributionPoint;
+
+},{"./GeneralName.js":40,"./RelativeDistinguishedNames.js":89,"asn1js":112,"pvutils":113}],30:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC6318
+ */
+class ECCCMSSharedInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for ECCCMSSharedInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc keyInfo
+ */
+ this.keyInfo = (0, _pvutils.getParametersValue)(parameters, "keyInfo", ECCCMSSharedInfo.defaultValues("keyInfo"));
+ if ("entityUInfo" in parameters)
+ /**
+ * @type {OctetString}
+ * @desc entityUInfo
+ */
+ this.entityUInfo = (0, _pvutils.getParametersValue)(parameters, "entityUInfo", ECCCMSSharedInfo.defaultValues("entityUInfo"));
+ /**
+ * @type {OctetString}
+ * @desc suppPubInfo
+ */
+
+ this.suppPubInfo = (0, _pvutils.getParametersValue)(parameters, "suppPubInfo", ECCCMSSharedInfo.defaultValues("suppPubInfo")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "keyInfo":
+ return new _AlgorithmIdentifier.default();
+
+ case "entityUInfo":
+ return new asn1js.OctetString();
+
+ case "suppPubInfo":
+ return new asn1js.OctetString();
+
+ default:
+ throw new Error(`Invalid member name for ECCCMSSharedInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "keyInfo":
+ case "entityUInfo":
+ case "suppPubInfo":
+ return memberValue.isEqual(ECCCMSSharedInfo.defaultValues(memberName));
+
+ default:
+ throw new Error(`Invalid member name for ECCCMSSharedInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * ECC-CMS-SharedInfo ::= SEQUENCE {
+ * keyInfo AlgorithmIdentifier,
+ * entityUInfo [0] EXPLICIT OCTET STRING OPTIONAL,
+ * suppPubInfo [2] EXPLICIT OCTET STRING }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [keyInfo]
+ * @property {string} [entityUInfo]
+ * @property {string} [suppPubInfo]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [_AlgorithmIdentifier.default.schema(names.keyInfo || {}), new asn1js.Constructed({
+ name: names.entityUInfo || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ optional: true,
+ value: [new asn1js.OctetString()]
+ }), new asn1js.Constructed({
+ name: names.suppPubInfo || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ value: [new asn1js.OctetString()]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["keyInfo", "entityUInfo", "suppPubInfo"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, ECCCMSSharedInfo.schema({
+ names: {
+ keyInfo: {
+ names: {
+ blockName: "keyInfo"
+ }
+ },
+ entityUInfo: "entityUInfo",
+ suppPubInfo: "suppPubInfo"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for ECCCMSSharedInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.keyInfo = new _AlgorithmIdentifier.default({
+ schema: asn1.result.keyInfo
+ });
+ if ("entityUInfo" in asn1.result) this.entityUInfo = asn1.result.entityUInfo.valueBlock.value[0];
+ this.suppPubInfo = asn1.result.suppPubInfo.valueBlock.value[0]; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create output array for sequence
+ const outputArray = [];
+ outputArray.push(this.keyInfo.toSchema());
+
+ if ("entityUInfo" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [this.entityUInfo]
+ }));
+ }
+
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ value: [this.suppPubInfo]
+ })); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ keyInfo: this.keyInfo.toJSON()
+ };
+ if ("entityUInfo" in this) _object.entityUInfo = this.entityUInfo.toJSON();
+ _object.suppPubInfo = this.suppPubInfo.toJSON();
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = ECCCMSSharedInfo;
+
+},{"./AlgorithmIdentifier.js":4,"asn1js":112,"pvutils":113}],31:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _ECPublicKey = _interopRequireDefault(require("./ECPublicKey.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5915
+ */
+class ECPrivateKey {
+ //**********************************************************************************
+
+ /**
+ * Constructor for ECPrivateKey class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", ECPrivateKey.defaultValues("version"));
+ /**
+ * @type {OctetString}
+ * @desc privateKey
+ */
+
+ this.privateKey = (0, _pvutils.getParametersValue)(parameters, "privateKey", ECPrivateKey.defaultValues("privateKey"));
+ if ("namedCurve" in parameters)
+ /**
+ * @type {string}
+ * @desc namedCurve
+ */
+ this.namedCurve = (0, _pvutils.getParametersValue)(parameters, "namedCurve", ECPrivateKey.defaultValues("namedCurve"));
+ if ("publicKey" in parameters)
+ /**
+ * @type {ECPublicKey}
+ * @desc publicKey
+ */
+ this.publicKey = (0, _pvutils.getParametersValue)(parameters, "publicKey", ECPrivateKey.defaultValues("publicKey")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ //region If input argument array contains "json" for this object
+
+ if ("json" in parameters) this.fromJSON(parameters.json); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return 1;
+
+ case "privateKey":
+ return new asn1js.OctetString();
+
+ case "namedCurve":
+ return "";
+
+ case "publicKey":
+ return new _ECPublicKey.default();
+
+ default:
+ throw new Error(`Invalid member name for ECCPrivateKey class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "version":
+ return memberValue === ECPrivateKey.defaultValues(memberName);
+
+ case "privateKey":
+ return memberValue.isEqual(ECPrivateKey.defaultValues(memberName));
+
+ case "namedCurve":
+ return memberValue === "";
+
+ case "publicKey":
+ return _ECPublicKey.default.compareWithDefault("namedCurve", memberValue.namedCurve) && _ECPublicKey.default.compareWithDefault("x", memberValue.x) && _ECPublicKey.default.compareWithDefault("y", memberValue.y);
+
+ default:
+ throw new Error(`Invalid member name for ECCPrivateKey class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * ECPrivateKey ::= SEQUENCE {
+ * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+ * privateKey OCTET STRING,
+ * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
+ * publicKey [1] BIT STRING OPTIONAL
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [version]
+ * @property {string} [privateKey]
+ * @property {string} [namedCurve]
+ * @property {string} [publicKey]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Integer({
+ name: names.version || ""
+ }), new asn1js.OctetString({
+ name: names.privateKey || ""
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.ObjectIdentifier({
+ name: names.namedCurve || ""
+ })]
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [new asn1js.BitString({
+ name: names.publicKey || ""
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["version", "privateKey", "namedCurve", "publicKey"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, ECPrivateKey.schema({
+ names: {
+ version: "version",
+ privateKey: "privateKey",
+ namedCurve: "namedCurve",
+ publicKey: "publicKey"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for ECPrivateKey"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.version = asn1.result.version.valueBlock.valueDec;
+ this.privateKey = asn1.result.privateKey;
+ if ("namedCurve" in asn1.result) this.namedCurve = asn1.result.namedCurve.valueBlock.toString();
+
+ if ("publicKey" in asn1.result) {
+ const publicKeyData = {
+ schema: asn1.result.publicKey.valueBlock.valueHex
+ };
+ if ("namedCurve" in this) publicKeyData.namedCurve = this.namedCurve;
+ this.publicKey = new _ECPublicKey.default(publicKeyData);
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ const outputArray = [new asn1js.Integer({
+ value: this.version
+ }), this.privateKey];
+
+ if ("namedCurve" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.ObjectIdentifier({
+ value: this.namedCurve
+ })]
+ }));
+ }
+
+ if ("publicKey" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [new asn1js.BitString({
+ valueHex: this.publicKey.toSchema().toBER(false)
+ })]
+ }));
+ }
+
+ return new asn1js.Sequence({
+ value: outputArray
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ if ("namedCurve" in this === false || ECPrivateKey.compareWithDefault("namedCurve", this.namedCurve)) throw new Error("Not enough information for making JSON: absent \"namedCurve\" value");
+ let crvName = "";
+
+ switch (this.namedCurve) {
+ case "1.2.840.10045.3.1.7":
+ // P-256
+ crvName = "P-256";
+ break;
+
+ case "1.3.132.0.34":
+ // P-384
+ crvName = "P-384";
+ break;
+
+ case "1.3.132.0.35":
+ // P-521
+ crvName = "P-521";
+ break;
+
+ default:
+ }
+
+ const privateKeyJSON = {
+ crv: crvName,
+ d: (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(this.privateKey.valueBlock.valueHex), true, true, false)
+ };
+
+ if ("publicKey" in this) {
+ const publicKeyJSON = this.publicKey.toJSON();
+ privateKeyJSON.x = publicKeyJSON.x;
+ privateKeyJSON.y = publicKeyJSON.y;
+ }
+
+ return privateKeyJSON;
+ } //**********************************************************************************
+
+ /**
+ * Convert JSON value into current object
+ * @param {Object} json
+ */
+
+
+ fromJSON(json) {
+ let coodinateLength = 0;
+
+ if ("crv" in json) {
+ switch (json.crv.toUpperCase()) {
+ case "P-256":
+ this.namedCurve = "1.2.840.10045.3.1.7";
+ coodinateLength = 32;
+ break;
+
+ case "P-384":
+ this.namedCurve = "1.3.132.0.34";
+ coodinateLength = 48;
+ break;
+
+ case "P-521":
+ this.namedCurve = "1.3.132.0.35";
+ coodinateLength = 66;
+ break;
+
+ default:
+ }
+ } else throw new Error("Absent mandatory parameter \"crv\"");
+
+ if ("d" in json) {
+ const convertBuffer = (0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(json.d, true));
+
+ if (convertBuffer.byteLength < coodinateLength) {
+ const buffer = new ArrayBuffer(coodinateLength);
+ const view = new Uint8Array(buffer);
+ const convertBufferView = new Uint8Array(convertBuffer);
+ view.set(convertBufferView, 1);
+ this.privateKey = new asn1js.OctetString({
+ valueHex: buffer
+ });
+ } else this.privateKey = new asn1js.OctetString({
+ valueHex: convertBuffer.slice(0, coodinateLength)
+ });
+ } else throw new Error("Absent mandatory parameter \"d\"");
+
+ if ("x" in json && "y" in json) this.publicKey = new _ECPublicKey.default({
+ json
+ });
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = ECPrivateKey;
+
+},{"./ECPublicKey.js":32,"asn1js":112,"pvutils":113}],32:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5480
+ */
+class ECPublicKey {
+ //**********************************************************************************
+
+ /**
+ * Constructor for ECCPublicKey class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {ArrayBuffer}
+ * @desc type
+ */
+ this.x = (0, _pvutils.getParametersValue)(parameters, "x", ECPublicKey.defaultValues("x"));
+ /**
+ * @type {ArrayBuffer}
+ * @desc values
+ */
+
+ this.y = (0, _pvutils.getParametersValue)(parameters, "y", ECPublicKey.defaultValues("y"));
+ /**
+ * @type {string}
+ * @desc namedCurve
+ */
+
+ this.namedCurve = (0, _pvutils.getParametersValue)(parameters, "namedCurve", ECPublicKey.defaultValues("namedCurve")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ //region If input argument array contains "json" for this object
+
+ if ("json" in parameters) this.fromJSON(parameters.json); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "x":
+ case "y":
+ return new ArrayBuffer(0);
+
+ case "namedCurve":
+ return "";
+
+ default:
+ throw new Error(`Invalid member name for ECCPublicKey class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "x":
+ case "y":
+ return (0, _pvutils.isEqualBuffer)(memberValue, ECPublicKey.defaultValues(memberName));
+
+ case "namedCurve":
+ return memberValue === "";
+
+ default:
+ throw new Error(`Invalid member name for ECCPublicKey class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ return new asn1js.RawData();
+ } //**********************************************************************************
+
+ /**
+ * Convert ArrayBuffer into current class
+ * @param {!ArrayBuffer} schema Special case: schema is an ArrayBuffer
+ */
+
+
+ fromSchema(schema) {
+ //region Check the schema is valid
+ if (schema instanceof ArrayBuffer === false) throw new Error("Object's schema was not verified against input data for ECPublicKey");
+ const view = new Uint8Array(schema);
+ if (view[0] !== 0x04) throw new Error("Object's schema was not verified against input data for ECPublicKey"); //endregion
+ //region Get internal properties from parsed schema
+
+ let coordinateLength;
+
+ switch (this.namedCurve) {
+ case "1.2.840.10045.3.1.7":
+ // P-256
+ coordinateLength = 32;
+ break;
+
+ case "1.3.132.0.34":
+ // P-384
+ coordinateLength = 48;
+ break;
+
+ case "1.3.132.0.35":
+ // P-521
+ coordinateLength = 66;
+ break;
+
+ default:
+ throw new Error(`Incorrect curve OID: ${this.namedCurve}`);
+ }
+
+ if (schema.byteLength !== coordinateLength * 2 + 1) throw new Error("Object's schema was not verified against input data for ECPublicKey");
+ this.x = schema.slice(1, coordinateLength + 1);
+ this.y = schema.slice(1 + coordinateLength, coordinateLength * 2 + 1); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ return new asn1js.RawData({
+ data: (0, _pvutils.utilConcatBuf)(new Uint8Array([0x04]).buffer, this.x, this.y)
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ let crvName = "";
+
+ switch (this.namedCurve) {
+ case "1.2.840.10045.3.1.7":
+ // P-256
+ crvName = "P-256";
+ break;
+
+ case "1.3.132.0.34":
+ // P-384
+ crvName = "P-384";
+ break;
+
+ case "1.3.132.0.35":
+ // P-521
+ crvName = "P-521";
+ break;
+
+ default:
+ }
+
+ return {
+ crv: crvName,
+ x: (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(this.x), true, true, false),
+ y: (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(this.y), true, true, false)
+ };
+ } //**********************************************************************************
+
+ /**
+ * Convert JSON value into current object
+ * @param {Object} json
+ */
+
+
+ fromJSON(json) {
+ let coodinateLength = 0;
+
+ if ("crv" in json) {
+ switch (json.crv.toUpperCase()) {
+ case "P-256":
+ this.namedCurve = "1.2.840.10045.3.1.7";
+ coodinateLength = 32;
+ break;
+
+ case "P-384":
+ this.namedCurve = "1.3.132.0.34";
+ coodinateLength = 48;
+ break;
+
+ case "P-521":
+ this.namedCurve = "1.3.132.0.35";
+ coodinateLength = 66;
+ break;
+
+ default:
+ }
+ } else throw new Error("Absent mandatory parameter \"crv\"");
+
+ if ("x" in json) {
+ const convertBuffer = (0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(json.x, true));
+
+ if (convertBuffer.byteLength < coodinateLength) {
+ this.x = new ArrayBuffer(coodinateLength);
+ const view = new Uint8Array(this.x);
+ const convertBufferView = new Uint8Array(convertBuffer);
+ view.set(convertBufferView, 1);
+ } else this.x = convertBuffer.slice(0, coodinateLength);
+ } else throw new Error("Absent mandatory parameter \"x\"");
+
+ if ("y" in json) {
+ const convertBuffer = (0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(json.y, true));
+
+ if (convertBuffer.byteLength < coodinateLength) {
+ this.y = new ArrayBuffer(coodinateLength);
+ const view = new Uint8Array(this.y);
+ const convertBufferView = new Uint8Array(convertBuffer);
+ view.set(convertBufferView, 1);
+ } else this.y = convertBuffer.slice(0, coodinateLength);
+ } else throw new Error("Absent mandatory parameter \"y\"");
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = ECPublicKey;
+
+},{"asn1js":112,"pvutils":113}],33:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class EncapsulatedContentInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for EncapsulatedContentInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc eContentType
+ */
+ this.eContentType = (0, _pvutils.getParametersValue)(parameters, "eContentType", EncapsulatedContentInfo.defaultValues("eContentType"));
+
+ if ("eContent" in parameters) {
+ /**
+ * @type {OctetString}
+ * @desc eContent
+ */
+ this.eContent = (0, _pvutils.getParametersValue)(parameters, "eContent", EncapsulatedContentInfo.defaultValues("eContent"));
+
+ if (this.eContent.idBlock.tagClass === 1 && this.eContent.idBlock.tagNumber === 4) {
+ //region Divide OCTETSTRING value down to small pieces
+ if (this.eContent.idBlock.isConstructed === false) {
+ const constrString = new asn1js.OctetString({
+ idBlock: {
+ isConstructed: true
+ },
+ isConstructed: true
+ });
+ let offset = 0;
+ let length = this.eContent.valueBlock.valueHex.byteLength;
+
+ while (length > 0) {
+ const pieceView = new Uint8Array(this.eContent.valueBlock.valueHex, offset, offset + 65536 > this.eContent.valueBlock.valueHex.byteLength ? this.eContent.valueBlock.valueHex.byteLength - offset : 65536);
+
+ const _array = new ArrayBuffer(pieceView.length);
+
+ const _view = new Uint8Array(_array);
+
+ for (let i = 0; i < _view.length; i++) _view[i] = pieceView[i];
+
+ constrString.valueBlock.value.push(new asn1js.OctetString({
+ valueHex: _array
+ }));
+ length -= pieceView.length;
+ offset += pieceView.length;
+ }
+
+ this.eContent = constrString;
+ } //endregion
+
+ }
+ } //endregion
+ //region If input argument array contains "schema" for this object
+
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "eContentType":
+ return "";
+
+ case "eContent":
+ return new asn1js.OctetString();
+
+ default:
+ throw new Error(`Invalid member name for EncapsulatedContentInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "eContentType":
+ return memberValue === "";
+
+ case "eContent":
+ {
+ if (memberValue.idBlock.tagClass === 1 && memberValue.idBlock.tagNumber === 4) return memberValue.isEqual(EncapsulatedContentInfo.defaultValues("eContent"));
+ return false;
+ }
+
+ default:
+ throw new Error(`Invalid member name for EncapsulatedContentInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * EncapsulatedContentInfo ::= SEQUENCE {
+ * eContentType ContentType,
+ * eContent [0] EXPLICIT OCTET STRING OPTIONAL } * Changed it to ANY, as in PKCS#7
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [type]
+ * @property {string} [setName]
+ * @property {string} [values]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.eContentType || ""
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Any({
+ name: names.eContent || ""
+ }) // In order to aling this with PKCS#7 and CMS as well
+ ]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["eContentType", "eContent"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, EncapsulatedContentInfo.schema({
+ names: {
+ eContentType: "eContentType",
+ eContent: "eContent"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for EncapsulatedContentInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.eContentType = asn1.result.eContentType.valueBlock.toString();
+ if ("eContent" in asn1.result) this.eContent = asn1.result.eContent; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(new asn1js.ObjectIdentifier({
+ value: this.eContentType
+ }));
+
+ if ("eContent" in this) {
+ if (EncapsulatedContentInfo.compareWithDefault("eContent", this.eContent) === false) {
+ outputArray.push(new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [this.eContent]
+ }));
+ }
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ eContentType: this.eContentType
+ };
+
+ if ("eContent" in this) {
+ if (EncapsulatedContentInfo.compareWithDefault("eContent", this.eContent) === false) _object.eContent = this.eContent.toJSON();
+ }
+
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = EncapsulatedContentInfo;
+
+},{"asn1js":112,"pvutils":113}],34:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class EncryptedContentInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for EncryptedContentInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc contentType
+ */
+ this.contentType = (0, _pvutils.getParametersValue)(parameters, "contentType", EncryptedContentInfo.defaultValues("contentType"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc contentEncryptionAlgorithm
+ */
+
+ this.contentEncryptionAlgorithm = (0, _pvutils.getParametersValue)(parameters, "contentEncryptionAlgorithm", EncryptedContentInfo.defaultValues("contentEncryptionAlgorithm"));
+
+ if ("encryptedContent" in parameters) {
+ /**
+ * @type {OctetString}
+ * @desc encryptedContent (!!!) could be contructive or primitive value (!!!)
+ */
+ this.encryptedContent = parameters.encryptedContent;
+
+ if (this.encryptedContent.idBlock.tagClass === 1 && this.encryptedContent.idBlock.tagNumber === 4) {
+ //region Divide OCTETSTRING value down to small pieces
+ if (this.encryptedContent.idBlock.isConstructed === false) {
+ const constrString = new asn1js.OctetString({
+ idBlock: {
+ isConstructed: true
+ },
+ isConstructed: true
+ });
+ let offset = 0;
+ let length = this.encryptedContent.valueBlock.valueHex.byteLength;
+
+ while (length > 0) {
+ const pieceView = new Uint8Array(this.encryptedContent.valueBlock.valueHex, offset, offset + 1024 > this.encryptedContent.valueBlock.valueHex.byteLength ? this.encryptedContent.valueBlock.valueHex.byteLength - offset : 1024);
+
+ const _array = new ArrayBuffer(pieceView.length);
+
+ const _view = new Uint8Array(_array);
+
+ for (let i = 0; i < _view.length; i++) _view[i] = pieceView[i];
+
+ constrString.valueBlock.value.push(new asn1js.OctetString({
+ valueHex: _array
+ }));
+ length -= pieceView.length;
+ offset += pieceView.length;
+ }
+
+ this.encryptedContent = constrString;
+ } //endregion
+
+ }
+ } //endregion
+ //region If input argument array contains "schema" for this object
+
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "contentType":
+ return "";
+
+ case "contentEncryptionAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "encryptedContent":
+ return new asn1js.OctetString();
+
+ default:
+ throw new Error(`Invalid member name for EncryptedContentInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "contentType":
+ return memberValue === "";
+
+ case "contentEncryptionAlgorithm":
+ return memberValue.algorithmId === "" && "algorithmParams" in memberValue === false;
+
+ case "encryptedContent":
+ return memberValue.isEqual(EncryptedContentInfo.defaultValues(memberName));
+
+ default:
+ throw new Error(`Invalid member name for EncryptedContentInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * EncryptedContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+ * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
+ *
+ * Comment: Strange, but modern crypto engines create "encryptedContent" as "[0] EXPLICIT EncryptedContent"
+ *
+ * EncryptedContent ::= OCTET STRING
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [contentType]
+ * @property {string} [contentEncryptionAlgorithm]
+ * @property {string} [encryptedContent]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.contentType || ""
+ }), _AlgorithmIdentifier.default.schema(names.contentEncryptionAlgorithm || {}), // The CHOICE we need because "EncryptedContent" could have either "constructive"
+ // or "primitive" form of encoding and we need to handle both variants
+ new asn1js.Choice({
+ value: [new asn1js.Constructed({
+ name: names.encryptedContent || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Repeated({
+ value: new asn1js.OctetString()
+ })]
+ }), new asn1js.Primitive({
+ name: names.encryptedContent || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ }
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["contentType", "contentEncryptionAlgorithm", "encryptedContent"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, EncryptedContentInfo.schema({
+ names: {
+ contentType: "contentType",
+ contentEncryptionAlgorithm: {
+ names: {
+ blockName: "contentEncryptionAlgorithm"
+ }
+ },
+ encryptedContent: "encryptedContent"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for EncryptedContentInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.contentType = asn1.result.contentType.valueBlock.toString();
+ this.contentEncryptionAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.contentEncryptionAlgorithm
+ });
+
+ if ("encryptedContent" in asn1.result) {
+ this.encryptedContent = asn1.result.encryptedContent;
+ this.encryptedContent.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.encryptedContent.idBlock.tagNumber = 4; // OCTETSTRING (!!!) The value still has instance of "in_window.org.pkijs.asn1.ASN1_CONSTRUCTED / ASN1_PRIMITIVE"
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const sequenceLengthBlock = {
+ isIndefiniteForm: false
+ };
+ const outputArray = [];
+ outputArray.push(new asn1js.ObjectIdentifier({
+ value: this.contentType
+ }));
+ outputArray.push(this.contentEncryptionAlgorithm.toSchema());
+
+ if ("encryptedContent" in this) {
+ sequenceLengthBlock.isIndefiniteForm = this.encryptedContent.idBlock.isConstructed;
+ const encryptedValue = this.encryptedContent;
+ encryptedValue.idBlock.tagClass = 3; // CONTEXT-SPECIFIC
+
+ encryptedValue.idBlock.tagNumber = 0; // [0]
+
+ encryptedValue.lenBlock.isIndefiniteForm = this.encryptedContent.idBlock.isConstructed;
+ outputArray.push(encryptedValue);
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ lenBlock: sequenceLengthBlock,
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ contentType: this.contentType,
+ contentEncryptionAlgorithm: this.contentEncryptionAlgorithm.toJSON()
+ };
+ if ("encryptedContent" in this) _object.encryptedContent = this.encryptedContent.toJSON();
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = EncryptedContentInfo;
+
+},{"./AlgorithmIdentifier.js":4,"asn1js":112,"pvutils":113}],35:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _common = require("./common.js");
+
+var _EncryptedContentInfo = _interopRequireDefault(require("./EncryptedContentInfo.js"));
+
+var _Attribute = _interopRequireDefault(require("./Attribute.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class EncryptedData {
+ //**********************************************************************************
+
+ /**
+ * Constructor for EncryptedData class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", EncryptedData.defaultValues("version"));
+ /**
+ * @type {EncryptedContentInfo}
+ * @desc encryptedContentInfo
+ */
+
+ this.encryptedContentInfo = (0, _pvutils.getParametersValue)(parameters, "encryptedContentInfo", EncryptedData.defaultValues("encryptedContentInfo"));
+ if ("unprotectedAttrs" in parameters)
+ /**
+ * @type {Array.<Attribute>}
+ * @desc unprotectedAttrs
+ */
+ this.unprotectedAttrs = (0, _pvutils.getParametersValue)(parameters, "unprotectedAttrs", EncryptedData.defaultValues("unprotectedAttrs")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return 0;
+
+ case "encryptedContentInfo":
+ return new _EncryptedContentInfo.default();
+
+ case "unprotectedAttrs":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for EncryptedData class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "version":
+ return memberValue === 0;
+
+ case "encryptedContentInfo":
+ return _EncryptedContentInfo.default.compareWithDefault("contentType", memberValue.contentType) && _EncryptedContentInfo.default.compareWithDefault("contentEncryptionAlgorithm", memberValue.contentEncryptionAlgorithm) && _EncryptedContentInfo.default.compareWithDefault("encryptedContent", memberValue.encryptedContent);
+
+ case "unprotectedAttrs":
+ return memberValue.length === 0;
+
+ default:
+ throw new Error(`Invalid member name for EncryptedData class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * EncryptedData ::= SEQUENCE {
+ * version CMSVersion,
+ * encryptedContentInfo EncryptedContentInfo,
+ * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [version]
+ * @property {string} [encryptedContentInfo]
+ * @property {string} [unprotectedAttrs]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Integer({
+ name: names.version || ""
+ }), _EncryptedContentInfo.default.schema(names.encryptedContentInfo || {}), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [new asn1js.Repeated({
+ name: names.unprotectedAttrs || "",
+ value: _Attribute.default.schema()
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["version", "encryptedContentInfo", "unprotectedAttrs"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, EncryptedData.schema({
+ names: {
+ version: "version",
+ encryptedContentInfo: {
+ names: {
+ blockName: "encryptedContentInfo"
+ }
+ },
+ unprotectedAttrs: "unprotectedAttrs"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for EncryptedData"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.version = asn1.result.version.valueBlock.valueDec;
+ this.encryptedContentInfo = new _EncryptedContentInfo.default({
+ schema: asn1.result.encryptedContentInfo
+ });
+ if ("unprotectedAttrs" in asn1.result) this.unprotectedAttrs = Array.from(asn1.result.unprotectedAttrs, element => new _Attribute.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(new asn1js.Integer({
+ value: this.version
+ }));
+ outputArray.push(this.encryptedContentInfo.toSchema());
+
+ if ("unprotectedAttrs" in this) {
+ outputArray.push(new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: Array.from(this.unprotectedAttrs, element => element.toSchema())
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ version: this.version,
+ encryptedContentInfo: this.encryptedContentInfo.toJSON()
+ };
+ if ("unprotectedAttrs" in this) _object.unprotectedAttrs = Array.from(this.unprotectedAttrs, element => element.toJSON());
+ return _object;
+ } //**********************************************************************************
+
+ /**
+ * Create a new CMS Encrypted Data content
+ * @param {Object} parameters Parameters neccessary for encryption
+ * @returns {Promise}
+ */
+
+
+ encrypt(parameters) {
+ //region Check for input parameters
+ if (parameters instanceof Object === false) return Promise.reject("Parameters must have type \"Object\""); //endregion
+ //region Get cryptographic engine
+
+ const engine = (0, _common.getEngine)();
+ if (typeof engine === "undefined") return Promise.reject("Unable to initialize cryptographic engine"); //endregion
+ //region Set "contentType" parameter
+
+ parameters.contentType = "1.2.840.113549.1.7.1"; // "data"
+ //endregion
+
+ if ("encryptEncryptedContentInfo" in engine.subtle) {
+ return engine.subtle.encryptEncryptedContentInfo(parameters).then(result => {
+ this.encryptedContentInfo = result;
+ });
+ }
+
+ return Promise.reject(`No support for "encryptEncryptedContentInfo" in current crypto engine ${engine.name}`);
+ } //**********************************************************************************
+
+ /**
+ * Create a new CMS Encrypted Data content
+ * @param {Object} parameters Parameters neccessary for encryption
+ */
+
+
+ decrypt(parameters) {
+ //region Check for input parameters
+ if (parameters instanceof Object === false) return Promise.reject("Parameters must have type \"Object\""); //endregion
+ //region Get cryptographic engine
+
+ const engine = (0, _common.getEngine)();
+ if (typeof engine === "undefined") return Promise.reject("Unable to initialize cryptographic engine"); //endregion
+ //region Set "encryptedContentInfo" value
+
+ parameters.encryptedContentInfo = this.encryptedContentInfo; //endregion
+
+ if ("decryptEncryptedContentInfo" in engine.subtle) return engine.subtle.decryptEncryptedContentInfo(parameters);
+ return Promise.reject(`No support for "decryptEncryptedContentInfo" in current crypto engine ${engine.name}`);
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = EncryptedData;
+
+},{"./Attribute.js":6,"./EncryptedContentInfo.js":34,"./common.js":110,"asn1js":112,"pvutils":113}],36:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _common = require("./common.js");
+
+var _OriginatorInfo = _interopRequireDefault(require("./OriginatorInfo.js"));
+
+var _RecipientInfo = _interopRequireDefault(require("./RecipientInfo.js"));
+
+var _EncryptedContentInfo = _interopRequireDefault(require("./EncryptedContentInfo.js"));
+
+var _Attribute = _interopRequireDefault(require("./Attribute.js"));
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _RSAESOAEPParams = _interopRequireDefault(require("./RSAESOAEPParams.js"));
+
+var _KeyTransRecipientInfo = _interopRequireDefault(require("./KeyTransRecipientInfo.js"));
+
+var _IssuerAndSerialNumber = _interopRequireDefault(require("./IssuerAndSerialNumber.js"));
+
+var _RecipientEncryptedKey = _interopRequireDefault(require("./RecipientEncryptedKey.js"));
+
+var _KeyAgreeRecipientIdentifier = _interopRequireDefault(require("./KeyAgreeRecipientIdentifier.js"));
+
+var _KeyAgreeRecipientInfo = _interopRequireDefault(require("./KeyAgreeRecipientInfo.js"));
+
+var _RecipientEncryptedKeys = _interopRequireDefault(require("./RecipientEncryptedKeys.js"));
+
+var _KEKRecipientInfo = _interopRequireDefault(require("./KEKRecipientInfo.js"));
+
+var _KEKIdentifier = _interopRequireDefault(require("./KEKIdentifier.js"));
+
+var _PBKDF2Params = _interopRequireDefault(require("./PBKDF2Params.js"));
+
+var _PasswordRecipientinfo = _interopRequireDefault(require("./PasswordRecipientinfo.js"));
+
+var _ECCCMSSharedInfo = _interopRequireDefault(require("./ECCCMSSharedInfo.js"));
+
+var _OriginatorIdentifierOrKey = _interopRequireDefault(require("./OriginatorIdentifierOrKey.js"));
+
+var _OriginatorPublicKey = _interopRequireDefault(require("./OriginatorPublicKey.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class EnvelopedData {
+ //**********************************************************************************
+
+ /**
+ * Constructor for EnvelopedData class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", EnvelopedData.defaultValues("version"));
+ if ("originatorInfo" in parameters)
+ /**
+ * @type {OriginatorInfo}
+ * @desc originatorInfo
+ */
+ this.originatorInfo = (0, _pvutils.getParametersValue)(parameters, "originatorInfo", EnvelopedData.defaultValues("originatorInfo"));
+ /**
+ * @type {Array.<RecipientInfo>}
+ * @desc recipientInfos
+ */
+
+ this.recipientInfos = (0, _pvutils.getParametersValue)(parameters, "recipientInfos", EnvelopedData.defaultValues("recipientInfos"));
+ /**
+ * @type {EncryptedContentInfo}
+ * @desc encryptedContentInfo
+ */
+
+ this.encryptedContentInfo = (0, _pvutils.getParametersValue)(parameters, "encryptedContentInfo", EnvelopedData.defaultValues("encryptedContentInfo"));
+ if ("unprotectedAttrs" in parameters)
+ /**
+ * @type {Array.<Attribute>}
+ * @desc unprotectedAttrs
+ */
+ this.unprotectedAttrs = (0, _pvutils.getParametersValue)(parameters, "unprotectedAttrs", EnvelopedData.defaultValues("unprotectedAttrs")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return 0;
+
+ case "originatorInfo":
+ return new _OriginatorInfo.default();
+
+ case "recipientInfos":
+ return [];
+
+ case "encryptedContentInfo":
+ return new _EncryptedContentInfo.default();
+
+ case "unprotectedAttrs":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for EnvelopedData class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "version":
+ return memberValue === EnvelopedData.defaultValues(memberName);
+
+ case "originatorInfo":
+ return memberValue.certs.certificates.length === 0 && memberValue.crls.crls.length === 0;
+
+ case "recipientInfos":
+ case "unprotectedAttrs":
+ return memberValue.length === 0;
+
+ case "encryptedContentInfo":
+ return _EncryptedContentInfo.default.compareWithDefault("contentType", memberValue.contentType) && _EncryptedContentInfo.default.compareWithDefault("contentEncryptionAlgorithm", memberValue.contentEncryptionAlgorithm) && _EncryptedContentInfo.default.compareWithDefault("encryptedContent", memberValue.encryptedContent);
+
+ default:
+ throw new Error(`Invalid member name for EnvelopedData class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * EnvelopedData ::= SEQUENCE {
+ * version CMSVersion,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * encryptedContentInfo EncryptedContentInfo,
+ * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [version]
+ * @property {string} [originatorInfo]
+ * @property {string} [recipientInfos]
+ * @property {string} [encryptedContentInfo]
+ * @property {string} [unprotectedAttrs]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Integer({
+ name: names.version || ""
+ }), new asn1js.Constructed({
+ name: names.originatorInfo || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: _OriginatorInfo.default.schema().valueBlock.value
+ }), new asn1js.Set({
+ value: [new asn1js.Repeated({
+ name: names.recipientInfos || "",
+ value: _RecipientInfo.default.schema()
+ })]
+ }), _EncryptedContentInfo.default.schema(names.encryptedContentInfo || {}), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [new asn1js.Repeated({
+ name: names.unprotectedAttrs || "",
+ value: _Attribute.default.schema()
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["version", "originatorInfo", "recipientInfos", "encryptedContentInfo", "unprotectedAttrs"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, EnvelopedData.schema({
+ names: {
+ version: "version",
+ originatorInfo: "originatorInfo",
+ recipientInfos: "recipientInfos",
+ encryptedContentInfo: {
+ names: {
+ blockName: "encryptedContentInfo"
+ }
+ },
+ unprotectedAttrs: "unprotectedAttrs"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for EnvelopedData"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.version = asn1.result.version.valueBlock.valueDec;
+
+ if ("originatorInfo" in asn1.result) {
+ this.originatorInfo = new _OriginatorInfo.default({
+ schema: new asn1js.Sequence({
+ value: asn1.result.originatorInfo.valueBlock.value
+ })
+ });
+ }
+
+ this.recipientInfos = Array.from(asn1.result.recipientInfos, element => new _RecipientInfo.default({
+ schema: element
+ }));
+ this.encryptedContentInfo = new _EncryptedContentInfo.default({
+ schema: asn1.result.encryptedContentInfo
+ });
+ if ("unprotectedAttrs" in asn1.result) this.unprotectedAttrs = Array.from(asn1.result.unprotectedAttrs, element => new _Attribute.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(new asn1js.Integer({
+ value: this.version
+ }));
+
+ if ("originatorInfo" in this) {
+ outputArray.push(new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: this.originatorInfo.toSchema().valueBlock.value
+ }));
+ }
+
+ outputArray.push(new asn1js.Set({
+ value: Array.from(this.recipientInfos, element => element.toSchema())
+ }));
+ outputArray.push(this.encryptedContentInfo.toSchema());
+
+ if ("unprotectedAttrs" in this) {
+ outputArray.push(new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: Array.from(this.unprotectedAttrs, element => element.toSchema())
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ version: this.version
+ };
+ if ("originatorInfo" in this) _object.originatorInfo = this.originatorInfo.toJSON();
+ _object.recipientInfos = Array.from(this.recipientInfos, element => element.toJSON());
+ _object.encryptedContentInfo = this.encryptedContentInfo.toJSON();
+ if ("unprotectedAttrs" in this) _object.unprotectedAttrs = Array.from(this.unprotectedAttrs, element => element.toJSON());
+ return _object;
+ } //**********************************************************************************
+
+ /**
+ * Helpers function for filling "RecipientInfo" based on recipient's certificate.
+ * Problem with WebCrypto is that for RSA certificates we have only one option - "key transport" and
+ * for ECC certificates we also have one option - "key agreement". As soon as Google will implement
+ * DH algorithm it would be possible to use "key agreement" also for RSA certificates.
+ * @param {Certificate} [certificate] Recipient's certificate
+ * @param {Object} [parameters] Additional parameters neccessary for "fine tunning" of encryption process
+ * @param {number} [variant] Variant = 1 is for "key transport", variant = 2 is for "key agreement". In fact the "variant" is unneccessary now because Google has no DH algorithm implementation. Thus key encryption scheme would be choosen by certificate type only: "key transport" for RSA and "key agreement" for ECC certificates.
+ */
+
+
+ addRecipientByCertificate(certificate, parameters, variant) {
+ //region Initial variables
+ const encryptionParameters = parameters || {}; //endregion
+ //region Check type of certificate
+
+ if (certificate.subjectPublicKeyInfo.algorithm.algorithmId.indexOf("1.2.840.113549") !== -1) variant = 1; // For the moment it is the only variant for RSA-based certificates
+ else {
+ if (certificate.subjectPublicKeyInfo.algorithm.algorithmId.indexOf("1.2.840.10045") !== -1) variant = 2; // For the moment it is the only variant for ECC-based certificates
+ else throw new Error(`Unknown type of certificate's public key: ${certificate.subjectPublicKeyInfo.algorithm.algorithmId}`);
+ } //endregion
+ //region Initialize encryption parameters
+
+ if ("oaepHashAlgorithm" in encryptionParameters === false) encryptionParameters.oaepHashAlgorithm = "SHA-512";
+ if ("kdfAlgorithm" in encryptionParameters === false) encryptionParameters.kdfAlgorithm = "SHA-512";
+ if ("kekEncryptionLength" in encryptionParameters === false) encryptionParameters.kekEncryptionLength = 256; //endregion
+ //region Add new "recipient" depends on "variant" and certificate type
+
+ switch (variant) {
+ case 1:
+ // Key transport scheme
+ {
+ //region keyEncryptionAlgorithm
+ const oaepOID = (0, _common.getOIDByAlgorithm)({
+ name: "RSA-OAEP"
+ });
+ if (oaepOID === "") throw new Error("Can not find OID for OAEP"); //endregion
+ //region RSAES-OAEP-params
+
+ const hashOID = (0, _common.getOIDByAlgorithm)({
+ name: encryptionParameters.oaepHashAlgorithm
+ });
+ if (hashOID === "") throw new Error(`Unknown OAEP hash algorithm: ${encryptionParameters.oaepHashAlgorithm}`);
+ const hashAlgorithm = new _AlgorithmIdentifier.default({
+ algorithmId: hashOID,
+ algorithmParams: new asn1js.Null()
+ });
+ const rsaOAEPParams = new _RSAESOAEPParams.default({
+ hashAlgorithm,
+ maskGenAlgorithm: new _AlgorithmIdentifier.default({
+ algorithmId: "1.2.840.113549.1.1.8",
+ // id-mgf1
+ algorithmParams: hashAlgorithm.toSchema()
+ })
+ }); //endregion
+ //region KeyTransRecipientInfo
+
+ const keyInfo = new _KeyTransRecipientInfo.default({
+ version: 0,
+ rid: new _IssuerAndSerialNumber.default({
+ issuer: certificate.issuer,
+ serialNumber: certificate.serialNumber
+ }),
+ keyEncryptionAlgorithm: new _AlgorithmIdentifier.default({
+ algorithmId: oaepOID,
+ algorithmParams: rsaOAEPParams.toSchema()
+ }),
+ recipientCertificate: certificate // "encryptedKey" will be calculated in "encrypt" function
+
+ }); //endregion
+ //region Final values for "CMS_ENVELOPED_DATA"
+
+ this.recipientInfos.push(new _RecipientInfo.default({
+ variant: 1,
+ value: keyInfo
+ })); //endregion
+ }
+ break;
+
+ case 2:
+ // Key agreement scheme
+ {
+ //region RecipientEncryptedKey
+ const encryptedKey = new _RecipientEncryptedKey.default({
+ rid: new _KeyAgreeRecipientIdentifier.default({
+ variant: 1,
+ value: new _IssuerAndSerialNumber.default({
+ issuer: certificate.issuer,
+ serialNumber: certificate.serialNumber
+ })
+ }) // "encryptedKey" will be calculated in "encrypt" function
+
+ }); //endregion
+ //region keyEncryptionAlgorithm
+
+ const aesKWoid = (0, _common.getOIDByAlgorithm)({
+ name: "AES-KW",
+ length: encryptionParameters.kekEncryptionLength
+ });
+ if (aesKWoid === "") throw new Error(`Unknown length for key encryption algorithm: ${encryptionParameters.kekEncryptionLength}`);
+ const aesKW = new _AlgorithmIdentifier.default({
+ algorithmId: aesKWoid,
+ algorithmParams: new asn1js.Null()
+ }); //endregion
+ //region KeyAgreeRecipientInfo
+
+ const ecdhOID = (0, _common.getOIDByAlgorithm)({
+ name: "ECDH",
+ kdf: encryptionParameters.kdfAlgorithm
+ });
+ if (ecdhOID === "") throw new Error(`Unknown KDF algorithm: ${encryptionParameters.kdfAlgorithm}`); // In fact there is no need in so long UKM, but RFC2631
+ // has requirement that "UserKeyMaterial" must be 512 bits long
+
+ const ukmBuffer = new ArrayBuffer(64);
+ const ukmView = new Uint8Array(ukmBuffer);
+ (0, _common.getRandomValues)(ukmView); // Generate random values in 64 bytes long buffer
+
+ const keyInfo = new _KeyAgreeRecipientInfo.default({
+ version: 3,
+ // "originator" will be calculated in "encrypt" function because ephemeral key would be generated there
+ ukm: new asn1js.OctetString({
+ valueHex: ukmBuffer
+ }),
+ keyEncryptionAlgorithm: new _AlgorithmIdentifier.default({
+ algorithmId: ecdhOID,
+ algorithmParams: aesKW.toSchema()
+ }),
+ recipientEncryptedKeys: new _RecipientEncryptedKeys.default({
+ encryptedKeys: [encryptedKey]
+ }),
+ recipientCertificate: certificate
+ }); //endregion
+ //region Final values for "CMS_ENVELOPED_DATA"
+
+ this.recipientInfos.push(new _RecipientInfo.default({
+ variant: 2,
+ value: keyInfo
+ })); //endregion
+ }
+ break;
+
+ default:
+ throw new Error(`Unknown "variant" value: ${variant}`);
+ } //endregion
+
+
+ return true;
+ } //**********************************************************************************
+
+ /**
+ * Add recipient based on pre-defined data like password or KEK
+ * @param {ArrayBuffer} preDefinedData ArrayBuffer with pre-defined data
+ * @param {Object} parameters Additional parameters neccessary for "fine tunning" of encryption process
+ * @param {number} variant Variant = 1 for pre-defined "key encryption key" (KEK). Variant = 2 for password-based encryption.
+ */
+
+
+ addRecipientByPreDefinedData(preDefinedData, parameters, variant) {
+ //region Initial variables
+ const encryptionParameters = parameters || {}; //endregion
+ //region Check initial parameters
+
+ if (preDefinedData instanceof ArrayBuffer === false) throw new Error("Please pass \"preDefinedData\" in ArrayBuffer type");
+ if (preDefinedData.byteLength === 0) throw new Error("Pre-defined data could have zero length"); //endregion
+ //region Initialize encryption parameters
+
+ if ("keyIdentifier" in encryptionParameters === false) {
+ const keyIdentifierBuffer = new ArrayBuffer(16);
+ const keyIdentifierView = new Uint8Array(keyIdentifierBuffer);
+ (0, _common.getRandomValues)(keyIdentifierView);
+ encryptionParameters.keyIdentifier = keyIdentifierBuffer;
+ }
+
+ if ("hmacHashAlgorithm" in encryptionParameters === false) encryptionParameters.hmacHashAlgorithm = "SHA-512";
+ if ("iterationCount" in encryptionParameters === false) encryptionParameters.iterationCount = 2048;
+
+ if ("keyEncryptionAlgorithm" in encryptionParameters === false) {
+ encryptionParameters.keyEncryptionAlgorithm = {
+ name: "AES-KW",
+ length: 256
+ };
+ }
+
+ if ("keyEncryptionAlgorithmParams" in encryptionParameters === false) encryptionParameters.keyEncryptionAlgorithmParams = new asn1js.Null(); //endregion
+ //region Add new recipient based on passed variant
+
+ switch (variant) {
+ case 1:
+ // KEKRecipientInfo
+ {
+ //region keyEncryptionAlgorithm
+ const kekOID = (0, _common.getOIDByAlgorithm)(encryptionParameters.keyEncryptionAlgorithm);
+ if (kekOID === "") throw new Error("Incorrect value for \"keyEncryptionAlgorithm\""); //endregion
+ //region KEKRecipientInfo
+
+ const keyInfo = new _KEKRecipientInfo.default({
+ version: 4,
+ kekid: new _KEKIdentifier.default({
+ keyIdentifier: new asn1js.OctetString({
+ valueHex: encryptionParameters.keyIdentifier
+ })
+ }),
+ keyEncryptionAlgorithm: new _AlgorithmIdentifier.default({
+ algorithmId: kekOID,
+
+ /*
+ For AES-KW params are NULL, but for other algorithm could another situation.
+ */
+ algorithmParams: encryptionParameters.keyEncryptionAlgorithmParams
+ }),
+ preDefinedKEK: preDefinedData // "encryptedKey" would be set in "ecrypt" function
+
+ }); //endregion
+ //region Final values for "CMS_ENVELOPED_DATA"
+
+ this.recipientInfos.push(new _RecipientInfo.default({
+ variant: 3,
+ value: keyInfo
+ })); //endregion
+ }
+ break;
+
+ case 2:
+ // PasswordRecipientinfo
+ {
+ //region keyDerivationAlgorithm
+ const pbkdf2OID = (0, _common.getOIDByAlgorithm)({
+ name: "PBKDF2"
+ });
+ if (pbkdf2OID === "") throw new Error("Can not find OID for PBKDF2"); //endregion
+ //region Salt
+
+ const saltBuffer = new ArrayBuffer(64);
+ const saltView = new Uint8Array(saltBuffer);
+ (0, _common.getRandomValues)(saltView); //endregion
+ //region HMAC-based algorithm
+
+ const hmacOID = (0, _common.getOIDByAlgorithm)({
+ name: "HMAC",
+ hash: {
+ name: encryptionParameters.hmacHashAlgorithm
+ }
+ });
+ if (hmacOID === "") throw new Error(`Incorrect value for "hmacHashAlgorithm": ${encryptionParameters.hmacHashAlgorithm}`); //endregion
+ //region PBKDF2-params
+
+ const pbkdf2Params = new _PBKDF2Params.default({
+ salt: new asn1js.OctetString({
+ valueHex: saltBuffer
+ }),
+ iterationCount: encryptionParameters.iterationCount,
+ prf: new _AlgorithmIdentifier.default({
+ algorithmId: hmacOID,
+ algorithmParams: new asn1js.Null()
+ })
+ }); //endregion
+ //region keyEncryptionAlgorithm
+
+ const kekOID = (0, _common.getOIDByAlgorithm)(encryptionParameters.keyEncryptionAlgorithm);
+ if (kekOID === "") throw new Error("Incorrect value for \"keyEncryptionAlgorithm\""); //endregion
+ //region PasswordRecipientinfo
+
+ const keyInfo = new _PasswordRecipientinfo.default({
+ version: 0,
+ keyDerivationAlgorithm: new _AlgorithmIdentifier.default({
+ algorithmId: pbkdf2OID,
+ algorithmParams: pbkdf2Params.toSchema()
+ }),
+ keyEncryptionAlgorithm: new _AlgorithmIdentifier.default({
+ algorithmId: kekOID,
+
+ /*
+ For AES-KW params are NULL, but for other algorithm could be another situation.
+ */
+ algorithmParams: encryptionParameters.keyEncryptionAlgorithmParams
+ }),
+ password: preDefinedData // "encryptedKey" would be set in "ecrypt" function
+
+ }); //endregion
+ //region Final values for "CMS_ENVELOPED_DATA"
+
+ this.recipientInfos.push(new _RecipientInfo.default({
+ variant: 4,
+ value: keyInfo
+ })); //endregion
+ }
+ break;
+
+ default:
+ throw new Error(`Unknown value for "variant": ${variant}`);
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Create a new CMS Enveloped Data content with encrypted data
+ * @param {Object} contentEncryptionAlgorithm WebCrypto algorithm. For the moment here could be only "AES-CBC" or "AES-GCM" algorithms.
+ * @param {ArrayBuffer} contentToEncrypt Content to encrypt
+ * @returns {Promise}
+ */
+
+
+ encrypt(contentEncryptionAlgorithm, contentToEncrypt) {
+ //region Initial variables
+ let sequence = Promise.resolve();
+ const ivBuffer = new ArrayBuffer(16); // For AES we need IV 16 bytes long
+
+ const ivView = new Uint8Array(ivBuffer);
+ (0, _common.getRandomValues)(ivView);
+ const contentView = new Uint8Array(contentToEncrypt);
+ let sessionKey;
+ let encryptedContent;
+ let exportedSessionKey;
+ const recipientsPromises = [];
+
+ const _this = this; //endregion
+ //region Check for input parameters
+
+
+ const contentEncryptionOID = (0, _common.getOIDByAlgorithm)(contentEncryptionAlgorithm);
+ if (contentEncryptionOID === "") return Promise.reject("Wrong \"contentEncryptionAlgorithm\" value"); //endregion
+ //region Get a "crypto" extension
+
+ const crypto = (0, _common.getCrypto)();
+ if (typeof crypto === "undefined") return Promise.reject("Unable to create WebCrypto object"); //endregion
+ //region Generate new content encryption key
+
+ sequence = sequence.then(() => crypto.generateKey(contentEncryptionAlgorithm, true, ["encrypt"])); //endregion
+ //region Encrypt content
+
+ sequence = sequence.then(result => {
+ sessionKey = result;
+ return crypto.encrypt({
+ name: contentEncryptionAlgorithm.name,
+ iv: ivView
+ }, sessionKey, contentView);
+ }, error => Promise.reject(error)); //endregion
+ //region Export raw content of content encryption key
+
+ sequence = sequence.then(result => {
+ //region Create output OCTETSTRING with encrypted content
+ encryptedContent = result; //endregion
+
+ return crypto.exportKey("raw", sessionKey);
+ }, error => Promise.reject(error)).then(result => {
+ exportedSessionKey = result;
+ return true;
+ }, error => Promise.reject(error)); //endregion
+ //region Append common information to CMS_ENVELOPED_DATA
+
+ sequence = sequence.then(() => {
+ this.version = 2;
+ this.encryptedContentInfo = new _EncryptedContentInfo.default({
+ contentType: "1.2.840.113549.1.7.1",
+ // "data"
+ contentEncryptionAlgorithm: new _AlgorithmIdentifier.default({
+ algorithmId: contentEncryptionOID,
+ algorithmParams: new asn1js.OctetString({
+ valueHex: ivBuffer
+ })
+ }),
+ encryptedContent: new asn1js.OctetString({
+ valueHex: encryptedContent
+ })
+ });
+ }, error => Promise.reject(error)); //endregion
+ //region Special sub-functions to work with each recipient's type
+
+ function SubKeyAgreeRecipientInfo(index) {
+ //region Initial variables
+ let currentSequence = Promise.resolve();
+ let ecdhPublicKey;
+ let ecdhPrivateKey;
+ let recipientCurve;
+ let recipientCurveLength;
+ let exportedECDHPublicKey; //endregion
+ //region Get "namedCurve" parameter from recipient's certificate
+
+ currentSequence = currentSequence.then(() => {
+ const curveObject = _this.recipientInfos[index].value.recipientCertificate.subjectPublicKeyInfo.algorithm.algorithmParams;
+ if (curveObject instanceof asn1js.ObjectIdentifier === false) return Promise.reject(`Incorrect "recipientCertificate" for index ${index}`);
+ const curveOID = curveObject.valueBlock.toString();
+
+ switch (curveOID) {
+ case "1.2.840.10045.3.1.7":
+ recipientCurve = "P-256";
+ recipientCurveLength = 256;
+ break;
+
+ case "1.3.132.0.34":
+ recipientCurve = "P-384";
+ recipientCurveLength = 384;
+ break;
+
+ case "1.3.132.0.35":
+ recipientCurve = "P-521";
+ recipientCurveLength = 528;
+ break;
+
+ default:
+ return Promise.reject(`Incorrect curve OID for index ${index}`);
+ }
+
+ return recipientCurve;
+ }, error => Promise.reject(error)); //endregion
+ //region Generate ephemeral ECDH key
+
+ currentSequence = currentSequence.then(result => crypto.generateKey({
+ name: "ECDH",
+ namedCurve: result
+ }, true, ["deriveBits"]), error => Promise.reject(error)); //endregion
+ //region Export public key of ephemeral ECDH key pair
+
+ currentSequence = currentSequence.then(result => {
+ ecdhPublicKey = result.publicKey;
+ ecdhPrivateKey = result.privateKey;
+ return crypto.exportKey("spki", ecdhPublicKey);
+ }, error => Promise.reject(error)); //endregion
+ //region Import recipient's public key
+
+ currentSequence = currentSequence.then(result => {
+ exportedECDHPublicKey = result;
+ return _this.recipientInfos[index].value.recipientCertificate.getPublicKey({
+ algorithm: {
+ algorithm: {
+ name: "ECDH",
+ namedCurve: recipientCurve
+ },
+ usages: []
+ }
+ });
+ }, error => Promise.reject(error)); //endregion
+ //region Create shared secret
+
+ currentSequence = currentSequence.then(result => crypto.deriveBits({
+ name: "ECDH",
+ public: result
+ }, ecdhPrivateKey, recipientCurveLength), error => Promise.reject(error)); //endregion
+ //region Apply KDF function to shared secret
+
+ currentSequence = currentSequence.then(
+ /**
+ * @param {ArrayBuffer} result
+ */
+ result => {
+ //region Get length of used AES-KW algorithm
+ const aesKWAlgorithm = new _AlgorithmIdentifier.default({
+ schema: _this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithmParams
+ });
+ const KWalgorithm = (0, _common.getAlgorithmByOID)(aesKWAlgorithm.algorithmId);
+ if ("name" in KWalgorithm === false) return Promise.reject(`Incorrect OID for key encryption algorithm: ${aesKWAlgorithm.algorithmId}`); //endregion
+ //region Translate AES-KW length to ArrayBuffer
+
+ let kwLength = KWalgorithm.length;
+ const kwLengthBuffer = new ArrayBuffer(4);
+ const kwLengthView = new Uint8Array(kwLengthBuffer);
+
+ for (let j = 3; j >= 0; j--) {
+ kwLengthView[j] = kwLength;
+ kwLength >>= 8;
+ } //endregion
+ //region Create and encode "ECC-CMS-SharedInfo" structure
+
+
+ const eccInfo = new _ECCCMSSharedInfo.default({
+ keyInfo: new _AlgorithmIdentifier.default({
+ algorithmId: aesKWAlgorithm.algorithmId,
+
+ /*
+ Initially RFC5753 says that AES algorithms have absent parameters.
+ But since early implementations all put NULL here. Thus, in order to be
+ "backward compatible", index also put NULL here.
+ */
+ algorithmParams: new asn1js.Null()
+ }),
+ entityUInfo: _this.recipientInfos[index].value.ukm,
+ suppPubInfo: new asn1js.OctetString({
+ valueHex: kwLengthBuffer
+ })
+ });
+ const encodedInfo = eccInfo.toSchema().toBER(false); //endregion
+ //region Get SHA algorithm used together with ECDH
+
+ const ecdhAlgorithm = (0, _common.getAlgorithmByOID)(_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithmId);
+ if ("name" in ecdhAlgorithm === false) return Promise.reject(`Incorrect OID for key encryption algorithm: ${_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithmId}`); //endregion
+
+ return (0, _common.kdf)(ecdhAlgorithm.kdf, result, KWalgorithm.length, encodedInfo);
+ }, error => Promise.reject(error)); //endregion
+ //region Import AES-KW key from result of KDF function
+
+ currentSequence = currentSequence.then(result => crypto.importKey("raw", result, {
+ name: "AES-KW"
+ }, true, ["wrapKey"]), error => Promise.reject(error)); //endregion
+ //region Finally wrap session key by using AES-KW algorithm
+
+ currentSequence = currentSequence.then(result => crypto.wrapKey("raw", sessionKey, result, {
+ name: "AES-KW"
+ }), error => Promise.reject(error)); //endregion
+ //region Append all neccessary data to current CMS_RECIPIENT_INFO object
+
+ currentSequence = currentSequence.then(result => {
+ //region OriginatorIdentifierOrKey
+ const asn1 = asn1js.fromBER(exportedECDHPublicKey);
+ const originator = new _OriginatorIdentifierOrKey.default();
+ originator.variant = 3;
+ originator.value = new _OriginatorPublicKey.default({
+ schema: asn1.result
+ }); // There is option when we can stay with ECParameters, but here index prefer to avoid the params
+
+ if ("algorithmParams" in originator.value.algorithm) delete originator.value.algorithm.algorithmParams;
+ _this.recipientInfos[index].value.originator = originator; //endregion
+ //region RecipientEncryptedKey
+
+ /*
+ We will not support using of same ephemeral key for many recipients
+ */
+
+ _this.recipientInfos[index].value.recipientEncryptedKeys.encryptedKeys[0].encryptedKey = new asn1js.OctetString({
+ valueHex: result
+ }); //endregion
+ }, error => Promise.reject(error)); //endregion
+
+ return currentSequence;
+ }
+
+ function SubKeyTransRecipientInfo(index) {
+ //region Initial variables
+ let currentSequence = Promise.resolve(); //endregion
+ //region Get recipient's public key
+
+ currentSequence = currentSequence.then(() => {
+ //region Get current used SHA algorithm
+ const schema = _this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithmParams;
+ const rsaOAEPParams = new _RSAESOAEPParams.default({
+ schema
+ });
+ const hashAlgorithm = (0, _common.getAlgorithmByOID)(rsaOAEPParams.hashAlgorithm.algorithmId);
+ if ("name" in hashAlgorithm === false) return Promise.reject(`Incorrect OID for hash algorithm: ${rsaOAEPParams.hashAlgorithm.algorithmId}`); //endregion
+
+ return _this.recipientInfos[index].value.recipientCertificate.getPublicKey({
+ algorithm: {
+ algorithm: {
+ name: "RSA-OAEP",
+ hash: {
+ name: hashAlgorithm.name
+ }
+ },
+ usages: ["encrypt", "wrapKey"]
+ }
+ });
+ }, error => Promise.reject(error)); //endregion
+ //region Encrypt early exported session key on recipient's public key
+
+ currentSequence = currentSequence.then(result => crypto.encrypt(result.algorithm, result, exportedSessionKey), error => Promise.reject(error)); //endregion
+ //region Append all neccessary data to current CMS_RECIPIENT_INFO object
+
+ currentSequence = currentSequence.then(result => {
+ //region RecipientEncryptedKey
+ _this.recipientInfos[index].value.encryptedKey = new asn1js.OctetString({
+ valueHex: result
+ }); //endregion
+ }, error => Promise.reject(error)); //endregion
+
+ return currentSequence;
+ }
+
+ function SubKEKRecipientInfo(index) {
+ //region Initial variables
+ let currentSequence = Promise.resolve();
+ let kekAlgorithm; //endregion
+ //region Import KEK from pre-defined data
+
+ currentSequence = currentSequence.then(() => {
+ //region Get WebCrypto form of "keyEncryptionAlgorithm"
+ kekAlgorithm = (0, _common.getAlgorithmByOID)(_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithmId);
+ if ("name" in kekAlgorithm === false) return Promise.reject(`Incorrect OID for "keyEncryptionAlgorithm": ${_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithmId}`); //endregion
+
+ return crypto.importKey("raw", new Uint8Array(_this.recipientInfos[index].value.preDefinedKEK), kekAlgorithm, true, ["wrapKey"]); // Too specific for AES-KW
+ }, error => Promise.reject(error)); //endregion
+ //region Wrap previously exported session key
+
+ currentSequence = currentSequence.then(result => crypto.wrapKey("raw", sessionKey, result, kekAlgorithm), error => Promise.reject(error)); //endregion
+ //region Append all neccessary data to current CMS_RECIPIENT_INFO object
+
+ currentSequence = currentSequence.then(result => {
+ //region RecipientEncryptedKey
+ _this.recipientInfos[index].value.encryptedKey = new asn1js.OctetString({
+ valueHex: result
+ }); //endregion
+ }, error => Promise.reject(error)); //endregion
+
+ return currentSequence;
+ }
+
+ function SubPasswordRecipientinfo(index) {
+ //region Initial variables
+ let currentSequence = Promise.resolve();
+ let pbkdf2Params;
+ let kekAlgorithm; //endregion
+ //region Check that we have encoded "keyDerivationAlgorithm" plus "PBKDF2_params" in there
+
+ currentSequence = currentSequence.then(() => {
+ if ("keyDerivationAlgorithm" in _this.recipientInfos[index].value === false) return Promise.reject("Please append encoded \"keyDerivationAlgorithm\"");
+ if ("algorithmParams" in _this.recipientInfos[index].value.keyDerivationAlgorithm === false) return Promise.reject("Incorrectly encoded \"keyDerivationAlgorithm\"");
+
+ try {
+ pbkdf2Params = new _PBKDF2Params.default({
+ schema: _this.recipientInfos[index].value.keyDerivationAlgorithm.algorithmParams
+ });
+ } catch (ex) {
+ return Promise.reject("Incorrectly encoded \"keyDerivationAlgorithm\"");
+ }
+
+ return Promise.resolve();
+ }, error => Promise.reject(error)); //endregion
+ //region Derive PBKDF2 key from "password" buffer
+
+ currentSequence = currentSequence.then(() => {
+ const passwordView = new Uint8Array(_this.recipientInfos[index].value.password);
+ return crypto.importKey("raw", passwordView, "PBKDF2", false, ["deriveKey"]);
+ }, error => Promise.reject(error)); //endregion
+ //region Derive key for "keyEncryptionAlgorithm"
+
+ currentSequence = currentSequence.then(result => {
+ //region Get WebCrypto form of "keyEncryptionAlgorithm"
+ kekAlgorithm = (0, _common.getAlgorithmByOID)(_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithmId);
+ if ("name" in kekAlgorithm === false) return Promise.reject(`Incorrect OID for "keyEncryptionAlgorithm": ${_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithmId}`); //endregion
+ //region Get HMAC hash algorithm
+
+ let hmacHashAlgorithm = "SHA-1";
+
+ if ("prf" in pbkdf2Params) {
+ const algorithm = (0, _common.getAlgorithmByOID)(pbkdf2Params.prf.algorithmId);
+ if ("name" in algorithm === false) return Promise.reject("Incorrect OID for HMAC hash algorithm");
+ hmacHashAlgorithm = algorithm.hash.name;
+ } //endregion
+ //region Get PBKDF2 "salt" value
+
+
+ const saltView = new Uint8Array(pbkdf2Params.salt.valueBlock.valueHex); //endregion
+ //region Get PBKDF2 iterations count
+
+ const iterations = pbkdf2Params.iterationCount; //endregion
+
+ return crypto.deriveKey({
+ name: "PBKDF2",
+ hash: {
+ name: hmacHashAlgorithm
+ },
+ salt: saltView,
+ iterations
+ }, result, kekAlgorithm, true, ["wrapKey"]); // Usages are too specific for KEK algorithm
+ }, error => Promise.reject(error)); //endregion
+ //region Wrap previously exported session key (Also too specific for KEK algorithm)
+
+ currentSequence = currentSequence.then(result => crypto.wrapKey("raw", sessionKey, result, kekAlgorithm), error => Promise.reject(error)); //endregion
+ //region Append all neccessary data to current CMS_RECIPIENT_INFO object
+
+ currentSequence = currentSequence.then(result => {
+ //region RecipientEncryptedKey
+ _this.recipientInfos[index].value.encryptedKey = new asn1js.OctetString({
+ valueHex: result
+ }); //endregion
+ }, error => Promise.reject(error)); //endregion
+
+ return currentSequence;
+ } //endregion
+ //region Create special routines for each "recipient"
+
+
+ sequence = sequence.then(() => {
+ for (let i = 0; i < this.recipientInfos.length; i++) {
+ //region Initial variables
+ let currentSequence = Promise.resolve(); //endregion
+
+ switch (this.recipientInfos[i].variant) {
+ case 1:
+ // KeyTransRecipientInfo
+ currentSequence = SubKeyTransRecipientInfo(i);
+ break;
+
+ case 2:
+ // KeyAgreeRecipientInfo
+ currentSequence = SubKeyAgreeRecipientInfo(i);
+ break;
+
+ case 3:
+ // KEKRecipientInfo
+ currentSequence = SubKEKRecipientInfo(i);
+ break;
+
+ case 4:
+ // PasswordRecipientinfo
+ currentSequence = SubPasswordRecipientinfo(i);
+ break;
+
+ default:
+ return Promise.reject(`Uknown recipient type in array with index ${i}`);
+ }
+
+ recipientsPromises.push(currentSequence);
+ }
+
+ return Promise.all(recipientsPromises);
+ }, error => Promise.reject(error)); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+ /**
+ * Decrypt existing CMS Enveloped Data content
+ * @param {number} recipientIndex Index of recipient
+ * @param {Object} parameters Additional parameters
+ * @returns {Promise}
+ */
+
+
+ decrypt(recipientIndex, parameters) {
+ //region Initial variables
+ let sequence = Promise.resolve();
+ const decryptionParameters = parameters || {};
+
+ const _this = this; //endregion
+ //region Check for input parameters
+
+
+ if (recipientIndex + 1 > this.recipientInfos.length) return Promise.reject(`Maximum value for "index" is: ${this.recipientInfos.length - 1}`); //endregion
+ //region Get a "crypto" extension
+
+ const crypto = (0, _common.getCrypto)();
+ if (typeof crypto === "undefined") return Promise.reject("Unable to create WebCrypto object"); //endregion
+ //region Special sub-functions to work with each recipient's type
+
+ function SubKeyAgreeRecipientInfo(index) {
+ //region Initial variables
+ let currentSequence = Promise.resolve();
+ let recipientCurve;
+ let recipientCurveLength;
+ let curveOID;
+ let ecdhPrivateKey; //endregion
+ //region Get "namedCurve" parameter from recipient's certificate
+
+ currentSequence = currentSequence.then(() => {
+ if ("recipientCertificate" in decryptionParameters === false) return Promise.reject("Parameter \"recipientCertificate\" is mandatory for \"KeyAgreeRecipientInfo\"");
+ if ("recipientPrivateKey" in decryptionParameters === false) return Promise.reject("Parameter \"recipientPrivateKey\" is mandatory for \"KeyAgreeRecipientInfo\"");
+ const curveObject = decryptionParameters.recipientCertificate.subjectPublicKeyInfo.algorithm.algorithmParams;
+ if (curveObject instanceof asn1js.ObjectIdentifier === false) return Promise.reject(`Incorrect "recipientCertificate" for index ${index}`);
+ curveOID = curveObject.valueBlock.toString();
+
+ switch (curveOID) {
+ case "1.2.840.10045.3.1.7":
+ recipientCurve = "P-256";
+ recipientCurveLength = 256;
+ break;
+
+ case "1.3.132.0.34":
+ recipientCurve = "P-384";
+ recipientCurveLength = 384;
+ break;
+
+ case "1.3.132.0.35":
+ recipientCurve = "P-521";
+ recipientCurveLength = 528;
+ break;
+
+ default:
+ return Promise.reject(`Incorrect curve OID for index ${index}`);
+ }
+
+ return crypto.importKey("pkcs8", decryptionParameters.recipientPrivateKey, {
+ name: "ECDH",
+ namedCurve: recipientCurve
+ }, true, ["deriveBits"]);
+ }, error => Promise.reject(error)); //endregion
+ //region Import sender's ephemeral public key
+
+ currentSequence = currentSequence.then(result => {
+ ecdhPrivateKey = result; //region Change "OriginatorPublicKey" if "curve" parameter absent
+
+ if ("algorithmParams" in _this.recipientInfos[index].value.originator.value.algorithm === false) _this.recipientInfos[index].value.originator.value.algorithm.algorithmParams = new asn1js.ObjectIdentifier({
+ value: curveOID
+ }); //endregion
+ //region Create ArrayBuffer with sender's public key
+
+ const buffer = _this.recipientInfos[index].value.originator.value.toSchema().toBER(false); //endregion
+
+
+ return crypto.importKey("spki", buffer, {
+ name: "ECDH",
+ namedCurve: recipientCurve
+ }, true, []);
+ }, error => Promise.reject(error)); //endregion
+ //region Create shared secret
+
+ currentSequence = currentSequence.then(result => crypto.deriveBits({
+ name: "ECDH",
+ public: result
+ }, ecdhPrivateKey, recipientCurveLength), error => Promise.reject(error)); //endregion
+ //region Apply KDF function to shared secret
+
+ currentSequence = currentSequence.then(
+ /**
+ * @param {ArrayBuffer} result
+ */
+ result => {
+ //region Get length of used AES-KW algorithm
+ const aesKWAlgorithm = new _AlgorithmIdentifier.default({
+ schema: _this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithmParams
+ });
+ const KWalgorithm = (0, _common.getAlgorithmByOID)(aesKWAlgorithm.algorithmId);
+ if ("name" in KWalgorithm === false) return Promise.reject(`Incorrect OID for key encryption algorithm: ${aesKWAlgorithm.algorithmId}`); //endregion
+ //region Translate AES-KW length to ArrayBuffer
+
+ let kwLength = KWalgorithm.length;
+ const kwLengthBuffer = new ArrayBuffer(4);
+ const kwLengthView = new Uint8Array(kwLengthBuffer);
+
+ for (let j = 3; j >= 0; j--) {
+ kwLengthView[j] = kwLength;
+ kwLength >>= 8;
+ } //endregion
+ //region Create and encode "ECC-CMS-SharedInfo" structure
+
+
+ const eccInfo = new _ECCCMSSharedInfo.default({
+ keyInfo: new _AlgorithmIdentifier.default({
+ algorithmId: aesKWAlgorithm.algorithmId,
+
+ /*
+ Initially RFC5753 says that AES algorithms have absent parameters.
+ But since early implementations all put NULL here. Thus, in order to be
+ "backward compatible", index also put NULL here.
+ */
+ algorithmParams: new asn1js.Null()
+ }),
+ entityUInfo: _this.recipientInfos[index].value.ukm,
+ suppPubInfo: new asn1js.OctetString({
+ valueHex: kwLengthBuffer
+ })
+ });
+ const encodedInfo = eccInfo.toSchema().toBER(false); //endregion
+ //region Get SHA algorithm used together with ECDH
+
+ const ecdhAlgorithm = (0, _common.getAlgorithmByOID)(_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithmId);
+ if ("name" in ecdhAlgorithm === false) return Promise.reject(`Incorrect OID for key encryption algorithm: ${_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithmId}`); //endregion
+
+ return (0, _common.kdf)(ecdhAlgorithm.kdf, result, KWalgorithm.length, encodedInfo);
+ }, error => Promise.reject(error)); //endregion
+ //region Import AES-KW key from result of KDF function
+
+ currentSequence = currentSequence.then(result => crypto.importKey("raw", result, {
+ name: "AES-KW"
+ }, true, ["unwrapKey"]), error => Promise.reject(error)); //endregion
+ //region Finally unwrap session key
+
+ currentSequence = currentSequence.then(result => {
+ //region Get WebCrypto form of content encryption algorithm
+ const contentEncryptionAlgorithm = (0, _common.getAlgorithmByOID)(_this.encryptedContentInfo.contentEncryptionAlgorithm.algorithmId);
+ if ("name" in contentEncryptionAlgorithm === false) return Promise.reject(`Incorrect "contentEncryptionAlgorithm": ${_this.encryptedContentInfo.contentEncryptionAlgorithm.algorithmId}`); //endregion
+
+ return crypto.unwrapKey("raw", _this.recipientInfos[index].value.recipientEncryptedKeys.encryptedKeys[0].encryptedKey.valueBlock.valueHex, result, {
+ name: "AES-KW"
+ }, contentEncryptionAlgorithm, true, ["decrypt"]);
+ }, error => Promise.reject(error)); //endregion
+
+ return currentSequence;
+ }
+
+ function SubKeyTransRecipientInfo(index) {
+ //region Initial variables
+ let currentSequence = Promise.resolve(); //endregion
+ //region Import recipient's private key
+
+ currentSequence = currentSequence.then(() => {
+ if ("recipientPrivateKey" in decryptionParameters === false) return Promise.reject("Parameter \"recipientPrivateKey\" is mandatory for \"KeyTransRecipientInfo\""); //region Get current used SHA algorithm
+
+ const schema = _this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithmParams;
+ const rsaOAEPParams = new _RSAESOAEPParams.default({
+ schema
+ });
+ const hashAlgorithm = (0, _common.getAlgorithmByOID)(rsaOAEPParams.hashAlgorithm.algorithmId);
+ if ("name" in hashAlgorithm === false) return Promise.reject(`Incorrect OID for hash algorithm: ${rsaOAEPParams.hashAlgorithm.algorithmId}`); //endregion
+
+ return crypto.importKey("pkcs8", decryptionParameters.recipientPrivateKey, {
+ name: "RSA-OAEP",
+ hash: {
+ name: hashAlgorithm.name
+ }
+ }, true, ["decrypt"]);
+ }, error => Promise.reject(error)); //endregion
+ //region Decrypt encrypted session key
+
+ currentSequence = currentSequence.then(result => crypto.decrypt(result.algorithm, result, _this.recipientInfos[index].value.encryptedKey.valueBlock.valueHex), error => Promise.reject(error)); //endregion
+ //region Import decrypted session key
+
+ currentSequence = currentSequence.then(result => {
+ //region Get WebCrypto form of content encryption algorithm
+ const contentEncryptionAlgorithm = (0, _common.getAlgorithmByOID)(_this.encryptedContentInfo.contentEncryptionAlgorithm.algorithmId);
+ if ("name" in contentEncryptionAlgorithm === false) return Promise.reject(`Incorrect "contentEncryptionAlgorithm": ${_this.encryptedContentInfo.contentEncryptionAlgorithm.algorithmId}`); //endregion
+
+ return crypto.importKey("raw", result, contentEncryptionAlgorithm, true, ["decrypt"]);
+ }, error => Promise.reject(error)); //endregion
+
+ return currentSequence;
+ }
+
+ function SubKEKRecipientInfo(index) {
+ //region Initial variables
+ let currentSequence = Promise.resolve();
+ let kekAlgorithm; //endregion
+ //region Import KEK from pre-defined data
+
+ currentSequence = currentSequence.then(() => {
+ if ("preDefinedData" in decryptionParameters === false) return Promise.reject("Parameter \"preDefinedData\" is mandatory for \"KEKRecipientInfo\""); //region Get WebCrypto form of "keyEncryptionAlgorithm"
+
+ kekAlgorithm = (0, _common.getAlgorithmByOID)(_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithmId);
+ if ("name" in kekAlgorithm === false) return Promise.reject(`Incorrect OID for "keyEncryptionAlgorithm": ${_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithmId}`); //endregion
+
+ return crypto.importKey("raw", decryptionParameters.preDefinedData, kekAlgorithm, true, ["unwrapKey"]); // Too specific for AES-KW
+ }, error => Promise.reject(error)); //endregion
+ //region Unwrap previously exported session key
+
+ currentSequence = currentSequence.then(result => {
+ //region Get WebCrypto form of content encryption algorithm
+ const contentEncryptionAlgorithm = (0, _common.getAlgorithmByOID)(_this.encryptedContentInfo.contentEncryptionAlgorithm.algorithmId);
+ if ("name" in contentEncryptionAlgorithm === false) return Promise.reject(`Incorrect "contentEncryptionAlgorithm": ${_this.encryptedContentInfo.contentEncryptionAlgorithm.algorithmId}`); //endregion
+
+ return crypto.unwrapKey("raw", _this.recipientInfos[index].value.encryptedKey.valueBlock.valueHex, result, kekAlgorithm, contentEncryptionAlgorithm, true, ["decrypt"]);
+ }, error => Promise.reject(error)); //endregion
+
+ return currentSequence;
+ }
+
+ function SubPasswordRecipientinfo(index) {
+ //region Initial variables
+ let currentSequence = Promise.resolve();
+ let pbkdf2Params;
+ let kekAlgorithm; //endregion
+ //region Derive PBKDF2 key from "password" buffer
+
+ currentSequence = currentSequence.then(() => {
+ if ("preDefinedData" in decryptionParameters === false) return Promise.reject("Parameter \"preDefinedData\" is mandatory for \"KEKRecipientInfo\"");
+ if ("keyDerivationAlgorithm" in _this.recipientInfos[index].value === false) return Promise.reject("Please append encoded \"keyDerivationAlgorithm\"");
+ if ("algorithmParams" in _this.recipientInfos[index].value.keyDerivationAlgorithm === false) return Promise.reject("Incorrectly encoded \"keyDerivationAlgorithm\"");
+
+ try {
+ pbkdf2Params = new _PBKDF2Params.default({
+ schema: _this.recipientInfos[index].value.keyDerivationAlgorithm.algorithmParams
+ });
+ } catch (ex) {
+ return Promise.reject("Incorrectly encoded \"keyDerivationAlgorithm\"");
+ }
+
+ return crypto.importKey("raw", decryptionParameters.preDefinedData, "PBKDF2", false, ["deriveKey"]);
+ }, error => Promise.reject(error)); //endregion
+ //region Derive key for "keyEncryptionAlgorithm"
+
+ currentSequence = currentSequence.then(result => {
+ //region Get WebCrypto form of "keyEncryptionAlgorithm"
+ kekAlgorithm = (0, _common.getAlgorithmByOID)(_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithmId);
+ if ("name" in kekAlgorithm === false) return Promise.reject(`Incorrect OID for "keyEncryptionAlgorithm": ${_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithmId}`); //endregion
+ //region Get HMAC hash algorithm
+
+ let hmacHashAlgorithm = "SHA-1";
+
+ if ("prf" in pbkdf2Params) {
+ const algorithm = (0, _common.getAlgorithmByOID)(pbkdf2Params.prf.algorithmId);
+ if ("name" in algorithm === false) return Promise.reject("Incorrect OID for HMAC hash algorithm");
+ hmacHashAlgorithm = algorithm.hash.name;
+ } //endregion
+ //region Get PBKDF2 "salt" value
+
+
+ const saltView = new Uint8Array(pbkdf2Params.salt.valueBlock.valueHex); //endregion
+ //region Get PBKDF2 iterations count
+
+ const iterations = pbkdf2Params.iterationCount; //endregion
+
+ return crypto.deriveKey({
+ name: "PBKDF2",
+ hash: {
+ name: hmacHashAlgorithm
+ },
+ salt: saltView,
+ iterations
+ }, result, kekAlgorithm, true, ["unwrapKey"]); // Usages are too specific for KEK algorithm
+ }, error => Promise.reject(error)); //endregion
+ //region Unwrap previously exported session key
+
+ currentSequence = currentSequence.then(result => {
+ //region Get WebCrypto form of content encryption algorithm
+ const contentEncryptionAlgorithm = (0, _common.getAlgorithmByOID)(_this.encryptedContentInfo.contentEncryptionAlgorithm.algorithmId);
+ if ("name" in contentEncryptionAlgorithm === false) return Promise.reject(`Incorrect "contentEncryptionAlgorithm": ${_this.encryptedContentInfo.contentEncryptionAlgorithm.algorithmId}`); //endregion
+
+ return crypto.unwrapKey("raw", _this.recipientInfos[index].value.encryptedKey.valueBlock.valueHex, result, kekAlgorithm, contentEncryptionAlgorithm, true, ["decrypt"]);
+ }, error => Promise.reject(error)); //endregion
+
+ return currentSequence;
+ } //endregion
+ //region Perform steps, specific to each type of session key encryption
+
+
+ sequence = sequence.then(() => {
+ //region Initial variables
+ let currentSequence = Promise.resolve(); //endregion
+
+ switch (this.recipientInfos[recipientIndex].variant) {
+ case 1:
+ // KeyTransRecipientInfo
+ currentSequence = SubKeyTransRecipientInfo(recipientIndex);
+ break;
+
+ case 2:
+ // KeyAgreeRecipientInfo
+ currentSequence = SubKeyAgreeRecipientInfo(recipientIndex);
+ break;
+
+ case 3:
+ // KEKRecipientInfo
+ currentSequence = SubKEKRecipientInfo(recipientIndex);
+ break;
+
+ case 4:
+ // PasswordRecipientinfo
+ currentSequence = SubPasswordRecipientinfo(recipientIndex);
+ break;
+
+ default:
+ return Promise.reject(`Uknown recipient type in array with index ${recipientIndex}`);
+ }
+
+ return currentSequence;
+ }, error => Promise.reject(error)); //endregion
+ //region Finally decrypt data by session key
+
+ sequence = sequence.then(result => {
+ //region Get WebCrypto form of content encryption algorithm
+ const contentEncryptionAlgorithm = (0, _common.getAlgorithmByOID)(this.encryptedContentInfo.contentEncryptionAlgorithm.algorithmId);
+ if ("name" in contentEncryptionAlgorithm === false) return Promise.reject(`Incorrect "contentEncryptionAlgorithm": ${this.encryptedContentInfo.contentEncryptionAlgorithm.algorithmId}`); //endregion
+ //region Get "intialization vector" for content encryption algorithm
+
+ const ivBuffer = this.encryptedContentInfo.contentEncryptionAlgorithm.algorithmParams.valueBlock.valueHex;
+ const ivView = new Uint8Array(ivBuffer); //endregion
+ //region Create correct data block for decryption
+
+ let dataBuffer = new ArrayBuffer(0);
+ if (this.encryptedContentInfo.encryptedContent.idBlock.isConstructed === false) dataBuffer = this.encryptedContentInfo.encryptedContent.valueBlock.valueHex;else {
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = this.encryptedContentInfo.encryptedContent.valueBlock.value[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ const content = _step.value;
+ dataBuffer = (0, _pvutils.utilConcatBuf)(dataBuffer, content.valueBlock.valueHex);
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+ } //endregion
+
+ return crypto.decrypt({
+ name: contentEncryptionAlgorithm.name,
+ iv: ivView
+ }, result, dataBuffer);
+ }, error => Promise.reject(error)); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = EnvelopedData;
+
+},{"./AlgorithmIdentifier.js":4,"./Attribute.js":6,"./ECCCMSSharedInfo.js":30,"./EncryptedContentInfo.js":34,"./IssuerAndSerialNumber.js":44,"./KEKIdentifier.js":46,"./KEKRecipientInfo.js":47,"./KeyAgreeRecipientIdentifier.js":48,"./KeyAgreeRecipientInfo.js":49,"./KeyTransRecipientInfo.js":51,"./OriginatorIdentifierOrKey.js":57,"./OriginatorInfo.js":58,"./OriginatorPublicKey.js":59,"./PBKDF2Params.js":66,"./PasswordRecipientinfo.js":70,"./RSAESOAEPParams.js":80,"./RecipientEncryptedKey.js":84,"./RecipientEncryptedKeys.js":85,"./RecipientInfo.js":87,"./common.js":110,"asn1js":112,"pvutils":113}],37:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class ExtKeyUsage {
+ //**********************************************************************************
+
+ /**
+ * Constructor for ExtKeyUsage class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array.<string>}
+ * @desc keyPurposes
+ */
+ this.keyPurposes = (0, _pvutils.getParametersValue)(parameters, "keyPurposes", ExtKeyUsage.defaultValues("keyPurposes")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "keyPurposes":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for ExtKeyUsage class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * ExtKeyUsage ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+ *
+ * KeyPurposeId ::= OBJECT IDENTIFIER
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [keyPurposes]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Repeated({
+ name: names.keyPurposes || "",
+ value: new asn1js.ObjectIdentifier()
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["keyPurposes"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, ExtKeyUsage.schema({
+ names: {
+ keyPurposes: "keyPurposes"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for ExtKeyUsage"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.keyPurposes = Array.from(asn1.result.keyPurposes, element => element.valueBlock.toString()); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: Array.from(this.keyPurposes, element => new asn1js.ObjectIdentifier({
+ value: element
+ }))
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ keyPurposes: Array.from(this.keyPurposes)
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = ExtKeyUsage;
+
+},{"asn1js":112,"pvutils":113}],38:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _SubjectDirectoryAttributes = _interopRequireDefault(require("./SubjectDirectoryAttributes.js"));
+
+var _PrivateKeyUsagePeriod = _interopRequireDefault(require("./PrivateKeyUsagePeriod.js"));
+
+var _AltName = _interopRequireDefault(require("./AltName.js"));
+
+var _BasicConstraints = _interopRequireDefault(require("./BasicConstraints.js"));
+
+var _IssuingDistributionPoint = _interopRequireDefault(require("./IssuingDistributionPoint.js"));
+
+var _GeneralNames = _interopRequireDefault(require("./GeneralNames.js"));
+
+var _NameConstraints = _interopRequireDefault(require("./NameConstraints.js"));
+
+var _CRLDistributionPoints = _interopRequireDefault(require("./CRLDistributionPoints.js"));
+
+var _CertificatePolicies = _interopRequireDefault(require("./CertificatePolicies.js"));
+
+var _PolicyMappings = _interopRequireDefault(require("./PolicyMappings.js"));
+
+var _AuthorityKeyIdentifier = _interopRequireDefault(require("./AuthorityKeyIdentifier.js"));
+
+var _PolicyConstraints = _interopRequireDefault(require("./PolicyConstraints.js"));
+
+var _ExtKeyUsage = _interopRequireDefault(require("./ExtKeyUsage.js"));
+
+var _InfoAccess = _interopRequireDefault(require("./InfoAccess.js"));
+
+var _SignedCertificateTimestampList = _interopRequireDefault(require("./SignedCertificateTimestampList.js"));
+
+var _CertificateTemplate = _interopRequireDefault(require("./CertificateTemplate.js"));
+
+var _CAVersion = _interopRequireDefault(require("./CAVersion.js"));
+
+var _QCStatements = _interopRequireDefault(require("./QCStatements.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class Extension {
+ //**********************************************************************************
+
+ /**
+ * Constructor for Extension class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc extnID
+ */
+ this.extnID = (0, _pvutils.getParametersValue)(parameters, "extnID", Extension.defaultValues("extnID"));
+ /**
+ * @type {boolean}
+ * @desc critical
+ */
+
+ this.critical = (0, _pvutils.getParametersValue)(parameters, "critical", Extension.defaultValues("critical"));
+ /**
+ * @type {OctetString}
+ * @desc extnValue
+ */
+
+ if ("extnValue" in parameters) this.extnValue = new asn1js.OctetString({
+ valueHex: parameters.extnValue
+ });else this.extnValue = Extension.defaultValues("extnValue");
+ if ("parsedValue" in parameters)
+ /**
+ * @type {Object}
+ * @desc parsedValue
+ */
+ this.parsedValue = (0, _pvutils.getParametersValue)(parameters, "parsedValue", Extension.defaultValues("parsedValue")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "extnID":
+ return "";
+
+ case "critical":
+ return false;
+
+ case "extnValue":
+ return new asn1js.OctetString();
+
+ case "parsedValue":
+ return {};
+
+ default:
+ throw new Error(`Invalid member name for Extension class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * Extension ::= SEQUENCE {
+ * extnID OBJECT IDENTIFIER,
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [extnID]
+ * @property {string} [critical]
+ * @property {string} [extnValue]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.extnID || ""
+ }), new asn1js.Boolean({
+ name: names.critical || "",
+ optional: true
+ }), new asn1js.OctetString({
+ name: names.extnValue || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["extnID", "critical", "extnValue"]); //endregion
+ //region Check the schema is valid
+
+ let asn1 = asn1js.compareSchema(schema, schema, Extension.schema({
+ names: {
+ extnID: "extnID",
+ critical: "critical",
+ extnValue: "extnValue"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for Extension"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.extnID = asn1.result.extnID.valueBlock.toString();
+ if ("critical" in asn1.result) this.critical = asn1.result.critical.valueBlock.value;
+ this.extnValue = asn1.result.extnValue; //region Get "parsedValue" for well-known extensions
+
+ asn1 = asn1js.fromBER(this.extnValue.valueBlock.valueHex);
+ if (asn1.offset === -1) return;
+
+ switch (this.extnID) {
+ case "2.5.29.9":
+ // SubjectDirectoryAttributes
+ try {
+ this.parsedValue = new _SubjectDirectoryAttributes.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _SubjectDirectoryAttributes.default();
+ this.parsedValue.parsingError = "Incorrectly formated SubjectDirectoryAttributes";
+ }
+
+ break;
+
+ case "2.5.29.14":
+ // SubjectKeyIdentifier
+ this.parsedValue = asn1.result; // Should be just a simple OCTETSTRING
+
+ break;
+
+ case "2.5.29.15":
+ // KeyUsage
+ this.parsedValue = asn1.result; // Should be just a simple BITSTRING
+
+ break;
+
+ case "2.5.29.16":
+ // PrivateKeyUsagePeriod
+ try {
+ this.parsedValue = new _PrivateKeyUsagePeriod.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _PrivateKeyUsagePeriod.default();
+ this.parsedValue.parsingError = "Incorrectly formated PrivateKeyUsagePeriod";
+ }
+
+ break;
+
+ case "2.5.29.17": // SubjectAltName
+
+ case "2.5.29.18":
+ // IssuerAltName
+ try {
+ this.parsedValue = new _AltName.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _AltName.default();
+ this.parsedValue.parsingError = "Incorrectly formated AltName";
+ }
+
+ break;
+
+ case "2.5.29.19":
+ // BasicConstraints
+ try {
+ this.parsedValue = new _BasicConstraints.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _BasicConstraints.default();
+ this.parsedValue.parsingError = "Incorrectly formated BasicConstraints";
+ }
+
+ break;
+
+ case "2.5.29.20": // CRLNumber
+
+ case "2.5.29.27":
+ // BaseCRLNumber (delta CRL indicator)
+ this.parsedValue = asn1.result; // Should be just a simple INTEGER
+
+ break;
+
+ case "2.5.29.21":
+ // CRLReason
+ this.parsedValue = asn1.result; // Should be just a simple ENUMERATED
+
+ break;
+
+ case "2.5.29.24":
+ // InvalidityDate
+ this.parsedValue = asn1.result; // Should be just a simple GeneralizedTime
+
+ break;
+
+ case "2.5.29.28":
+ // IssuingDistributionPoint
+ try {
+ this.parsedValue = new _IssuingDistributionPoint.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _IssuingDistributionPoint.default();
+ this.parsedValue.parsingError = "Incorrectly formated IssuingDistributionPoint";
+ }
+
+ break;
+
+ case "2.5.29.29":
+ // CertificateIssuer
+ try {
+ this.parsedValue = new _GeneralNames.default({
+ schema: asn1.result
+ }); // Should be just a simple
+ } catch (ex) {
+ this.parsedValue = new _GeneralNames.default();
+ this.parsedValue.parsingError = "Incorrectly formated GeneralNames";
+ }
+
+ break;
+
+ case "2.5.29.30":
+ // NameConstraints
+ try {
+ this.parsedValue = new _NameConstraints.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _NameConstraints.default();
+ this.parsedValue.parsingError = "Incorrectly formated NameConstraints";
+ }
+
+ break;
+
+ case "2.5.29.31": // CRLDistributionPoints
+
+ case "2.5.29.46":
+ // FreshestCRL
+ try {
+ this.parsedValue = new _CRLDistributionPoints.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _CRLDistributionPoints.default();
+ this.parsedValue.parsingError = "Incorrectly formated CRLDistributionPoints";
+ }
+
+ break;
+
+ case "2.5.29.32": // CertificatePolicies
+
+ case "1.3.6.1.4.1.311.21.10":
+ // szOID_APPLICATION_CERT_POLICIES - Microsoft-specific OID
+ try {
+ this.parsedValue = new _CertificatePolicies.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _CertificatePolicies.default();
+ this.parsedValue.parsingError = "Incorrectly formated CertificatePolicies";
+ }
+
+ break;
+
+ case "2.5.29.33":
+ // PolicyMappings
+ try {
+ this.parsedValue = new _PolicyMappings.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _PolicyMappings.default();
+ this.parsedValue.parsingError = "Incorrectly formated CertificatePolicies";
+ }
+
+ break;
+
+ case "2.5.29.35":
+ // AuthorityKeyIdentifier
+ try {
+ this.parsedValue = new _AuthorityKeyIdentifier.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _AuthorityKeyIdentifier.default();
+ this.parsedValue.parsingError = "Incorrectly formated AuthorityKeyIdentifier";
+ }
+
+ break;
+
+ case "2.5.29.36":
+ // PolicyConstraints
+ try {
+ this.parsedValue = new _PolicyConstraints.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _PolicyConstraints.default();
+ this.parsedValue.parsingError = "Incorrectly formated PolicyConstraints";
+ }
+
+ break;
+
+ case "2.5.29.37":
+ // ExtKeyUsage
+ try {
+ this.parsedValue = new _ExtKeyUsage.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _ExtKeyUsage.default();
+ this.parsedValue.parsingError = "Incorrectly formated ExtKeyUsage";
+ }
+
+ break;
+
+ case "2.5.29.54":
+ // InhibitAnyPolicy
+ this.parsedValue = asn1.result; // Should be just a simple INTEGER
+
+ break;
+
+ case "1.3.6.1.5.5.7.1.1": // AuthorityInfoAccess
+
+ case "1.3.6.1.5.5.7.1.11":
+ // SubjectInfoAccess
+ try {
+ this.parsedValue = new _InfoAccess.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _InfoAccess.default();
+ this.parsedValue.parsingError = "Incorrectly formated InfoAccess";
+ }
+
+ break;
+
+ case "1.3.6.1.4.1.11129.2.4.2":
+ // SignedCertificateTimestampList
+ try {
+ this.parsedValue = new _SignedCertificateTimestampList.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _SignedCertificateTimestampList.default();
+ this.parsedValue.parsingError = "Incorrectly formated SignedCertificateTimestampList";
+ }
+
+ break;
+
+ case "1.3.6.1.4.1.311.20.2":
+ // szOID_ENROLL_CERTTYPE_EXTENSION - Microsoft-specific extension
+ this.parsedValue = asn1.result; // Used to be simple Unicode string
+
+ break;
+
+ case "1.3.6.1.4.1.311.21.2":
+ // szOID_CERTSRV_PREVIOUS_CERT_HASH - Microsoft-specific extension
+ this.parsedValue = asn1.result; // Used to be simple OctetString
+
+ break;
+
+ case "1.3.6.1.4.1.311.21.7":
+ // szOID_CERTIFICATE_TEMPLATE - Microsoft-specific extension
+ try {
+ this.parsedValue = new _CertificateTemplate.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _CertificateTemplate.default();
+ this.parsedValue.parsingError = "Incorrectly formated CertificateTemplate";
+ }
+
+ break;
+
+ case "1.3.6.1.4.1.311.21.1":
+ // szOID_CERTSRV_CA_VERSION - Microsoft-specific extension
+ try {
+ this.parsedValue = new _CAVersion.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _CAVersion.default();
+ this.parsedValue.parsingError = "Incorrectly formated CAVersion";
+ }
+
+ break;
+
+ case "1.3.6.1.5.5.7.1.3":
+ // QCStatements
+ try {
+ this.parsedValue = new _QCStatements.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ this.parsedValue = new _QCStatements.default();
+ this.parsedValue.parsingError = "Incorrectly formated QCStatements";
+ }
+
+ break;
+
+ default:
+ } //endregion
+ //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(new asn1js.ObjectIdentifier({
+ value: this.extnID
+ }));
+ if (this.critical !== Extension.defaultValues("critical")) outputArray.push(new asn1js.Boolean({
+ value: this.critical
+ }));
+ outputArray.push(this.extnValue); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {
+ extnID: this.extnID,
+ extnValue: this.extnValue.toJSON()
+ };
+ if (this.critical !== Extension.defaultValues("critical")) object.critical = this.critical;
+
+ if ("parsedValue" in this) {
+ if ("toJSON" in this.parsedValue) object.parsedValue = this.parsedValue.toJSON();
+ }
+
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = Extension;
+
+},{"./AltName.js":5,"./AuthorityKeyIdentifier.js":11,"./BasicConstraints.js":12,"./CAVersion.js":14,"./CRLDistributionPoints.js":16,"./CertificatePolicies.js":21,"./CertificateTemplate.js":24,"./ExtKeyUsage.js":37,"./GeneralNames.js":41,"./InfoAccess.js":43,"./IssuingDistributionPoint.js":45,"./NameConstraints.js":54,"./PolicyConstraints.js":71,"./PolicyMappings.js":74,"./PrivateKeyUsagePeriod.js":77,"./QCStatements.js":79,"./SignedCertificateTimestampList.js":100,"./SubjectDirectoryAttributes.js":104,"asn1js":112,"pvutils":113}],39:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _Extension = _interopRequireDefault(require("./Extension.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class Extensions {
+ //**********************************************************************************
+
+ /**
+ * Constructor for Extensions class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array.<Extension>}
+ * @desc type
+ */
+ this.extensions = (0, _pvutils.getParametersValue)(parameters, "extensions", Extensions.defaultValues("extensions")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "extensions":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for Extensions class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @param {boolean} optional Flag that current schema should be optional
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}, optional = false) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [extensions]
+ * @property {string} [extension]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ optional,
+ name: names.blockName || "",
+ value: [new asn1js.Repeated({
+ name: names.extensions || "",
+ value: _Extension.default.schema(names.extension || {})
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["extensions"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, Extensions.schema({
+ names: {
+ extensions: "extensions"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for Extensions"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.extensions = Array.from(asn1.result.extensions, element => new _Extension.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: Array.from(this.extensions, element => element.toSchema())
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ extensions: Array.from(this.extensions, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = Extensions;
+
+},{"./Extension.js":38,"asn1js":112,"pvutils":113}],40:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _RelativeDistinguishedNames = _interopRequireDefault(require("./RelativeDistinguishedNames.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+//region Additional asn1js schema elements existing inside GeneralName schema
+//**************************************************************************************
+
+/**
+ * Schema for "builtInStandardAttributes" of "ORAddress"
+ * @param {Object} parameters
+ * @property {Object} [names]
+ * @param {boolean} optional
+ * @returns {Sequence}
+ */
+function builtInStandardAttributes(parameters = {}, optional = false) {
+ //builtInStandardAttributes ::= Sequence {
+ // country-name CountryName OPTIONAL,
+ // administration-domain-name AdministrationDomainName OPTIONAL,
+ // network-address [0] IMPLICIT NetworkAddress OPTIONAL,
+ // terminal-identifier [1] IMPLICIT TerminalIdentifier OPTIONAL,
+ // private-domain-name [2] PrivateDomainName OPTIONAL,
+ // organization-name [3] IMPLICIT OrganizationName OPTIONAL,
+ // numeric-user-identifier [4] IMPLICIT NumericUserIdentifier OPTIONAL,
+ // personal-name [5] IMPLICIT PersonalName OPTIONAL,
+ // organizational-unit-names [6] IMPLICIT OrganizationalUnitNames OPTIONAL }
+
+ /**
+ * @type {Object}
+ * @property {string} [country_name]
+ * @property {string} [administration_domain_name]
+ * @property {string} [network_address]
+ * @property {string} [terminal_identifier]
+ * @property {string} [private_domain_name]
+ * @property {string} [organization_name]
+ * @property {string} [numeric_user_identifier]
+ * @property {string} [personal_name]
+ * @property {string} [organizational_unit_names]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ optional,
+ value: [new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 2,
+ // APPLICATION-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ name: names.country_name || "",
+ value: [new asn1js.Choice({
+ value: [new asn1js.NumericString(), new asn1js.PrintableString()]
+ })]
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 2,
+ // APPLICATION-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ name: names.administration_domain_name || "",
+ value: [new asn1js.Choice({
+ value: [new asn1js.NumericString(), new asn1js.PrintableString()]
+ })]
+ }), new asn1js.Primitive({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ name: names.network_address || "",
+ isHexOnly: true
+ }), new asn1js.Primitive({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ name: names.terminal_identifier || "",
+ isHexOnly: true
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ name: names.private_domain_name || "",
+ value: [new asn1js.Choice({
+ value: [new asn1js.NumericString(), new asn1js.PrintableString()]
+ })]
+ }), new asn1js.Primitive({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 3 // [3]
+
+ },
+ name: names.organization_name || "",
+ isHexOnly: true
+ }), new asn1js.Primitive({
+ optional: true,
+ name: names.numeric_user_identifier || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 4 // [4]
+
+ },
+ isHexOnly: true
+ }), new asn1js.Constructed({
+ optional: true,
+ name: names.personal_name || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 5 // [5]
+
+ },
+ value: [new asn1js.Primitive({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ isHexOnly: true
+ }), new asn1js.Primitive({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ isHexOnly: true
+ }), new asn1js.Primitive({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ isHexOnly: true
+ }), new asn1js.Primitive({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 3 // [3]
+
+ },
+ isHexOnly: true
+ })]
+ }), new asn1js.Constructed({
+ optional: true,
+ name: names.organizational_unit_names || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 6 // [6]
+
+ },
+ value: [new asn1js.Repeated({
+ value: new asn1js.PrintableString()
+ })]
+ })]
+ });
+} //**************************************************************************************
+
+/**
+ * Schema for "builtInDomainDefinedAttributes" of "ORAddress"
+ * @param {boolean} optional
+ * @returns {Sequence}
+ */
+
+
+function builtInDomainDefinedAttributes(optional = false) {
+ return new asn1js.Sequence({
+ optional,
+ value: [new asn1js.PrintableString(), new asn1js.PrintableString()]
+ });
+} //**************************************************************************************
+
+/**
+ * Schema for "builtInDomainDefinedAttributes" of "ORAddress"
+ * @param {boolean} optional
+ * @returns {Set}
+ */
+
+
+function extensionAttributes(optional = false) {
+ return new asn1js.Set({
+ optional,
+ value: [new asn1js.Primitive({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ isHexOnly: true
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [new asn1js.Any()]
+ })]
+ });
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+
+
+class GeneralName {
+ //**********************************************************************************
+
+ /**
+ * Constructor for GeneralName class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ * @property {number} [type] value type - from a tagged value (0 for "otherName", 1 for "rfc822Name" etc.)
+ * @property {Object} [value] asn1js object having GeneralName value (type depends on "type" value)
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc value type - from a tagged value (0 for "otherName", 1 for "rfc822Name" etc.)
+ */
+ this.type = (0, _pvutils.getParametersValue)(parameters, "type", GeneralName.defaultValues("type"));
+ /**
+ * @type {Object}
+ * @desc asn1js object having GeneralName value (type depends on "type" value)
+ */
+
+ this.value = (0, _pvutils.getParametersValue)(parameters, "value", GeneralName.defaultValues("value")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "type":
+ return 9;
+
+ case "value":
+ return {};
+
+ default:
+ throw new Error(`Invalid member name for GeneralName class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "type":
+ return memberValue === GeneralName.defaultValues(memberName);
+
+ case "value":
+ return Object.keys(memberValue).length === 0;
+
+ default:
+ throw new Error(`Invalid member name for GeneralName class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * GeneralName ::= Choice {
+ * otherName [0] OtherName,
+ * rfc822Name [1] IA5String,
+ * dNSName [2] IA5String,
+ * x400Address [3] ORAddress,
+ * directoryName [4] value,
+ * ediPartyName [5] EDIPartyName,
+ * uniformResourceIdentifier [6] IA5String,
+ * iPAddress [7] OCTET STRING,
+ * registeredID [8] OBJECT IDENTIFIER }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {Object} [directoryName]
+ * @property {Object} [builtInStandardAttributes]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Choice({
+ value: [new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier(), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Any()]
+ })]
+ }), new asn1js.Primitive({
+ name: names.blockName || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ }
+ }), new asn1js.Primitive({
+ name: names.blockName || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ }
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 3 // [3]
+
+ },
+ name: names.blockName || "",
+ value: [builtInStandardAttributes(names.builtInStandardAttributes || {}, false), builtInDomainDefinedAttributes(true), extensionAttributes(true)]
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 4 // [4]
+
+ },
+ name: names.blockName || "",
+ value: [_RelativeDistinguishedNames.default.schema(names.directoryName || {})]
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 5 // [5]
+
+ },
+ name: names.blockName || "",
+ value: [new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Choice({
+ value: [new asn1js.TeletexString(), new asn1js.PrintableString(), new asn1js.UniversalString(), new asn1js.Utf8String(), new asn1js.BmpString()]
+ })]
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [new asn1js.Choice({
+ value: [new asn1js.TeletexString(), new asn1js.PrintableString(), new asn1js.UniversalString(), new asn1js.Utf8String(), new asn1js.BmpString()]
+ })]
+ })]
+ }), new asn1js.Primitive({
+ name: names.blockName || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 6 // [6]
+
+ }
+ }), new asn1js.Primitive({
+ name: names.blockName || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 7 // [7]
+
+ }
+ }), new asn1js.Primitive({
+ name: names.blockName || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 8 // [8]
+
+ }
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["blockName", "otherName", "rfc822Name", "dNSName", "x400Address", "directoryName", "ediPartyName", "uniformResourceIdentifier", "iPAddress", "registeredID"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, GeneralName.schema({
+ names: {
+ blockName: "blockName",
+ otherName: "otherName",
+ rfc822Name: "rfc822Name",
+ dNSName: "dNSName",
+ x400Address: "x400Address",
+ directoryName: {
+ names: {
+ blockName: "directoryName"
+ }
+ },
+ ediPartyName: "ediPartyName",
+ uniformResourceIdentifier: "uniformResourceIdentifier",
+ iPAddress: "iPAddress",
+ registeredID: "registeredID"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for GeneralName"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.type = asn1.result.blockName.idBlock.tagNumber;
+
+ switch (this.type) {
+ case 0:
+ // otherName
+ this.value = asn1.result.blockName;
+ break;
+
+ case 1: // rfc822Name + dNSName + uniformResourceIdentifier
+
+ case 2:
+ case 6:
+ {
+ const value = asn1.result.blockName;
+ value.idBlock.tagClass = 1; // UNIVERSAL
+
+ value.idBlock.tagNumber = 22; // IA5STRING
+
+ const valueBER = value.toBER(false);
+ this.value = asn1js.fromBER(valueBER).result.valueBlock.value;
+ }
+ break;
+
+ case 3:
+ // x400Address
+ this.value = asn1.result.blockName;
+ break;
+
+ case 4:
+ // directoryName
+ this.value = new _RelativeDistinguishedNames.default({
+ schema: asn1.result.directoryName
+ });
+ break;
+
+ case 5:
+ // ediPartyName
+ this.value = asn1.result.ediPartyName;
+ break;
+
+ case 7:
+ // iPAddress
+ this.value = new asn1js.OctetString({
+ valueHex: asn1.result.blockName.valueBlock.valueHex
+ });
+ break;
+
+ case 8:
+ // registeredID
+ {
+ const value = asn1.result.blockName;
+ value.idBlock.tagClass = 1; // UNIVERSAL
+
+ value.idBlock.tagNumber = 6; // ObjectIdentifier
+
+ const valueBER = value.toBER(false);
+ this.value = asn1js.fromBER(valueBER).result.valueBlock.toString(); // Getting a string representation of the ObjectIdentifier
+ }
+ break;
+
+ default:
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ switch (this.type) {
+ case 0:
+ case 3:
+ case 5:
+ return new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: this.type
+ },
+ value: [this.value]
+ });
+
+ case 1:
+ case 2:
+ case 6:
+ {
+ const value = new asn1js.IA5String({
+ value: this.value
+ });
+ value.idBlock.tagClass = 3;
+ value.idBlock.tagNumber = this.type;
+ return value;
+ }
+
+ case 4:
+ return new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 4
+ },
+ value: [this.value.toSchema()]
+ });
+
+ case 7:
+ {
+ const value = this.value;
+ value.idBlock.tagClass = 3;
+ value.idBlock.tagNumber = this.type;
+ return value;
+ }
+
+ case 8:
+ {
+ const value = new asn1js.ObjectIdentifier({
+ value: this.value
+ });
+ value.idBlock.tagClass = 3;
+ value.idBlock.tagNumber = this.type;
+ return value;
+ }
+
+ default:
+ return GeneralName.schema();
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ type: this.type,
+ value: ""
+ };
+ if (typeof this.value === "string") _object.value = this.value;else {
+ try {
+ _object.value = this.value.toJSON();
+ } catch (ex) {}
+ }
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = GeneralName;
+
+},{"./RelativeDistinguishedNames.js":89,"asn1js":112,"pvutils":113}],41:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _GeneralName = _interopRequireDefault(require("./GeneralName.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class GeneralNames {
+ //**********************************************************************************
+
+ /**
+ * Constructor for GeneralNames class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array.<GeneralName>}
+ * @desc Array of "general names"
+ */
+ this.names = (0, _pvutils.getParametersValue)(parameters, "names", GeneralNames.defaultValues("names")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "names":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for GeneralNames class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @param {boolean} [optional=false] Flag would be element optional or not
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}, optional = false) {
+ /**
+ * @type {Object}
+ * @property {string} utcTimeName Name for "utcTimeName" choice
+ * @property {string} generalTimeName Name for "generalTimeName" choice
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ optional,
+ name: names.blockName || "",
+ value: [new asn1js.Repeated({
+ name: names.generalNames || "",
+ value: _GeneralName.default.schema()
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["names", "generalNames"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, GeneralNames.schema({
+ names: {
+ blockName: "names",
+ generalNames: "generalNames"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for GeneralNames"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.names = Array.from(asn1.result.generalNames, element => new _GeneralName.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: Array.from(this.names, element => element.toSchema())
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ names: Array.from(this.names, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = GeneralNames;
+
+},{"./GeneralName.js":40,"asn1js":112,"pvutils":113}],42:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _GeneralName = _interopRequireDefault(require("./GeneralName.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class GeneralSubtree {
+ //**********************************************************************************
+
+ /**
+ * Constructor for GeneralSubtree class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {GeneralName}
+ * @desc base
+ */
+ this.base = (0, _pvutils.getParametersValue)(parameters, "base", GeneralSubtree.defaultValues("base"));
+ /**
+ * @type {number|Integer}
+ * @desc base
+ */
+
+ this.minimum = (0, _pvutils.getParametersValue)(parameters, "minimum", GeneralSubtree.defaultValues("minimum"));
+ if ("maximum" in parameters)
+ /**
+ * @type {number|Integer}
+ * @desc minimum
+ */
+ this.maximum = (0, _pvutils.getParametersValue)(parameters, "maximum", GeneralSubtree.defaultValues("maximum")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "base":
+ return new _GeneralName.default();
+
+ case "minimum":
+ return 0;
+
+ case "maximum":
+ return 0;
+
+ default:
+ throw new Error(`Invalid member name for GeneralSubtree class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * GeneralSubtree ::= SEQUENCE {
+ * base GeneralName,
+ * minimum [0] BaseDistance DEFAULT 0,
+ * maximum [1] BaseDistance OPTIONAL }
+ *
+ * BaseDistance ::= INTEGER (0..MAX)
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [base]
+ * @property {string} [minimum]
+ * @property {string} [maximum]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [_GeneralName.default.schema(names.base || {}), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Integer({
+ name: names.minimum || ""
+ })]
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [new asn1js.Integer({
+ name: names.maximum || ""
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["base", "minimum", "maximum"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, GeneralSubtree.schema({
+ names: {
+ base: {
+ names: {
+ blockName: "base"
+ }
+ },
+ minimum: "minimum",
+ maximum: "maximum"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for GeneralSubtree"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.base = new _GeneralName.default({
+ schema: asn1.result.base
+ });
+
+ if ("minimum" in asn1.result) {
+ if (asn1.result.minimum.valueBlock.isHexOnly) this.minimum = asn1.result.minimum;else this.minimum = asn1.result.minimum.valueBlock.valueDec;
+ }
+
+ if ("maximum" in asn1.result) {
+ if (asn1.result.maximum.valueBlock.isHexOnly) this.maximum = asn1.result.maximum;else this.maximum = asn1.result.maximum.valueBlock.valueDec;
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(this.base.toSchema());
+
+ if (this.minimum !== 0) {
+ let valueMinimum = 0;
+ if (this.minimum instanceof asn1js.Integer) valueMinimum = this.minimum;else valueMinimum = new asn1js.Integer({
+ value: this.minimum
+ });
+ outputArray.push(new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [valueMinimum]
+ }));
+ }
+
+ if ("maximum" in this) {
+ let valueMaximum = 0;
+ if (this.maximum instanceof asn1js.Integer) valueMaximum = this.maximum;else valueMaximum = new asn1js.Integer({
+ value: this.maximum
+ });
+ outputArray.push(new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [valueMaximum]
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {
+ base: this.base.toJSON()
+ };
+
+ if (this.minimum !== 0) {
+ if (typeof this.minimum === "number") object.minimum = this.minimum;else object.minimum = this.minimum.toJSON();
+ }
+
+ if ("maximum" in this) {
+ if (typeof this.maximum === "number") object.maximum = this.maximum;else object.maximum = this.maximum.toJSON();
+ }
+
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = GeneralSubtree;
+
+},{"./GeneralName.js":40,"asn1js":112,"pvutils":113}],43:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AccessDescription = _interopRequireDefault(require("./AccessDescription.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class InfoAccess {
+ //**********************************************************************************
+
+ /**
+ * Constructor for InfoAccess class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array.<AccessDescription>}
+ * @desc accessDescriptions
+ */
+ this.accessDescriptions = (0, _pvutils.getParametersValue)(parameters, "accessDescriptions", InfoAccess.defaultValues("accessDescriptions")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "accessDescriptions":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for InfoAccess class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * AuthorityInfoAccessSyntax ::=
+ * SEQUENCE SIZE (1..MAX) OF AccessDescription
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [accessDescriptions]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Repeated({
+ name: names.accessDescriptions || "",
+ value: _AccessDescription.default.schema()
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["accessDescriptions"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, InfoAccess.schema({
+ names: {
+ accessDescriptions: "accessDescriptions"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for InfoAccess"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.accessDescriptions = Array.from(asn1.result.accessDescriptions, element => new _AccessDescription.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: Array.from(this.accessDescriptions, element => element.toSchema())
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ accessDescriptions: Array.from(this.accessDescriptions, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = InfoAccess;
+
+},{"./AccessDescription.js":2,"asn1js":112,"pvutils":113}],44:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _RelativeDistinguishedNames = _interopRequireDefault(require("./RelativeDistinguishedNames.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class IssuerAndSerialNumber {
+ //**********************************************************************************
+
+ /**
+ * Constructor for IssuerAndSerialNumber class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {RelativeDistinguishedNames}
+ * @desc issuer
+ */
+ this.issuer = (0, _pvutils.getParametersValue)(parameters, "issuer", IssuerAndSerialNumber.defaultValues("issuer"));
+ /**
+ * @type {Integer}
+ * @desc serialNumber
+ */
+
+ this.serialNumber = (0, _pvutils.getParametersValue)(parameters, "serialNumber", IssuerAndSerialNumber.defaultValues("serialNumber")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "issuer":
+ return new _RelativeDistinguishedNames.default();
+
+ case "serialNumber":
+ return new asn1js.Integer();
+
+ default:
+ throw new Error(`Invalid member name for IssuerAndSerialNumber class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * IssuerAndSerialNumber ::= SEQUENCE {
+ * issuer Name,
+ * serialNumber CertificateSerialNumber }
+ *
+ * CertificateSerialNumber ::= INTEGER
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [issuer]
+ * @property {string} [serialNumber]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [_RelativeDistinguishedNames.default.schema(names.issuer || {}), new asn1js.Integer({
+ name: names.serialNumber || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["issuer", "serialNumber"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, IssuerAndSerialNumber.schema({
+ names: {
+ issuer: {
+ names: {
+ blockName: "issuer"
+ }
+ },
+ serialNumber: "serialNumber"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for IssuerAndSerialNumber"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.issuer = new _RelativeDistinguishedNames.default({
+ schema: asn1.result.issuer
+ });
+ this.serialNumber = asn1.result.serialNumber; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [this.issuer.toSchema(), this.serialNumber]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ issuer: this.issuer.toJSON(),
+ serialNumber: this.serialNumber.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = IssuerAndSerialNumber;
+
+},{"./RelativeDistinguishedNames.js":89,"asn1js":112,"pvutils":113}],45:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _GeneralName = _interopRequireDefault(require("./GeneralName.js"));
+
+var _RelativeDistinguishedNames = _interopRequireDefault(require("./RelativeDistinguishedNames.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class IssuingDistributionPoint {
+ //**********************************************************************************
+
+ /**
+ * Constructor for IssuingDistributionPoint class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+ if ("distributionPoint" in parameters)
+ /**
+ * @type {Array.<GeneralName>|RelativeDistinguishedNames}
+ * @desc distributionPoint
+ */
+ this.distributionPoint = (0, _pvutils.getParametersValue)(parameters, "distributionPoint", IssuingDistributionPoint.defaultValues("distributionPoint"));
+ /**
+ * @type {boolean}
+ * @desc onlyContainsUserCerts
+ */
+
+ this.onlyContainsUserCerts = (0, _pvutils.getParametersValue)(parameters, "onlyContainsUserCerts", IssuingDistributionPoint.defaultValues("onlyContainsUserCerts"));
+ /**
+ * @type {boolean}
+ * @desc onlyContainsCACerts
+ */
+
+ this.onlyContainsCACerts = (0, _pvutils.getParametersValue)(parameters, "onlyContainsCACerts", IssuingDistributionPoint.defaultValues("onlyContainsCACerts"));
+ if ("onlySomeReasons" in parameters)
+ /**
+ * @type {number}
+ * @desc onlySomeReasons
+ */
+ this.onlySomeReasons = (0, _pvutils.getParametersValue)(parameters, "onlySomeReasons", IssuingDistributionPoint.defaultValues("onlySomeReasons"));
+ /**
+ * @type {boolean}
+ * @desc indirectCRL
+ */
+
+ this.indirectCRL = (0, _pvutils.getParametersValue)(parameters, "indirectCRL", IssuingDistributionPoint.defaultValues("indirectCRL"));
+ /**
+ * @type {boolean}
+ * @desc onlyContainsAttributeCerts
+ */
+
+ this.onlyContainsAttributeCerts = (0, _pvutils.getParametersValue)(parameters, "onlyContainsAttributeCerts", IssuingDistributionPoint.defaultValues("onlyContainsAttributeCerts")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "distributionPoint":
+ return [];
+
+ case "onlyContainsUserCerts":
+ return false;
+
+ case "onlyContainsCACerts":
+ return false;
+
+ case "onlySomeReasons":
+ return 0;
+
+ case "indirectCRL":
+ return false;
+
+ case "onlyContainsAttributeCerts":
+ return false;
+
+ default:
+ throw new Error(`Invalid member name for IssuingDistributionPoint class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * IssuingDistributionPoint ::= SEQUENCE {
+ * distributionPoint [0] DistributionPointName OPTIONAL,
+ * onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE,
+ * onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE,
+ * onlySomeReasons [3] ReasonFlags OPTIONAL,
+ * indirectCRL [4] BOOLEAN DEFAULT FALSE,
+ * onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
+ *
+ * ReasonFlags ::= BIT STRING {
+ * unused (0),
+ * keyCompromise (1),
+ * cACompromise (2),
+ * affiliationChanged (3),
+ * superseded (4),
+ * cessationOfOperation (5),
+ * certificateHold (6),
+ * privilegeWithdrawn (7),
+ * aACompromise (8) }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [distributionPoint]
+ * @property {string} [distributionPointNames]
+ * @property {string} [onlyContainsUserCerts]
+ * @property {string} [onlyContainsCACerts]
+ * @property {string} [onlySomeReasons]
+ * @property {string} [indirectCRL]
+ * @property {string} [onlyContainsAttributeCerts]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Choice({
+ value: [new asn1js.Constructed({
+ name: names.distributionPoint || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Repeated({
+ name: names.distributionPointNames || "",
+ value: _GeneralName.default.schema()
+ })]
+ }), new asn1js.Constructed({
+ name: names.distributionPoint || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: _RelativeDistinguishedNames.default.schema().valueBlock.value
+ })]
+ })]
+ }), new asn1js.Primitive({
+ name: names.onlyContainsUserCerts || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ }
+ }), // IMPLICIT boolean value
+ new asn1js.Primitive({
+ name: names.onlyContainsCACerts || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ }
+ }), // IMPLICIT boolean value
+ new asn1js.Primitive({
+ name: names.onlySomeReasons || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 3 // [3]
+
+ }
+ }), // IMPLICIT bitstring value
+ new asn1js.Primitive({
+ name: names.indirectCRL || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 4 // [4]
+
+ }
+ }), // IMPLICIT boolean value
+ new asn1js.Primitive({
+ name: names.onlyContainsAttributeCerts || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 5 // [5]
+
+ }
+ }) // IMPLICIT boolean value
+ ]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["distributionPoint", "distributionPointNames", "onlyContainsUserCerts", "onlyContainsCACerts", "onlySomeReasons", "indirectCRL", "onlyContainsAttributeCerts"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, IssuingDistributionPoint.schema({
+ names: {
+ distributionPoint: "distributionPoint",
+ distributionPointNames: "distributionPointNames",
+ onlyContainsUserCerts: "onlyContainsUserCerts",
+ onlyContainsCACerts: "onlyContainsCACerts",
+ onlySomeReasons: "onlySomeReasons",
+ indirectCRL: "indirectCRL",
+ onlyContainsAttributeCerts: "onlyContainsAttributeCerts"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for IssuingDistributionPoint"); //endregion
+ //region Get internal properties from parsed schema
+
+ if ("distributionPoint" in asn1.result) {
+ switch (true) {
+ case asn1.result.distributionPoint.idBlock.tagNumber === 0:
+ // GENERAL_NAMES variant
+ this.distributionPoint = Array.from(asn1.result.distributionPointNames, element => new _GeneralName.default({
+ schema: element
+ }));
+ break;
+
+ case asn1.result.distributionPoint.idBlock.tagNumber === 1:
+ // RDN variant
+ {
+ this.distributionPoint = new _RelativeDistinguishedNames.default({
+ schema: new asn1js.Sequence({
+ value: asn1.result.distributionPoint.valueBlock.value
+ })
+ });
+ }
+ break;
+
+ default:
+ throw new Error("Unknown tagNumber for distributionPoint: {$asn1.result.distributionPoint.idBlock.tagNumber}");
+ }
+ }
+
+ if ("onlyContainsUserCerts" in asn1.result) {
+ const view = new Uint8Array(asn1.result.onlyContainsUserCerts.valueBlock.valueHex);
+ this.onlyContainsUserCerts = view[0] !== 0x00;
+ }
+
+ if ("onlyContainsCACerts" in asn1.result) {
+ const view = new Uint8Array(asn1.result.onlyContainsCACerts.valueBlock.valueHex);
+ this.onlyContainsCACerts = view[0] !== 0x00;
+ }
+
+ if ("onlySomeReasons" in asn1.result) {
+ const view = new Uint8Array(asn1.result.onlySomeReasons.valueBlock.valueHex);
+ this.onlySomeReasons = view[0];
+ }
+
+ if ("indirectCRL" in asn1.result) {
+ const view = new Uint8Array(asn1.result.indirectCRL.valueBlock.valueHex);
+ this.indirectCRL = view[0] !== 0x00;
+ }
+
+ if ("onlyContainsAttributeCerts" in asn1.result) {
+ const view = new Uint8Array(asn1.result.onlyContainsAttributeCerts.valueBlock.valueHex);
+ this.onlyContainsAttributeCerts = view[0] !== 0x00;
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+
+ if ("distributionPoint" in this) {
+ let value;
+
+ if (this.distributionPoint instanceof Array) {
+ value = new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: Array.from(this.distributionPoint, element => element.toSchema())
+ });
+ } else {
+ value = this.distributionPoint.toSchema();
+ value.idBlock.tagClass = 3; // CONTEXT - SPECIFIC
+
+ value.idBlock.tagNumber = 1; // [1]
+ }
+
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [value]
+ }));
+ }
+
+ if (this.onlyContainsUserCerts !== IssuingDistributionPoint.defaultValues("onlyContainsUserCerts")) {
+ outputArray.push(new asn1js.Primitive({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ valueHex: new Uint8Array([0xFF]).buffer
+ }));
+ }
+
+ if (this.onlyContainsCACerts !== IssuingDistributionPoint.defaultValues("onlyContainsCACerts")) {
+ outputArray.push(new asn1js.Primitive({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ valueHex: new Uint8Array([0xFF]).buffer
+ }));
+ }
+
+ if ("onlySomeReasons" in this) {
+ const buffer = new ArrayBuffer(1);
+ const view = new Uint8Array(buffer);
+ view[0] = this.onlySomeReasons;
+ outputArray.push(new asn1js.Primitive({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 3 // [3]
+
+ },
+ valueHex: buffer
+ }));
+ }
+
+ if (this.indirectCRL !== IssuingDistributionPoint.defaultValues("indirectCRL")) {
+ outputArray.push(new asn1js.Primitive({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 4 // [4]
+
+ },
+ valueHex: new Uint8Array([0xFF]).buffer
+ }));
+ }
+
+ if (this.onlyContainsAttributeCerts !== IssuingDistributionPoint.defaultValues("onlyContainsAttributeCerts")) {
+ outputArray.push(new asn1js.Primitive({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 5 // [5]
+
+ },
+ valueHex: new Uint8Array([0xFF]).buffer
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {};
+
+ if ("distributionPoint" in this) {
+ if (this.distributionPoint instanceof Array) object.distributionPoint = Array.from(this.distributionPoint, element => element.toJSON());else object.distributionPoint = this.distributionPoint.toJSON();
+ }
+
+ if (this.onlyContainsUserCerts !== IssuingDistributionPoint.defaultValues("onlyContainsUserCerts")) object.onlyContainsUserCerts = this.onlyContainsUserCerts;
+ if (this.onlyContainsCACerts !== IssuingDistributionPoint.defaultValues("onlyContainsCACerts")) object.onlyContainsCACerts = this.onlyContainsCACerts;
+ if ("onlySomeReasons" in this) object.onlySomeReasons = this.onlySomeReasons;
+ if (this.indirectCRL !== IssuingDistributionPoint.defaultValues("indirectCRL")) object.indirectCRL = this.indirectCRL;
+ if (this.onlyContainsAttributeCerts !== IssuingDistributionPoint.defaultValues("onlyContainsAttributeCerts")) object.onlyContainsAttributeCerts = this.onlyContainsAttributeCerts;
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = IssuingDistributionPoint;
+
+},{"./GeneralName.js":40,"./RelativeDistinguishedNames.js":89,"asn1js":112,"pvutils":113}],46:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _OtherKeyAttribute = _interopRequireDefault(require("./OtherKeyAttribute.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class KEKIdentifier {
+ //**********************************************************************************
+
+ /**
+ * Constructor for KEKIdentifier class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {OctetString}
+ * @desc keyIdentifier
+ */
+ this.keyIdentifier = (0, _pvutils.getParametersValue)(parameters, "keyIdentifier", KEKIdentifier.defaultValues("keyIdentifier"));
+ if ("date" in parameters)
+ /**
+ * @type {GeneralizedTime}
+ * @desc date
+ */
+ this.date = (0, _pvutils.getParametersValue)(parameters, "date", KEKIdentifier.defaultValues("date"));
+ if ("other" in parameters)
+ /**
+ * @type {OtherKeyAttribute}
+ * @desc other
+ */
+ this.other = (0, _pvutils.getParametersValue)(parameters, "other", KEKIdentifier.defaultValues("other")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "keyIdentifier":
+ return new asn1js.OctetString();
+
+ case "date":
+ return new asn1js.GeneralizedTime();
+
+ case "other":
+ return new _OtherKeyAttribute.default();
+
+ default:
+ throw new Error(`Invalid member name for KEKIdentifier class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "keyIdentifier":
+ return memberValue.isEqual(KEKIdentifier.defaultValues("keyIdentifier"));
+
+ case "date":
+ // noinspection OverlyComplexBooleanExpressionJS
+ return memberValue.year === 0 && memberValue.month === 0 && memberValue.day === 0 && memberValue.hour === 0 && memberValue.minute === 0 && memberValue.second === 0 && memberValue.millisecond === 0;
+
+ case "other":
+ return memberValue.compareWithDefault("keyAttrId", memberValue.keyAttrId) && "keyAttr" in memberValue === false;
+
+ default:
+ throw new Error(`Invalid member name for KEKIdentifier class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * KEKIdentifier ::= SEQUENCE {
+ * keyIdentifier OCTET STRING,
+ * date GeneralizedTime OPTIONAL,
+ * other OtherKeyAttribute OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [keyIdentifier]
+ * @property {string} [date]
+ * @property {string} [other]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.OctetString({
+ name: names.keyIdentifier || ""
+ }), new asn1js.GeneralizedTime({
+ optional: true,
+ name: names.date || ""
+ }), _OtherKeyAttribute.default.schema(names.other || {})]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["keyIdentifier", "date", "other"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, KEKIdentifier.schema({
+ names: {
+ keyIdentifier: "keyIdentifier",
+ date: "date",
+ other: {
+ names: {
+ blockName: "other"
+ }
+ }
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for KEKIdentifier"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.keyIdentifier = asn1.result.keyIdentifier;
+ if ("date" in asn1.result) this.date = asn1.result.date;
+ if ("other" in asn1.result) this.other = new _OtherKeyAttribute.default({
+ schema: asn1.result.other
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(this.keyIdentifier);
+ if ("date" in this) outputArray.push(this.date);
+ if ("other" in this) outputArray.push(this.other.toSchema()); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ keyIdentifier: this.keyIdentifier.toJSON()
+ };
+ if ("date" in this) _object.date = this.date;
+ if ("other" in this) _object.other = this.other.toJSON();
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = KEKIdentifier;
+
+},{"./OtherKeyAttribute.js":61,"asn1js":112,"pvutils":113}],47:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _KEKIdentifier = _interopRequireDefault(require("./KEKIdentifier.js"));
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class KEKRecipientInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for KEKRecipientInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", KEKRecipientInfo.defaultValues("version"));
+ /**
+ * @type {KEKIdentifier}
+ * @desc kekid
+ */
+
+ this.kekid = (0, _pvutils.getParametersValue)(parameters, "kekid", KEKRecipientInfo.defaultValues("kekid"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc keyEncryptionAlgorithm
+ */
+
+ this.keyEncryptionAlgorithm = (0, _pvutils.getParametersValue)(parameters, "keyEncryptionAlgorithm", KEKRecipientInfo.defaultValues("keyEncryptionAlgorithm"));
+ /**
+ * @type {OctetString}
+ * @desc encryptedKey
+ */
+
+ this.encryptedKey = (0, _pvutils.getParametersValue)(parameters, "encryptedKey", KEKRecipientInfo.defaultValues("encryptedKey"));
+ /**
+ * @type {ArrayBuffer}
+ * @desc preDefinedKEK KEK using to encrypt CEK
+ */
+
+ this.preDefinedKEK = (0, _pvutils.getParametersValue)(parameters, "preDefinedKEK", KEKRecipientInfo.defaultValues("preDefinedKEK")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return 0;
+
+ case "kekid":
+ return new _KEKIdentifier.default();
+
+ case "keyEncryptionAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "encryptedKey":
+ return new asn1js.OctetString();
+
+ case "preDefinedKEK":
+ return new ArrayBuffer(0);
+
+ default:
+ throw new Error(`Invalid member name for KEKRecipientInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "KEKRecipientInfo":
+ return memberValue === KEKRecipientInfo.defaultValues("version");
+
+ case "kekid":
+ return memberValue.compareWithDefault("keyIdentifier", memberValue.keyIdentifier) && "date" in memberValue === false && "other" in memberValue === false;
+
+ case "keyEncryptionAlgorithm":
+ return memberValue.algorithmId === "" && "algorithmParams" in memberValue === false;
+
+ case "encryptedKey":
+ return memberValue.isEqual(KEKRecipientInfo.defaultValues("encryptedKey"));
+
+ case "preDefinedKEK":
+ return memberValue.byteLength === 0;
+
+ default:
+ throw new Error(`Invalid member name for KEKRecipientInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * KEKRecipientInfo ::= SEQUENCE {
+ * version CMSVersion, -- always set to 4
+ * kekid KEKIdentifier,
+ * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ * encryptedKey EncryptedKey }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [version]
+ * @property {string} [kekid]
+ * @property {string} [keyEncryptionAlgorithm]
+ * @property {string} [encryptedKey]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Integer({
+ name: names.version || ""
+ }), _KEKIdentifier.default.schema(names.kekid || {}), _AlgorithmIdentifier.default.schema(names.keyEncryptionAlgorithm || {}), new asn1js.OctetString({
+ name: names.encryptedKey || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["version", "kekid", "keyEncryptionAlgorithm", "encryptedKey"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, KEKRecipientInfo.schema({
+ names: {
+ version: "version",
+ kekid: {
+ names: {
+ blockName: "kekid"
+ }
+ },
+ keyEncryptionAlgorithm: {
+ names: {
+ blockName: "keyEncryptionAlgorithm"
+ }
+ },
+ encryptedKey: "encryptedKey"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for KEKRecipientInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.version = asn1.result.version.valueBlock.valueDec;
+ this.kekid = new _KEKIdentifier.default({
+ schema: asn1.result.kekid
+ });
+ this.keyEncryptionAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.keyEncryptionAlgorithm
+ });
+ this.encryptedKey = asn1.result.encryptedKey; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [new asn1js.Integer({
+ value: this.version
+ }), this.kekid.toSchema(), this.keyEncryptionAlgorithm.toSchema(), this.encryptedKey]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ version: this.version,
+ kekid: this.kekid.toJSON(),
+ keyEncryptionAlgorithm: this.keyEncryptionAlgorithm.toJSON(),
+ encryptedKey: this.encryptedKey.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = KEKRecipientInfo;
+
+},{"./AlgorithmIdentifier.js":4,"./KEKIdentifier.js":46,"asn1js":112,"pvutils":113}],48:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _IssuerAndSerialNumber = _interopRequireDefault(require("./IssuerAndSerialNumber.js"));
+
+var _RecipientKeyIdentifier = _interopRequireDefault(require("./RecipientKeyIdentifier.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class KeyAgreeRecipientIdentifier {
+ //**********************************************************************************
+
+ /**
+ * Constructor for KeyAgreeRecipientIdentifier class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc variant
+ */
+ this.variant = (0, _pvutils.getParametersValue)(parameters, "variant", KeyAgreeRecipientIdentifier.defaultValues("variant"));
+ /**
+ * @type {*}
+ * @desc values
+ */
+
+ this.value = (0, _pvutils.getParametersValue)(parameters, "value", KeyAgreeRecipientIdentifier.defaultValues("value")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "variant":
+ return -1;
+
+ case "value":
+ return {};
+
+ default:
+ throw new Error(`Invalid member name for KeyAgreeRecipientIdentifier class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "variant":
+ return memberValue === -1;
+
+ case "value":
+ return Object.keys(memberValue).length === 0;
+
+ default:
+ throw new Error(`Invalid member name for KeyAgreeRecipientIdentifier class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * KeyAgreeRecipientIdentifier ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * rKeyId [0] IMPLICIT RecipientKeyIdentifier }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [issuerAndSerialNumber]
+ * @property {string} [rKeyId]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Choice({
+ value: [_IssuerAndSerialNumber.default.schema(names.issuerAndSerialNumber || {
+ names: {
+ blockName: names.blockName || ""
+ }
+ }), new asn1js.Constructed({
+ name: names.blockName || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: _RecipientKeyIdentifier.default.schema(names.rKeyId || {
+ names: {
+ blockName: names.blockName || ""
+ }
+ }).valueBlock.value
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["blockName"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, KeyAgreeRecipientIdentifier.schema({
+ names: {
+ blockName: "blockName"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for KeyAgreeRecipientIdentifier"); //endregion
+ //region Get internal properties from parsed schema
+
+ if (asn1.result.blockName.idBlock.tagClass === 1) {
+ this.variant = 1;
+ this.value = new _IssuerAndSerialNumber.default({
+ schema: asn1.result.blockName
+ });
+ } else {
+ this.variant = 2;
+ this.value = new _RecipientKeyIdentifier.default({
+ schema: new asn1js.Sequence({
+ value: asn1.result.blockName.valueBlock.value
+ })
+ });
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ switch (this.variant) {
+ case 1:
+ return this.value.toSchema();
+
+ case 2:
+ return new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: this.value.toSchema().valueBlock.value
+ });
+
+ default:
+ return new asn1js.Any();
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ variant: this.variant
+ };
+ if (this.variant === 1 || this.variant === 2) _object.value = this.value.toJSON();
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = KeyAgreeRecipientIdentifier;
+
+},{"./IssuerAndSerialNumber.js":44,"./RecipientKeyIdentifier.js":88,"asn1js":112,"pvutils":113}],49:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _OriginatorIdentifierOrKey = _interopRequireDefault(require("./OriginatorIdentifierOrKey.js"));
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _RecipientEncryptedKeys = _interopRequireDefault(require("./RecipientEncryptedKeys.js"));
+
+var _Certificate = _interopRequireDefault(require("./Certificate.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class KeyAgreeRecipientInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for KeyAgreeRecipientInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", KeyAgreeRecipientInfo.defaultValues("version"));
+ /**
+ * @type {OriginatorIdentifierOrKey}
+ * @desc originator
+ */
+
+ this.originator = (0, _pvutils.getParametersValue)(parameters, "originator", KeyAgreeRecipientInfo.defaultValues("originator"));
+ if ("ukm" in parameters)
+ /**
+ * @type {OctetString}
+ * @desc ukm
+ */
+ this.ukm = (0, _pvutils.getParametersValue)(parameters, "ukm", KeyAgreeRecipientInfo.defaultValues("ukm"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc keyEncryptionAlgorithm
+ */
+
+ this.keyEncryptionAlgorithm = (0, _pvutils.getParametersValue)(parameters, "keyEncryptionAlgorithm", KeyAgreeRecipientInfo.defaultValues("keyEncryptionAlgorithm"));
+ /**
+ * @type {RecipientEncryptedKeys}
+ * @desc recipientEncryptedKeys
+ */
+
+ this.recipientEncryptedKeys = (0, _pvutils.getParametersValue)(parameters, "recipientEncryptedKeys", KeyAgreeRecipientInfo.defaultValues("recipientEncryptedKeys"));
+ /**
+ * @type {Certificate}
+ * @desc recipientCertificate For some reasons we need to store recipient's certificate here
+ */
+
+ this.recipientCertificate = (0, _pvutils.getParametersValue)(parameters, "recipientCertificate", KeyAgreeRecipientInfo.defaultValues("recipientCertificate")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return 0;
+
+ case "originator":
+ return new _OriginatorIdentifierOrKey.default();
+
+ case "ukm":
+ return new asn1js.OctetString();
+
+ case "keyEncryptionAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "recipientEncryptedKeys":
+ return new _RecipientEncryptedKeys.default();
+
+ case "recipientCertificate":
+ return new _Certificate.default();
+
+ default:
+ throw new Error(`Invalid member name for KeyAgreeRecipientInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "version":
+ return memberValue === 0;
+
+ case "originator":
+ return memberValue.variant === -1 && "value" in memberValue === false;
+
+ case "ukm":
+ return memberValue.isEqual(KeyAgreeRecipientInfo.defaultValues("ukm"));
+
+ case "keyEncryptionAlgorithm":
+ return memberValue.algorithmId === "" && "algorithmParams" in memberValue === false;
+
+ case "recipientEncryptedKeys":
+ return memberValue.encryptedKeys.length === 0;
+
+ case "recipientCertificate":
+ return false;
+ // For now leave it as is
+
+ default:
+ throw new Error(`Invalid member name for KeyAgreeRecipientInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * KeyAgreeRecipientInfo ::= SEQUENCE {
+ * version CMSVersion, -- always set to 3
+ * originator [0] EXPLICIT OriginatorIdentifierOrKey,
+ * ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL,
+ * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ * recipientEncryptedKeys RecipientEncryptedKeys }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [version]
+ * @property {string} [originator]
+ * @property {string} [ukm]
+ * @property {string} [keyEncryptionAlgorithm]
+ * @property {string} [recipientEncryptedKeys]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Integer({
+ name: names.version || ""
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [_OriginatorIdentifierOrKey.default.schema(names.originator || {})]
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [new asn1js.OctetString({
+ name: names.ukm || ""
+ })]
+ }), _AlgorithmIdentifier.default.schema(names.keyEncryptionAlgorithm || {}), _RecipientEncryptedKeys.default.schema(names.recipientEncryptedKeys || {})]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["version", "originator", "ukm", "keyEncryptionAlgorithm", "recipientEncryptedKeys"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, KeyAgreeRecipientInfo.schema({
+ names: {
+ version: "version",
+ originator: {
+ names: {
+ blockName: "originator"
+ }
+ },
+ ukm: "ukm",
+ keyEncryptionAlgorithm: {
+ names: {
+ blockName: "keyEncryptionAlgorithm"
+ }
+ },
+ recipientEncryptedKeys: {
+ names: {
+ blockName: "recipientEncryptedKeys"
+ }
+ }
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for KeyAgreeRecipientInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.version = asn1.result.version.valueBlock.valueDec;
+ this.originator = new _OriginatorIdentifierOrKey.default({
+ schema: asn1.result.originator
+ });
+ if ("ukm" in asn1.result) this.ukm = asn1.result.ukm;
+ this.keyEncryptionAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.keyEncryptionAlgorithm
+ });
+ this.recipientEncryptedKeys = new _RecipientEncryptedKeys.default({
+ schema: asn1.result.recipientEncryptedKeys
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for final sequence
+ const outputArray = [];
+ outputArray.push(new asn1js.Integer({
+ value: this.version
+ }));
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [this.originator.toSchema()]
+ }));
+
+ if ("ukm" in this) {
+ outputArray.push(new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [this.ukm]
+ }));
+ }
+
+ outputArray.push(this.keyEncryptionAlgorithm.toSchema());
+ outputArray.push(this.recipientEncryptedKeys.toSchema()); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ version: this.version,
+ originator: this.originator.toJSON()
+ };
+ if ("ukm" in this) _object.ukm = this.ukm.toJSON();
+ _object.keyEncryptionAlgorithm = this.keyEncryptionAlgorithm.toJSON();
+ _object.recipientEncryptedKeys = this.recipientEncryptedKeys.toJSON();
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = KeyAgreeRecipientInfo;
+
+},{"./AlgorithmIdentifier.js":4,"./Certificate.js":19,"./OriginatorIdentifierOrKey.js":57,"./RecipientEncryptedKeys.js":85,"asn1js":112,"pvutils":113}],50:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var _PrivateKeyInfo = _interopRequireDefault(require("./PrivateKeyInfo.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5208
+ */
+class KeyBag extends _PrivateKeyInfo.default {
+ //**********************************************************************************
+
+ /**
+ * Constructor for Attribute class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = KeyBag;
+
+},{"./PrivateKeyInfo.js":76}],51:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _Certificate = _interopRequireDefault(require("./Certificate.js"));
+
+var _RecipientIdentifier = _interopRequireDefault(require("./RecipientIdentifier.js"));
+
+var _IssuerAndSerialNumber = _interopRequireDefault(require("./IssuerAndSerialNumber.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class KeyTransRecipientInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for KeyTransRecipientInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", KeyTransRecipientInfo.defaultValues("version"));
+ /**
+ * @type {RecipientIdentifier}
+ * @desc rid
+ */
+
+ this.rid = (0, _pvutils.getParametersValue)(parameters, "rid", KeyTransRecipientInfo.defaultValues("rid"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc keyEncryptionAlgorithm
+ */
+
+ this.keyEncryptionAlgorithm = (0, _pvutils.getParametersValue)(parameters, "keyEncryptionAlgorithm", KeyTransRecipientInfo.defaultValues("keyEncryptionAlgorithm"));
+ /**
+ * @type {OctetString}
+ * @desc encryptedKey
+ */
+
+ this.encryptedKey = (0, _pvutils.getParametersValue)(parameters, "encryptedKey", KeyTransRecipientInfo.defaultValues("encryptedKey"));
+ /**
+ * @type {Certificate}
+ * @desc recipientCertificate For some reasons we need to store recipient's certificate here
+ */
+
+ this.recipientCertificate = (0, _pvutils.getParametersValue)(parameters, "recipientCertificate", KeyTransRecipientInfo.defaultValues("recipientCertificate")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return -1;
+
+ case "rid":
+ return {};
+
+ case "keyEncryptionAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "encryptedKey":
+ return new asn1js.OctetString();
+
+ case "recipientCertificate":
+ return new _Certificate.default();
+
+ default:
+ throw new Error(`Invalid member name for KeyTransRecipientInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "version":
+ return memberValue === KeyTransRecipientInfo.defaultValues("version");
+
+ case "rid":
+ return Object.keys(memberValue).length === 0;
+
+ case "keyEncryptionAlgorithm":
+ case "encryptedKey":
+ return memberValue.isEqual(KeyTransRecipientInfo.defaultValues(memberName));
+
+ case "recipientCertificate":
+ return false;
+ // For now we do not need to compare any values with the "recipientCertificate"
+
+ default:
+ throw new Error(`Invalid member name for KeyTransRecipientInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * KeyTransRecipientInfo ::= SEQUENCE {
+ * version CMSVersion, -- always set to 0 or 2
+ * rid RecipientIdentifier,
+ * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ * encryptedKey EncryptedKey }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [version]
+ * @property {string} [rid]
+ * @property {string} [keyEncryptionAlgorithm]
+ * @property {string} [encryptedKey]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Integer({
+ name: names.version || ""
+ }), _RecipientIdentifier.default.schema(names.rid || {}), _AlgorithmIdentifier.default.schema(names.keyEncryptionAlgorithm || {}), new asn1js.OctetString({
+ name: names.encryptedKey || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["version", "rid", "keyEncryptionAlgorithm", "encryptedKey"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, KeyTransRecipientInfo.schema({
+ names: {
+ version: "version",
+ rid: {
+ names: {
+ blockName: "rid"
+ }
+ },
+ keyEncryptionAlgorithm: {
+ names: {
+ blockName: "keyEncryptionAlgorithm"
+ }
+ },
+ encryptedKey: "encryptedKey"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for KeyTransRecipientInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.version = asn1.result.version.valueBlock.valueDec;
+ if (asn1.result.rid.idBlock.tagClass === 3) this.rid = asn1.result.rid.valueBlock.value[0]; // SubjectKeyIdentifier
+ else this.rid = new _IssuerAndSerialNumber.default({
+ schema: asn1.result.rid
+ });
+ this.keyEncryptionAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.keyEncryptionAlgorithm
+ });
+ this.encryptedKey = asn1.result.encryptedKey; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+
+ if (this.rid instanceof _IssuerAndSerialNumber.default) {
+ this.version = 0;
+ outputArray.push(new asn1js.Integer({
+ value: this.version
+ }));
+ outputArray.push(this.rid.toSchema());
+ } else {
+ this.version = 2;
+ outputArray.push(new asn1js.Integer({
+ value: this.version
+ }));
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [this.rid]
+ }));
+ }
+
+ outputArray.push(this.keyEncryptionAlgorithm.toSchema());
+ outputArray.push(this.encryptedKey); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ version: this.version,
+ rid: this.rid.toJSON(),
+ keyEncryptionAlgorithm: this.keyEncryptionAlgorithm.toJSON(),
+ encryptedKey: this.encryptedKey.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = KeyTransRecipientInfo;
+
+},{"./AlgorithmIdentifier.js":4,"./Certificate.js":19,"./IssuerAndSerialNumber.js":44,"./RecipientIdentifier.js":86,"asn1js":112,"pvutils":113}],52:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _DigestInfo = _interopRequireDefault(require("./DigestInfo.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC7292
+ */
+class MacData {
+ //**********************************************************************************
+
+ /**
+ * Constructor for MacData class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {DigestInfo}
+ * @desc mac
+ */
+ this.mac = (0, _pvutils.getParametersValue)(parameters, "mac", MacData.defaultValues("mac"));
+ /**
+ * @type {OctetString}
+ * @desc macSalt
+ */
+
+ this.macSalt = (0, _pvutils.getParametersValue)(parameters, "macSalt", MacData.defaultValues("macSalt"));
+ if ("iterations" in parameters)
+ /**
+ * @type {number}
+ * @desc iterations
+ */
+ this.iterations = (0, _pvutils.getParametersValue)(parameters, "iterations", MacData.defaultValues("iterations")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "mac":
+ return new _DigestInfo.default();
+
+ case "macSalt":
+ return new asn1js.OctetString();
+
+ case "iterations":
+ return 1;
+
+ default:
+ throw new Error(`Invalid member name for MacData class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "mac":
+ return _DigestInfo.default.compareWithDefault("digestAlgorithm", memberValue.digestAlgorithm) && _DigestInfo.default.compareWithDefault("digest", memberValue.digest);
+
+ case "macSalt":
+ return memberValue.isEqual(MacData.defaultValues(memberName));
+
+ case "iterations":
+ return memberValue === MacData.defaultValues(memberName);
+
+ default:
+ throw new Error(`Invalid member name for MacData class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * MacData ::= SEQUENCE {
+ * mac DigestInfo,
+ * macSalt OCTET STRING,
+ * iterations INTEGER DEFAULT 1
+ * -- Note: The default is for historical reasons and its use is
+ * -- deprecated. A higher value, like 1024 is recommended.
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [optional]
+ * @property {string} [mac]
+ * @property {string} [macSalt]
+ * @property {string} [iterations]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ optional: names.optional || true,
+ value: [_DigestInfo.default.schema(names.mac || {
+ names: {
+ blockName: "mac"
+ }
+ }), new asn1js.OctetString({
+ name: names.macSalt || "macSalt"
+ }), new asn1js.Integer({
+ optional: true,
+ name: names.iterations || "iterations"
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["mac", "macSalt", "iterations"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, MacData.schema({
+ names: {
+ mac: {
+ names: {
+ blockName: "mac"
+ }
+ },
+ macSalt: "macSalt",
+ iterations: "iterations"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for MacData"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.mac = new _DigestInfo.default({
+ schema: asn1.result.mac
+ });
+ this.macSalt = asn1.result.macSalt;
+ if ("iterations" in asn1.result) this.iterations = asn1.result.iterations.valueBlock.valueDec; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ const outputArray = [this.mac.toSchema(), this.macSalt];
+ if ("iterations" in this) outputArray.push(new asn1js.Integer({
+ value: this.iterations
+ }));
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const output = {
+ mac: this.mac.toJSON(),
+ macSalt: this.macSalt.toJSON()
+ };
+ if ("iterations" in this) output.iterations = this.iterations.toJSON();
+ return output;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = MacData;
+
+},{"./DigestInfo.js":28,"asn1js":112,"pvutils":113}],53:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC3161
+ */
+class MessageImprint {
+ //**********************************************************************************
+
+ /**
+ * Constructor for MessageImprint class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc hashAlgorithm
+ */
+ this.hashAlgorithm = (0, _pvutils.getParametersValue)(parameters, "hashAlgorithm", MessageImprint.defaultValues("hashAlgorithm"));
+ /**
+ * @type {OctetString}
+ * @desc hashedMessage
+ */
+
+ this.hashedMessage = (0, _pvutils.getParametersValue)(parameters, "hashedMessage", MessageImprint.defaultValues("hashedMessage")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "hashAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "hashedMessage":
+ return new asn1js.OctetString();
+
+ default:
+ throw new Error(`Invalid member name for MessageImprint class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "hashAlgorithm":
+ return memberValue.algorithmId === "" && "algorithmParams" in memberValue === false;
+
+ case "hashedMessage":
+ return memberValue.isEqual(MessageImprint.defaultValues(memberName)) === 0;
+
+ default:
+ throw new Error(`Invalid member name for MessageImprint class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * MessageImprint ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * hashedMessage OCTET STRING }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [hashAlgorithm]
+ * @property {string} [hashedMessage]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [_AlgorithmIdentifier.default.schema(names.hashAlgorithm || {}), new asn1js.OctetString({
+ name: names.hashedMessage || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["hashAlgorithm", "hashedMessage"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, MessageImprint.schema({
+ names: {
+ hashAlgorithm: {
+ names: {
+ blockName: "hashAlgorithm"
+ }
+ },
+ hashedMessage: "hashedMessage"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for MessageImprint"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.hashAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.hashAlgorithm
+ });
+ this.hashedMessage = asn1.result.hashedMessage; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [this.hashAlgorithm.toSchema(), this.hashedMessage]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ hashAlgorithm: this.hashAlgorithm.toJSON(),
+ hashedMessage: this.hashedMessage.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = MessageImprint;
+
+},{"./AlgorithmIdentifier.js":4,"asn1js":112,"pvutils":113}],54:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _GeneralSubtree = _interopRequireDefault(require("./GeneralSubtree.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class NameConstraints {
+ //**********************************************************************************
+
+ /**
+ * Constructor for NameConstraints class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+ if ("permittedSubtrees" in parameters)
+ /**
+ * @type {Array.<GeneralSubtree>}
+ * @desc permittedSubtrees
+ */
+ this.permittedSubtrees = (0, _pvutils.getParametersValue)(parameters, "permittedSubtrees", NameConstraints.defaultValues("permittedSubtrees"));
+ if ("excludedSubtrees" in parameters)
+ /**
+ * @type {Array.<GeneralSubtree>}
+ * @desc excludedSubtrees
+ */
+ this.excludedSubtrees = (0, _pvutils.getParametersValue)(parameters, "excludedSubtrees", NameConstraints.defaultValues("excludedSubtrees")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "permittedSubtrees":
+ return [];
+
+ case "excludedSubtrees":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for NameConstraints class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * NameConstraints ::= SEQUENCE {
+ * permittedSubtrees [0] GeneralSubtrees OPTIONAL,
+ * excludedSubtrees [1] GeneralSubtrees OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [permittedSubtrees]
+ * @property {string} [excludedSubtrees]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Repeated({
+ name: names.permittedSubtrees || "",
+ value: _GeneralSubtree.default.schema()
+ })]
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [new asn1js.Repeated({
+ name: names.excludedSubtrees || "",
+ value: _GeneralSubtree.default.schema()
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["permittedSubtrees", "excludedSubtrees"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, NameConstraints.schema({
+ names: {
+ permittedSubtrees: "permittedSubtrees",
+ excludedSubtrees: "excludedSubtrees"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for NameConstraints"); //endregion
+ //region Get internal properties from parsed schema
+
+ if ("permittedSubtrees" in asn1.result) this.permittedSubtrees = Array.from(asn1.result.permittedSubtrees, element => new _GeneralSubtree.default({
+ schema: element
+ }));
+ if ("excludedSubtrees" in asn1.result) this.excludedSubtrees = Array.from(asn1.result.excludedSubtrees, element => new _GeneralSubtree.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+
+ if ("permittedSubtrees" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: Array.from(this.permittedSubtrees, element => element.toSchema())
+ }));
+ }
+
+ if ("excludedSubtrees" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: Array.from(this.excludedSubtrees, element => element.toSchema())
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {};
+ if ("permittedSubtrees" in this) object.permittedSubtrees = Array.from(this.permittedSubtrees, element => element.toJSON());
+ if ("excludedSubtrees" in this) object.excludedSubtrees = Array.from(this.excludedSubtrees, element => element.toJSON());
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = NameConstraints;
+
+},{"./GeneralSubtree.js":42,"asn1js":112,"pvutils":113}],55:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _common = require("./common.js");
+
+var _TBSRequest = _interopRequireDefault(require("./TBSRequest.js"));
+
+var _Signature = _interopRequireDefault(require("./Signature.js"));
+
+var _Request = _interopRequireDefault(require("./Request.js"));
+
+var _CertID = _interopRequireDefault(require("./CertID.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC6960
+ */
+class OCSPRequest {
+ //**********************************************************************************
+
+ /**
+ * Constructor for OCSPRequest class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {TBSRequest}
+ * @desc tbsRequest
+ */
+ this.tbsRequest = (0, _pvutils.getParametersValue)(parameters, "tbsRequest", OCSPRequest.defaultValues("tbsRequest"));
+ if ("optionalSignature" in parameters)
+ /**
+ * @type {Signature}
+ * @desc optionalSignature
+ */
+ this.optionalSignature = (0, _pvutils.getParametersValue)(parameters, "optionalSignature", OCSPRequest.defaultValues("optionalSignature")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "tbsRequest":
+ return new _TBSRequest.default();
+
+ case "optionalSignature":
+ return new _Signature.default();
+
+ default:
+ throw new Error(`Invalid member name for OCSPRequest class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "tbsRequest":
+ // noinspection OverlyComplexBooleanExpressionJS
+ return _TBSRequest.default.compareWithDefault("tbs", memberValue.tbs) && _TBSRequest.default.compareWithDefault("version", memberValue.version) && _TBSRequest.default.compareWithDefault("requestorName", memberValue.requestorName) && _TBSRequest.default.compareWithDefault("requestList", memberValue.requestList) && _TBSRequest.default.compareWithDefault("requestExtensions", memberValue.requestExtensions);
+
+ case "optionalSignature":
+ return _Signature.default.compareWithDefault("signatureAlgorithm", memberValue.signatureAlgorithm) && _Signature.default.compareWithDefault("signature", memberValue.signature) && _Signature.default.compareWithDefault("certs", memberValue.certs);
+
+ default:
+ throw new Error(`Invalid member name for OCSPRequest class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * OCSPRequest ::= SEQUENCE {
+ * tbsRequest TBSRequest,
+ * optionalSignature [0] EXPLICIT Signature OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [tbsRequest]
+ * @property {string} [optionalSignature]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "OCSPRequest",
+ value: [_TBSRequest.default.schema(names.tbsRequest || {
+ names: {
+ blockName: "tbsRequest"
+ }
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [_Signature.default.schema(names.optionalSignature || {
+ names: {
+ blockName: "optionalSignature"
+ }
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["tbsRequest", "optionalSignature"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, OCSPRequest.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for OCSPRequest"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.tbsRequest = new _TBSRequest.default({
+ schema: asn1.result.tbsRequest
+ });
+ if ("optionalSignature" in asn1.result) this.optionalSignature = new _Signature.default({
+ schema: asn1.result.optionalSignature
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @param {boolean} encodeFlag If param equal to false then create TBS schema via decoding stored value. In othe case create TBS schema via assembling from TBS parts.
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema(encodeFlag = false) {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(this.tbsRequest.toSchema(encodeFlag));
+ if ("optionalSignature" in this) outputArray.push(this.optionalSignature.toSchema()); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ tbsRequest: this.tbsRequest.toJSON()
+ };
+ if ("optionalSignature" in this) _object.optionalSignature = this.optionalSignature.toJSON();
+ return _object;
+ } //**********************************************************************************
+
+ /**
+ * Making OCSP Request for specific certificate
+ * @param {Certificate} certificate Certificate making OCSP Request for
+ * @param {Object} parameters Additional parameters
+ * @returns {Promise}
+ */
+
+
+ createForCertificate(certificate, parameters) {
+ //region Initial variables
+ let sequence = Promise.resolve();
+ const certID = new _CertID.default(); //endregion
+ //region Create OCSP certificate identifier for the certificate
+
+ sequence = sequence.then(() => certID.createForCertificate(certificate, parameters)); //endregion
+ //region Make final request data
+
+ sequence = sequence.then(() => {
+ this.tbsRequest = new _TBSRequest.default({
+ requestList: [new _Request.default({
+ reqCert: certID
+ })]
+ });
+ }, error => Promise.reject(error)); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+ /**
+ * Make signature for current OCSP Request
+ * @param {Object} privateKey Private key for "subjectPublicKeyInfo" structure
+ * @param {string} [hashAlgorithm] Hashing algorithm. Default SHA-1
+ * @returns {Promise}
+ */
+
+
+ sign(privateKey, hashAlgorithm = "SHA-1") {
+ //region Initial checking
+ //region Check private key
+ if (typeof privateKey === "undefined") return Promise.reject("Need to provide a private key for signing"); //endregion
+ //region Check that "optionalSignature" exists in the current request
+
+ if ("optionalSignature" in this === false) return Promise.reject("Need to create \"optionalSignature\" field before signing"); //endregion
+ //endregion
+ //region Initial variables
+
+ let sequence = Promise.resolve();
+ let parameters;
+ let tbs;
+ const engine = (0, _common.getEngine)(); //endregion
+ //region Get a "default parameters" for current algorithm and set correct signature algorithm
+
+ sequence = sequence.then(() => engine.subtle.getSignatureParameters(privateKey, hashAlgorithm));
+ sequence = sequence.then(result => {
+ parameters = result.parameters;
+ this.optionalSignature.signatureAlgorithm = result.signatureAlgorithm;
+ }); //endregion
+ //region Create TBS data for signing
+
+ sequence = sequence.then(() => {
+ tbs = this.tbsRequest.toSchema(true).toBER(false);
+ }); //endregion
+ //region Signing TBS data on provided private key
+
+ sequence = sequence.then(() => engine.subtle.signWithPrivateKey(tbs, privateKey, parameters));
+ sequence = sequence.then(result => {
+ this.optionalSignature.signature = new asn1js.BitString({
+ valueHex: result
+ });
+ }); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+
+ verify() {} // TODO: Create the function
+ //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = OCSPRequest;
+
+},{"./CertID.js":18,"./Request.js":90,"./Signature.js":98,"./TBSRequest.js":105,"./common.js":110,"asn1js":112,"pvutils":113}],56:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _ResponseBytes = _interopRequireDefault(require("./ResponseBytes.js"));
+
+var _BasicOCSPResponse = _interopRequireDefault(require("./BasicOCSPResponse.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC6960
+ */
+class OCSPResponse {
+ //**********************************************************************************
+
+ /**
+ * Constructor for OCSPResponse class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Enumerated}
+ * @desc responseStatus
+ */
+ this.responseStatus = (0, _pvutils.getParametersValue)(parameters, "responseStatus", OCSPResponse.defaultValues("responseStatus"));
+ if ("responseBytes" in parameters)
+ /**
+ * @type {ResponseBytes}
+ * @desc responseBytes
+ */
+ this.responseBytes = (0, _pvutils.getParametersValue)(parameters, "responseBytes", OCSPResponse.defaultValues("responseBytes")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "responseStatus":
+ return new asn1js.Enumerated();
+
+ case "responseBytes":
+ return new _ResponseBytes.default();
+
+ default:
+ throw new Error(`Invalid member name for OCSPResponse class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "responseStatus":
+ return memberValue.isEqual(OCSPResponse.defaultValues(memberName));
+
+ case "responseBytes":
+ return _ResponseBytes.default.compareWithDefault("responseType", memberValue.responseType) && _ResponseBytes.default.compareWithDefault("response", memberValue.response);
+
+ default:
+ throw new Error(`Invalid member name for OCSPResponse class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * OCSPResponse ::= SEQUENCE {
+ * responseStatus OCSPResponseStatus,
+ * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
+ *
+ * OCSPResponseStatus ::= ENUMERATED {
+ * successful (0), -- Response has valid confirmations
+ * malformedRequest (1), -- Illegal confirmation request
+ * internalError (2), -- Internal error in issuer
+ * tryLater (3), -- Try again later
+ * -- (4) is not used
+ * sigRequired (5), -- Must sign the request
+ * unauthorized (6) -- Request unauthorized
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [responseStatus]
+ * @property {string} [responseBytes]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "OCSPResponse",
+ value: [new asn1js.Enumerated({
+ name: names.responseStatus || "responseStatus"
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [_ResponseBytes.default.schema(names.responseBytes || {
+ names: {
+ blockName: "responseBytes"
+ }
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["responseStatus", "responseBytes"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, OCSPResponse.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for OCSPResponse"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.responseStatus = asn1.result.responseStatus;
+ if ("responseBytes" in asn1.result) this.responseBytes = new _ResponseBytes.default({
+ schema: asn1.result.responseBytes
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(this.responseStatus);
+
+ if ("responseBytes" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [this.responseBytes.toSchema()]
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ responseStatus: this.responseStatus.toJSON()
+ };
+ if ("responseBytes" in this) _object.responseBytes = this.responseBytes.toJSON();
+ return _object;
+ } //**********************************************************************************
+
+ /**
+ * Get OCSP response status for specific certificate
+ * @param {Certificate} certificate
+ * @param {Certificate} issuerCertificate
+ * @returns {*}
+ */
+
+
+ getCertificateStatus(certificate, issuerCertificate) {
+ //region Initial variables
+ let basicResponse;
+ const result = {
+ isForCertificate: false,
+ status: 2 // 0 = good, 1 = revoked, 2 = unknown
+
+ }; //endregion
+ //region Check that "ResponseBytes" contain "OCSP_BASIC_RESPONSE"
+
+ if ("responseBytes" in this === false) return result;
+ if (this.responseBytes.responseType !== "1.3.6.1.5.5.7.48.1.1") // id-pkix-ocsp-basic
+ return result;
+
+ try {
+ const asn1Basic = asn1js.fromBER(this.responseBytes.response.valueBlock.valueHex);
+ basicResponse = new _BasicOCSPResponse.default({
+ schema: asn1Basic.result
+ });
+ } catch (ex) {
+ return result;
+ } //endregion
+
+
+ return basicResponse.getCertificateStatus(certificate, issuerCertificate);
+ } //**********************************************************************************
+
+ /**
+ * Make a signature for current OCSP Response
+ * @param {Object} privateKey Private key for "subjectPublicKeyInfo" structure
+ * @param {string} [hashAlgorithm] Hashing algorithm. Default SHA-1
+ * @returns {Promise}
+ */
+
+
+ sign(privateKey, hashAlgorithm) {
+ //region Check that ResponseData has type BasicOCSPResponse and sign it
+ if (this.responseBytes.responseType === "1.3.6.1.5.5.7.48.1.1") {
+ const asn1 = asn1js.fromBER(this.responseBytes.response.valueBlock.valueHex);
+ const basicResponse = new _BasicOCSPResponse.default({
+ schema: asn1.result
+ });
+ return basicResponse.sign(privateKey, hashAlgorithm);
+ }
+
+ return Promise.reject(`Unknown ResponseBytes type: ${this.responseBytes.responseType}`); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Verify current OCSP Response
+ * @param {Certificate|null} issuerCertificate In order to decrease size of resp issuer cert could be ommited. In such case you need manually provide it.
+ * @returns {Promise}
+ */
+
+
+ verify(issuerCertificate = null) {
+ //region Check that ResponseBytes exists in the object
+ if ("responseBytes" in this === false) return Promise.reject("Empty ResponseBytes field"); //endregion
+ //region Check that ResponceData has type BasicOCSPResponse and verify it
+
+ if (this.responseBytes.responseType === "1.3.6.1.5.5.7.48.1.1") {
+ const asn1 = asn1js.fromBER(this.responseBytes.response.valueBlock.valueHex);
+ const basicResponse = new _BasicOCSPResponse.default({
+ schema: asn1.result
+ });
+
+ if (issuerCertificate !== null) {
+ if ("certs" in basicResponse === false) basicResponse.certs = [];
+ basicResponse.certs.push(issuerCertificate);
+ }
+
+ return basicResponse.verify();
+ }
+
+ return Promise.reject(`Unknown ResponseBytes type: ${this.responseBytes.responseType}`); //endregion
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = OCSPResponse;
+
+},{"./BasicOCSPResponse.js":13,"./ResponseBytes.js":91,"asn1js":112,"pvutils":113}],57:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _IssuerAndSerialNumber = _interopRequireDefault(require("./IssuerAndSerialNumber.js"));
+
+var _OriginatorPublicKey = _interopRequireDefault(require("./OriginatorPublicKey.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class OriginatorIdentifierOrKey {
+ //**********************************************************************************
+
+ /**
+ * Constructor for OriginatorIdentifierOrKey class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc variant
+ */
+ this.variant = (0, _pvutils.getParametersValue)(parameters, "variant", OriginatorIdentifierOrKey.defaultValues("variant"));
+ if ("value" in parameters)
+ /**
+ * @type {IssuerAndSerialNumber|OctetString|OriginatorPublicKey}
+ * @desc value
+ */
+ this.value = (0, _pvutils.getParametersValue)(parameters, "value", OriginatorIdentifierOrKey.defaultValues("value")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "variant":
+ return -1;
+
+ case "value":
+ return {};
+
+ default:
+ throw new Error(`Invalid member name for OriginatorIdentifierOrKey class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "variant":
+ return memberValue === -1;
+
+ case "value":
+ return Object.keys(memberValue).length === 0;
+
+ default:
+ throw new Error(`Invalid member name for OriginatorIdentifierOrKey class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * OriginatorIdentifierOrKey ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * subjectKeyIdentifier [0] SubjectKeyIdentifier,
+ * originatorKey [1] OriginatorPublicKey }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Choice({
+ value: [_IssuerAndSerialNumber.default.schema({
+ names: {
+ blockName: names.blockName || ""
+ }
+ }), new asn1js.Primitive({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ name: names.blockName || ""
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ name: names.blockName || "",
+ value: _OriginatorPublicKey.default.schema().valueBlock.value
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["blockName"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, OriginatorIdentifierOrKey.schema({
+ names: {
+ blockName: "blockName"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for OriginatorIdentifierOrKey"); //endregion
+ //region Get internal properties from parsed schema
+
+ if (asn1.result.blockName.idBlock.tagClass === 1) {
+ this.variant = 1;
+ this.value = new _IssuerAndSerialNumber.default({
+ schema: asn1.result.blockName
+ });
+ } else {
+ if (asn1.result.blockName.idBlock.tagNumber === 0) {
+ //region Create "OCTETSTRING" from "ASN1_PRIMITIVE"
+ asn1.result.blockName.idBlock.tagClass = 1; // UNIVERSAL
+
+ asn1.result.blockName.idBlock.tagNumber = 4; // OCTETSTRING
+ //endregion
+
+ this.variant = 2;
+ this.value = asn1.result.blockName;
+ } else {
+ this.variant = 3;
+ this.value = new _OriginatorPublicKey.default({
+ schema: new asn1js.Sequence({
+ value: asn1.result.blockName.valueBlock.value
+ })
+ });
+ }
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ switch (this.variant) {
+ case 1:
+ return this.value.toSchema();
+
+ case 2:
+ this.value.idBlock.tagClass = 3; // CONTEXT-SPECIFIC
+
+ this.value.idBlock.tagNumber = 0; // [0]
+
+ return this.value;
+
+ case 3:
+ {
+ const _schema = this.value.toSchema();
+
+ _schema.idBlock.tagClass = 3; // CONTEXT-SPECIFIC
+
+ _schema.idBlock.tagNumber = 1; // [1]
+
+ return _schema;
+ }
+
+ default:
+ return new asn1js.Any();
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ variant: this.variant
+ };
+ if (this.variant === 1 || this.variant === 2 || this.variant === 3) _object.value = this.value.toJSON();
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = OriginatorIdentifierOrKey;
+
+},{"./IssuerAndSerialNumber.js":44,"./OriginatorPublicKey.js":59,"asn1js":112,"pvutils":113}],58:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _CertificateSet = _interopRequireDefault(require("./CertificateSet.js"));
+
+var _RevocationInfoChoices = _interopRequireDefault(require("./RevocationInfoChoices.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class OriginatorInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for OriginatorInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+ if ("certs" in parameters)
+ /**
+ * @type {CertificateSet}
+ * @desc certs
+ */
+ this.certs = (0, _pvutils.getParametersValue)(parameters, "certs", OriginatorInfo.defaultValues("certs"));
+ if ("crls" in parameters)
+ /**
+ * @type {RevocationInfoChoices}
+ * @desc crls
+ */
+ this.crls = (0, _pvutils.getParametersValue)(parameters, "crls", OriginatorInfo.defaultValues("crls")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "certs":
+ return new _CertificateSet.default();
+
+ case "crls":
+ return new _RevocationInfoChoices.default();
+
+ default:
+ throw new Error(`Invalid member name for OriginatorInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "certs":
+ return memberValue.certificates.length === 0;
+
+ case "crls":
+ return memberValue.crls.length === 0 && memberValue.otherRevocationInfos.length === 0;
+
+ default:
+ throw new Error(`Invalid member name for OriginatorInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * OriginatorInfo ::= SEQUENCE {
+ * certs [0] IMPLICIT CertificateSet OPTIONAL,
+ * crls [1] IMPLICIT RevocationInfoChoices OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [certs]
+ * @property {string} [crls]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Constructed({
+ name: names.certs || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: _CertificateSet.default.schema().valueBlock.value
+ }), new asn1js.Constructed({
+ name: names.crls || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: _RevocationInfoChoices.default.schema().valueBlock.value
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["certs", "crls"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, OriginatorInfo.schema({
+ names: {
+ certs: "certs",
+ crls: "crls"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for OriginatorInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ if ("certs" in asn1.result) {
+ this.certs = new _CertificateSet.default({
+ schema: new asn1js.Set({
+ value: asn1.result.certs.valueBlock.value
+ })
+ });
+ }
+
+ if ("crls" in asn1.result) {
+ this.crls = new _RevocationInfoChoices.default({
+ schema: new asn1js.Set({
+ value: asn1.result.crls.valueBlock.value
+ })
+ });
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ const sequenceValue = [];
+
+ if ("certs" in this) {
+ sequenceValue.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: this.certs.toSchema().valueBlock.value
+ }));
+ }
+
+ if ("crls" in this) {
+ sequenceValue.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: this.crls.toSchema().valueBlock.value
+ }));
+ } //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: sequenceValue
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {};
+ if ("certs" in this) object.certs = this.certs.toJSON();
+ if ("crls" in this) object.crls = this.crls.toJSON();
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = OriginatorInfo;
+
+},{"./CertificateSet.js":23,"./RevocationInfoChoices.js":93,"asn1js":112,"pvutils":113}],59:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class OriginatorPublicKey {
+ //**********************************************************************************
+
+ /**
+ * Constructor for OriginatorPublicKey class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc algorithm
+ */
+ this.algorithm = (0, _pvutils.getParametersValue)(parameters, "algorithm", OriginatorPublicKey.defaultValues("algorithm"));
+ /**
+ * @type {BitString}
+ * @desc publicKey
+ */
+
+ this.publicKey = (0, _pvutils.getParametersValue)(parameters, "publicKey", OriginatorPublicKey.defaultValues("publicKey")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "algorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "publicKey":
+ return new asn1js.BitString();
+
+ default:
+ throw new Error(`Invalid member name for OriginatorPublicKey class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "algorithm":
+ case "publicKey":
+ return memberValue.isEqual(OriginatorPublicKey.defaultValues(memberName));
+
+ default:
+ throw new Error(`Invalid member name for OriginatorPublicKey class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * OriginatorPublicKey ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * publicKey BIT STRING }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [algorithm]
+ * @property {string} [publicKey]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [_AlgorithmIdentifier.default.schema(names.algorithm || {}), new asn1js.BitString({
+ name: names.publicKey || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["algorithm", "publicKey"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, OriginatorPublicKey.schema({
+ names: {
+ algorithm: {
+ names: {
+ blockName: "algorithm"
+ }
+ },
+ publicKey: "publicKey"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for OriginatorPublicKey"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.algorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.algorithm
+ });
+ this.publicKey = asn1.result.publicKey; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [this.algorithm.toSchema(), this.publicKey]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ algorithm: this.algorithm.toJSON(),
+ publicKey: this.publicKey.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = OriginatorPublicKey;
+
+},{"./AlgorithmIdentifier.js":4,"asn1js":112,"pvutils":113}],60:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class OtherCertificateFormat {
+ //**********************************************************************************
+
+ /**
+ * Constructor for OtherCertificateFormat class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc otherCertFormat
+ */
+ this.otherCertFormat = (0, _pvutils.getParametersValue)(parameters, "otherCertFormat", OtherCertificateFormat.defaultValues("otherCertFormat"));
+ /**
+ * @type {Any}
+ * @desc otherCert
+ */
+
+ this.otherCert = (0, _pvutils.getParametersValue)(parameters, "otherCert", OtherCertificateFormat.defaultValues("otherCert")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "otherCertFormat":
+ return "";
+
+ case "otherCert":
+ return new asn1js.Any();
+
+ default:
+ throw new Error(`Invalid member name for OtherCertificateFormat class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * OtherCertificateFormat ::= SEQUENCE {
+ * otherCertFormat OBJECT IDENTIFIER,
+ * otherCert ANY DEFINED BY otherCertFormat }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [otherCertFormat]
+ * @property {string} [otherCert]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.otherCertFormat || "otherCertFormat"
+ }), new asn1js.Any({
+ name: names.otherCert || "otherCert"
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["otherCertFormat", "otherCert"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, OtherCertificateFormat.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for OtherCertificateFormat"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.otherCertFormat = asn1.result.otherCertFormat.valueBlock.toString();
+ this.otherCert = asn1.result.otherCert; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [new asn1js.ObjectIdentifier({
+ value: this.otherCertFormat
+ }), this.otherCert]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {
+ otherCertFormat: this.otherCertFormat
+ };
+ if (!(this.otherCert instanceof asn1js.Any)) object.otherCert = this.otherCert.toJSON();
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = OtherCertificateFormat;
+
+},{"asn1js":112,"pvutils":113}],61:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class OtherKeyAttribute {
+ //**********************************************************************************
+
+ /**
+ * Constructor for OtherKeyAttribute class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc keyAttrId
+ */
+ this.keyAttrId = (0, _pvutils.getParametersValue)(parameters, "keyAttrId", OtherKeyAttribute.defaultValues("keyAttrId"));
+ if ("keyAttr" in parameters)
+ /**
+ * @type {*}
+ * @desc keyAttr
+ */
+ this.keyAttr = (0, _pvutils.getParametersValue)(parameters, "keyAttr", OtherKeyAttribute.defaultValues("keyAttr")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "keyAttrId":
+ return "";
+
+ case "keyAttr":
+ return {};
+
+ default:
+ throw new Error(`Invalid member name for OtherKeyAttribute class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "keyAttrId":
+ return memberValue === "";
+
+ case "keyAttr":
+ return Object.keys(memberValue).length === 0;
+
+ default:
+ throw new Error(`Invalid member name for OtherKeyAttribute class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * OtherKeyAttribute ::= SEQUENCE {
+ * keyAttrId OBJECT IDENTIFIER,
+ * keyAttr ANY DEFINED BY keyAttrId OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [optional]
+ * @property {string} [keyAttrId]
+ * @property {string} [keyAttr]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ optional: names.optional || true,
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.keyAttrId || ""
+ }), new asn1js.Any({
+ optional: true,
+ name: names.keyAttr || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["keyAttrId", "keyAttr"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, OtherKeyAttribute.schema({
+ names: {
+ keyAttrId: "keyAttrId",
+ keyAttr: "keyAttr"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for OtherKeyAttribute"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.keyAttrId = asn1.result.keyAttrId.valueBlock.toString();
+ if ("keyAttr" in asn1.result) this.keyAttr = asn1.result.keyAttr; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(new asn1js.ObjectIdentifier({
+ value: this.keyAttrId
+ }));
+ if ("keyAttr" in this) outputArray.push(this.keyAttr); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ keyAttrId: this.keyAttrId
+ };
+ if ("keyAttr" in this) _object.keyAttr = this.keyAttr.toJSON();
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = OtherKeyAttribute;
+
+},{"asn1js":112,"pvutils":113}],62:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC3447
+ */
+class OtherPrimeInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for OtherPrimeInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Integer}
+ * @desc prime
+ */
+ this.prime = (0, _pvutils.getParametersValue)(parameters, "prime", OtherPrimeInfo.defaultValues("prime"));
+ /**
+ * @type {Integer}
+ * @desc exponent
+ */
+
+ this.exponent = (0, _pvutils.getParametersValue)(parameters, "exponent", OtherPrimeInfo.defaultValues("exponent"));
+ /**
+ * @type {Integer}
+ * @desc coefficient
+ */
+
+ this.coefficient = (0, _pvutils.getParametersValue)(parameters, "coefficient", OtherPrimeInfo.defaultValues("coefficient")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ //region If input argument array contains "json" for this object
+
+ if ("json" in parameters) this.fromJSON(parameters.json); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "prime":
+ return new asn1js.Integer();
+
+ case "exponent":
+ return new asn1js.Integer();
+
+ case "coefficient":
+ return new asn1js.Integer();
+
+ default:
+ throw new Error(`Invalid member name for OtherPrimeInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * OtherPrimeInfo ::= Sequence {
+ * prime Integer, -- ri
+ * exponent Integer, -- di
+ * coefficient Integer -- ti
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} prime
+ * @property {string} exponent
+ * @property {string} coefficient
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Integer({
+ name: names.prime || ""
+ }), new asn1js.Integer({
+ name: names.exponent || ""
+ }), new asn1js.Integer({
+ name: names.coefficient || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["prime", "exponent", "coefficient"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, OtherPrimeInfo.schema({
+ names: {
+ prime: "prime",
+ exponent: "exponent",
+ coefficient: "coefficient"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for OtherPrimeInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.prime = asn1.result.prime.convertFromDER();
+ this.exponent = asn1.result.exponent.convertFromDER();
+ this.coefficient = asn1.result.coefficient.convertFromDER(); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [this.prime.convertToDER(), this.exponent.convertToDER(), this.coefficient.convertToDER()]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ r: (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(this.prime.valueBlock.valueHex), true, true),
+ d: (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(this.exponent.valueBlock.valueHex), true, true),
+ t: (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(this.coefficient.valueBlock.valueHex), true, true)
+ };
+ } //**********************************************************************************
+
+ /**
+ * Convert JSON value into current object
+ * @param {Object} json
+ */
+
+
+ fromJSON(json) {
+ if ("r" in json) this.prime = new asn1js.Integer({
+ valueHex: (0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(json.r, true))
+ });else throw new Error("Absent mandatory parameter \"r\"");
+ if ("d" in json) this.exponent = new asn1js.Integer({
+ valueHex: (0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(json.d, true))
+ });else throw new Error("Absent mandatory parameter \"d\"");
+ if ("t" in json) this.coefficient = new asn1js.Integer({
+ valueHex: (0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(json.t, true))
+ });else throw new Error("Absent mandatory parameter \"t\"");
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = OtherPrimeInfo;
+
+},{"asn1js":112,"pvutils":113}],63:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class OtherRecipientInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for OtherRecipientInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc oriType
+ */
+ this.oriType = (0, _pvutils.getParametersValue)(parameters, "oriType", OtherRecipientInfo.defaultValues("oriType"));
+ /**
+ * @type {*}
+ * @desc oriValue
+ */
+
+ this.oriValue = (0, _pvutils.getParametersValue)(parameters, "oriValue", OtherRecipientInfo.defaultValues("oriValue")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "oriType":
+ return "";
+
+ case "oriValue":
+ return {};
+
+ default:
+ throw new Error(`Invalid member name for OtherRecipientInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "oriType":
+ return memberValue === "";
+
+ case "oriValue":
+ return Object.keys(memberValue).length === 0;
+
+ default:
+ throw new Error(`Invalid member name for OtherRecipientInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * OtherRecipientInfo ::= SEQUENCE {
+ * oriType OBJECT IDENTIFIER,
+ * oriValue ANY DEFINED BY oriType }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [oriType]
+ * @property {string} [oriValue]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.oriType || ""
+ }), new asn1js.Any({
+ name: names.oriValue || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["oriType", "oriValue"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, OtherRecipientInfo.schema({
+ names: {
+ oriType: "oriType",
+ oriValue: "oriValue"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for OtherRecipientInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.oriType = asn1.result.oriType.valueBlock.toString();
+ this.oriValue = asn1.result.oriValue; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [new asn1js.ObjectIdentifier({
+ value: this.oriType
+ }), this.oriValue]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ oriType: this.oriType
+ };
+ if (OtherRecipientInfo.compareWithDefault("oriValue", this.oriValue) === false) _object.oriValue = this.oriValue.toJSON();
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = OtherRecipientInfo;
+
+},{"asn1js":112,"pvutils":113}],64:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class OtherRevocationInfoFormat {
+ //**********************************************************************************
+
+ /**
+ * Constructor for OtherRevocationInfoFormat class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc otherRevInfoFormat
+ */
+ this.otherRevInfoFormat = (0, _pvutils.getParametersValue)(parameters, "otherRevInfoFormat", OtherRevocationInfoFormat.defaultValues("otherRevInfoFormat"));
+ /**
+ * @type {Any}
+ * @desc otherRevInfo
+ */
+
+ this.otherRevInfo = (0, _pvutils.getParametersValue)(parameters, "otherRevInfo", OtherRevocationInfoFormat.defaultValues("otherRevInfo")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "otherRevInfoFormat":
+ return "";
+
+ case "otherRevInfo":
+ return new asn1js.Any();
+
+ default:
+ throw new Error(`Invalid member name for OtherRevocationInfoFormat class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * OtherCertificateFormat ::= SEQUENCE {
+ * otherRevInfoFormat OBJECT IDENTIFIER,
+ * otherRevInfo ANY DEFINED BY otherCertFormat }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [otherRevInfoFormat]
+ * @property {string} [otherRevInfo]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.otherRevInfoFormat || "otherRevInfoFormat"
+ }), new asn1js.Any({
+ name: names.otherRevInfo || "otherRevInfo"
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["otherRevInfoFormat", "otherRevInfo"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, OtherRevocationInfoFormat.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for OtherRevocationInfoFormat"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.otherRevInfoFormat = asn1.result.otherRevInfoFormat.valueBlock.toString();
+ this.otherRevInfo = asn1.result.otherRevInfo; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [new asn1js.ObjectIdentifier({
+ value: this.otherRevInfoFormat
+ }), this.otherRevInfo]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {
+ otherRevInfoFormat: this.otherRevInfoFormat
+ };
+ if (!(this.otherRevInfo instanceof asn1js.Any)) object.otherRevInfo = this.otherRevInfo.toJSON();
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = OtherRevocationInfoFormat;
+
+},{"asn1js":112,"pvutils":113}],65:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC2898
+ */
+class PBES2Params {
+ //**********************************************************************************
+
+ /**
+ * Constructor for PBES2Params class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc keyDerivationFunc
+ */
+ this.keyDerivationFunc = (0, _pvutils.getParametersValue)(parameters, "keyDerivationFunc", PBES2Params.defaultValues("keyDerivationFunc"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc encryptionScheme
+ */
+
+ this.encryptionScheme = (0, _pvutils.getParametersValue)(parameters, "encryptionScheme", PBES2Params.defaultValues("encryptionScheme")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "keyDerivationFunc":
+ return new _AlgorithmIdentifier.default();
+
+ case "encryptionScheme":
+ return new _AlgorithmIdentifier.default();
+
+ default:
+ throw new Error(`Invalid member name for PBES2Params class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * PBES2-params ::= SEQUENCE {
+ * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
+ * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [keyDerivationFunc]
+ * @property {string} [encryptionScheme]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [_AlgorithmIdentifier.default.schema(names.keyDerivationFunc || {}), _AlgorithmIdentifier.default.schema(names.encryptionScheme || {})]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["keyDerivationFunc", "encryptionScheme"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, PBES2Params.schema({
+ names: {
+ keyDerivationFunc: {
+ names: {
+ blockName: "keyDerivationFunc"
+ }
+ },
+ encryptionScheme: {
+ names: {
+ blockName: "encryptionScheme"
+ }
+ }
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for PBES2Params"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.keyDerivationFunc = new _AlgorithmIdentifier.default({
+ schema: asn1.result.keyDerivationFunc
+ });
+ this.encryptionScheme = new _AlgorithmIdentifier.default({
+ schema: asn1.result.encryptionScheme
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [this.keyDerivationFunc.toSchema(), this.encryptionScheme.toSchema()]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ keyDerivationFunc: this.keyDerivationFunc.toJSON(),
+ encryptionScheme: this.encryptionScheme.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = PBES2Params;
+
+},{"./AlgorithmIdentifier.js":4,"asn1js":112,"pvutils":113}],66:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC2898
+ */
+class PBKDF2Params {
+ //**********************************************************************************
+
+ /**
+ * Constructor for PBKDF2Params class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Object}
+ * @desc salt
+ */
+ this.salt = (0, _pvutils.getParametersValue)(parameters, "salt", PBKDF2Params.defaultValues("salt"));
+ /**
+ * @type {number}
+ * @desc iterationCount
+ */
+
+ this.iterationCount = (0, _pvutils.getParametersValue)(parameters, "iterationCount", PBKDF2Params.defaultValues("iterationCount"));
+ if ("keyLength" in parameters)
+ /**
+ * @type {number}
+ * @desc keyLength
+ */
+ this.keyLength = (0, _pvutils.getParametersValue)(parameters, "keyLength", PBKDF2Params.defaultValues("keyLength"));
+ if ("prf" in parameters)
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc prf
+ */
+ this.prf = (0, _pvutils.getParametersValue)(parameters, "prf", PBKDF2Params.defaultValues("prf")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "salt":
+ return {};
+
+ case "iterationCount":
+ return -1;
+
+ case "keyLength":
+ return 0;
+
+ case "prf":
+ return new _AlgorithmIdentifier.default({
+ algorithmId: "1.3.14.3.2.26",
+ // SHA-1
+ algorithmParams: new asn1js.Null()
+ });
+
+ default:
+ throw new Error(`Invalid member name for PBKDF2Params class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * PBKDF2-params ::= SEQUENCE {
+ * salt CHOICE {
+ * specified OCTET STRING,
+ * otherSource AlgorithmIdentifier },
+ * iterationCount INTEGER (1..MAX),
+ * keyLength INTEGER (1..MAX) OPTIONAL,
+ * prf AlgorithmIdentifier
+ * DEFAULT { algorithm hMAC-SHA1, parameters NULL } }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [saltPrimitive]
+ * @property {string} [saltConstructed]
+ * @property {string} [iterationCount]
+ * @property {string} [keyLength]
+ * @property {string} [prf]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Choice({
+ value: [new asn1js.OctetString({
+ name: names.saltPrimitive || ""
+ }), _AlgorithmIdentifier.default.schema(names.saltConstructed || {})]
+ }), new asn1js.Integer({
+ name: names.iterationCount || ""
+ }), new asn1js.Integer({
+ name: names.keyLength || "",
+ optional: true
+ }), _AlgorithmIdentifier.default.schema(names.prf || {
+ names: {
+ optional: true
+ }
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["salt", "iterationCount", "keyLength", "prf"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, PBKDF2Params.schema({
+ names: {
+ saltPrimitive: "salt",
+ saltConstructed: {
+ names: {
+ blockName: "salt"
+ }
+ },
+ iterationCount: "iterationCount",
+ keyLength: "keyLength",
+ prf: {
+ names: {
+ blockName: "prf",
+ optional: true
+ }
+ }
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for PBKDF2Params"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.salt = asn1.result.salt;
+ this.iterationCount = asn1.result.iterationCount.valueBlock.valueDec;
+ if ("keyLength" in asn1.result) this.keyLength = asn1.result.keyLength.valueBlock.valueDec;
+ if ("prf" in asn1.result) this.prf = new _AlgorithmIdentifier.default({
+ schema: asn1.result.prf
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(this.salt);
+ outputArray.push(new asn1js.Integer({
+ value: this.iterationCount
+ }));
+
+ if ("keyLength" in this) {
+ if (PBKDF2Params.defaultValues("keyLength") !== this.keyLength) outputArray.push(new asn1js.Integer({
+ value: this.keyLength
+ }));
+ }
+
+ if ("prf" in this) {
+ if (PBKDF2Params.defaultValues("prf").isEqual(this.prf) === false) outputArray.push(this.prf.toSchema());
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ salt: this.salt.toJSON(),
+ iterationCount: this.iterationCount
+ };
+
+ if ("keyLength" in this) {
+ if (PBKDF2Params.defaultValues("keyLength") !== this.keyLength) _object.keyLength = this.keyLength;
+ }
+
+ if ("prf" in this) {
+ if (PBKDF2Params.defaultValues("prf").isEqual(this.prf) === false) _object.prf = this.prf.toJSON();
+ }
+
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = PBKDF2Params;
+
+},{"./AlgorithmIdentifier.js":4,"asn1js":112,"pvutils":113}],67:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _common = require("./common.js");
+
+var _ContentInfo = _interopRequireDefault(require("./ContentInfo.js"));
+
+var _MacData = _interopRequireDefault(require("./MacData.js"));
+
+var _DigestInfo = _interopRequireDefault(require("./DigestInfo.js"));
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _SignedData = _interopRequireDefault(require("./SignedData.js"));
+
+var _EncapsulatedContentInfo = _interopRequireDefault(require("./EncapsulatedContentInfo.js"));
+
+var _Attribute = _interopRequireDefault(require("./Attribute.js"));
+
+var _SignerInfo = _interopRequireDefault(require("./SignerInfo.js"));
+
+var _IssuerAndSerialNumber = _interopRequireDefault(require("./IssuerAndSerialNumber.js"));
+
+var _SignedAndUnsignedAttributes = _interopRequireDefault(require("./SignedAndUnsignedAttributes.js"));
+
+var _AuthenticatedSafe = _interopRequireDefault(require("./AuthenticatedSafe.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC7292
+ */
+class PFX {
+ //**********************************************************************************
+
+ /**
+ * Constructor for PFX class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", PFX.defaultValues("version"));
+ /**
+ * @type {ContentInfo}
+ * @desc authSafe
+ */
+
+ this.authSafe = (0, _pvutils.getParametersValue)(parameters, "authSafe", PFX.defaultValues("authSafe"));
+ if ("macData" in parameters)
+ /**
+ * @type {MacData}
+ * @desc macData
+ */
+ this.macData = (0, _pvutils.getParametersValue)(parameters, "macData", PFX.defaultValues("macData"));
+ if ("parsedValue" in parameters)
+ /**
+ * @type {*}
+ * @desc parsedValue
+ */
+ this.parsedValue = (0, _pvutils.getParametersValue)(parameters, "parsedValue", PFX.defaultValues("parsedValue")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return 3;
+
+ case "authSafe":
+ return new _ContentInfo.default();
+
+ case "macData":
+ return new _MacData.default();
+
+ case "parsedValue":
+ return {};
+
+ default:
+ throw new Error(`Invalid member name for PFX class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "version":
+ return memberValue === PFX.defaultValues(memberName);
+
+ case "authSafe":
+ return _ContentInfo.default.compareWithDefault("contentType", memberValue.contentType) && _ContentInfo.default.compareWithDefault("content", memberValue.content);
+
+ case "macData":
+ return _MacData.default.compareWithDefault("mac", memberValue.mac) && _MacData.default.compareWithDefault("macSalt", memberValue.macSalt) && _MacData.default.compareWithDefault("iterations", memberValue.iterations);
+
+ case "parsedValue":
+ return memberValue instanceof Object && Object.keys(memberValue).length === 0;
+
+ default:
+ throw new Error(`Invalid member name for PFX class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * PFX ::= SEQUENCE {
+ * version INTEGER {v3(3)}(v3,...),
+ * authSafe ContentInfo,
+ * macData MacData OPTIONAL
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [version]
+ * @property {string} [authSafe]
+ * @property {string} [macData]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Integer({
+ name: names.version || "version"
+ }), _ContentInfo.default.schema(names.authSafe || {
+ names: {
+ blockName: "authSafe"
+ }
+ }), _MacData.default.schema(names.macData || {
+ names: {
+ blockName: "macData",
+ optional: true
+ }
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["version", "authSafe", "macData"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, PFX.schema({
+ names: {
+ version: "version",
+ authSafe: {
+ names: {
+ blockName: "authSafe"
+ }
+ },
+ macData: {
+ names: {
+ blockName: "macData"
+ }
+ }
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for PFX"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.version = asn1.result.version.valueBlock.valueDec;
+ this.authSafe = new _ContentInfo.default({
+ schema: asn1.result.authSafe
+ });
+ if ("macData" in asn1.result) this.macData = new _MacData.default({
+ schema: asn1.result.macData
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ const outputArray = [new asn1js.Integer({
+ value: this.version
+ }), this.authSafe.toSchema()];
+ if ("macData" in this) outputArray.push(this.macData.toSchema());
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const output = {
+ version: this.version,
+ authSafe: this.authSafe.toJSON()
+ };
+ if ("macData" in this) output.macData = this.macData.toJSON();
+ return output;
+ } //**********************************************************************************
+
+ /**
+ * Making ContentInfo from "parsedValue" object
+ * @param {Object} parameters Parameters, specific to each "integrity mode"
+ */
+
+
+ makeInternalValues(parameters = {}) {
+ //region Check mandatory parameter
+ if (parameters instanceof Object === false) return Promise.reject("The \"parameters\" must has \"Object\" type");
+ if ("parsedValue" in this === false) return Promise.reject("Please call \"parseValues\" function first in order to make \"parsedValue\" data");
+ if ("integrityMode" in this.parsedValue === false) return Promise.reject("Absent mandatory parameter \"integrityMode\" inside \"parsedValue\""); //endregion
+ //region Initial variables
+
+ let sequence = Promise.resolve(); //endregion
+ //region Get a "crypto" extension
+
+ const crypto = (0, _common.getCrypto)();
+ if (typeof crypto === "undefined") return Promise.reject("Unable to create WebCrypto object"); //endregion
+ //region Makes values for each particular integrity mode
+ //region Check that we do have neccessary fields in "parsedValue" object
+
+ if ("authenticatedSafe" in this.parsedValue === false) return Promise.reject("Absent mandatory parameter \"authenticatedSafe\" in \"parsedValue\""); //endregion
+
+ switch (this.parsedValue.integrityMode) {
+ //region HMAC-based integrity
+ case 0:
+ {
+ //region Check additional mandatory parameters
+ if ("iterations" in parameters === false) return Promise.reject("Absent mandatory parameter \"iterations\"");
+ if ("pbkdf2HashAlgorithm" in parameters === false) return Promise.reject("Absent mandatory parameter \"pbkdf2HashAlgorithm\"");
+ if ("hmacHashAlgorithm" in parameters === false) return Promise.reject("Absent mandatory parameter \"hmacHashAlgorithm\"");
+ if ("password" in parameters === false) return Promise.reject("Absent mandatory parameter \"password\""); //endregion
+ //region Initial variables
+
+ const saltBuffer = new ArrayBuffer(64);
+ const saltView = new Uint8Array(saltBuffer);
+ (0, _common.getRandomValues)(saltView);
+ const data = this.parsedValue.authenticatedSafe.toSchema().toBER(false);
+ this.authSafe = new _ContentInfo.default({
+ contentType: "1.2.840.113549.1.7.1",
+ content: new asn1js.OctetString({
+ valueHex: data
+ })
+ }); //endregion
+ //region Call current crypto engine for making HMAC-based data stamp
+
+ const engine = (0, _common.getEngine)();
+ if ("stampDataWithPassword" in engine.subtle === false) return Promise.reject(`No support for "stampDataWithPassword" in current engine "${engine.name}"`);
+ sequence = sequence.then(() => engine.subtle.stampDataWithPassword({
+ password: parameters.password,
+ hashAlgorithm: parameters.hmacHashAlgorithm,
+ salt: saltBuffer,
+ iterationCount: parameters.iterations,
+ contentToStamp: data
+ })); //endregion
+ //region Make "MacData" values
+
+ sequence = sequence.then(result => {
+ this.macData = new _MacData.default({
+ mac: new _DigestInfo.default({
+ digestAlgorithm: new _AlgorithmIdentifier.default({
+ algorithmId: (0, _common.getOIDByAlgorithm)({
+ name: parameters.hmacHashAlgorithm
+ })
+ }),
+ digest: new asn1js.OctetString({
+ valueHex: result
+ })
+ }),
+ macSalt: new asn1js.OctetString({
+ valueHex: saltBuffer
+ }),
+ iterations: parameters.iterations
+ });
+ }, error => Promise.reject(error)); //endregion
+ //endregion
+ }
+ break;
+ //endregion
+ //region publicKey-based integrity
+
+ case 1:
+ {
+ //region Check additional mandatory parameters
+ if ("signingCertificate" in parameters === false) return Promise.reject("Absent mandatory parameter \"signingCertificate\"");
+ if ("privateKey" in parameters === false) return Promise.reject("Absent mandatory parameter \"privateKey\"");
+ if ("hashAlgorithm" in parameters === false) return Promise.reject("Absent mandatory parameter \"hashAlgorithm\""); //endregion
+ //region Making data to be signed
+ // NOTE: all internal data for "authenticatedSafe" must be already prepared.
+ // Thus user must call "makeValues" for all internal "SafeContent" value with appropriate parameters.
+ // Or user can choose to use values from initial parsing of existing PKCS#12 data.
+
+ const toBeSigned = this.parsedValue.authenticatedSafe.toSchema().toBER(false); //endregion
+ //region Initial variables
+
+ const cmsSigned = new _SignedData.default({
+ version: 1,
+ encapContentInfo: new _EncapsulatedContentInfo.default({
+ eContentType: "1.2.840.113549.1.7.1",
+ // "data" content type
+ eContent: new asn1js.OctetString({
+ valueHex: toBeSigned
+ })
+ }),
+ certificates: [parameters.signingCertificate]
+ }); //endregion
+ //region Making additional attributes for CMS Signed Data
+ //region Create a message digest
+
+ sequence = sequence.then(() => crypto.digest({
+ name: parameters.hashAlgorithm
+ }, new Uint8Array(toBeSigned))); //endregion
+ //region Combine all signed extensions
+
+ sequence = sequence.then(result => {
+ //region Initial variables
+ const signedAttr = []; //endregion
+ //region contentType
+
+ signedAttr.push(new _Attribute.default({
+ type: "1.2.840.113549.1.9.3",
+ values: [new asn1js.ObjectIdentifier({
+ value: "1.2.840.113549.1.7.1"
+ })]
+ })); //endregion
+ //region signingTime
+
+ signedAttr.push(new _Attribute.default({
+ type: "1.2.840.113549.1.9.5",
+ values: [new asn1js.UTCTime({
+ valueDate: new Date()
+ })]
+ })); //endregion
+ //region messageDigest
+
+ signedAttr.push(new _Attribute.default({
+ type: "1.2.840.113549.1.9.4",
+ values: [new asn1js.OctetString({
+ valueHex: result
+ })]
+ })); //endregion
+ //region Making final value for "SignerInfo" type
+
+ cmsSigned.signerInfos.push(new _SignerInfo.default({
+ version: 1,
+ sid: new _IssuerAndSerialNumber.default({
+ issuer: parameters.signingCertificate.issuer,
+ serialNumber: parameters.signingCertificate.serialNumber
+ }),
+ signedAttrs: new _SignedAndUnsignedAttributes.default({
+ type: 0,
+ attributes: signedAttr
+ })
+ })); //endregion
+ }, error => Promise.reject(`Error during making digest for message: ${error}`)); //endregion
+ //endregion
+ //region Signing CMS Signed Data
+
+ sequence = sequence.then(() => cmsSigned.sign(parameters.privateKey, 0, parameters.hashAlgorithm)); //endregion
+ //region Making final CMS_CONTENT_INFO type
+
+ sequence = sequence.then(() => {
+ this.authSafe = new _ContentInfo.default({
+ contentType: "1.2.840.113549.1.7.2",
+ content: cmsSigned.toSchema(true)
+ });
+ }, error => Promise.reject(`Error during making signature: ${error}`)); //endregion
+ }
+ break;
+ //endregion
+ //region default
+
+ default:
+ return Promise.reject(`Parameter "integrityMode" has unknown value: ${parameters.integrityMode}`);
+ //endregion
+ } //endregion
+
+
+ return sequence;
+ } //**********************************************************************************
+
+
+ parseInternalValues(parameters) {
+ //region Check input data from "parameters"
+ if (parameters instanceof Object === false) return Promise.reject("The \"parameters\" must has \"Object\" type");
+ if ("checkIntegrity" in parameters === false) parameters.checkIntegrity = true; //endregion
+ //region Initial variables
+
+ let sequence = Promise.resolve(); //endregion
+ //region Get a "crypto" extension
+
+ const crypto = (0, _common.getCrypto)();
+ if (typeof crypto === "undefined") return Promise.reject("Unable to create WebCrypto object"); //endregion
+ //region Create value for "this.parsedValue.authenticatedSafe" and check integrity
+
+ this.parsedValue = {};
+
+ switch (this.authSafe.contentType) {
+ //region data
+ case "1.2.840.113549.1.7.1":
+ {
+ //region Check additional mandatory parameters
+ if ("password" in parameters === false) return Promise.reject("Absent mandatory parameter \"password\""); //endregion
+ //region Integrity based on HMAC
+
+ this.parsedValue.integrityMode = 0; //endregion
+ //region Check that we do have OCTETSTRING as "content"
+
+ if (this.authSafe.content instanceof asn1js.OctetString === false) return Promise.reject("Wrong type of \"this.authSafe.content\""); //endregion
+ //region Check we have "constructive encoding" for AuthSafe content
+
+ let authSafeContent = new ArrayBuffer(0);
+
+ if (this.authSafe.content.valueBlock.isConstructed) {
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = this.authSafe.content.valueBlock.value[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ const contentValue = _step.value;
+ authSafeContent = (0, _pvutils.utilConcatBuf)(authSafeContent, contentValue.valueBlock.valueHex);
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+ } else authSafeContent = this.authSafe.content.valueBlock.valueHex; //endregion
+ //region Parse internal ASN.1 data
+
+
+ const asn1 = asn1js.fromBER(authSafeContent);
+ if (asn1.offset === -1) return Promise.reject("Error during parsing of ASN.1 data inside \"this.authSafe.content\""); //endregion
+ //region Set "authenticatedSafe" value
+
+ this.parsedValue.authenticatedSafe = new _AuthenticatedSafe.default({
+ schema: asn1.result
+ }); //endregion
+ //region Check integrity
+
+ if (parameters.checkIntegrity) {
+ //region Check that "MacData" exists
+ if ("macData" in this === false) return Promise.reject("Absent \"macData\" value, can not check PKCS#12 data integrity"); //endregion
+ //region Initial variables
+
+ const hashAlgorithm = (0, _common.getAlgorithmByOID)(this.macData.mac.digestAlgorithm.algorithmId);
+ if ("name" in hashAlgorithm === false) return Promise.reject(`Unsupported digest algorithm: ${this.macData.mac.digestAlgorithm.algorithmId}`); //endregion
+ //region Call current crypto engine for verifying HMAC-based data stamp
+
+ const engine = (0, _common.getEngine)();
+ sequence = sequence.then(() => engine.subtle.verifyDataStampedWithPassword({
+ password: parameters.password,
+ hashAlgorithm: hashAlgorithm.name,
+ salt: this.macData.macSalt.valueBlock.valueHex,
+ iterationCount: this.macData.iterations,
+ contentToVerify: authSafeContent,
+ signatureToVerify: this.macData.mac.digest.valueBlock.valueHex
+ })); //endregion
+ //region Verify HMAC signature
+
+ sequence = sequence.then(result => {
+ if (result === false) return Promise.reject("Integrity for the PKCS#12 data is broken!");
+ return Promise.resolve();
+ }, error => Promise.reject(error)); //endregion
+ } //endregion
+
+ }
+ break;
+ //endregion
+ //region signedData
+
+ case "1.2.840.113549.1.7.2":
+ {
+ //region Integrity based on signature using public key
+ this.parsedValue.integrityMode = 1; //endregion
+ //region Parse CMS Signed Data
+
+ const cmsSigned = new _SignedData.default({
+ schema: this.authSafe.content
+ }); //endregion
+ //region Check that we do have OCTETSTRING as "content"
+
+ if ("eContent" in cmsSigned.encapContentInfo === false) return Promise.reject("Absent of attached data in \"cmsSigned.encapContentInfo\"");
+ if (cmsSigned.encapContentInfo.eContent instanceof asn1js.OctetString === false) return Promise.reject("Wrong type of \"cmsSigned.encapContentInfo.eContent\""); //endregion
+ //region Create correct data block for verification
+
+ let data = new ArrayBuffer(0);
+ if (cmsSigned.encapContentInfo.eContent.idBlock.isConstructed === false) data = cmsSigned.encapContentInfo.eContent.valueBlock.valueHex;else {
+ for (let i = 0; i < cmsSigned.encapContentInfo.eContent.valueBlock.value.length; i++) data = (0, _pvutils.utilConcatBuf)(data, cmsSigned.encapContentInfo.eContent.valueBlock.value[i].valueBlock.valueHex);
+ } //endregion
+ //region Parse internal ASN.1 data
+
+ const asn1 = asn1js.fromBER(data);
+ if (asn1.offset === -1) return Promise.reject("Error during parsing of ASN.1 data inside \"this.authSafe.content\""); //endregion
+ //region Set "authenticatedSafe" value
+
+ this.parsedValue.authenticatedSafe = new _AuthenticatedSafe.default({
+ schema: asn1.result
+ }); //endregion
+ //region Check integrity
+
+ sequence = sequence.then(() => cmsSigned.verify({
+ signer: 0,
+ checkChain: false
+ })).then(result => {
+ if (result === false) return Promise.reject("Integrity for the PKCS#12 data is broken!");
+ return Promise.resolve();
+ }, error => Promise.reject(`Error during integrity verification: ${error}`)); //endregion
+ }
+ break;
+ //endregion
+ //region default
+
+ default:
+ return Promise.reject(`Incorrect value for "this.authSafe.contentType": ${this.authSafe.contentType}`);
+ //endregion
+ } //endregion
+ //region Return result of the function
+
+
+ return sequence.then(() => this, error => Promise.reject(`Error during parsing: ${error}`)); //endregion
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = PFX;
+
+},{"./AlgorithmIdentifier.js":4,"./Attribute.js":6,"./AuthenticatedSafe.js":10,"./ContentInfo.js":26,"./DigestInfo.js":28,"./EncapsulatedContentInfo.js":33,"./IssuerAndSerialNumber.js":44,"./MacData.js":52,"./SignedAndUnsignedAttributes.js":99,"./SignedData.js":101,"./SignerInfo.js":102,"./common.js":110,"asn1js":112,"pvutils":113}],68:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _EncryptedData = _interopRequireDefault(require("./EncryptedData.js"));
+
+var _EncryptedContentInfo = _interopRequireDefault(require("./EncryptedContentInfo.js"));
+
+var _PrivateKeyInfo = _interopRequireDefault(require("./PrivateKeyInfo.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC7292
+ */
+class PKCS8ShroudedKeyBag {
+ //**********************************************************************************
+
+ /**
+ * Constructor for PKCS8ShroudedKeyBag class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc encryptionAlgorithm
+ */
+ this.encryptionAlgorithm = (0, _pvutils.getParametersValue)(parameters, "encryptionAlgorithm", PKCS8ShroudedKeyBag.defaultValues("encryptionAlgorithm"));
+ /**
+ * @type {OctetString}
+ * @desc encryptedData
+ */
+
+ this.encryptedData = (0, _pvutils.getParametersValue)(parameters, "encryptedData", PKCS8ShroudedKeyBag.defaultValues("encryptedData"));
+ if ("parsedValue" in parameters)
+ /**
+ * @type {*}
+ * @desc parsedValue
+ */
+ this.parsedValue = (0, _pvutils.getParametersValue)(parameters, "parsedValue", PKCS8ShroudedKeyBag.defaultValues("parsedValue")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "encryptionAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "encryptedData":
+ return new asn1js.OctetString();
+
+ case "parsedValue":
+ return {};
+
+ default:
+ throw new Error(`Invalid member name for PKCS8ShroudedKeyBag class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "encryptionAlgorithm":
+ return _AlgorithmIdentifier.default.compareWithDefault("algorithmId", memberValue.algorithmId) && "algorithmParams" in memberValue === false;
+
+ case "encryptedData":
+ return memberValue.isEqual(PKCS8ShroudedKeyBag.defaultValues(memberName));
+
+ case "parsedValue":
+ return memberValue instanceof Object && Object.keys(memberValue).length === 0;
+
+ default:
+ throw new Error(`Invalid member name for PKCS8ShroudedKeyBag class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * PKCS8ShroudedKeyBag ::= EncryptedPrivateKeyInfo
+ *
+ * EncryptedPrivateKeyInfo ::= SEQUENCE {
+ * encryptionAlgorithm AlgorithmIdentifier {{KeyEncryptionAlgorithms}},
+ * encryptedData EncryptedData
+ * }
+ *
+ * EncryptedData ::= OCTET STRING
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [encryptionAlgorithm]
+ * @property {string} [encryptedData]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [_AlgorithmIdentifier.default.schema(names.encryptionAlgorithm || {
+ names: {
+ blockName: "encryptionAlgorithm"
+ }
+ }), new asn1js.Choice({
+ value: [new asn1js.OctetString({
+ name: names.encryptedData || "encryptedData"
+ }), new asn1js.OctetString({
+ idBlock: {
+ isConstructed: true
+ },
+ name: names.encryptedData || "encryptedData"
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["encryptionAlgorithm", "encryptedData"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, PKCS8ShroudedKeyBag.schema({
+ names: {
+ encryptionAlgorithm: {
+ names: {
+ blockName: "encryptionAlgorithm"
+ }
+ },
+ encryptedData: "encryptedData"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for PKCS8ShroudedKeyBag"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.encryptionAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.encryptionAlgorithm
+ });
+ this.encryptedData = asn1.result.encryptedData; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [this.encryptionAlgorithm.toSchema(), this.encryptedData]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ encryptionAlgorithm: this.encryptionAlgorithm.toJSON(),
+ encryptedData: this.encryptedData.toJSON()
+ };
+ } //**********************************************************************************
+
+
+ parseInternalValues(parameters) {
+ //region Initial variables
+ let sequence = Promise.resolve();
+ const cmsEncrypted = new _EncryptedData.default({
+ encryptedContentInfo: new _EncryptedContentInfo.default({
+ contentEncryptionAlgorithm: this.encryptionAlgorithm,
+ encryptedContent: this.encryptedData
+ })
+ }); //endregion
+ //region Decrypt internal data
+
+ sequence = sequence.then(() => cmsEncrypted.decrypt(parameters), error => Promise.reject(error)); //endregion
+ //region Initialize "parsedValue" with decrypted PKCS#8 private key
+
+ sequence = sequence.then(
+ /**
+ * @param {ArrayBuffer} result
+ */
+ result => {
+ const asn1 = asn1js.fromBER(result);
+ if (asn1.offset === -1) return Promise.reject("Error during parsing ASN.1 data");
+ this.parsedValue = new _PrivateKeyInfo.default({
+ schema: asn1.result
+ });
+ return Promise.resolve();
+ }, error => Promise.reject(error)); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+
+ makeInternalValues(parameters) {
+ //region Check that we do have "parsedValue"
+ if ("parsedValue" in this === false) return Promise.reject("Please initialize \"parsedValue\" first"); //endregion
+ //region Initial variables
+
+ let sequence = Promise.resolve();
+ const cmsEncrypted = new _EncryptedData.default(); //endregion
+ //region Encrypt internal data
+
+ sequence = sequence.then(() => {
+ parameters.contentToEncrypt = this.parsedValue.toSchema().toBER(false);
+ return cmsEncrypted.encrypt(parameters);
+ }, error => Promise.reject(error)); //endregion
+ //region Initialize internal values
+
+ sequence = sequence.then(() => {
+ this.encryptionAlgorithm = cmsEncrypted.encryptedContentInfo.contentEncryptionAlgorithm;
+ this.encryptedData = cmsEncrypted.encryptedContentInfo.encryptedContent;
+ }); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = PKCS8ShroudedKeyBag;
+
+},{"./AlgorithmIdentifier.js":4,"./EncryptedContentInfo.js":34,"./EncryptedData.js":35,"./PrivateKeyInfo.js":76,"asn1js":112,"pvutils":113}],69:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC3161
+ */
+class PKIStatusInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for PKIStatusInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc status
+ */
+ this.status = (0, _pvutils.getParametersValue)(parameters, "status", PKIStatusInfo.defaultValues("status"));
+ if ("statusStrings" in parameters)
+ /**
+ * @type {Array.<Utf8String>}
+ * @desc statusStrings
+ */
+ this.statusStrings = (0, _pvutils.getParametersValue)(parameters, "statusStrings", PKIStatusInfo.defaultValues("statusStrings"));
+ if ("failInfo" in parameters)
+ /**
+ * @type {BitString}
+ * @desc failInfo
+ */
+ this.failInfo = (0, _pvutils.getParametersValue)(parameters, "failInfo", PKIStatusInfo.defaultValues("failInfo")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "status":
+ return 2;
+
+ case "statusStrings":
+ return [];
+
+ case "failInfo":
+ return new asn1js.BitString();
+
+ default:
+ throw new Error(`Invalid member name for PKIStatusInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "status":
+ return memberValue === PKIStatusInfo.defaultValues(memberName);
+
+ case "statusStrings":
+ return memberValue.length === 0;
+
+ case "failInfo":
+ return memberValue.isEqual(PKIStatusInfo.defaultValues(memberName));
+
+ default:
+ throw new Error(`Invalid member name for PKIStatusInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * PKIStatusInfo ::= SEQUENCE {
+ * status PKIStatus,
+ * statusString PKIFreeText OPTIONAL,
+ * failInfo PKIFailureInfo OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [status]
+ * @property {string} [statusStrings]
+ * @property {string} [failInfo]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Integer({
+ name: names.status || ""
+ }), new asn1js.Sequence({
+ optional: true,
+ value: [new asn1js.Repeated({
+ name: names.statusStrings || "",
+ value: new asn1js.Utf8String()
+ })]
+ }), new asn1js.BitString({
+ name: names.failInfo || "",
+ optional: true
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["status", "statusStrings", "failInfo"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, PKIStatusInfo.schema({
+ names: {
+ status: "status",
+ statusStrings: "statusStrings",
+ failInfo: "failInfo"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for PKIStatusInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ const _status = asn1.result.status;
+ if (_status.valueBlock.isHexOnly === true || _status.valueBlock.valueDec < 0 || _status.valueBlock.valueDec > 5) throw new Error("PKIStatusInfo \"status\" has invalid value");
+ this.status = _status.valueBlock.valueDec;
+ if ("statusStrings" in asn1.result) this.statusStrings = asn1.result.statusStrings;
+ if ("failInfo" in asn1.result) this.failInfo = asn1.result.failInfo; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array of output sequence
+ const outputArray = [];
+ outputArray.push(new asn1js.Integer({
+ value: this.status
+ }));
+
+ if ("statusStrings" in this) {
+ outputArray.push(new asn1js.Sequence({
+ optional: true,
+ value: this.statusStrings
+ }));
+ }
+
+ if ("failInfo" in this) outputArray.push(this.failInfo); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ status: this.status
+ };
+ if ("statusStrings" in this) _object.statusStrings = Array.from(this.statusStrings, element => element.toJSON());
+ if ("failInfo" in this) _object.failInfo = this.failInfo.toJSON();
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = PKIStatusInfo;
+
+},{"asn1js":112,"pvutils":113}],70:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class PasswordRecipientinfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for PasswordRecipientinfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", PasswordRecipientinfo.defaultValues("version"));
+ if ("keyDerivationAlgorithm" in parameters)
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc keyDerivationAlgorithm
+ */
+ this.keyDerivationAlgorithm = (0, _pvutils.getParametersValue)(parameters, "keyDerivationAlgorithm", PasswordRecipientinfo.defaultValues("keyDerivationAlgorithm"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc keyEncryptionAlgorithm
+ */
+
+ this.keyEncryptionAlgorithm = (0, _pvutils.getParametersValue)(parameters, "keyEncryptionAlgorithm", PasswordRecipientinfo.defaultValues("keyEncryptionAlgorithm"));
+ /**
+ * @type {OctetString}
+ * @desc encryptedKey
+ */
+
+ this.encryptedKey = (0, _pvutils.getParametersValue)(parameters, "encryptedKey", PasswordRecipientinfo.defaultValues("encryptedKey"));
+ /**
+ * @type {ArrayBuffer}
+ * @desc password Password to derive key from
+ */
+
+ this.password = (0, _pvutils.getParametersValue)(parameters, "password", PasswordRecipientinfo.defaultValues("password")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return -1;
+
+ case "keyDerivationAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "keyEncryptionAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "encryptedKey":
+ return new asn1js.OctetString();
+
+ case "password":
+ return new ArrayBuffer(0);
+
+ default:
+ throw new Error(`Invalid member name for PasswordRecipientinfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "version":
+ return memberValue === -1;
+
+ case "keyDerivationAlgorithm":
+ case "keyEncryptionAlgorithm":
+ return memberValue.algorithmId === "" && "algorithmParams" in memberValue === false;
+
+ case "encryptedKey":
+ return memberValue.isEqual(PasswordRecipientinfo.defaultValues("encryptedKey"));
+
+ case "password":
+ return memberValue.byteLength === 0;
+
+ default:
+ throw new Error(`Invalid member name for PasswordRecipientinfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * PasswordRecipientInfo ::= SEQUENCE {
+ * version CMSVersion, -- Always set to 0
+ * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL,
+ * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ * encryptedKey EncryptedKey }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [keyDerivationAlgorithm]
+ * @property {string} [keyEncryptionAlgorithm]
+ * @property {string} [encryptedKey]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Integer({
+ name: names.version || ""
+ }), new asn1js.Constructed({
+ name: names.keyDerivationAlgorithm || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: _AlgorithmIdentifier.default.schema().valueBlock.value
+ }), _AlgorithmIdentifier.default.schema(names.keyEncryptionAlgorithm || {}), new asn1js.OctetString({
+ name: names.encryptedKey || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["version", "keyDerivationAlgorithm", "keyEncryptionAlgorithm", "encryptedKey"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, PasswordRecipientinfo.schema({
+ names: {
+ version: "version",
+ keyDerivationAlgorithm: "keyDerivationAlgorithm",
+ keyEncryptionAlgorithm: {
+ names: {
+ blockName: "keyEncryptionAlgorithm"
+ }
+ },
+ encryptedKey: "encryptedKey"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for PasswordRecipientinfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.version = asn1.result.version.valueBlock.valueDec;
+
+ if ("keyDerivationAlgorithm" in asn1.result) {
+ this.keyDerivationAlgorithm = new _AlgorithmIdentifier.default({
+ schema: new asn1js.Sequence({
+ value: asn1.result.keyDerivationAlgorithm.valueBlock.value
+ })
+ });
+ }
+
+ this.keyEncryptionAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.keyEncryptionAlgorithm
+ });
+ this.encryptedKey = asn1.result.encryptedKey; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create output array for sequence
+ const outputArray = [];
+ outputArray.push(new asn1js.Integer({
+ value: this.version
+ }));
+
+ if ("keyDerivationAlgorithm" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: this.keyDerivationAlgorithm.toSchema().valueBlock.value
+ }));
+ }
+
+ outputArray.push(this.keyEncryptionAlgorithm.toSchema());
+ outputArray.push(this.encryptedKey); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ version: this.version,
+ keyDerivationAlgorithm: this.keyDerivationAlgorithm.toJSON(),
+ keyEncryptionAlgorithm: this.keyEncryptionAlgorithm.toJSON(),
+ encryptedKey: this.encryptedKey.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = PasswordRecipientinfo;
+
+},{"./AlgorithmIdentifier.js":4,"asn1js":112,"pvutils":113}],71:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class PolicyConstraints {
+ //**********************************************************************************
+
+ /**
+ * Constructor for PolicyConstraints class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+ if ("requireExplicitPolicy" in parameters)
+ /**
+ * @type {number}
+ * @desc requireExplicitPolicy
+ */
+ this.requireExplicitPolicy = (0, _pvutils.getParametersValue)(parameters, "requireExplicitPolicy", PolicyConstraints.defaultValues("requireExplicitPolicy"));
+ if ("inhibitPolicyMapping" in parameters)
+ /**
+ * @type {number}
+ * @desc Value of the TIME class
+ */
+ this.inhibitPolicyMapping = (0, _pvutils.getParametersValue)(parameters, "inhibitPolicyMapping", PolicyConstraints.defaultValues("inhibitPolicyMapping")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "requireExplicitPolicy":
+ return 0;
+
+ case "inhibitPolicyMapping":
+ return 0;
+
+ default:
+ throw new Error(`Invalid member name for PolicyConstraints class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * PolicyConstraints ::= SEQUENCE {
+ * requireExplicitPolicy [0] SkipCerts OPTIONAL,
+ * inhibitPolicyMapping [1] SkipCerts OPTIONAL }
+ *
+ * SkipCerts ::= INTEGER (0..MAX)
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [requireExplicitPolicy]
+ * @property {string} [inhibitPolicyMapping]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Primitive({
+ name: names.requireExplicitPolicy || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ }
+ }), // IMPLICIT integer value
+ new asn1js.Primitive({
+ name: names.inhibitPolicyMapping || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ }
+ }) // IMPLICIT integer value
+ ]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["requireExplicitPolicy", "inhibitPolicyMapping"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, PolicyConstraints.schema({
+ names: {
+ requireExplicitPolicy: "requireExplicitPolicy",
+ inhibitPolicyMapping: "inhibitPolicyMapping"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for PolicyConstraints"); //endregion
+ //region Get internal properties from parsed schema
+
+ if ("requireExplicitPolicy" in asn1.result) {
+ const field1 = asn1.result.requireExplicitPolicy;
+ field1.idBlock.tagClass = 1; // UNIVERSAL
+
+ field1.idBlock.tagNumber = 2; // INTEGER
+
+ const ber1 = field1.toBER(false);
+ const int1 = asn1js.fromBER(ber1);
+ this.requireExplicitPolicy = int1.result.valueBlock.valueDec;
+ }
+
+ if ("inhibitPolicyMapping" in asn1.result) {
+ const field2 = asn1.result.inhibitPolicyMapping;
+ field2.idBlock.tagClass = 1; // UNIVERSAL
+
+ field2.idBlock.tagNumber = 2; // INTEGER
+
+ const ber2 = field2.toBER(false);
+ const int2 = asn1js.fromBER(ber2);
+ this.inhibitPolicyMapping = int2.result.valueBlock.valueDec;
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create correct values for output sequence
+ const outputArray = [];
+
+ if ("requireExplicitPolicy" in this) {
+ const int1 = new asn1js.Integer({
+ value: this.requireExplicitPolicy
+ });
+ int1.idBlock.tagClass = 3; // CONTEXT-SPECIFIC
+
+ int1.idBlock.tagNumber = 0; // [0]
+
+ outputArray.push(int1);
+ }
+
+ if ("inhibitPolicyMapping" in this) {
+ const int2 = new asn1js.Integer({
+ value: this.inhibitPolicyMapping
+ });
+ int2.idBlock.tagClass = 3; // CONTEXT-SPECIFIC
+
+ int2.idBlock.tagNumber = 1; // [1]
+
+ outputArray.push(int2);
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {};
+ if ("requireExplicitPolicy" in this) object.requireExplicitPolicy = this.requireExplicitPolicy;
+ if ("inhibitPolicyMapping" in this) object.inhibitPolicyMapping = this.inhibitPolicyMapping;
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = PolicyConstraints;
+
+},{"asn1js":112,"pvutils":113}],72:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _PolicyQualifierInfo = _interopRequireDefault(require("./PolicyQualifierInfo.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class PolicyInformation {
+ //**********************************************************************************
+
+ /**
+ * Constructor for PolicyInformation class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc policyIdentifier
+ */
+ this.policyIdentifier = (0, _pvutils.getParametersValue)(parameters, "policyIdentifier", PolicyInformation.defaultValues("policyIdentifier"));
+ if ("policyQualifiers" in parameters)
+ /**
+ * @type {Array.<PolicyQualifierInfo>}
+ * @desc Value of the TIME class
+ */
+ this.policyQualifiers = (0, _pvutils.getParametersValue)(parameters, "policyQualifiers", PolicyInformation.defaultValues("policyQualifiers")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "policyIdentifier":
+ return "";
+
+ case "policyQualifiers":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for PolicyInformation class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * PolicyInformation ::= SEQUENCE {
+ * policyIdentifier CertPolicyId,
+ * policyQualifiers SEQUENCE SIZE (1..MAX) OF
+ * PolicyQualifierInfo OPTIONAL }
+ *
+ * CertPolicyId ::= OBJECT IDENTIFIER
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [policyIdentifier]
+ * @property {string} [policyQualifiers]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.policyIdentifier || ""
+ }), new asn1js.Sequence({
+ optional: true,
+ value: [new asn1js.Repeated({
+ name: names.policyQualifiers || "",
+ value: _PolicyQualifierInfo.default.schema()
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["policyIdentifier", "policyQualifiers"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, PolicyInformation.schema({
+ names: {
+ policyIdentifier: "policyIdentifier",
+ policyQualifiers: "policyQualifiers"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for PolicyInformation"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.policyIdentifier = asn1.result.policyIdentifier.valueBlock.toString();
+ if ("policyQualifiers" in asn1.result) this.policyQualifiers = Array.from(asn1.result.policyQualifiers, element => new _PolicyQualifierInfo.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(new asn1js.ObjectIdentifier({
+ value: this.policyIdentifier
+ }));
+
+ if ("policyQualifiers" in this) {
+ outputArray.push(new asn1js.Sequence({
+ value: Array.from(this.policyQualifiers, element => element.toSchema())
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {
+ policyIdentifier: this.policyIdentifier
+ };
+ if ("policyQualifiers" in this) object.policyQualifiers = Array.from(this.policyQualifiers, element => element.toJSON());
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = PolicyInformation;
+
+},{"./PolicyQualifierInfo.js":75,"asn1js":112,"pvutils":113}],73:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class PolicyMapping {
+ //**********************************************************************************
+
+ /**
+ * Constructor for PolicyMapping class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc issuerDomainPolicy
+ */
+ this.issuerDomainPolicy = (0, _pvutils.getParametersValue)(parameters, "issuerDomainPolicy", PolicyMapping.defaultValues("issuerDomainPolicy"));
+ /**
+ * @type {string}
+ * @desc subjectDomainPolicy
+ */
+
+ this.subjectDomainPolicy = (0, _pvutils.getParametersValue)(parameters, "subjectDomainPolicy", PolicyMapping.defaultValues("subjectDomainPolicy")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "issuerDomainPolicy":
+ return "";
+
+ case "subjectDomainPolicy":
+ return "";
+
+ default:
+ throw new Error(`Invalid member name for PolicyMapping class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * PolicyMapping ::= SEQUENCE {
+ * issuerDomainPolicy CertPolicyId,
+ * subjectDomainPolicy CertPolicyId }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [issuerDomainPolicy]
+ * @property {string} [subjectDomainPolicy]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.issuerDomainPolicy || ""
+ }), new asn1js.ObjectIdentifier({
+ name: names.subjectDomainPolicy || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["issuerDomainPolicy", "subjectDomainPolicy"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, PolicyMapping.schema({
+ names: {
+ issuerDomainPolicy: "issuerDomainPolicy",
+ subjectDomainPolicy: "subjectDomainPolicy"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for PolicyMapping"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.issuerDomainPolicy = asn1.result.issuerDomainPolicy.valueBlock.toString();
+ this.subjectDomainPolicy = asn1.result.subjectDomainPolicy.valueBlock.toString(); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [new asn1js.ObjectIdentifier({
+ value: this.issuerDomainPolicy
+ }), new asn1js.ObjectIdentifier({
+ value: this.subjectDomainPolicy
+ })]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ issuerDomainPolicy: this.issuerDomainPolicy,
+ subjectDomainPolicy: this.subjectDomainPolicy
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = PolicyMapping;
+
+},{"asn1js":112,"pvutils":113}],74:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _PolicyMapping = _interopRequireDefault(require("./PolicyMapping.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class PolicyMappings {
+ //**********************************************************************************
+
+ /**
+ * Constructor for PolicyMappings class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array.<PolicyMapping>}
+ * @desc mappings
+ */
+ this.mappings = (0, _pvutils.getParametersValue)(parameters, "mappings", PolicyMappings.defaultValues("mappings")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "mappings":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for PolicyMappings class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF PolicyMapping
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [utcTimeName] Name for "utcTimeName" choice
+ * @property {string} [generalTimeName] Name for "generalTimeName" choice
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Repeated({
+ name: names.mappings || "",
+ value: _PolicyMapping.default.schema()
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["mappings"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, PolicyMappings.schema({
+ names: {
+ mappings: "mappings"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for PolicyMappings"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.mappings = Array.from(asn1.result.mappings, element => new _PolicyMapping.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: Array.from(this.mappings, element => element.toSchema())
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ mappings: Array.from(this.mappings, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = PolicyMappings;
+
+},{"./PolicyMapping.js":73,"asn1js":112,"pvutils":113}],75:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class PolicyQualifierInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for PolicyQualifierInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc policyQualifierId
+ */
+ this.policyQualifierId = (0, _pvutils.getParametersValue)(parameters, "policyQualifierId", PolicyQualifierInfo.defaultValues("policyQualifierId"));
+ /**
+ * @type {Object}
+ * @desc qualifier
+ */
+
+ this.qualifier = (0, _pvutils.getParametersValue)(parameters, "qualifier", PolicyQualifierInfo.defaultValues("qualifier")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "policyQualifierId":
+ return "";
+
+ case "qualifier":
+ return new asn1js.Any();
+
+ default:
+ throw new Error(`Invalid member name for PolicyQualifierInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * PolicyQualifierInfo ::= SEQUENCE {
+ * policyQualifierId PolicyQualifierId,
+ * qualifier ANY DEFINED BY policyQualifierId }
+ *
+ * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 }
+ * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 }
+ * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 }
+ *
+ * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [policyQualifierId]
+ * @property {string} [qualifier]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.policyQualifierId || ""
+ }), new asn1js.Any({
+ name: names.qualifier || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["policyQualifierId", "qualifier"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, PolicyQualifierInfo.schema({
+ names: {
+ policyQualifierId: "policyQualifierId",
+ qualifier: "qualifier"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for PolicyQualifierInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.policyQualifierId = asn1.result.policyQualifierId.valueBlock.toString();
+ this.qualifier = asn1.result.qualifier; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [new asn1js.ObjectIdentifier({
+ value: this.policyQualifierId
+ }), this.qualifier]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ policyQualifierId: this.policyQualifierId,
+ qualifier: this.qualifier.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = PolicyQualifierInfo;
+
+},{"asn1js":112,"pvutils":113}],76:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _Attribute = _interopRequireDefault(require("./Attribute.js"));
+
+var _ECPrivateKey = _interopRequireDefault(require("./ECPrivateKey.js"));
+
+var _RSAPrivateKey = _interopRequireDefault(require("./RSAPrivateKey.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5208
+ */
+class PrivateKeyInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for PrivateKeyInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", PrivateKeyInfo.defaultValues("version"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc privateKeyAlgorithm
+ */
+
+ this.privateKeyAlgorithm = (0, _pvutils.getParametersValue)(parameters, "privateKeyAlgorithm", PrivateKeyInfo.defaultValues("privateKeyAlgorithm"));
+ /**
+ * @type {OctetString}
+ * @desc privateKey
+ */
+
+ this.privateKey = (0, _pvutils.getParametersValue)(parameters, "privateKey", PrivateKeyInfo.defaultValues("privateKey"));
+ if ("attributes" in parameters)
+ /**
+ * @type {Array.<Attribute>}
+ * @desc attributes
+ */
+ this.attributes = (0, _pvutils.getParametersValue)(parameters, "attributes", PrivateKeyInfo.defaultValues("attributes"));
+ if ("parsedKey" in parameters)
+ /**
+ * @type {ECPrivateKey|RSAPrivateKey}
+ * @desc Parsed public key value
+ */
+ this.parsedKey = (0, _pvutils.getParametersValue)(parameters, "parsedKey", PrivateKeyInfo.defaultValues("parsedKey")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ //region If input argument array contains "json" for this object
+
+ if ("json" in parameters) this.fromJSON(parameters.json); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return 0;
+
+ case "privateKeyAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "privateKey":
+ return new asn1js.OctetString();
+
+ case "attributes":
+ return [];
+
+ case "parsedKey":
+ return {};
+
+ default:
+ throw new Error(`Invalid member name for PrivateKeyInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * PrivateKeyInfo ::= SEQUENCE {
+ * version Version,
+ * privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
+ * privateKey PrivateKey,
+ * attributes [0] Attributes OPTIONAL }
+ *
+ * Version ::= INTEGER {v1(0)} (v1,...)
+ *
+ * PrivateKey ::= OCTET STRING
+ *
+ * Attributes ::= SET OF Attribute
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [version]
+ * @property {string} [privateKeyAlgorithm]
+ * @property {string} [privateKey]
+ * @property {string} [attributes]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Integer({
+ name: names.version || ""
+ }), _AlgorithmIdentifier.default.schema(names.privateKeyAlgorithm || {}), new asn1js.OctetString({
+ name: names.privateKey || ""
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Repeated({
+ name: names.attributes || "",
+ value: _Attribute.default.schema()
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["version", "privateKeyAlgorithm", "privateKey", "attributes"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, PrivateKeyInfo.schema({
+ names: {
+ version: "version",
+ privateKeyAlgorithm: {
+ names: {
+ blockName: "privateKeyAlgorithm"
+ }
+ },
+ privateKey: "privateKey",
+ attributes: "attributes"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for PrivateKeyInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.version = asn1.result.version.valueBlock.valueDec;
+ this.privateKeyAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.privateKeyAlgorithm
+ });
+ this.privateKey = asn1.result.privateKey;
+ if ("attributes" in asn1.result) this.attributes = Array.from(asn1.result.attributes, element => new _Attribute.default({
+ schema: element
+ }));
+
+ switch (this.privateKeyAlgorithm.algorithmId) {
+ case "1.2.840.113549.1.1.1":
+ // RSA
+ {
+ const privateKeyASN1 = asn1js.fromBER(this.privateKey.valueBlock.valueHex);
+ if (privateKeyASN1.offset !== -1) this.parsedKey = new _RSAPrivateKey.default({
+ schema: privateKeyASN1.result
+ });
+ }
+ break;
+
+ case "1.2.840.10045.2.1":
+ // ECDSA
+ if ("algorithmParams" in this.privateKeyAlgorithm) {
+ if (this.privateKeyAlgorithm.algorithmParams instanceof asn1js.ObjectIdentifier) {
+ const privateKeyASN1 = asn1js.fromBER(this.privateKey.valueBlock.valueHex);
+
+ if (privateKeyASN1.offset !== -1) {
+ this.parsedKey = new _ECPrivateKey.default({
+ namedCurve: this.privateKeyAlgorithm.algorithmParams.valueBlock.toString(),
+ schema: privateKeyASN1.result
+ });
+ }
+ }
+ }
+
+ break;
+
+ default:
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [new asn1js.Integer({
+ value: this.version
+ }), this.privateKeyAlgorithm.toSchema(), this.privateKey];
+
+ if ("attributes" in this) {
+ outputArray.push(new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: Array.from(this.attributes, element => element.toSchema())
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ //region Return common value in case we do not have enough info fo making JWK
+ if ("parsedKey" in this === false) {
+ const object = {
+ version: this.version,
+ privateKeyAlgorithm: this.privateKeyAlgorithm.toJSON(),
+ privateKey: this.privateKey.toJSON()
+ };
+ if ("attributes" in this) object.attributes = Array.from(this.attributes, element => element.toJSON());
+ return object;
+ } //endregion
+ //region Making JWK
+
+
+ const jwk = {};
+
+ switch (this.privateKeyAlgorithm.algorithmId) {
+ case "1.2.840.10045.2.1":
+ // ECDSA
+ jwk.kty = "EC";
+ break;
+
+ case "1.2.840.113549.1.1.1":
+ // RSA
+ jwk.kty = "RSA";
+ break;
+
+ default:
+ }
+
+ const publicKeyJWK = this.parsedKey.toJSON();
+
+ for (var _i = 0, _Object$keys = Object.keys(publicKeyJWK); _i < _Object$keys.length; _i++) {
+ const key = _Object$keys[_i];
+ jwk[key] = publicKeyJWK[key];
+ }
+
+ return jwk; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert JSON value into current object
+ * @param {Object} json
+ */
+
+
+ fromJSON(json) {
+ if ("kty" in json) {
+ switch (json.kty.toUpperCase()) {
+ case "EC":
+ this.parsedKey = new _ECPrivateKey.default({
+ json
+ });
+ this.privateKeyAlgorithm = new _AlgorithmIdentifier.default({
+ algorithmId: "1.2.840.10045.2.1",
+ algorithmParams: new asn1js.ObjectIdentifier({
+ value: this.parsedKey.namedCurve
+ })
+ });
+ break;
+
+ case "RSA":
+ this.parsedKey = new _RSAPrivateKey.default({
+ json
+ });
+ this.privateKeyAlgorithm = new _AlgorithmIdentifier.default({
+ algorithmId: "1.2.840.113549.1.1.1",
+ algorithmParams: new asn1js.Null()
+ });
+ break;
+
+ default:
+ throw new Error(`Invalid value for "kty" parameter: ${json.kty}`);
+ }
+
+ this.privateKey = new asn1js.OctetString({
+ valueHex: this.parsedKey.toSchema().toBER(false)
+ });
+ }
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = PrivateKeyInfo;
+
+},{"./AlgorithmIdentifier.js":4,"./Attribute.js":6,"./ECPrivateKey.js":31,"./RSAPrivateKey.js":81,"asn1js":112,"pvutils":113}],77:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class PrivateKeyUsagePeriod {
+ //**********************************************************************************
+
+ /**
+ * Constructor for PrivateKeyUsagePeriod class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+ if ("notBefore" in parameters)
+ /**
+ * @type {Date}
+ * @desc notBefore
+ */
+ this.notBefore = (0, _pvutils.getParametersValue)(parameters, "notBefore", PrivateKeyUsagePeriod.defaultValues("notBefore"));
+ if ("notAfter" in parameters)
+ /**
+ * @type {Date}
+ * @desc notAfter
+ */
+ this.notAfter = (0, _pvutils.getParametersValue)(parameters, "notAfter", PrivateKeyUsagePeriod.defaultValues("notAfter")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "notBefore":
+ return new Date();
+
+ case "notAfter":
+ return new Date();
+
+ default:
+ throw new Error(`Invalid member name for PrivateKeyUsagePeriod class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * PrivateKeyUsagePeriod OID ::= 2.5.29.16
+ *
+ * PrivateKeyUsagePeriod ::= SEQUENCE {
+ * notBefore [0] GeneralizedTime OPTIONAL,
+ * notAfter [1] GeneralizedTime OPTIONAL }
+ * -- either notBefore or notAfter MUST be present
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [notBefore]
+ * @property {string} [notAfter]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Primitive({
+ name: names.notBefore || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ }
+ }), new asn1js.Primitive({
+ name: names.notAfter || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ }
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["notBefore", "notAfter"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, PrivateKeyUsagePeriod.schema({
+ names: {
+ notBefore: "notBefore",
+ notAfter: "notAfter"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for PrivateKeyUsagePeriod"); //endregion
+ //region Get internal properties from parsed schema
+
+ if ("notBefore" in asn1.result) {
+ const localNotBefore = new asn1js.GeneralizedTime();
+ localNotBefore.fromBuffer(asn1.result.notBefore.valueBlock.valueHex);
+ this.notBefore = localNotBefore.toDate();
+ }
+
+ if ("notAfter" in asn1.result) {
+ const localNotAfter = new asn1js.GeneralizedTime({
+ valueHex: asn1.result.notAfter.valueBlock.valueHex
+ });
+ localNotAfter.fromBuffer(asn1.result.notAfter.valueBlock.valueHex);
+ this.notAfter = localNotAfter.toDate();
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+
+ if ("notBefore" in this) {
+ outputArray.push(new asn1js.Primitive({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ valueHex: new asn1js.GeneralizedTime({
+ valueDate: this.notBefore
+ }).valueBlock.valueHex
+ }));
+ }
+
+ if ("notAfter" in this) {
+ outputArray.push(new asn1js.Primitive({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ valueHex: new asn1js.GeneralizedTime({
+ valueDate: this.notAfter
+ }).valueBlock.valueHex
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {};
+ if ("notBefore" in this) object.notBefore = this.notBefore;
+ if ("notAfter" in this) object.notAfter = this.notAfter;
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = PrivateKeyUsagePeriod;
+
+},{"asn1js":112,"pvutils":113}],78:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _common = require("./common.js");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _ECPublicKey = _interopRequireDefault(require("./ECPublicKey.js"));
+
+var _RSAPublicKey = _interopRequireDefault(require("./RSAPublicKey.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class PublicKeyInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for PublicKeyInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc Algorithm identifier
+ */
+ this.algorithm = (0, _pvutils.getParametersValue)(parameters, "algorithm", PublicKeyInfo.defaultValues("algorithm"));
+ /**
+ * @type {BitString}
+ * @desc Subject public key value
+ */
+
+ this.subjectPublicKey = (0, _pvutils.getParametersValue)(parameters, "subjectPublicKey", PublicKeyInfo.defaultValues("subjectPublicKey"));
+ if ("parsedKey" in parameters)
+ /**
+ * @type {ECPublicKey|RSAPublicKey}
+ * @desc Parsed public key value
+ */
+ this.parsedKey = (0, _pvutils.getParametersValue)(parameters, "parsedKey", PublicKeyInfo.defaultValues("parsedKey")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ //region If input argument array contains "json" for this object
+
+ if ("json" in parameters) this.fromJSON(parameters.json); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "algorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "subjectPublicKey":
+ return new asn1js.BitString();
+
+ default:
+ throw new Error(`Invalid member name for PublicKeyInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * SubjectPublicKeyInfo ::= Sequence {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [algorithm]
+ * @property {string} [subjectPublicKey]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [_AlgorithmIdentifier.default.schema(names.algorithm || {}), new asn1js.BitString({
+ name: names.subjectPublicKey || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["algorithm", "subjectPublicKey"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, PublicKeyInfo.schema({
+ names: {
+ algorithm: {
+ names: {
+ blockName: "algorithm"
+ }
+ },
+ subjectPublicKey: "subjectPublicKey"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for PublicKeyInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.algorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.algorithm
+ });
+ this.subjectPublicKey = asn1.result.subjectPublicKey;
+
+ switch (this.algorithm.algorithmId) {
+ case "1.2.840.10045.2.1":
+ // ECDSA
+ if ("algorithmParams" in this.algorithm) {
+ if (this.algorithm.algorithmParams.constructor.blockName() === asn1js.ObjectIdentifier.blockName()) {
+ try {
+ this.parsedKey = new _ECPublicKey.default({
+ namedCurve: this.algorithm.algorithmParams.valueBlock.toString(),
+ schema: this.subjectPublicKey.valueBlock.valueHex
+ });
+ } catch (ex) {} // Could be a problems during recognision of internal public key data here. Let's ignore them.
+
+ }
+ }
+
+ break;
+
+ case "1.2.840.113549.1.1.1":
+ // RSA
+ {
+ const publicKeyASN1 = asn1js.fromBER(this.subjectPublicKey.valueBlock.valueHex);
+
+ if (publicKeyASN1.offset !== -1) {
+ try {
+ this.parsedKey = new _RSAPublicKey.default({
+ schema: publicKeyASN1.result
+ });
+ } catch (ex) {} // Could be a problems during recognision of internal public key data here. Let's ignore them.
+
+ }
+ }
+ break;
+
+ default:
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [this.algorithm.toSchema(), this.subjectPublicKey]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ //region Return common value in case we do not have enough info fo making JWK
+ if ("parsedKey" in this === false) {
+ return {
+ algorithm: this.algorithm.toJSON(),
+ subjectPublicKey: this.subjectPublicKey.toJSON()
+ };
+ } //endregion
+ //region Making JWK
+
+
+ const jwk = {};
+
+ switch (this.algorithm.algorithmId) {
+ case "1.2.840.10045.2.1":
+ // ECDSA
+ jwk.kty = "EC";
+ break;
+
+ case "1.2.840.113549.1.1.1":
+ // RSA
+ jwk.kty = "RSA";
+ break;
+
+ default:
+ }
+
+ const publicKeyJWK = this.parsedKey.toJSON();
+
+ for (var _i = 0, _Object$keys = Object.keys(publicKeyJWK); _i < _Object$keys.length; _i++) {
+ const key = _Object$keys[_i];
+ jwk[key] = publicKeyJWK[key];
+ }
+
+ return jwk; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert JSON value into current object
+ * @param {Object} json
+ */
+
+
+ fromJSON(json) {
+ if ("kty" in json) {
+ switch (json.kty.toUpperCase()) {
+ case "EC":
+ this.parsedKey = new _ECPublicKey.default({
+ json
+ });
+ this.algorithm = new _AlgorithmIdentifier.default({
+ algorithmId: "1.2.840.10045.2.1",
+ algorithmParams: new asn1js.ObjectIdentifier({
+ value: this.parsedKey.namedCurve
+ })
+ });
+ break;
+
+ case "RSA":
+ this.parsedKey = new _RSAPublicKey.default({
+ json
+ });
+ this.algorithm = new _AlgorithmIdentifier.default({
+ algorithmId: "1.2.840.113549.1.1.1",
+ algorithmParams: new asn1js.Null()
+ });
+ break;
+
+ default:
+ throw new Error(`Invalid value for "kty" parameter: ${json.kty}`);
+ }
+
+ this.subjectPublicKey = new asn1js.BitString({
+ valueHex: this.parsedKey.toSchema().toBER(false)
+ });
+ }
+ } //**********************************************************************************
+
+
+ importKey(publicKey) {
+ //region Initial variables
+ let sequence = Promise.resolve();
+
+ const _this = this; //endregion
+ //region Initial check
+
+
+ if (typeof publicKey === "undefined") return Promise.reject("Need to provide publicKey input parameter"); //endregion
+ //region Get a "crypto" extension
+
+ const crypto = (0, _common.getCrypto)();
+ if (typeof crypto === "undefined") return Promise.reject("Unable to create WebCrypto object"); //endregion
+ //region Export public key
+
+ sequence = sequence.then(() => crypto.exportKey("spki", publicKey)); //endregion
+ //region Initialize internal variables by parsing exported value
+
+ sequence = sequence.then(
+ /**
+ * @param {ArrayBuffer} exportedKey
+ */
+ exportedKey => {
+ const asn1 = asn1js.fromBER(exportedKey);
+
+ try {
+ _this.fromSchema(asn1.result);
+ } catch (exception) {
+ return Promise.reject("Error during initializing object from schema");
+ }
+
+ return undefined;
+ }, error => Promise.reject(`Error during exporting public key: ${error}`)); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = PublicKeyInfo;
+
+},{"./AlgorithmIdentifier.js":4,"./ECPublicKey.js":32,"./RSAPublicKey.js":82,"./common.js":110,"asn1js":112,"pvutils":113}],79:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = exports.QCStatement = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC3739
+ */
+class QCStatement {
+ //**********************************************************************************
+
+ /**
+ * Constructor for QCStatement class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ */
+ this.id = (0, _pvutils.getParametersValue)(parameters, "id", QCStatement.defaultValues("id"));
+
+ if ("type" in parameters) {
+ /**
+ * @type {*} Any data described by "id"
+ */
+ this.type = (0, _pvutils.getParametersValue)(parameters, "type", QCStatement.defaultValues("type"));
+ } //endregion
+ //region If input argument array contains "schema" for this object
+
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "id":
+ return "";
+
+ case "type":
+ return new asn1js.Null();
+
+ default:
+ throw new Error(`Invalid member name for QCStatement class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "id":
+ return memberValue === "";
+
+ case "type":
+ return memberValue instanceof asn1js.Null;
+
+ default:
+ throw new Error(`Invalid member name for QCStatement class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * QCStatement ::= SEQUENCE {
+ * statementId QC-STATEMENT.&id({SupportedStatements}),
+ * statementInfo QC-STATEMENT.&Type({SupportedStatements}{@statementId}) OPTIONAL
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [id]
+ * @property {string} [type]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.id || ""
+ }), new asn1js.Any({
+ name: names.type || "",
+ optional: true
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["id", "type"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, QCStatement.schema({
+ names: {
+ id: "id",
+ type: "type"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for QCStatement"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.id = asn1.result.id.valueBlock.toString();
+ if ("type" in asn1.result) this.type = asn1.result.type; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ const value = [new asn1js.ObjectIdentifier({
+ value: this.id
+ })];
+ if ("type" in this) value.push(this.type); //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Sequence({
+ value
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {
+ id: this.id
+ };
+ if ("type" in this) object.type = this.type.toJSON();
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * Class from RFC3739
+ */
+
+
+exports.QCStatement = QCStatement;
+
+class QCStatements {
+ //**********************************************************************************
+
+ /**
+ * Constructor for QCStatements class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array<QCStatement>}
+ */
+ this.values = (0, _pvutils.getParametersValue)(parameters, "values", QCStatements.defaultValues("values")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "values":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for QCStatements class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "values":
+ return memberValue.length === 0;
+
+ default:
+ throw new Error(`Invalid member name for QCStatements class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * QCStatements ::= SEQUENCE OF QCStatement
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [values]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Repeated({
+ name: names.values || "",
+ value: QCStatement.schema(names.value || {})
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["values"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, QCStatements.schema({
+ names: {
+ values: "values"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for QCStatements"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.values = Array.from(asn1.result.values, element => new QCStatement({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: Array.from(this.values, element => element.toSchema())
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ extensions: Array.from(this.values, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = QCStatements;
+
+},{"asn1js":112,"pvutils":113}],80:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC3447
+ */
+class RSAESOAEPParams {
+ //**********************************************************************************
+
+ /**
+ * Constructor for RSAESOAEPParams class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc hashAlgorithm
+ */
+ this.hashAlgorithm = (0, _pvutils.getParametersValue)(parameters, "hashAlgorithm", RSAESOAEPParams.defaultValues("hashAlgorithm"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc maskGenAlgorithm
+ */
+
+ this.maskGenAlgorithm = (0, _pvutils.getParametersValue)(parameters, "maskGenAlgorithm", RSAESOAEPParams.defaultValues("maskGenAlgorithm"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc pSourceAlgorithm
+ */
+
+ this.pSourceAlgorithm = (0, _pvutils.getParametersValue)(parameters, "pSourceAlgorithm", RSAESOAEPParams.defaultValues("pSourceAlgorithm")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "hashAlgorithm":
+ return new _AlgorithmIdentifier.default({
+ algorithmId: "1.3.14.3.2.26",
+ // SHA-1
+ algorithmParams: new asn1js.Null()
+ });
+
+ case "maskGenAlgorithm":
+ return new _AlgorithmIdentifier.default({
+ algorithmId: "1.2.840.113549.1.1.8",
+ // MGF1
+ algorithmParams: new _AlgorithmIdentifier.default({
+ algorithmId: "1.3.14.3.2.26",
+ // SHA-1
+ algorithmParams: new asn1js.Null()
+ }).toSchema()
+ });
+
+ case "pSourceAlgorithm":
+ return new _AlgorithmIdentifier.default({
+ algorithmId: "1.2.840.113549.1.1.9",
+ // id-pSpecified
+ algorithmParams: new asn1js.OctetString({
+ valueHex: new Uint8Array([0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09]).buffer
+ }) // SHA-1 hash of empty string
+
+ });
+
+ default:
+ throw new Error(`Invalid member name for RSAESOAEPParams class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * RSAES-OAEP-params ::= SEQUENCE {
+ * hashAlgorithm [0] HashAlgorithm DEFAULT sha1,
+ * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1,
+ * pSourceAlgorithm [2] PSourceAlgorithm DEFAULT pSpecifiedEmpty
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [hashAlgorithm]
+ * @property {string} [maskGenAlgorithm]
+ * @property {string} [pSourceAlgorithm]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ optional: true,
+ value: [_AlgorithmIdentifier.default.schema(names.hashAlgorithm || {})]
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ optional: true,
+ value: [_AlgorithmIdentifier.default.schema(names.maskGenAlgorithm || {})]
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ optional: true,
+ value: [_AlgorithmIdentifier.default.schema(names.pSourceAlgorithm || {})]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["hashAlgorithm", "maskGenAlgorithm", "pSourceAlgorithm"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, RSAESOAEPParams.schema({
+ names: {
+ hashAlgorithm: {
+ names: {
+ blockName: "hashAlgorithm"
+ }
+ },
+ maskGenAlgorithm: {
+ names: {
+ blockName: "maskGenAlgorithm"
+ }
+ },
+ pSourceAlgorithm: {
+ names: {
+ blockName: "pSourceAlgorithm"
+ }
+ }
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for RSAESOAEPParams"); //endregion
+ //region Get internal properties from parsed schema
+
+ if ("hashAlgorithm" in asn1.result) this.hashAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.hashAlgorithm
+ });
+ if ("maskGenAlgorithm" in asn1.result) this.maskGenAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.maskGenAlgorithm
+ });
+ if ("pSourceAlgorithm" in asn1.result) this.pSourceAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.pSourceAlgorithm
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+
+ if (!this.hashAlgorithm.isEqual(RSAESOAEPParams.defaultValues("hashAlgorithm"))) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [this.hashAlgorithm.toSchema()]
+ }));
+ }
+
+ if (!this.maskGenAlgorithm.isEqual(RSAESOAEPParams.defaultValues("maskGenAlgorithm"))) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [this.maskGenAlgorithm.toSchema()]
+ }));
+ }
+
+ if (!this.pSourceAlgorithm.isEqual(RSAESOAEPParams.defaultValues("pSourceAlgorithm"))) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ value: [this.pSourceAlgorithm.toSchema()]
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {};
+ if (!this.hashAlgorithm.isEqual(RSAESOAEPParams.defaultValues("hashAlgorithm"))) object.hashAlgorithm = this.hashAlgorithm.toJSON();
+ if (!this.maskGenAlgorithm.isEqual(RSAESOAEPParams.defaultValues("maskGenAlgorithm"))) object.maskGenAlgorithm = this.maskGenAlgorithm.toJSON();
+ if (!this.pSourceAlgorithm.isEqual(RSAESOAEPParams.defaultValues("pSourceAlgorithm"))) object.pSourceAlgorithm = this.pSourceAlgorithm.toJSON();
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = RSAESOAEPParams;
+
+},{"./AlgorithmIdentifier.js":4,"asn1js":112,"pvutils":113}],81:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _OtherPrimeInfo = _interopRequireDefault(require("./OtherPrimeInfo.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC3447
+ */
+class RSAPrivateKey {
+ //**********************************************************************************
+
+ /**
+ * Constructor for RSAPrivateKey class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", RSAPrivateKey.defaultValues("version"));
+ /**
+ * @type {Integer}
+ * @desc modulus
+ */
+
+ this.modulus = (0, _pvutils.getParametersValue)(parameters, "modulus", RSAPrivateKey.defaultValues("modulus"));
+ /**
+ * @type {Integer}
+ * @desc publicExponent
+ */
+
+ this.publicExponent = (0, _pvutils.getParametersValue)(parameters, "publicExponent", RSAPrivateKey.defaultValues("publicExponent"));
+ /**
+ * @type {Integer}
+ * @desc privateExponent
+ */
+
+ this.privateExponent = (0, _pvutils.getParametersValue)(parameters, "privateExponent", RSAPrivateKey.defaultValues("privateExponent"));
+ /**
+ * @type {Integer}
+ * @desc prime1
+ */
+
+ this.prime1 = (0, _pvutils.getParametersValue)(parameters, "prime1", RSAPrivateKey.defaultValues("prime1"));
+ /**
+ * @type {Integer}
+ * @desc prime2
+ */
+
+ this.prime2 = (0, _pvutils.getParametersValue)(parameters, "prime2", RSAPrivateKey.defaultValues("prime2"));
+ /**
+ * @type {Integer}
+ * @desc exponent1
+ */
+
+ this.exponent1 = (0, _pvutils.getParametersValue)(parameters, "exponent1", RSAPrivateKey.defaultValues("exponent1"));
+ /**
+ * @type {Integer}
+ * @desc exponent2
+ */
+
+ this.exponent2 = (0, _pvutils.getParametersValue)(parameters, "exponent2", RSAPrivateKey.defaultValues("exponent2"));
+ /**
+ * @type {Integer}
+ * @desc coefficient
+ */
+
+ this.coefficient = (0, _pvutils.getParametersValue)(parameters, "coefficient", RSAPrivateKey.defaultValues("coefficient"));
+ if ("otherPrimeInfos" in parameters)
+ /**
+ * @type {Array.<OtherPrimeInfo>}
+ * @desc otherPrimeInfos
+ */
+ this.otherPrimeInfos = (0, _pvutils.getParametersValue)(parameters, "otherPrimeInfos", RSAPrivateKey.defaultValues("otherPrimeInfos")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ //region If input argument array contains "json" for this object
+
+ if ("json" in parameters) this.fromJSON(parameters.json); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return 0;
+
+ case "modulus":
+ return new asn1js.Integer();
+
+ case "publicExponent":
+ return new asn1js.Integer();
+
+ case "privateExponent":
+ return new asn1js.Integer();
+
+ case "prime1":
+ return new asn1js.Integer();
+
+ case "prime2":
+ return new asn1js.Integer();
+
+ case "exponent1":
+ return new asn1js.Integer();
+
+ case "exponent2":
+ return new asn1js.Integer();
+
+ case "coefficient":
+ return new asn1js.Integer();
+
+ case "otherPrimeInfos":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for RSAPrivateKey class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * RSAPrivateKey ::= Sequence {
+ * version Version,
+ * modulus Integer, -- n
+ * publicExponent Integer, -- e
+ * privateExponent Integer, -- d
+ * prime1 Integer, -- p
+ * prime2 Integer, -- q
+ * exponent1 Integer, -- d mod (p-1)
+ * exponent2 Integer, -- d mod (q-1)
+ * coefficient Integer, -- (inverse of q) mod p
+ * otherPrimeInfos OtherPrimeInfos OPTIONAL
+ * }
+ *
+ * OtherPrimeInfos ::= Sequence SIZE(1..MAX) OF OtherPrimeInfo
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [version]
+ * @property {string} [modulus]
+ * @property {string} [publicExponent]
+ * @property {string} [privateExponent]
+ * @property {string} [prime1]
+ * @property {string} [prime2]
+ * @property {string} [exponent1]
+ * @property {string} [exponent2]
+ * @property {string} [coefficient]
+ * @property {string} [otherPrimeInfosName]
+ * @property {Object} [otherPrimeInfo]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Integer({
+ name: names.version || ""
+ }), new asn1js.Integer({
+ name: names.modulus || ""
+ }), new asn1js.Integer({
+ name: names.publicExponent || ""
+ }), new asn1js.Integer({
+ name: names.privateExponent || ""
+ }), new asn1js.Integer({
+ name: names.prime1 || ""
+ }), new asn1js.Integer({
+ name: names.prime2 || ""
+ }), new asn1js.Integer({
+ name: names.exponent1 || ""
+ }), new asn1js.Integer({
+ name: names.exponent2 || ""
+ }), new asn1js.Integer({
+ name: names.coefficient || ""
+ }), new asn1js.Sequence({
+ optional: true,
+ value: [new asn1js.Repeated({
+ name: names.otherPrimeInfosName || "",
+ value: _OtherPrimeInfo.default.schema(names.otherPrimeInfo || {})
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["version", "modulus", "publicExponent", "privateExponent", "prime1", "prime2", "exponent1", "exponent2", "coefficient", "otherPrimeInfos"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, RSAPrivateKey.schema({
+ names: {
+ version: "version",
+ modulus: "modulus",
+ publicExponent: "publicExponent",
+ privateExponent: "privateExponent",
+ prime1: "prime1",
+ prime2: "prime2",
+ exponent1: "exponent1",
+ exponent2: "exponent2",
+ coefficient: "coefficient",
+ otherPrimeInfo: {
+ names: {
+ blockName: "otherPrimeInfos"
+ }
+ }
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for RSAPrivateKey"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.version = asn1.result.version.valueBlock.valueDec;
+ this.modulus = asn1.result.modulus.convertFromDER(256);
+ this.publicExponent = asn1.result.publicExponent;
+ this.privateExponent = asn1.result.privateExponent.convertFromDER(256);
+ this.prime1 = asn1.result.prime1.convertFromDER(128);
+ this.prime2 = asn1.result.prime2.convertFromDER(128);
+ this.exponent1 = asn1.result.exponent1.convertFromDER(128);
+ this.exponent2 = asn1.result.exponent2.convertFromDER(128);
+ this.coefficient = asn1.result.coefficient.convertFromDER(128);
+ if ("otherPrimeInfos" in asn1.result) this.otherPrimeInfos = Array.from(asn1.result.otherPrimeInfos, element => new _OtherPrimeInfo.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(new asn1js.Integer({
+ value: this.version
+ }));
+ outputArray.push(this.modulus.convertToDER());
+ outputArray.push(this.publicExponent);
+ outputArray.push(this.privateExponent.convertToDER());
+ outputArray.push(this.prime1.convertToDER());
+ outputArray.push(this.prime2.convertToDER());
+ outputArray.push(this.exponent1.convertToDER());
+ outputArray.push(this.exponent2.convertToDER());
+ outputArray.push(this.coefficient.convertToDER());
+
+ if ("otherPrimeInfos" in this) {
+ outputArray.push(new asn1js.Sequence({
+ value: Array.from(this.otherPrimeInfos, element => element.toSchema())
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const jwk = {
+ n: (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(this.modulus.valueBlock.valueHex), true, true, true),
+ e: (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(this.publicExponent.valueBlock.valueHex), true, true, true),
+ d: (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(this.privateExponent.valueBlock.valueHex), true, true, true),
+ p: (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(this.prime1.valueBlock.valueHex), true, true, true),
+ q: (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(this.prime2.valueBlock.valueHex), true, true, true),
+ dp: (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(this.exponent1.valueBlock.valueHex), true, true, true),
+ dq: (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(this.exponent2.valueBlock.valueHex), true, true, true),
+ qi: (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(this.coefficient.valueBlock.valueHex), true, true, true)
+ };
+ if ("otherPrimeInfos" in this) jwk.oth = Array.from(this.otherPrimeInfos, element => element.toJSON());
+ return jwk;
+ } //**********************************************************************************
+
+ /**
+ * Convert JSON value into current object
+ * @param {Object} json
+ */
+
+
+ fromJSON(json) {
+ if ("n" in json) this.modulus = new asn1js.Integer({
+ valueHex: (0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(json.n, true, true))
+ });else throw new Error("Absent mandatory parameter \"n\"");
+ if ("e" in json) this.publicExponent = new asn1js.Integer({
+ valueHex: (0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(json.e, true, true))
+ });else throw new Error("Absent mandatory parameter \"e\"");
+ if ("d" in json) this.privateExponent = new asn1js.Integer({
+ valueHex: (0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(json.d, true, true))
+ });else throw new Error("Absent mandatory parameter \"d\"");
+ if ("p" in json) this.prime1 = new asn1js.Integer({
+ valueHex: (0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(json.p, true, true))
+ });else throw new Error("Absent mandatory parameter \"p\"");
+ if ("q" in json) this.prime2 = new asn1js.Integer({
+ valueHex: (0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(json.q, true, true))
+ });else throw new Error("Absent mandatory parameter \"q\"");
+ if ("dp" in json) this.exponent1 = new asn1js.Integer({
+ valueHex: (0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(json.dp, true, true))
+ });else throw new Error("Absent mandatory parameter \"dp\"");
+ if ("dq" in json) this.exponent2 = new asn1js.Integer({
+ valueHex: (0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(json.dq, true, true))
+ });else throw new Error("Absent mandatory parameter \"dq\"");
+ if ("qi" in json) this.coefficient = new asn1js.Integer({
+ valueHex: (0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(json.qi, true, true))
+ });else throw new Error("Absent mandatory parameter \"qi\"");
+ if ("oth" in json) this.otherPrimeInfos = Array.from(json.oth, element => new _OtherPrimeInfo.default({
+ json: element
+ }));
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = RSAPrivateKey;
+
+},{"./OtherPrimeInfo.js":62,"asn1js":112,"pvutils":113}],82:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC3447
+ */
+class RSAPublicKey {
+ //**********************************************************************************
+
+ /**
+ * Constructor for RSAPublicKey class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ * @property {Integer} [modulus]
+ * @property {Integer} [publicExponent]
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Integer}
+ * @desc Modulus part of RSA public key
+ */
+ this.modulus = (0, _pvutils.getParametersValue)(parameters, "modulus", RSAPublicKey.defaultValues("modulus"));
+ /**
+ * @type {Integer}
+ * @desc Public exponent of RSA public key
+ */
+
+ this.publicExponent = (0, _pvutils.getParametersValue)(parameters, "publicExponent", RSAPublicKey.defaultValues("publicExponent")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ //region If input argument array contains "json" for this object
+
+ if ("json" in parameters) this.fromJSON(parameters.json); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "modulus":
+ return new asn1js.Integer();
+
+ case "publicExponent":
+ return new asn1js.Integer();
+
+ default:
+ throw new Error(`Invalid member name for RSAPublicKey class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * RSAPublicKey ::= Sequence {
+ * modulus Integer, -- n
+ * publicExponent Integer -- e
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} utcTimeName Name for "utcTimeName" choice
+ * @property {string} generalTimeName Name for "generalTimeName" choice
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Integer({
+ name: names.modulus || ""
+ }), new asn1js.Integer({
+ name: names.publicExponent || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["modulus", "publicExponent"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, RSAPublicKey.schema({
+ names: {
+ modulus: "modulus",
+ publicExponent: "publicExponent"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for RSAPublicKey"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.modulus = asn1.result.modulus.convertFromDER(256);
+ this.publicExponent = asn1.result.publicExponent; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [this.modulus.convertToDER(), this.publicExponent]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ n: (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(this.modulus.valueBlock.valueHex), true, true, true),
+ e: (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(this.publicExponent.valueBlock.valueHex), true, true, true)
+ };
+ } //**********************************************************************************
+
+ /**
+ * Convert JSON value into current object
+ * @param {Object} json
+ */
+
+
+ fromJSON(json) {
+ if ("n" in json) {
+ const array = (0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(json.n, true));
+ this.modulus = new asn1js.Integer({
+ valueHex: array.slice(0, Math.pow(2, (0, _pvutils.nearestPowerOf2)(array.byteLength)))
+ });
+ } else throw new Error("Absent mandatory parameter \"n\"");
+
+ if ("e" in json) this.publicExponent = new asn1js.Integer({
+ valueHex: (0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(json.e, true)).slice(0, 3)
+ });else throw new Error("Absent mandatory parameter \"e\"");
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = RSAPublicKey;
+
+},{"asn1js":112,"pvutils":113}],83:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC4055
+ */
+class RSASSAPSSParams {
+ //**********************************************************************************
+
+ /**
+ * Constructor for RSASSAPSSParams class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc Algorithms of hashing (DEFAULT sha1)
+ */
+ this.hashAlgorithm = (0, _pvutils.getParametersValue)(parameters, "hashAlgorithm", RSASSAPSSParams.defaultValues("hashAlgorithm"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc Algorithm of "mask generaion function (MGF)" (DEFAULT mgf1SHA1)
+ */
+
+ this.maskGenAlgorithm = (0, _pvutils.getParametersValue)(parameters, "maskGenAlgorithm", RSASSAPSSParams.defaultValues("maskGenAlgorithm"));
+ /**
+ * @type {number}
+ * @desc Salt length (DEFAULT 20)
+ */
+
+ this.saltLength = (0, _pvutils.getParametersValue)(parameters, "saltLength", RSASSAPSSParams.defaultValues("saltLength"));
+ /**
+ * @type {number}
+ * @desc (DEFAULT 1)
+ */
+
+ this.trailerField = (0, _pvutils.getParametersValue)(parameters, "trailerField", RSASSAPSSParams.defaultValues("trailerField")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "hashAlgorithm":
+ return new _AlgorithmIdentifier.default({
+ algorithmId: "1.3.14.3.2.26",
+ // SHA-1
+ algorithmParams: new asn1js.Null()
+ });
+
+ case "maskGenAlgorithm":
+ return new _AlgorithmIdentifier.default({
+ algorithmId: "1.2.840.113549.1.1.8",
+ // MGF1
+ algorithmParams: new _AlgorithmIdentifier.default({
+ algorithmId: "1.3.14.3.2.26",
+ // SHA-1
+ algorithmParams: new asn1js.Null()
+ }).toSchema()
+ });
+
+ case "saltLength":
+ return 20;
+
+ case "trailerField":
+ return 1;
+
+ default:
+ throw new Error(`Invalid member name for RSASSAPSSParams class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * RSASSA-PSS-params ::= Sequence {
+ * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier,
+ * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
+ * saltLength [2] Integer DEFAULT 20,
+ * trailerField [3] Integer DEFAULT 1 }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [hashAlgorithm]
+ * @property {string} [maskGenAlgorithm]
+ * @property {string} [saltLength]
+ * @property {string} [trailerField]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ optional: true,
+ value: [_AlgorithmIdentifier.default.schema(names.hashAlgorithm || {})]
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ optional: true,
+ value: [_AlgorithmIdentifier.default.schema(names.maskGenAlgorithm || {})]
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ optional: true,
+ value: [new asn1js.Integer({
+ name: names.saltLength || ""
+ })]
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 3 // [3]
+
+ },
+ optional: true,
+ value: [new asn1js.Integer({
+ name: names.trailerField || ""
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["hashAlgorithm", "maskGenAlgorithm", "saltLength", "trailerField"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, RSASSAPSSParams.schema({
+ names: {
+ hashAlgorithm: {
+ names: {
+ blockName: "hashAlgorithm"
+ }
+ },
+ maskGenAlgorithm: {
+ names: {
+ blockName: "maskGenAlgorithm"
+ }
+ },
+ saltLength: "saltLength",
+ trailerField: "trailerField"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for RSASSAPSSParams"); //endregion
+ //region Get internal properties from parsed schema
+
+ if ("hashAlgorithm" in asn1.result) this.hashAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.hashAlgorithm
+ });
+ if ("maskGenAlgorithm" in asn1.result) this.maskGenAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.maskGenAlgorithm
+ });
+ if ("saltLength" in asn1.result) this.saltLength = asn1.result.saltLength.valueBlock.valueDec;
+ if ("trailerField" in asn1.result) this.trailerField = asn1.result.trailerField.valueBlock.valueDec; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+
+ if (!this.hashAlgorithm.isEqual(RSASSAPSSParams.defaultValues("hashAlgorithm"))) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [this.hashAlgorithm.toSchema()]
+ }));
+ }
+
+ if (!this.maskGenAlgorithm.isEqual(RSASSAPSSParams.defaultValues("maskGenAlgorithm"))) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [this.maskGenAlgorithm.toSchema()]
+ }));
+ }
+
+ if (this.saltLength !== RSASSAPSSParams.defaultValues("saltLength")) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ value: [new asn1js.Integer({
+ value: this.saltLength
+ })]
+ }));
+ }
+
+ if (this.trailerField !== RSASSAPSSParams.defaultValues("trailerField")) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 3 // [3]
+
+ },
+ value: [new asn1js.Integer({
+ value: this.trailerField
+ })]
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {};
+ if (!this.hashAlgorithm.isEqual(RSASSAPSSParams.defaultValues("hashAlgorithm"))) object.hashAlgorithm = this.hashAlgorithm.toJSON();
+ if (!this.maskGenAlgorithm.isEqual(RSASSAPSSParams.defaultValues("maskGenAlgorithm"))) object.maskGenAlgorithm = this.maskGenAlgorithm.toJSON();
+ if (this.saltLength !== RSASSAPSSParams.defaultValues("saltLength")) object.saltLength = this.saltLength;
+ if (this.trailerField !== RSASSAPSSParams.defaultValues("trailerField")) object.trailerField = this.trailerField;
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = RSASSAPSSParams;
+
+},{"./AlgorithmIdentifier.js":4,"asn1js":112,"pvutils":113}],84:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _KeyAgreeRecipientIdentifier = _interopRequireDefault(require("./KeyAgreeRecipientIdentifier.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class RecipientEncryptedKey {
+ //**********************************************************************************
+
+ /**
+ * Constructor for RecipientEncryptedKey class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {KeyAgreeRecipientIdentifier}
+ * @desc rid
+ */
+ this.rid = (0, _pvutils.getParametersValue)(parameters, "rid", RecipientEncryptedKey.defaultValues("rid"));
+ /**
+ * @type {OctetString}
+ * @desc encryptedKey
+ */
+
+ this.encryptedKey = (0, _pvutils.getParametersValue)(parameters, "encryptedKey", RecipientEncryptedKey.defaultValues("encryptedKey")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "rid":
+ return new _KeyAgreeRecipientIdentifier.default();
+
+ case "encryptedKey":
+ return new asn1js.OctetString();
+
+ default:
+ throw new Error(`Invalid member name for RecipientEncryptedKey class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "rid":
+ return memberValue.variant === -1 && "value" in memberValue === false;
+
+ case "encryptedKey":
+ return memberValue.isEqual(RecipientEncryptedKey.defaultValues("encryptedKey"));
+
+ default:
+ throw new Error(`Invalid member name for RecipientEncryptedKey class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * RecipientEncryptedKey ::= SEQUENCE {
+ * rid KeyAgreeRecipientIdentifier,
+ * encryptedKey EncryptedKey }
+ *
+ * EncryptedKey ::= OCTET STRING
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [rid]
+ * @property {string} [encryptedKey]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [_KeyAgreeRecipientIdentifier.default.schema(names.rid || {}), new asn1js.OctetString({
+ name: names.encryptedKey || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["rid", "encryptedKey"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, RecipientEncryptedKey.schema({
+ names: {
+ rid: {
+ names: {
+ blockName: "rid"
+ }
+ },
+ encryptedKey: "encryptedKey"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for RecipientEncryptedKey"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.rid = new _KeyAgreeRecipientIdentifier.default({
+ schema: asn1.result.rid
+ });
+ this.encryptedKey = asn1.result.encryptedKey; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [this.rid.toSchema(), this.encryptedKey]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ rid: this.rid.toJSON(),
+ encryptedKey: this.encryptedKey.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = RecipientEncryptedKey;
+
+},{"./KeyAgreeRecipientIdentifier.js":48,"asn1js":112,"pvutils":113}],85:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _RecipientEncryptedKey = _interopRequireDefault(require("./RecipientEncryptedKey.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class RecipientEncryptedKeys {
+ //**********************************************************************************
+
+ /**
+ * Constructor for RecipientEncryptedKeys class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array.<RecipientEncryptedKey>}
+ * @desc encryptedKeys
+ */
+ this.encryptedKeys = (0, _pvutils.getParametersValue)(parameters, "encryptedKeys", RecipientEncryptedKeys.defaultValues("encryptedKeys")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "encryptedKeys":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for RecipientEncryptedKeys class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "encryptedKeys":
+ return memberValue.length === 0;
+
+ default:
+ throw new Error(`Invalid member name for RecipientEncryptedKeys class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * RecipientEncryptedKeys ::= SEQUENCE OF RecipientEncryptedKey
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [RecipientEncryptedKeys]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Repeated({
+ name: names.RecipientEncryptedKeys || "",
+ value: _RecipientEncryptedKey.default.schema()
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["RecipientEncryptedKeys"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, RecipientEncryptedKeys.schema({
+ names: {
+ RecipientEncryptedKeys: "RecipientEncryptedKeys"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for RecipientEncryptedKeys"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.encryptedKeys = Array.from(asn1.result.RecipientEncryptedKeys, element => new _RecipientEncryptedKey.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: Array.from(this.encryptedKeys, element => element.toSchema())
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ encryptedKeys: Array.from(this.encryptedKeys, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = RecipientEncryptedKeys;
+
+},{"./RecipientEncryptedKey.js":84,"asn1js":112,"pvutils":113}],86:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _IssuerAndSerialNumber = _interopRequireDefault(require("./IssuerAndSerialNumber.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class RecipientIdentifier {
+ //**********************************************************************************
+
+ /**
+ * Constructor for RecipientIdentifier class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc variant
+ */
+ this.variant = (0, _pvutils.getParametersValue)(parameters, "variant", RecipientIdentifier.defaultValues("variant"));
+ if ("value" in parameters)
+ /**
+ * @type {*}
+ * @desc value
+ */
+ this.value = (0, _pvutils.getParametersValue)(parameters, "value", RecipientIdentifier.defaultValues("value")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "variant":
+ return -1;
+
+ case "value":
+ return {};
+
+ default:
+ throw new Error(`Invalid member name for RecipientIdentifier class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "variant":
+ return memberValue === -1;
+
+ case "values":
+ return Object.keys(memberValue).length === 0;
+
+ default:
+ throw new Error(`Invalid member name for RecipientIdentifier class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * RecipientIdentifier ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * subjectKeyIdentifier [0] SubjectKeyIdentifier }
+ *
+ * SubjectKeyIdentifier ::= OCTET STRING
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Choice({
+ value: [_IssuerAndSerialNumber.default.schema({
+ names: {
+ blockName: names.blockName || ""
+ }
+ }), new asn1js.Constructed({
+ name: names.blockName || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.OctetString()]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["blockName"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, RecipientIdentifier.schema({
+ names: {
+ blockName: "blockName"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for RecipientIdentifier"); //endregion
+ //region Get internal properties from parsed schema
+
+ if (asn1.result.blockName.idBlock.tagClass === 1) {
+ this.variant = 1;
+ this.value = new _IssuerAndSerialNumber.default({
+ schema: asn1.result.blockName
+ });
+ } else {
+ this.variant = 2;
+ this.value = asn1.result.blockName.valueBlock.value[0];
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ switch (this.variant) {
+ case 1:
+ return this.value.toSchema();
+
+ case 2:
+ return new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [this.value]
+ });
+
+ default:
+ return new asn1js.Any();
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ variant: this.variant
+ };
+ if (this.variant === 1 || this.variant === 2) _object.value = this.value.toJSON();
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = RecipientIdentifier;
+
+},{"./IssuerAndSerialNumber.js":44,"asn1js":112,"pvutils":113}],87:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _KeyTransRecipientInfo = _interopRequireDefault(require("./KeyTransRecipientInfo.js"));
+
+var _KeyAgreeRecipientInfo = _interopRequireDefault(require("./KeyAgreeRecipientInfo.js"));
+
+var _KEKRecipientInfo = _interopRequireDefault(require("./KEKRecipientInfo.js"));
+
+var _PasswordRecipientinfo = _interopRequireDefault(require("./PasswordRecipientinfo.js"));
+
+var _OtherRecipientInfo = _interopRequireDefault(require("./OtherRecipientInfo.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class RecipientInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for RecipientInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc variant
+ */
+ this.variant = (0, _pvutils.getParametersValue)(parameters, "variant", RecipientInfo.defaultValues("variant"));
+ if ("value" in parameters)
+ /**
+ * @type {*}
+ * @desc value
+ */
+ this.value = (0, _pvutils.getParametersValue)(parameters, "value", RecipientInfo.defaultValues("value")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "variant":
+ return -1;
+
+ case "value":
+ return {};
+
+ default:
+ throw new Error(`Invalid member name for RecipientInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "variant":
+ return memberValue === RecipientInfo.defaultValues(memberName);
+
+ case "value":
+ return Object.keys(memberValue).length === 0;
+
+ default:
+ throw new Error(`Invalid member name for RecipientInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * RecipientInfo ::= CHOICE {
+ * ktri KeyTransRecipientInfo,
+ * kari [1] KeyAgreeRecipientInfo,
+ * kekri [2] KEKRecipientInfo,
+ * pwri [3] PasswordRecipientinfo,
+ * ori [4] OtherRecipientInfo }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [type]
+ * @property {string} [setName]
+ * @property {string} [values]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Choice({
+ value: [_KeyTransRecipientInfo.default.schema({
+ names: {
+ blockName: names.blockName || ""
+ }
+ }), new asn1js.Constructed({
+ name: names.blockName || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: _KeyAgreeRecipientInfo.default.schema().valueBlock.value
+ }), new asn1js.Constructed({
+ name: names.blockName || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ value: _KEKRecipientInfo.default.schema().valueBlock.value
+ }), new asn1js.Constructed({
+ name: names.blockName || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 3 // [3]
+
+ },
+ value: _PasswordRecipientinfo.default.schema().valueBlock.value
+ }), new asn1js.Constructed({
+ name: names.blockName || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 4 // [4]
+
+ },
+ value: _OtherRecipientInfo.default.schema().valueBlock.value
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["blockName"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, RecipientInfo.schema({
+ names: {
+ blockName: "blockName"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for RecipientInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ if (asn1.result.blockName.idBlock.tagClass === 1) {
+ this.variant = 1;
+ this.value = new _KeyTransRecipientInfo.default({
+ schema: asn1.result.blockName
+ });
+ } else {
+ //region Create "SEQUENCE" from "ASN1_CONSTRUCTED"
+ const blockSequence = new asn1js.Sequence({
+ value: asn1.result.blockName.valueBlock.value
+ }); //endregion
+
+ switch (asn1.result.blockName.idBlock.tagNumber) {
+ case 1:
+ this.variant = 2;
+ this.value = new _KeyAgreeRecipientInfo.default({
+ schema: blockSequence
+ });
+ break;
+
+ case 2:
+ this.variant = 3;
+ this.value = new _KEKRecipientInfo.default({
+ schema: blockSequence
+ });
+ break;
+
+ case 3:
+ this.variant = 4;
+ this.value = new _PasswordRecipientinfo.default({
+ schema: blockSequence
+ });
+ break;
+
+ case 4:
+ this.variant = 5;
+ this.value = new _OtherRecipientInfo.default({
+ schema: blockSequence
+ });
+ break;
+
+ default:
+ throw new Error("Incorrect structure of RecipientInfo block");
+ }
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ const _schema = this.value.toSchema();
+
+ switch (this.variant) {
+ case 1:
+ return _schema;
+
+ case 2:
+ case 3:
+ case 4:
+ //region Create "ASN1_CONSTRUCTED" from "SEQUENCE"
+ _schema.idBlock.tagClass = 3; // CONTEXT-SPECIFIC
+
+ _schema.idBlock.tagNumber = this.variant - 1; //endregion
+
+ return _schema;
+
+ default:
+ return new asn1js.Any();
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ variant: this.variant
+ };
+ if (this.variant >= 1 && this.variant <= 4) _object.value = this.value.toJSON();
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = RecipientInfo;
+
+},{"./KEKRecipientInfo.js":47,"./KeyAgreeRecipientInfo.js":49,"./KeyTransRecipientInfo.js":51,"./OtherRecipientInfo.js":63,"./PasswordRecipientinfo.js":70,"asn1js":112,"pvutils":113}],88:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _OtherKeyAttribute = _interopRequireDefault(require("./OtherKeyAttribute.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class RecipientKeyIdentifier {
+ //**********************************************************************************
+
+ /**
+ * Constructor for RecipientKeyIdentifier class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {OctetString}
+ * @desc subjectKeyIdentifier
+ */
+ this.subjectKeyIdentifier = (0, _pvutils.getParametersValue)(parameters, "subjectKeyIdentifier", RecipientKeyIdentifier.defaultValues("subjectKeyIdentifier"));
+ if ("date" in parameters)
+ /**
+ * @type {GeneralizedTime}
+ * @desc date
+ */
+ this.date = (0, _pvutils.getParametersValue)(parameters, "date", RecipientKeyIdentifier.defaultValues("date"));
+ if ("other" in parameters)
+ /**
+ * @type {OtherKeyAttribute}
+ * @desc other
+ */
+ this.other = (0, _pvutils.getParametersValue)(parameters, "other", RecipientKeyIdentifier.defaultValues("other")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "subjectKeyIdentifier":
+ return new asn1js.OctetString();
+
+ case "date":
+ return new asn1js.GeneralizedTime();
+
+ case "other":
+ return new _OtherKeyAttribute.default();
+
+ default:
+ throw new Error(`Invalid member name for RecipientKeyIdentifier class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "subjectKeyIdentifier":
+ return memberValue.isEqual(RecipientKeyIdentifier.defaultValues("subjectKeyIdentifier"));
+
+ case "date":
+ // noinspection OverlyComplexBooleanExpressionJS
+ return memberValue.year === 0 && memberValue.month === 0 && memberValue.day === 0 && memberValue.hour === 0 && memberValue.minute === 0 && memberValue.second === 0 && memberValue.millisecond === 0;
+
+ case "other":
+ return memberValue.keyAttrId === "" && "keyAttr" in memberValue === false;
+
+ default:
+ throw new Error(`Invalid member name for RecipientKeyIdentifier class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * RecipientKeyIdentifier ::= SEQUENCE {
+ * subjectKeyIdentifier SubjectKeyIdentifier,
+ * date GeneralizedTime OPTIONAL,
+ * other OtherKeyAttribute OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [type]
+ * @property {string} [setName]
+ * @property {string} [values]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.OctetString({
+ name: names.subjectKeyIdentifier || ""
+ }), new asn1js.GeneralizedTime({
+ optional: true,
+ name: names.date || ""
+ }), _OtherKeyAttribute.default.schema(names.other || {})]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["subjectKeyIdentifier", "date", "other"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, RecipientKeyIdentifier.schema({
+ names: {
+ subjectKeyIdentifier: "subjectKeyIdentifier",
+ date: "date",
+ other: {
+ names: {
+ blockName: "other"
+ }
+ }
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for RecipientKeyIdentifier"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.subjectKeyIdentifier = asn1.result.subjectKeyIdentifier;
+ if ("date" in asn1.result) this.date = asn1.result.date;
+ if ("other" in asn1.result) this.other = new _OtherKeyAttribute.default({
+ schema: asn1.result.other
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(this.subjectKeyIdentifier);
+ if ("date" in this) outputArray.push(this.date);
+ if ("other" in this) outputArray.push(this.other.toSchema()); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ subjectKeyIdentifier: this.subjectKeyIdentifier.toJSON()
+ };
+ if ("date" in this) _object.date = this.date;
+ if ("other" in this) _object.other = this.other.toJSON();
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = RecipientKeyIdentifier;
+
+},{"./OtherKeyAttribute.js":61,"asn1js":112,"pvutils":113}],89:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AttributeTypeAndValue = _interopRequireDefault(require("./AttributeTypeAndValue.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
+
+function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
+
+function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
+
+function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class RelativeDistinguishedNames {
+ //**********************************************************************************
+
+ /**
+ * Constructor for RelativeDistinguishedNames class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ * @property {Array.<AttributeTypeAndValue>} [typesAndValues] Array of "type and value" objects
+ * @property {ArrayBuffer} [valueBeforeDecode] Value of the RDN before decoding from schema
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array.<AttributeTypeAndValue>}
+ * @desc Array of "type and value" objects
+ */
+ this.typesAndValues = (0, _pvutils.getParametersValue)(parameters, "typesAndValues", RelativeDistinguishedNames.defaultValues("typesAndValues"));
+ /**
+ * @type {ArrayBuffer}
+ * @desc Value of the RDN before decoding from schema
+ */
+
+ this.valueBeforeDecode = (0, _pvutils.getParametersValue)(parameters, "valueBeforeDecode", RelativeDistinguishedNames.defaultValues("valueBeforeDecode")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "typesAndValues":
+ return [];
+
+ case "valueBeforeDecode":
+ return new ArrayBuffer(0);
+
+ default:
+ throw new Error(`Invalid member name for RelativeDistinguishedNames class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "typesAndValues":
+ return memberValue.length === 0;
+
+ case "valueBeforeDecode":
+ return memberValue.byteLength === 0;
+
+ default:
+ throw new Error(`Invalid member name for RelativeDistinguishedNames class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * RDNSequence ::= Sequence OF RelativeDistinguishedName
+ *
+ * RelativeDistinguishedName ::=
+ * SET SIZE (1..MAX) OF AttributeTypeAndValue
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName] Name for entire block
+ * @property {string} [repeatedSequence] Name for "repeatedSequence" block
+ * @property {string} [repeatedSet] Name for "repeatedSet" block
+ * @property {string} [typeAndValue] Name for "typeAndValue" block
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Repeated({
+ name: names.repeatedSequence || "",
+ value: new asn1js.Set({
+ value: [new asn1js.Repeated({
+ name: names.repeatedSet || "",
+ value: _AttributeTypeAndValue.default.schema(names.typeAndValue || {})
+ })]
+ })
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["RDN", "typesAndValues"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, RelativeDistinguishedNames.schema({
+ names: {
+ blockName: "RDN",
+ repeatedSet: "typesAndValues"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for RelativeDistinguishedNames"); //endregion
+ //region Get internal properties from parsed schema
+
+ if ("typesAndValues" in asn1.result) // Could be a case when there is no "types and values"
+ this.typesAndValues = Array.from(asn1.result.typesAndValues, element => new _AttributeTypeAndValue.default({
+ schema: element
+ })); // noinspection JSUnresolvedVariable
+
+ this.valueBeforeDecode = asn1.result.RDN.valueBeforeDecode; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Decode stored TBS value
+ if (this.valueBeforeDecode.byteLength === 0) // No stored encoded array, create "from scratch"
+ {
+ return new asn1js.Sequence({
+ value: [new asn1js.Set({
+ value: Array.from(this.typesAndValues, element => element.toSchema())
+ })]
+ });
+ }
+
+ const asn1 = asn1js.fromBER(this.valueBeforeDecode); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return asn1.result; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ typesAndValues: Array.from(this.typesAndValues, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+ /**
+ * Compare two RDN values, or RDN with ArrayBuffer value
+ * @param {(RelativeDistinguishedNames|ArrayBuffer)} compareTo The value compare to current
+ * @returns {boolean}
+ */
+
+
+ isEqual(compareTo) {
+ if (compareTo instanceof RelativeDistinguishedNames) {
+ if (this.typesAndValues.length !== compareTo.typesAndValues.length) return false;
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = this.typesAndValues.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ const _step$value = _slicedToArray(_step.value, 2),
+ index = _step$value[0],
+ typeAndValue = _step$value[1];
+
+ if (typeAndValue.isEqual(compareTo.typesAndValues[index]) === false) return false;
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ if (compareTo instanceof ArrayBuffer) return (0, _pvutils.isEqualBuffer)(this.valueBeforeDecode, compareTo);
+ return false;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = RelativeDistinguishedNames;
+
+},{"./AttributeTypeAndValue.js":9,"asn1js":112,"pvutils":113}],90:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _CertID = _interopRequireDefault(require("./CertID.js"));
+
+var _Extension = _interopRequireDefault(require("./Extension.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC6960
+ */
+class Request {
+ //**********************************************************************************
+
+ /**
+ * Constructor for Request class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {CertID}
+ * @desc reqCert
+ */
+ this.reqCert = (0, _pvutils.getParametersValue)(parameters, "reqCert", Request.defaultValues("reqCert"));
+ if ("singleRequestExtensions" in parameters)
+ /**
+ * @type {Array.<Extension>}
+ * @desc singleRequestExtensions
+ */
+ this.singleRequestExtensions = (0, _pvutils.getParametersValue)(parameters, "singleRequestExtensions", Request.defaultValues("singleRequestExtensions")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "reqCert":
+ return new _CertID.default();
+
+ case "singleRequestExtensions":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for Request class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "reqCert":
+ return memberValue.isEqual(Request.defaultValues(memberName));
+
+ case "singleRequestExtensions":
+ return memberValue.length === 0;
+
+ default:
+ throw new Error(`Invalid member name for Request class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * Request ::= SEQUENCE {
+ * reqCert CertID,
+ * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [reqCert]
+ * @property {string} [extensions]
+ * @property {string} [singleRequestExtensions]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [_CertID.default.schema(names.reqCert || {}), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [_Extension.default.schema(names.extensions || {
+ names: {
+ blockName: names.singleRequestExtensions || ""
+ }
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["reqCert", "singleRequestExtensions"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, Request.schema({
+ names: {
+ reqCert: {
+ names: {
+ blockName: "reqCert"
+ }
+ },
+ singleRequestExtensions: {
+ names: {
+ blockName: "singleRequestExtensions"
+ }
+ }
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for Request"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.reqCert = new _CertID.default({
+ schema: asn1.result.reqCert
+ });
+ if ("singleRequestExtensions" in asn1.result) this.singleRequestExtensions = Array.from(asn1.result.singleRequestExtensions.valueBlock.value, element => new _Extension.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(this.reqCert.toSchema());
+
+ if ("singleRequestExtensions" in this) {
+ outputArray.push(new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Sequence({
+ value: Array.from(this.singleRequestExtensions, element => element.toSchema())
+ })]
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ reqCert: this.reqCert.toJSON()
+ };
+ if ("singleRequestExtensions" in this) _object.singleRequestExtensions = Array.from(this.singleRequestExtensions, element => element.toJSON());
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = Request;
+
+},{"./CertID.js":18,"./Extension.js":38,"asn1js":112,"pvutils":113}],91:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC6960
+ */
+class ResponseBytes {
+ //**********************************************************************************
+
+ /**
+ * Constructor for ResponseBytes class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc responseType
+ */
+ this.responseType = (0, _pvutils.getParametersValue)(parameters, "responseType", ResponseBytes.defaultValues("responseType"));
+ /**
+ * @type {OctetString}
+ * @desc response
+ */
+
+ this.response = (0, _pvutils.getParametersValue)(parameters, "response", ResponseBytes.defaultValues("response")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "responseType":
+ return "";
+
+ case "response":
+ return new asn1js.OctetString();
+
+ default:
+ throw new Error(`Invalid member name for ResponseBytes class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "responseType":
+ return memberValue === "";
+
+ case "response":
+ return memberValue.isEqual(ResponseBytes.defaultValues(memberName));
+
+ default:
+ throw new Error(`Invalid member name for ResponseBytes class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * ResponseBytes ::= SEQUENCE {
+ * responseType OBJECT IDENTIFIER,
+ * response OCTET STRING }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [responseType]
+ * @property {string} [response]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.responseType || ""
+ }), new asn1js.OctetString({
+ name: names.response || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["responseType", "response"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, ResponseBytes.schema({
+ names: {
+ responseType: "responseType",
+ response: "response"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for ResponseBytes"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.responseType = asn1.result.responseType.valueBlock.toString();
+ this.response = asn1.result.response; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [new asn1js.ObjectIdentifier({
+ value: this.responseType
+ }), this.response]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ responseType: this.responseType,
+ response: this.response.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = ResponseBytes;
+
+},{"asn1js":112,"pvutils":113}],92:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _RelativeDistinguishedNames = _interopRequireDefault(require("./RelativeDistinguishedNames.js"));
+
+var _SingleResponse = _interopRequireDefault(require("./SingleResponse.js"));
+
+var _Extension = _interopRequireDefault(require("./Extension.js"));
+
+var _Extensions = _interopRequireDefault(require("./Extensions.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC6960
+ */
+class ResponseData {
+ //**********************************************************************************
+
+ /**
+ * Constructor for ResponseData class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {ArrayBuffer}
+ * @desc tbs
+ */
+ this.tbs = (0, _pvutils.getParametersValue)(parameters, "tbs", ResponseData.defaultValues("tbs"));
+ /**
+ * @type {Object}
+ * @desc responderID
+ */
+
+ this.responderID = (0, _pvutils.getParametersValue)(parameters, "responderID", ResponseData.defaultValues("responderID"));
+ /**
+ * @type {Date}
+ * @desc producedAt
+ */
+
+ this.producedAt = (0, _pvutils.getParametersValue)(parameters, "producedAt", ResponseData.defaultValues("producedAt"));
+ /**
+ * @type {Array.<SingleResponse>}
+ * @desc responses
+ */
+
+ this.responses = (0, _pvutils.getParametersValue)(parameters, "responses", ResponseData.defaultValues("responses"));
+ if ("responseExtensions" in parameters)
+ /**
+ * @type {Array.<Extension>}
+ * @desc responseExtensions
+ */
+ this.responseExtensions = (0, _pvutils.getParametersValue)(parameters, "responseExtensions", ResponseData.defaultValues("responseExtensions")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "tbs":
+ return new ArrayBuffer(0);
+
+ case "responderID":
+ return {};
+
+ case "producedAt":
+ return new Date(0, 0, 0);
+
+ case "responses":
+ case "responseExtensions":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for ResponseData class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "tbs":
+ return memberValue.byteLength === 0;
+
+ case "responderID":
+ return Object.keys(memberValue).length === 0;
+
+ case "producedAt":
+ return memberValue === ResponseData.defaultValues(memberName);
+
+ case "responses":
+ case "responseExtensions":
+ return memberValue.length === 0;
+
+ default:
+ throw new Error(`Invalid member name for ResponseData class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * ResponseData ::= SEQUENCE {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * responderID ResponderID,
+ * producedAt GeneralizedTime,
+ * responses SEQUENCE OF SingleResponse,
+ * responseExtensions [1] EXPLICIT Extensions OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [version]
+ * @property {string} [ResponseDataByName]
+ * @property {string} [ResponseDataByKey]
+ * @property {string} [producedAt]
+ * @property {string} [response]
+ * @property {string} [extensions]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "ResponseData",
+ value: [new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Integer({
+ name: names.version || "ResponseData.version"
+ })]
+ }), new asn1js.Choice({
+ value: [new asn1js.Constructed({
+ name: names.responderID || "ResponseData.responderID",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [_RelativeDistinguishedNames.default.schema(names.ResponseDataByName || {
+ names: {
+ blockName: "ResponseData.byName"
+ }
+ })]
+ }), new asn1js.Constructed({
+ name: names.responderID || "ResponseData.responderID",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ value: [new asn1js.OctetString({
+ name: names.ResponseDataByKey || "ResponseData.byKey"
+ })]
+ })]
+ }), new asn1js.GeneralizedTime({
+ name: names.producedAt || "ResponseData.producedAt"
+ }), new asn1js.Sequence({
+ value: [new asn1js.Repeated({
+ name: "ResponseData.responses",
+ value: _SingleResponse.default.schema(names.response || {})
+ })]
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [_Extensions.default.schema(names.extensions || {
+ names: {
+ blockName: "ResponseData.responseExtensions"
+ }
+ })]
+ }) // EXPLICIT SEQUENCE value
+ ]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["ResponseData", "ResponseData.version", "ResponseData.responderID", "ResponseData.producedAt", "ResponseData.responses", "ResponseData.responseExtensions"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, ResponseData.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for ResponseData"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.tbs = asn1.result.ResponseData.valueBeforeDecode;
+ if ("ResponseData.version" in asn1.result) this.version = asn1.result["ResponseData.version"].valueBlock.valueDec;
+ if (asn1.result["ResponseData.responderID"].idBlock.tagNumber === 1) this.responderID = new _RelativeDistinguishedNames.default({
+ schema: asn1.result["ResponseData.responderID"].valueBlock.value[0]
+ });else this.responderID = asn1.result["ResponseData.responderID"].valueBlock.value[0]; // OCTETSTRING
+
+ this.producedAt = asn1.result["ResponseData.producedAt"].toDate();
+ this.responses = Array.from(asn1.result["ResponseData.responses"], element => new _SingleResponse.default({
+ schema: element
+ }));
+ if ("ResponseData.responseExtensions" in asn1.result) this.responseExtensions = Array.from(asn1.result["ResponseData.responseExtensions"].valueBlock.value, element => new _Extension.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @param {boolean} encodeFlag If param equal to false then create TBS schema via decoding stored value. In othe case create TBS schema via assembling from TBS parts.
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema(encodeFlag = false) {
+ //region Decode stored TBS value
+ let tbsSchema;
+
+ if (encodeFlag === false) {
+ if (this.tbs.length === 0) // No stored certificate TBS part
+ return ResponseData.schema();
+ tbsSchema = asn1js.fromBER(this.tbs).result;
+ } //endregion
+ //region Create TBS schema via assembling from TBS parts
+ else {
+ const outputArray = [];
+
+ if ("version" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Integer({
+ value: this.version
+ })]
+ }));
+ }
+
+ if (this.responderID instanceof _RelativeDistinguishedNames.default) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [this.responderID.toSchema()]
+ }));
+ } else {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ value: [this.responderID]
+ }));
+ }
+
+ outputArray.push(new asn1js.GeneralizedTime({
+ valueDate: this.producedAt
+ }));
+ outputArray.push(new asn1js.Sequence({
+ value: Array.from(this.responses, element => element.toSchema())
+ }));
+
+ if ("responseExtensions" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [new asn1js.Sequence({
+ value: Array.from(this.responseExtensions, element => element.toSchema())
+ })]
+ }));
+ }
+
+ tbsSchema = new asn1js.Sequence({
+ value: outputArray
+ });
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return tbsSchema; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {};
+ if ("version" in this) _object.version = this.version;
+ if ("responderID" in this) _object.responderID = this.responderID;
+ if ("producedAt" in this) _object.producedAt = this.producedAt;
+ if ("responses" in this) _object.responses = Array.from(this.responses, element => element.toJSON());
+ if ("responseExtensions" in this) _object.responseExtensions = Array.from(this.responseExtensions, element => element.toJSON());
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = ResponseData;
+
+},{"./Extension.js":38,"./Extensions.js":39,"./RelativeDistinguishedNames.js":89,"./SingleResponse.js":103,"asn1js":112,"pvutils":113}],93:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _CertificateRevocationList = _interopRequireDefault(require("./CertificateRevocationList.js"));
+
+var _OtherRevocationInfoFormat = _interopRequireDefault(require("./OtherRevocationInfoFormat.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class RevocationInfoChoices {
+ //**********************************************************************************
+
+ /**
+ * Constructor for RevocationInfoChoices class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array.<CertificateRevocationList>}
+ * @desc crls
+ */
+ this.crls = (0, _pvutils.getParametersValue)(parameters, "crls", RevocationInfoChoices.defaultValues("crls"));
+ /**
+ * @type {Array.<OtherRevocationInfoFormat>}
+ * @desc otherRevocationInfos
+ */
+
+ this.otherRevocationInfos = (0, _pvutils.getParametersValue)(parameters, "otherRevocationInfos", RevocationInfoChoices.defaultValues("otherRevocationInfos")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "crls":
+ return [];
+
+ case "otherRevocationInfos":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for RevocationInfoChoices class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * RevocationInfoChoices ::= SET OF RevocationInfoChoice
+ *
+ * RevocationInfoChoice ::= CHOICE {
+ * crl CertificateList,
+ * other [1] IMPLICIT OtherRevocationInfoFormat }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [crls]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Set({
+ name: names.blockName || "",
+ value: [new asn1js.Repeated({
+ name: names.crls || "",
+ value: new asn1js.Choice({
+ value: [_CertificateRevocationList.default.schema(), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [new asn1js.ObjectIdentifier(), new asn1js.Any()]
+ })]
+ })
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["crls"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, RevocationInfoChoices.schema({
+ names: {
+ crls: "crls"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for RevocationInfoChoices"); //endregion
+ //region Get internal properties from parsed schema
+
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = asn1.result.crls[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ const element = _step.value;
+ if (element.idBlock.tagClass === 1) this.crls.push(new _CertificateRevocationList.default({
+ schema: element
+ }));else this.otherRevocationInfos.push(new _OtherRevocationInfoFormat.default({
+ schema: element
+ }));
+ } //endregion
+
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output set
+ const outputArray = [];
+ outputArray.push(...Array.from(this.crls, element => element.toSchema()));
+ outputArray.push(...Array.from(this.otherRevocationInfos, element => {
+ const schema = element.toSchema();
+ schema.idBlock.tagClass = 3;
+ schema.idBlock.tagNumber = 1;
+ return schema;
+ })); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Set({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ crls: Array.from(this.crls, element => element.toJSON()),
+ otherRevocationInfos: Array.from(this.otherRevocationInfos, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = RevocationInfoChoices;
+
+},{"./CertificateRevocationList.js":22,"./OtherRevocationInfoFormat.js":64,"asn1js":112,"pvutils":113}],94:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _Time = _interopRequireDefault(require("./Time.js"));
+
+var _Extensions = _interopRequireDefault(require("./Extensions.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class RevokedCertificate {
+ //**********************************************************************************
+
+ /**
+ * Constructor for RevokedCertificate class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Integer}
+ * @desc userCertificate
+ */
+ this.userCertificate = (0, _pvutils.getParametersValue)(parameters, "userCertificate", RevokedCertificate.defaultValues("userCertificate"));
+ /**
+ * @type {Time}
+ * @desc revocationDate
+ */
+
+ this.revocationDate = (0, _pvutils.getParametersValue)(parameters, "revocationDate", RevokedCertificate.defaultValues("revocationDate"));
+ if ("crlEntryExtensions" in parameters)
+ /**
+ * @type {Extensions}
+ * @desc crlEntryExtensions
+ */
+ this.crlEntryExtensions = (0, _pvutils.getParametersValue)(parameters, "crlEntryExtensions", RevokedCertificate.defaultValues("crlEntryExtensions")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "userCertificate":
+ return new asn1js.Integer();
+
+ case "revocationDate":
+ return new _Time.default();
+
+ case "crlEntryExtensions":
+ return new _Extensions.default();
+
+ default:
+ throw new Error(`Invalid member name for RevokedCertificate class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * revokedCertificates SEQUENCE OF SEQUENCE {
+ * userCertificate CertificateSerialNumber,
+ * revocationDate Time,
+ * crlEntryExtensions Extensions OPTIONAL
+ * -- if present, version MUST be v2
+ * } OPTIONAL,
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [userCertificate]
+ * @property {string} [revocationDate]
+ * @property {string} [crlEntryExtensions]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Integer({
+ name: names.userCertificate || "userCertificate"
+ }), _Time.default.schema({
+ names: {
+ utcTimeName: names.revocationDate || "revocationDate",
+ generalTimeName: names.revocationDate || "revocationDate"
+ }
+ }), _Extensions.default.schema({
+ names: {
+ blockName: names.crlEntryExtensions || "crlEntryExtensions"
+ }
+ }, true)]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["userCertificate", "revocationDate", "crlEntryExtensions"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, RevokedCertificate.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for RevokedCertificate"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.userCertificate = asn1.result.userCertificate;
+ this.revocationDate = new _Time.default({
+ schema: asn1.result.revocationDate
+ });
+ if ("crlEntryExtensions" in asn1.result) this.crlEntryExtensions = new _Extensions.default({
+ schema: asn1.result.crlEntryExtensions
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [this.userCertificate, this.revocationDate.toSchema()];
+ if ("crlEntryExtensions" in this) outputArray.push(this.crlEntryExtensions.toSchema()); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const object = {
+ userCertificate: this.userCertificate.toJSON(),
+ revocationDate: this.revocationDate.toJSON
+ };
+ if ("crlEntryExtensions" in this) object.crlEntryExtensions = this.crlEntryExtensions.toJSON();
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = RevokedCertificate;
+
+},{"./Extensions.js":39,"./Time.js":107,"asn1js":112,"pvutils":113}],95:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _Attribute = _interopRequireDefault(require("./Attribute.js"));
+
+var _PrivateKeyInfo = _interopRequireDefault(require("./PrivateKeyInfo.js"));
+
+var _PKCS8ShroudedKeyBag = _interopRequireDefault(require("./PKCS8ShroudedKeyBag.js"));
+
+var _CertBag = _interopRequireDefault(require("./CertBag.js"));
+
+var _CRLBag = _interopRequireDefault(require("./CRLBag.js"));
+
+var _SecretBag = _interopRequireDefault(require("./SecretBag.js"));
+
+var _SafeContents = _interopRequireDefault(require("./SafeContents.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC7292
+ */
+class SafeBag {
+ //**********************************************************************************
+
+ /**
+ * Constructor for SafeBag class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc bagId
+ */
+ this.bagId = (0, _pvutils.getParametersValue)(parameters, "bagId", SafeBag.defaultValues("bagId"));
+ /**
+ * @type {*}
+ * @desc bagValue
+ */
+
+ this.bagValue = (0, _pvutils.getParametersValue)(parameters, "bagValue", SafeBag.defaultValues("bagValue"));
+ if ("bagAttributes" in parameters)
+ /**
+ * @type {Array.<Attribute>}
+ * @desc bagAttributes
+ */
+ this.bagAttributes = (0, _pvutils.getParametersValue)(parameters, "bagAttributes", SafeBag.defaultValues("bagAttributes")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "bagId":
+ return "";
+
+ case "bagValue":
+ return new asn1js.Any();
+
+ case "bagAttributes":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for SafeBag class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "bagId":
+ return memberValue === "";
+
+ case "bagValue":
+ return memberValue instanceof asn1js.Any;
+
+ case "bagAttributes":
+ return memberValue.length === 0;
+
+ default:
+ throw new Error(`Invalid member name for SafeBag class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * SafeBag ::= SEQUENCE {
+ * bagId BAG-TYPE.&id ({PKCS12BagSet}),
+ * bagValue [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}),
+ * bagAttributes SET OF PKCS12Attribute OPTIONAL
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [bagId]
+ * @property {string} [bagValue]
+ * @property {string} [bagAttributes]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.bagId || "bagId"
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Any({
+ name: names.bagValue || "bagValue"
+ })] // EXPLICIT ANY value
+
+ }), new asn1js.Set({
+ optional: true,
+ value: [new asn1js.Repeated({
+ name: names.bagAttributes || "bagAttributes",
+ value: _Attribute.default.schema()
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["bagId", "bagValue", "bagAttributes"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, SafeBag.schema({
+ names: {
+ bagId: "bagId",
+ bagValue: "bagValue",
+ bagAttributes: "bagAttributes"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for SafeBag"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.bagId = asn1.result.bagId.valueBlock.toString();
+
+ switch (this.bagId) {
+ case "1.2.840.113549.1.12.10.1.1":
+ // keyBag
+ this.bagValue = new _PrivateKeyInfo.default({
+ schema: asn1.result.bagValue
+ });
+ break;
+
+ case "1.2.840.113549.1.12.10.1.2":
+ // pkcs8ShroudedKeyBag
+ this.bagValue = new _PKCS8ShroudedKeyBag.default({
+ schema: asn1.result.bagValue
+ });
+ break;
+
+ case "1.2.840.113549.1.12.10.1.3":
+ // certBag
+ this.bagValue = new _CertBag.default({
+ schema: asn1.result.bagValue
+ });
+ break;
+
+ case "1.2.840.113549.1.12.10.1.4":
+ // crlBag
+ this.bagValue = new _CRLBag.default({
+ schema: asn1.result.bagValue
+ });
+ break;
+
+ case "1.2.840.113549.1.12.10.1.5":
+ // secretBag
+ this.bagValue = new _SecretBag.default({
+ schema: asn1.result.bagValue
+ });
+ break;
+
+ case "1.2.840.113549.1.12.10.1.6":
+ // safeContentsBag
+ this.bagValue = new _SafeContents.default({
+ schema: asn1.result.bagValue
+ });
+ break;
+
+ default:
+ throw new Error(`Invalid "bagId" for SafeBag: ${this.bagId}`);
+ }
+
+ if ("bagAttributes" in asn1.result) this.bagAttributes = Array.from(asn1.result.bagAttributes, element => new _Attribute.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ const outputArray = [new asn1js.ObjectIdentifier({
+ value: this.bagId
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [this.bagValue.toSchema()]
+ })];
+
+ if ("bagAttributes" in this) {
+ outputArray.push(new asn1js.Set({
+ value: Array.from(this.bagAttributes, element => element.toSchema())
+ }));
+ }
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const output = {
+ bagId: this.bagId,
+ bagValue: this.bagValue.toJSON()
+ };
+ if ("bagAttributes" in this) output.bagAttributes = Array.from(this.bagAttributes, element => element.toJSON());
+ return output;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = SafeBag;
+
+},{"./Attribute.js":6,"./CRLBag.js":15,"./CertBag.js":17,"./PKCS8ShroudedKeyBag.js":68,"./PrivateKeyInfo.js":76,"./SafeContents.js":96,"./SecretBag.js":97,"asn1js":112,"pvutils":113}],96:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _SafeBag = _interopRequireDefault(require("./SafeBag.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC7292
+ */
+class SafeContents {
+ //**********************************************************************************
+
+ /**
+ * Constructor for SafeContents class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array.<SafeBag>}
+ * @desc safeBags
+ */
+ this.safeBags = (0, _pvutils.getParametersValue)(parameters, "safeBags", SafeContents.defaultValues("safeBags")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "safeBags":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for SafeContents class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "safeBags":
+ return memberValue.length === 0;
+
+ default:
+ throw new Error(`Invalid member name for SafeContents class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * SafeContents ::= SEQUENCE OF SafeBag
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [safeBags]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Repeated({
+ name: names.safeBags || "",
+ value: _SafeBag.default.schema()
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["safeBags"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, SafeContents.schema({
+ names: {
+ safeBags: "safeBags"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for SafeContents"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.safeBags = Array.from(asn1.result.safeBags, element => new _SafeBag.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: Array.from(this.safeBags, element => element.toSchema())
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ safeBags: Array.from(this.safeBags, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = SafeContents;
+
+},{"./SafeBag.js":95,"asn1js":112,"pvutils":113}],97:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC7292
+ */
+class SecretBag {
+ //**********************************************************************************
+
+ /**
+ * Constructor for SecretBag class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc secretTypeId
+ */
+ this.secretTypeId = (0, _pvutils.getParametersValue)(parameters, "secretTypeId", SecretBag.defaultValues("secretTypeId"));
+ /**
+ * @type {*}
+ * @desc secretValue
+ */
+
+ this.secretValue = (0, _pvutils.getParametersValue)(parameters, "secretValue", SecretBag.defaultValues("secretValue")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "secretTypeId":
+ return "";
+
+ case "secretValue":
+ return new asn1js.Any();
+
+ default:
+ throw new Error(`Invalid member name for SecretBag class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "secretTypeId":
+ return memberValue === "";
+
+ case "secretValue":
+ return memberValue instanceof asn1js.Any;
+
+ default:
+ throw new Error(`Invalid member name for SecretBag class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * SecretBag ::= SEQUENCE {
+ * secretTypeId BAG-TYPE.&id ({SecretTypes}),
+ * secretValue [0] EXPLICIT BAG-TYPE.&Type ({SecretTypes}{@secretTypeId})
+ * }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [id]
+ * @property {string} [value]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.ObjectIdentifier({
+ name: names.id || "id"
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Any({
+ name: names.value || "value"
+ })] // EXPLICIT ANY value
+
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["secretTypeId", "secretValue"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, SecretBag.schema({
+ names: {
+ id: "secretTypeId",
+ value: "secretValue"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for SecretBag"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.secretTypeId = asn1.result.secretTypeId.valueBlock.toString();
+ this.secretValue = asn1.result.secretValue; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: [new asn1js.ObjectIdentifier({
+ value: this.secretTypeId
+ }), new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [this.secretValue.toSchema()]
+ })]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ secretTypeId: this.secretTypeId,
+ secretValue: this.secretValue.toJSON()
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = SecretBag;
+
+},{"asn1js":112,"pvutils":113}],98:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _Certificate = _interopRequireDefault(require("./Certificate.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC6960
+ */
+class Signature {
+ //**********************************************************************************
+
+ /**
+ * Constructor for Signature class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc signatureAlgorithm
+ */
+ this.signatureAlgorithm = (0, _pvutils.getParametersValue)(parameters, "signatureAlgorithm", Signature.defaultValues("signatureAlgorithm"));
+ /**
+ * @type {BitString}
+ * @desc signature
+ */
+
+ this.signature = (0, _pvutils.getParametersValue)(parameters, "signature", Signature.defaultValues("signature"));
+ if ("certs" in parameters)
+ /**
+ * @type {Array.<Certificate>}
+ * @desc certs
+ */
+ this.certs = (0, _pvutils.getParametersValue)(parameters, "certs", Signature.defaultValues("certs")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "signatureAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "signature":
+ return new asn1js.BitString();
+
+ case "certs":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for Signature class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "signatureAlgorithm":
+ return memberValue.algorithmId === "" && "algorithmParams" in memberValue === false;
+
+ case "signature":
+ return memberValue.isEqual(Signature.defaultValues(memberName));
+
+ case "certs":
+ return memberValue.length === 0;
+
+ default:
+ throw new Error(`Invalid member name for Signature class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * Signature ::= SEQUENCE {
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING,
+ * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [signatureAlgorithm]
+ * @property {string} [signature]
+ * @property {string} [certs]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [_AlgorithmIdentifier.default.schema(names.signatureAlgorithm || {}), new asn1js.BitString({
+ name: names.signature || ""
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Sequence({
+ value: [new asn1js.Repeated({
+ name: names.certs || "",
+ value: _Certificate.default.schema(names.certs || {})
+ })]
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["signatureAlgorithm", "signature", "certs"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, Signature.schema({
+ names: {
+ signatureAlgorithm: {
+ names: {
+ blockName: "signatureAlgorithm"
+ }
+ },
+ signature: "signature",
+ certs: "certs"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for Signature"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.signatureAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result.signatureAlgorithm
+ });
+ this.signature = asn1.result.signature;
+ if ("certs" in asn1.result) this.certs = Array.from(asn1.result.certs, element => new _Certificate.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array of output sequence
+ const outputArray = [];
+ outputArray.push(this.signatureAlgorithm.toSchema());
+ outputArray.push(this.signature);
+
+ if ("certs" in this) {
+ outputArray.push(new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Sequence({
+ value: Array.from(this.certs, element => element.toSchema())
+ })]
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ signatureAlgorithm: this.signatureAlgorithm.toJSON(),
+ signature: this.signature.toJSON()
+ };
+ if ("certs" in this) _object.certs = Array.from(this.certs, element => element.toJSON());
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = Signature;
+
+},{"./AlgorithmIdentifier.js":4,"./Certificate.js":19,"asn1js":112,"pvutils":113}],99:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _Attribute = _interopRequireDefault(require("./Attribute.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class SignedAndUnsignedAttributes {
+ //**********************************************************************************
+
+ /**
+ * Constructor for SignedAndUnsignedAttributes class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc type
+ */
+ this.type = (0, _pvutils.getParametersValue)(parameters, "type", SignedAndUnsignedAttributes.defaultValues("type"));
+ /**
+ * @type {Array}
+ * @desc attributes
+ */
+
+ this.attributes = (0, _pvutils.getParametersValue)(parameters, "attributes", SignedAndUnsignedAttributes.defaultValues("attributes"));
+ /**
+ * @type {ArrayBuffer}
+ * @desc encodedValue Need to have it in order to successfully process with signature verification
+ */
+
+ this.encodedValue = (0, _pvutils.getParametersValue)(parameters, "encodedValue", SignedAndUnsignedAttributes.defaultValues("encodedValue")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "type":
+ return -1;
+
+ case "attributes":
+ return [];
+
+ case "encodedValue":
+ return new ArrayBuffer(0);
+
+ default:
+ throw new Error(`Invalid member name for SignedAndUnsignedAttributes class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "type":
+ return memberValue === SignedAndUnsignedAttributes.defaultValues("type");
+
+ case "attributes":
+ return memberValue.length === 0;
+
+ case "encodedValue":
+ return memberValue.byteLength === 0;
+
+ default:
+ throw new Error(`Invalid member name for SignedAndUnsignedAttributes class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * SignedAttributes ::= SET SIZE (1..MAX) OF Attribute
+ *
+ * UnsignedAttributes ::= SET SIZE (1..MAX) OF Attribute
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {number} [tagNumber]
+ * @property {string} [attributes]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Constructed({
+ name: names.blockName || "",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: names.tagNumber // "SignedAttributes" = 0, "UnsignedAttributes" = 1
+
+ },
+ value: [new asn1js.Repeated({
+ name: names.attributes || "",
+ value: _Attribute.default.schema()
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["attributes"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, SignedAndUnsignedAttributes.schema({
+ names: {
+ tagNumber: this.type,
+ attributes: "attributes"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for SignedAndUnsignedAttributes"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.type = asn1.result.idBlock.tagNumber;
+ this.encodedValue = asn1.result.valueBeforeDecode; //region Change type from "[0]" to "SET" accordingly to standard
+
+ const encodedView = new Uint8Array(this.encodedValue);
+ encodedView[0] = 0x31; //endregion
+
+ if ("attributes" in asn1.result === false) {
+ if (this.type === 0) throw new Error("Wrong structure of SignedUnsignedAttributes");else return; // Not so important in case of "UnsignedAttributes"
+ }
+
+ this.attributes = Array.from(asn1.result.attributes, element => new _Attribute.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ if (SignedAndUnsignedAttributes.compareWithDefault("type", this.type) || SignedAndUnsignedAttributes.compareWithDefault("attributes", this.attributes)) throw new Error("Incorrectly initialized \"SignedAndUnsignedAttributes\" class"); //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: this.type // "SignedAttributes" = 0, "UnsignedAttributes" = 1
+
+ },
+ value: Array.from(this.attributes, element => element.toSchema())
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ if (SignedAndUnsignedAttributes.compareWithDefault("type", this.type) || SignedAndUnsignedAttributes.compareWithDefault("attributes", this.attributes)) throw new Error("Incorrectly initialized \"SignedAndUnsignedAttributes\" class");
+ return {
+ type: this.type,
+ attributes: Array.from(this.attributes, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = SignedAndUnsignedAttributes;
+
+},{"./Attribute.js":6,"asn1js":112,"pvutils":113}],100:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.verifySCTsForCertificate = verifySCTsForCertificate;
+exports.default = exports.SignedCertificateTimestamp = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _bytestreamjs = require("bytestreamjs");
+
+var _common = require("./common.js");
+
+var _PublicKeyInfo = _interopRequireDefault(require("./PublicKeyInfo.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+
+//**************************************************************************************
+class SignedCertificateTimestamp {
+ //**********************************************************************************
+
+ /**
+ * Constructor for SignedCertificateTimestamp class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", SignedCertificateTimestamp.defaultValues("version"));
+ /**
+ * @type {ArrayBuffer}
+ * @desc logID
+ */
+
+ this.logID = (0, _pvutils.getParametersValue)(parameters, "logID", SignedCertificateTimestamp.defaultValues("logID"));
+ /**
+ * @type {Date}
+ * @desc timestamp
+ */
+
+ this.timestamp = (0, _pvutils.getParametersValue)(parameters, "timestamp", SignedCertificateTimestamp.defaultValues("timestamp"));
+ /**
+ * @type {ArrayBuffer}
+ * @desc extensions
+ */
+
+ this.extensions = (0, _pvutils.getParametersValue)(parameters, "extensions", SignedCertificateTimestamp.defaultValues("extensions"));
+ /**
+ * @type {string}
+ * @desc hashAlgorithm
+ */
+
+ this.hashAlgorithm = (0, _pvutils.getParametersValue)(parameters, "hashAlgorithm", SignedCertificateTimestamp.defaultValues("hashAlgorithm"));
+ /**
+ * @type {string}
+ * @desc signatureAlgorithm
+ */
+
+ this.signatureAlgorithm = (0, _pvutils.getParametersValue)(parameters, "signatureAlgorithm", SignedCertificateTimestamp.defaultValues("signatureAlgorithm"));
+ /**
+ * @type {Object}
+ * @desc signature
+ */
+
+ this.signature = (0, _pvutils.getParametersValue)(parameters, "signature", SignedCertificateTimestamp.defaultValues("signature")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ //region If input argument array contains "stream"
+
+ if ("stream" in parameters) this.fromStream(parameters.stream); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return 0;
+
+ case "logID":
+ case "extensions":
+ return new ArrayBuffer(0);
+
+ case "timestamp":
+ return new Date(0);
+
+ case "hashAlgorithm":
+ case "signatureAlgorithm":
+ return "";
+
+ case "signature":
+ return new asn1js.Any();
+
+ default:
+ throw new Error(`Invalid member name for SignedCertificateTimestamp class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ if (schema instanceof asn1js.RawData === false) throw new Error("Object's schema was not verified against input data for SignedCertificateTimestamp");
+ const seqStream = new _bytestreamjs.SeqStream({
+ stream: new _bytestreamjs.ByteStream({
+ buffer: schema.data
+ })
+ });
+ this.fromStream(seqStream);
+ } //**********************************************************************************
+
+ /**
+ * Convert SeqStream data into current class
+ * @param {!SeqStream} stream
+ */
+
+
+ fromStream(stream) {
+ const blockLength = stream.getUint16();
+ this.version = stream.getBlock(1)[0];
+
+ if (this.version === 0) {
+ this.logID = new Uint8Array(stream.getBlock(32)).buffer.slice(0);
+ this.timestamp = new Date((0, _pvutils.utilFromBase)(new Uint8Array(stream.getBlock(8)), 8)); //region Extensions
+
+ const extensionsLength = stream.getUint16();
+ this.extensions = new Uint8Array(stream.getBlock(extensionsLength)).buffer.slice(0); //endregion
+ //region Hash algorithm
+
+ switch (stream.getBlock(1)[0]) {
+ case 0:
+ this.hashAlgorithm = "none";
+ break;
+
+ case 1:
+ this.hashAlgorithm = "md5";
+ break;
+
+ case 2:
+ this.hashAlgorithm = "sha1";
+ break;
+
+ case 3:
+ this.hashAlgorithm = "sha224";
+ break;
+
+ case 4:
+ this.hashAlgorithm = "sha256";
+ break;
+
+ case 5:
+ this.hashAlgorithm = "sha384";
+ break;
+
+ case 6:
+ this.hashAlgorithm = "sha512";
+ break;
+
+ default:
+ throw new Error("Object's stream was not correct for SignedCertificateTimestamp");
+ } //endregion
+ //region Signature algorithm
+
+
+ switch (stream.getBlock(1)[0]) {
+ case 0:
+ this.signatureAlgorithm = "anonymous";
+ break;
+
+ case 1:
+ this.signatureAlgorithm = "rsa";
+ break;
+
+ case 2:
+ this.signatureAlgorithm = "dsa";
+ break;
+
+ case 3:
+ this.signatureAlgorithm = "ecdsa";
+ break;
+
+ default:
+ throw new Error("Object's stream was not correct for SignedCertificateTimestamp");
+ } //endregion
+ //region Signature
+
+
+ const signatureLength = stream.getUint16();
+ const signatureData = new Uint8Array(stream.getBlock(signatureLength)).buffer.slice(0);
+ const asn1 = asn1js.fromBER(signatureData);
+ if (asn1.offset === -1) throw new Error("Object's stream was not correct for SignedCertificateTimestamp");
+ this.signature = asn1.result; //endregion
+
+ if (blockLength !== 47 + extensionsLength + signatureLength) throw new Error("Object's stream was not correct for SignedCertificateTimestamp");
+ }
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ const stream = this.toStream();
+ return new asn1js.RawData({
+ data: stream.stream.buffer
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to SeqStream data
+ * @returns {SeqStream} SeqStream object
+ */
+
+
+ toStream() {
+ const stream = new _bytestreamjs.SeqStream();
+ stream.appendUint16(47 + this.extensions.byteLength + this.signature.valueBeforeDecode.byteLength);
+ stream.appendChar(this.version);
+ stream.appendView(new Uint8Array(this.logID));
+ const timeBuffer = new ArrayBuffer(8);
+ const timeView = new Uint8Array(timeBuffer);
+ const baseArray = (0, _pvutils.utilToBase)(this.timestamp.valueOf(), 8);
+ timeView.set(new Uint8Array(baseArray), 8 - baseArray.byteLength);
+ stream.appendView(timeView);
+ stream.appendUint16(this.extensions.byteLength);
+ if (this.extensions.byteLength) stream.appendView(new Uint8Array(this.extensions));
+
+ let _hashAlgorithm;
+
+ switch (this.hashAlgorithm.toLowerCase()) {
+ case "none":
+ _hashAlgorithm = 0;
+ break;
+
+ case "md5":
+ _hashAlgorithm = 1;
+ break;
+
+ case "sha1":
+ _hashAlgorithm = 2;
+ break;
+
+ case "sha224":
+ _hashAlgorithm = 3;
+ break;
+
+ case "sha256":
+ _hashAlgorithm = 4;
+ break;
+
+ case "sha384":
+ _hashAlgorithm = 5;
+ break;
+
+ case "sha512":
+ _hashAlgorithm = 6;
+ break;
+
+ default:
+ throw new Error(`Incorrect data for hashAlgorithm: ${this.hashAlgorithm}`);
+ }
+
+ stream.appendChar(_hashAlgorithm);
+
+ let _signatureAlgorithm;
+
+ switch (this.signatureAlgorithm.toLowerCase()) {
+ case "anonymous":
+ _signatureAlgorithm = 0;
+ break;
+
+ case "rsa":
+ _signatureAlgorithm = 1;
+ break;
+
+ case "dsa":
+ _signatureAlgorithm = 2;
+ break;
+
+ case "ecdsa":
+ _signatureAlgorithm = 3;
+ break;
+
+ default:
+ throw new Error(`Incorrect data for signatureAlgorithm: ${this.signatureAlgorithm}`);
+ }
+
+ stream.appendChar(_signatureAlgorithm);
+
+ const _signature = this.signature.toBER(false);
+
+ stream.appendUint16(_signature.byteLength);
+ stream.appendView(new Uint8Array(_signature));
+ return stream;
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ version: this.version,
+ logID: (0, _pvutils.bufferToHexCodes)(this.logID),
+ timestamp: this.timestamp,
+ extensions: (0, _pvutils.bufferToHexCodes)(this.extensions),
+ hashAlgorithm: this.hashAlgorithm,
+ signatureAlgorithm: this.signatureAlgorithm,
+ signature: this.signature.toJSON()
+ };
+ } //**********************************************************************************
+
+ /**
+ * Verify SignedCertificateTimestamp for specific input data
+ * @param {Object[]} logs Array of objects with information about each CT Log (like here: https://ct.grahamedgecombe.com/logs.json)
+ * @param {String} logs.log_id Identifier of the CT Log encoded in BASE-64 format
+ * @param {String} logs.key Public key of the CT Log encoded in BASE-64 format
+ * @param {ArrayBuffer} data Data to verify signature against. Could be encoded Certificate or encoded PreCert
+ * @param {Number} [dataType=0] Type = 0 (data is encoded Certificate), type = 1 (data is encoded PreCert)
+ * @return {Promise<void>}
+ */
+
+
+ verify(logs, data, dataType = 0) {
+ var _this = this;
+
+ return _asyncToGenerator(function* () {
+ //region Initial variables
+ let logId = (0, _pvutils.toBase64)((0, _pvutils.arrayBufferToString)(_this.logID));
+ let publicKeyBase64 = null;
+ let publicKeyInfo;
+ let stream = new _bytestreamjs.SeqStream(); //endregion
+ //region Found and init public key
+
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = logs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ const log = _step.value;
+
+ if (log.log_id === logId) {
+ publicKeyBase64 = log.key;
+ break;
+ }
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+
+ if (publicKeyBase64 === null) throw new Error(`Public key not found for CT with logId: ${logId}`);
+ const asn1 = asn1js.fromBER((0, _pvutils.stringToArrayBuffer)((0, _pvutils.fromBase64)(publicKeyBase64)));
+ if (asn1.offset === -1) throw new Error(`Incorrect key value for CT Log with logId: ${logId}`);
+ publicKeyInfo = new _PublicKeyInfo.default({
+ schema: asn1.result
+ }); //endregion
+ //region Initialize signed data block
+
+ stream.appendChar(0x00); // sct_version
+
+ stream.appendChar(0x00); // signature_type = certificate_timestamp
+
+ const timeBuffer = new ArrayBuffer(8);
+ const timeView = new Uint8Array(timeBuffer);
+ const baseArray = (0, _pvutils.utilToBase)(_this.timestamp.valueOf(), 8);
+ timeView.set(new Uint8Array(baseArray), 8 - baseArray.byteLength);
+ stream.appendView(timeView);
+ stream.appendUint16(dataType);
+ if (dataType === 0) stream.appendUint24(data.byteLength);
+ stream.appendView(new Uint8Array(data));
+ stream.appendUint16(_this.extensions.byteLength);
+ if (_this.extensions.byteLength !== 0) stream.appendView(new Uint8Array(_this.extensions)); //endregion
+ //region Perform verification
+
+ return (0, _common.getEngine)().subtle.verifyWithPublicKey(stream._stream._buffer.slice(0, stream._length), {
+ valueBlock: {
+ valueHex: _this.signature.toBER(false)
+ }
+ }, publicKeyInfo, {
+ algorithmId: ""
+ }, "SHA-256"); //endregion
+ })();
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * Class from RFC6962
+ */
+
+
+exports.SignedCertificateTimestamp = SignedCertificateTimestamp;
+
+class SignedCertificateTimestampList {
+ //**********************************************************************************
+
+ /**
+ * Constructor for SignedCertificateTimestampList class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array.<SignedCertificateTimestamp>}
+ * @desc timestamps
+ */
+ this.timestamps = (0, _pvutils.getParametersValue)(parameters, "timestamps", SignedCertificateTimestampList.defaultValues("timestamps")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "timestamps":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for SignedCertificateTimestampList class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "timestamps":
+ return memberValue.length === 0;
+
+ default:
+ throw new Error(`Invalid member name for SignedCertificateTimestampList class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * SignedCertificateTimestampList ::= OCTET STRING
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [optional]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ if ("optional" in names === false) names.optional = false;
+ return new asn1js.OctetString({
+ name: names.blockName || "SignedCertificateTimestampList",
+ optional: names.optional
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Check the schema is valid
+ if (schema instanceof asn1js.OctetString === false) throw new Error("Object's schema was not verified against input data for SignedCertificateTimestampList"); //endregion
+ //region Get internal properties from parsed schema
+
+ const seqStream = new _bytestreamjs.SeqStream({
+ stream: new _bytestreamjs.ByteStream({
+ buffer: schema.valueBlock.valueHex
+ })
+ });
+ let dataLength = seqStream.getUint16();
+ if (dataLength !== seqStream.length) throw new Error("Object's schema was not verified against input data for SignedCertificateTimestampList");
+
+ while (seqStream.length) this.timestamps.push(new SignedCertificateTimestamp({
+ stream: seqStream
+ })); //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Initial variables
+ const stream = new _bytestreamjs.SeqStream();
+ let overallLength = 0;
+ const timestampsData = []; //endregion
+ //region Get overall length
+
+ var _iteratorNormalCompletion2 = true;
+ var _didIteratorError2 = false;
+ var _iteratorError2 = undefined;
+
+ try {
+ for (var _iterator2 = this.timestamps[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+ const timestamp = _step2.value;
+ const timestampStream = timestamp.toStream();
+ timestampsData.push(timestampStream);
+ overallLength += timestampStream.stream.buffer.byteLength;
+ } //endregion
+
+ } catch (err) {
+ _didIteratorError2 = true;
+ _iteratorError2 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
+ _iterator2.return();
+ }
+ } finally {
+ if (_didIteratorError2) {
+ throw _iteratorError2;
+ }
+ }
+ }
+
+ stream.appendUint16(overallLength); //region Set data from all timestamps
+
+ for (var _i = 0, _timestampsData = timestampsData; _i < _timestampsData.length; _i++) {
+ const timestamp = _timestampsData[_i];
+ stream.appendView(timestamp.stream.view);
+ } //endregion
+
+
+ return new asn1js.OctetString({
+ valueHex: stream.stream.buffer.slice(0)
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ timestamps: Array.from(this.timestamps, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * Verify SignedCertificateTimestamp for specific certificate content
+ * @param {Certificate} certificate Certificate for which verification would be performed
+ * @param {Certificate} issuerCertificate Certificate of the issuer of target certificate
+ * @param {Object[]} logs Array of objects with information about each CT Log (like here: https://ct.grahamedgecombe.com/logs.json)
+ * @param {String} logs.log_id Identifier of the CT Log encoded in BASE-64 format
+ * @param {String} logs.key Public key of the CT Log encoded in BASE-64 format
+ * @param {Number} [index=-1] Index of SignedCertificateTimestamp inside SignedCertificateTimestampList (for -1 would verify all)
+ * @return {Array} Array of verification results
+ */
+
+
+exports.default = SignedCertificateTimestampList;
+
+function verifySCTsForCertificate(_x, _x2, _x3) {
+ return _verifySCTsForCertificate.apply(this, arguments);
+} //**********************************************************************************
+
+
+function _verifySCTsForCertificate() {
+ _verifySCTsForCertificate = _asyncToGenerator(function* (certificate, issuerCertificate, logs, index = -1) {
+ //region Initial variables
+ let parsedValue = null;
+ let tbs;
+ let issuerId;
+ const stream = new _bytestreamjs.SeqStream();
+ let preCert; //endregion
+ //region Get a "crypto" extension
+
+ const crypto = (0, _common.getCrypto)();
+ if (typeof crypto === "undefined") return Promise.reject("Unable to create WebCrypto object"); //endregion
+ //region Remove certificate extension
+
+ for (let i = 0; i < certificate.extensions.length; i++) {
+ switch (certificate.extensions[i].extnID) {
+ case "1.3.6.1.4.1.11129.2.4.2":
+ {
+ parsedValue = certificate.extensions[i].parsedValue;
+ if (parsedValue.timestamps.length === 0) throw new Error("Nothing to verify in the certificate");
+ certificate.extensions.splice(i, 1);
+ }
+ break;
+
+ default:
+ }
+ } //endregion
+ //region Check we do have what to verify
+
+
+ if (parsedValue === null) throw new Error("No SignedCertificateTimestampList extension in the specified certificate"); //endregion
+ //region Prepare modifier TBS value
+
+ tbs = certificate.encodeTBS().toBER(false); //endregion
+ //region Initialize "issuer_key_hash" value
+
+ issuerId = yield crypto.digest({
+ name: "SHA-256"
+ }, new Uint8Array(issuerCertificate.subjectPublicKeyInfo.toSchema().toBER(false))); //endregion
+ //region Make final "PreCert" value
+
+ stream.appendView(new Uint8Array(issuerId));
+ stream.appendUint24(tbs.byteLength);
+ stream.appendView(new Uint8Array(tbs));
+ preCert = stream._stream._buffer.slice(0, stream._length); //endregion
+ //region Call verification function for specified index
+
+ if (index === -1) {
+ const verifyArray = [];
+ var _iteratorNormalCompletion3 = true;
+ var _didIteratorError3 = false;
+ var _iteratorError3 = undefined;
+
+ try {
+ for (var _iterator3 = parsedValue.timestamps[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
+ const timestamp = _step3.value;
+ const verifyResult = yield timestamp.verify(logs, preCert, 1);
+ verifyArray.push(verifyResult);
+ }
+ } catch (err) {
+ _didIteratorError3 = true;
+ _iteratorError3 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
+ _iterator3.return();
+ }
+ } finally {
+ if (_didIteratorError3) {
+ throw _iteratorError3;
+ }
+ }
+ }
+
+ return verifyArray;
+ }
+
+ if (index >= parsedValue.timestamps.length) index = parsedValue.timestamps.length - 1;
+ return [yield parsedValue.timestamps[index].verify(logs, preCert, 1)]; //endregion
+ });
+ return _verifySCTsForCertificate.apply(this, arguments);
+}
+
+},{"./PublicKeyInfo.js":78,"./common.js":110,"asn1js":112,"bytestreamjs":1,"pvutils":113}],101:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _common = require("./common.js");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _EncapsulatedContentInfo = _interopRequireDefault(require("./EncapsulatedContentInfo.js"));
+
+var _Certificate = _interopRequireDefault(require("./Certificate.js"));
+
+var _CertificateRevocationList = _interopRequireDefault(require("./CertificateRevocationList.js"));
+
+var _OtherRevocationInfoFormat = _interopRequireDefault(require("./OtherRevocationInfoFormat.js"));
+
+var _SignerInfo = _interopRequireDefault(require("./SignerInfo.js"));
+
+var _CertificateSet = _interopRequireDefault(require("./CertificateSet.js"));
+
+var _RevocationInfoChoices = _interopRequireDefault(require("./RevocationInfoChoices.js"));
+
+var _IssuerAndSerialNumber = _interopRequireDefault(require("./IssuerAndSerialNumber.js"));
+
+var _TSTInfo = _interopRequireDefault(require("./TSTInfo.js"));
+
+var _CertificateChainValidationEngine = _interopRequireDefault(require("./CertificateChainValidationEngine.js"));
+
+var _BasicOCSPResponse = _interopRequireDefault(require("./BasicOCSPResponse.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
+
+function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
+
+function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
+
+function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class SignedData {
+ //**********************************************************************************
+
+ /**
+ * Constructor for SignedData class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", SignedData.defaultValues("version"));
+ /**
+ * @type {Array.<AlgorithmIdentifier>}
+ * @desc digestAlgorithms
+ */
+
+ this.digestAlgorithms = (0, _pvutils.getParametersValue)(parameters, "digestAlgorithms", SignedData.defaultValues("digestAlgorithms"));
+ /**
+ * @type {EncapsulatedContentInfo}
+ * @desc encapContentInfo
+ */
+
+ this.encapContentInfo = (0, _pvutils.getParametersValue)(parameters, "encapContentInfo", SignedData.defaultValues("encapContentInfo"));
+ if ("certificates" in parameters)
+ /**
+ * @type {Array.<Certificate|OtherCertificateFormat>}
+ * @desc certificates
+ */
+ this.certificates = (0, _pvutils.getParametersValue)(parameters, "certificates", SignedData.defaultValues("certificates"));
+ if ("crls" in parameters)
+ /**
+ * @type {Array.<CertificateRevocationList|OtherRevocationInfoFormat>}
+ * @desc crls
+ */
+ this.crls = (0, _pvutils.getParametersValue)(parameters, "crls", SignedData.defaultValues("crls"));
+ if ("ocsps" in parameters)
+ /**
+ * @type {Array.<BasicOCSPResponse>}
+ * @desc crls
+ */
+ this.ocsps = (0, _pvutils.getParametersValue)(parameters, "ocsps", SignedData.defaultValues("ocsps"));
+ /**
+ * @type {Array.<SignerInfo>}
+ * @desc signerInfos
+ */
+
+ this.signerInfos = (0, _pvutils.getParametersValue)(parameters, "signerInfos", SignedData.defaultValues("signerInfos")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return 0;
+
+ case "digestAlgorithms":
+ return [];
+
+ case "encapContentInfo":
+ return new _EncapsulatedContentInfo.default();
+
+ case "certificates":
+ return [];
+
+ case "crls":
+ return [];
+
+ case "ocsps":
+ return [];
+
+ case "signerInfos":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for SignedData class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "version":
+ return memberValue === SignedData.defaultValues("version");
+
+ case "encapContentInfo":
+ return new _EncapsulatedContentInfo.default();
+
+ case "digestAlgorithms":
+ case "certificates":
+ case "crls":
+ case "ocsps":
+ case "signerInfos":
+ return memberValue.length === 0;
+
+ default:
+ throw new Error(`Invalid member name for SignedData class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * SignedData ::= SEQUENCE {
+ * version CMSVersion,
+ * digestAlgorithms DigestAlgorithmIdentifiers,
+ * encapContentInfo EncapsulatedContentInfo,
+ * certificates [0] IMPLICIT CertificateSet OPTIONAL,
+ * crls [1] IMPLICIT RevocationInfoChoices OPTIONAL,
+ * signerInfos SignerInfos }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [optional]
+ * @property {string} [digestAlgorithms]
+ * @property {string} [encapContentInfo]
+ * @property {string} [certificates]
+ * @property {string} [crls]
+ * @property {string} [signerInfos]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ if ("optional" in names === false) names.optional = false;
+ return new asn1js.Sequence({
+ name: names.blockName || "SignedData",
+ optional: names.optional,
+ value: [new asn1js.Integer({
+ name: names.version || "SignedData.version"
+ }), new asn1js.Set({
+ value: [new asn1js.Repeated({
+ name: names.digestAlgorithms || "SignedData.digestAlgorithms",
+ value: _AlgorithmIdentifier.default.schema()
+ })]
+ }), _EncapsulatedContentInfo.default.schema(names.encapContentInfo || {
+ names: {
+ blockName: "SignedData.encapContentInfo"
+ }
+ }), new asn1js.Constructed({
+ name: names.certificates || "SignedData.certificates",
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: _CertificateSet.default.schema().valueBlock.value
+ }), // IMPLICIT CertificateSet
+ new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: _RevocationInfoChoices.default.schema(names.crls || {
+ names: {
+ crls: "SignedData.crls"
+ }
+ }).valueBlock.value
+ }), // IMPLICIT RevocationInfoChoices
+ new asn1js.Set({
+ value: [new asn1js.Repeated({
+ name: names.signerInfos || "SignedData.signerInfos",
+ value: _SignerInfo.default.schema()
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["SignedData.version", "SignedData.digestAlgorithms", "SignedData.encapContentInfo", "SignedData.certificates", "SignedData.crls", "SignedData.signerInfos"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, SignedData.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for SignedData"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.version = asn1.result["SignedData.version"].valueBlock.valueDec;
+ if ("SignedData.digestAlgorithms" in asn1.result) // Could be empty SET of digest algorithms
+ this.digestAlgorithms = Array.from(asn1.result["SignedData.digestAlgorithms"], algorithm => new _AlgorithmIdentifier.default({
+ schema: algorithm
+ }));
+ this.encapContentInfo = new _EncapsulatedContentInfo.default({
+ schema: asn1.result["SignedData.encapContentInfo"]
+ });
+
+ if ("SignedData.certificates" in asn1.result) {
+ const certificateSet = new _CertificateSet.default({
+ schema: new asn1js.Set({
+ value: asn1.result["SignedData.certificates"].valueBlock.value
+ })
+ });
+ this.certificates = certificateSet.certificates.slice(0); // Copy all just for making comfortable access
+ }
+
+ if ("SignedData.crls" in asn1.result) {
+ this.crls = Array.from(asn1.result["SignedData.crls"], crl => {
+ if (crl.idBlock.tagClass === 1) return new _CertificateRevocationList.default({
+ schema: crl
+ }); //region Create SEQUENCE from [1]
+
+ crl.idBlock.tagClass = 1; // UNIVERSAL
+
+ crl.idBlock.tagNumber = 16; // SEQUENCE
+ //endregion
+
+ return new _OtherRevocationInfoFormat.default({
+ schema: crl
+ });
+ });
+ }
+
+ if ("SignedData.signerInfos" in asn1.result) // Could be empty SET SignerInfos
+ this.signerInfos = Array.from(asn1.result["SignedData.signerInfos"], signerInfoSchema => new _SignerInfo.default({
+ schema: signerInfoSchema
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema(encodeFlag = false) {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(new asn1js.Integer({
+ value: this.version
+ })); //region Create array of digest algorithms
+
+ outputArray.push(new asn1js.Set({
+ value: Array.from(this.digestAlgorithms, algorithm => algorithm.toSchema(encodeFlag))
+ })); //endregion
+
+ outputArray.push(this.encapContentInfo.toSchema());
+
+ if ("certificates" in this) {
+ const certificateSet = new _CertificateSet.default({
+ certificates: this.certificates
+ });
+ const certificateSetSchema = certificateSet.toSchema();
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ tagNumber: 0
+ },
+ value: certificateSetSchema.valueBlock.value
+ }));
+ }
+
+ if ("crls" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: Array.from(this.crls, crl => {
+ if (crl instanceof _OtherRevocationInfoFormat.default) {
+ const crlSchema = crl.toSchema(encodeFlag);
+ crlSchema.idBlock.tagClass = 3;
+ crlSchema.idBlock.tagNumber = 1;
+ return crlSchema;
+ }
+
+ return crl.toSchema(encodeFlag);
+ })
+ }));
+ } //region Create array of signer infos
+
+
+ outputArray.push(new asn1js.Set({
+ value: Array.from(this.signerInfos, signerInfo => signerInfo.toSchema(encodeFlag))
+ })); //endregion
+ //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ version: this.version,
+ digestAlgorithms: Array.from(this.digestAlgorithms, algorithm => algorithm.toJSON()),
+ encapContentInfo: this.encapContentInfo.toJSON()
+ };
+ if ("certificates" in this) _object.certificates = Array.from(this.certificates, certificate => certificate.toJSON());
+ if ("crls" in this) _object.crls = Array.from(this.crls, crl => crl.toJSON());
+ _object.signerInfos = Array.from(this.signerInfos, signerInfo => signerInfo.toJSON());
+ return _object;
+ } //**********************************************************************************
+
+ /**
+ * Verify current SignedData value
+ * @param {Object} [param={}]
+ * @param {Number} [param.signer = -1] Index of the signer which information we need to verify
+ * @param {ArrayBuffer} [param.data=new ArrayBuffer(0)]
+ * @param {Array.<Certificate>} [param.trustedCerts=[]]
+ * @param {Date} [param.checkDate=new Date()]
+ * @param {Boolean} [param.checkChain=false]
+ * @param {Boolean} [param.extendedMode=false]
+ * @param {?Function} [findOrigin=null]
+ * @param {?Function} [findIssuer=null]
+ */
+
+
+ verify({
+ signer = -1,
+ data = new ArrayBuffer(0),
+ trustedCerts = [],
+ checkDate = new Date(),
+ checkChain = false,
+ extendedMode = false,
+ passedWhenNotRevValues = false,
+ findOrigin = null,
+ findIssuer = null
+ } = {}) {
+ //region Global variables
+ let sequence = Promise.resolve();
+ let messageDigestValue = new ArrayBuffer(0);
+ let shaAlgorithm = "";
+ let signerCertificate = {};
+ let timestampSerial = null;
+ let certificatePath = [];
+ const engine = (0, _common.getEngine)(); //endregion
+ //region Get a "crypto" extension
+
+ const crypto = (0, _common.getCrypto)();
+ if (typeof crypto === "undefined") return Promise.reject("Unable to create WebCrypto object"); //endregion
+ //region Get a signer number
+
+ if (signer === -1) {
+ if (extendedMode) {
+ return Promise.reject({
+ date: checkDate,
+ code: 1,
+ message: "Unable to get signer index from input parameters",
+ signatureVerified: null,
+ signerCertificate: null,
+ signerCertificateVerified: null
+ });
+ }
+
+ return Promise.reject("Unable to get signer index from input parameters");
+ } //endregion
+ //region Check that certificates field was included in signed data
+
+
+ if ("certificates" in this === false) {
+ if (extendedMode) {
+ return Promise.reject({
+ date: checkDate,
+ code: 2,
+ message: "No certificates attached to this signed data",
+ signatureVerified: null,
+ signerCertificate: null,
+ signerCertificateVerified: null
+ });
+ }
+
+ return Promise.reject("No certificates attached to this signed data");
+ } //endregion
+ //region Find a certificate for specified signer
+
+
+ if (this.signerInfos[signer].sid instanceof _IssuerAndSerialNumber.default) {
+ sequence = sequence.then(() => {
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = this.certificates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ const certificate = _step.value;
+ if (certificate instanceof _Certificate.default === false) continue;
+
+ if (certificate.issuer.isEqual(this.signerInfos[signer].sid.issuer) && certificate.serialNumber.isEqual(this.signerInfos[signer].sid.serialNumber)) {
+ signerCertificate = certificate;
+ return Promise.resolve();
+ }
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+
+ if (extendedMode) {
+ return Promise.reject({
+ date: checkDate,
+ code: 3,
+ message: "Unable to find signer certificate",
+ signatureVerified: null,
+ signerCertificate: null,
+ signerCertificateVerified: null
+ });
+ }
+
+ return Promise.reject("Unable to find signer certificate");
+ });
+ } else // Find by SubjectKeyIdentifier
+ {
+ sequence = sequence.then(() => Promise.all(Array.from(this.certificates.filter(certificate => certificate instanceof _Certificate.default), certificate => crypto.digest({
+ name: "sha-1"
+ }, new Uint8Array(certificate.subjectPublicKeyInfo.subjectPublicKey.valueBlock.valueHex)))).then(results => {
+ var _iteratorNormalCompletion2 = true;
+ var _didIteratorError2 = false;
+ var _iteratorError2 = undefined;
+
+ try {
+ for (var _iterator2 = this.certificates.entries()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+ const _step2$value = _slicedToArray(_step2.value, 2),
+ index = _step2$value[0],
+ certificate = _step2$value[1];
+
+ if (certificate instanceof _Certificate.default === false) continue;
+
+ if ((0, _pvutils.isEqualBuffer)(results[index], this.signerInfos[signer].sid.valueBlock.valueHex)) {
+ signerCertificate = certificate;
+ return Promise.resolve();
+ }
+ }
+ } catch (err) {
+ _didIteratorError2 = true;
+ _iteratorError2 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
+ _iterator2.return();
+ }
+ } finally {
+ if (_didIteratorError2) {
+ throw _iteratorError2;
+ }
+ }
+ }
+
+ if (extendedMode) {
+ return Promise.reject({
+ date: checkDate,
+ code: 3,
+ message: "Unable to find signer certificate",
+ signatureVerified: null,
+ signerCertificate: null,
+ signerCertificateVerified: null
+ });
+ }
+
+ return Promise.reject("Unable to find signer certificate");
+ }, () => {
+ if (extendedMode) {
+ return Promise.reject({
+ date: checkDate,
+ code: 3,
+ message: "Unable to find signer certificate",
+ signatureVerified: null,
+ signerCertificate: null,
+ signerCertificateVerified: null
+ });
+ }
+
+ return Promise.reject("Unable to find signer certificate");
+ }));
+ } //endregion
+ //region Verify internal digest in case of "tSTInfo" content type
+
+
+ sequence = sequence.then(() => {
+ if (this.encapContentInfo.eContentType === "1.2.840.113549.1.9.16.1.4") {
+ //region Check "eContent" precense
+ if ("eContent" in this.encapContentInfo === false) return false; //endregion
+ //region Initialize TST_INFO value
+
+ const asn1 = asn1js.fromBER(this.encapContentInfo.eContent.valueBlock.valueHex);
+ let tstInfo;
+
+ try {
+ tstInfo = new _TSTInfo.default({
+ schema: asn1.result
+ });
+ } catch (ex) {
+ return false;
+ } //endregion
+ //region Change "checkDate" and append "timestampSerial"
+
+
+ checkDate = tstInfo.genTime;
+ timestampSerial = tstInfo.serialNumber.valueBlock.valueHex; //endregion
+ //region Check that we do have detached data content
+
+ if (data.byteLength === 0) {
+ if (extendedMode) {
+ return Promise.reject({
+ date: checkDate,
+ code: 4,
+ message: "Missed detached data input array",
+ signatureVerified: null,
+ signerCertificate,
+ signerCertificateVerified: null
+ });
+ }
+
+ return Promise.reject("Missed detached data input array");
+ } //endregion
+
+
+ return tstInfo.verify({
+ data
+ });
+ }
+
+ return true;
+ }); //endregion
+ //region Make additional verification for signer's certificate
+
+ function checkCA(cert) {
+ /// <param name="cert" type="in_window.org.pkijs.simpl.CERT">Certificate to find CA flag for</param>
+ //region Do not include signer's certificate
+ if (cert.issuer.isEqual(signerCertificate.issuer) === true && cert.serialNumber.isEqual(signerCertificate.serialNumber) === true) return null; //endregion
+
+ let isCA = false;
+
+ if ("extensions" in cert) {
+ var _iteratorNormalCompletion3 = true;
+ var _didIteratorError3 = false;
+ var _iteratorError3 = undefined;
+
+ try {
+ for (var _iterator3 = cert.extensions[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
+ const extension = _step3.value;
+
+ if (extension.extnID === "2.5.29.19") // BasicConstraints
+ {
+ if ("cA" in extension.parsedValue) {
+ if (extension.parsedValue.cA === true) isCA = true;
+ }
+ }
+ }
+ } catch (err) {
+ _didIteratorError3 = true;
+ _iteratorError3 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
+ _iterator3.return();
+ }
+ } finally {
+ if (_didIteratorError3) {
+ throw _iteratorError3;
+ }
+ }
+ }
+ }
+
+ if (isCA) return cert;
+ return null;
+ }
+
+ if (checkChain) {
+ sequence = sequence.then(result => {
+ //region Verify result of previous operation
+ if (result === false) return false; //endregion
+
+ const promiseResults = Array.from(this.certificates.filter(certificate => certificate instanceof _Certificate.default), certificate => checkCA(certificate));
+ const certificateChainValidationEngineParameters = {
+ checkDate,
+ certs: Array.from(promiseResults.filter(_result => _result !== null)),
+ trustedCerts
+ };
+ if (findIssuer !== null) certificateChainValidationEngineParameters.findIssuer = findIssuer;
+ if (findOrigin !== null) certificateChainValidationEngineParameters.findOrigin = findOrigin;
+ const certificateChainEngine = new _CertificateChainValidationEngine.default(certificateChainValidationEngineParameters);
+ certificateChainEngine.certs.push(signerCertificate);
+
+ if ("crls" in this) {
+ var _iteratorNormalCompletion4 = true;
+ var _didIteratorError4 = false;
+ var _iteratorError4 = undefined;
+
+ try {
+ for (var _iterator4 = this.crls[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
+ const crl = _step4.value;
+ if ("thisUpdate" in crl) certificateChainEngine.crls.push(crl);else // Assumed "revocation value" has "OtherRevocationInfoFormat"
+ {
+ if (crl.otherRevInfoFormat === "1.3.6.1.5.5.7.48.1.1") // Basic OCSP response
+ certificateChainEngine.ocsps.push(new _BasicOCSPResponse.default({
+ schema: crl.otherRevInfo
+ }));
+ }
+ }
+ } catch (err) {
+ _didIteratorError4 = true;
+ _iteratorError4 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion4 && _iterator4.return != null) {
+ _iterator4.return();
+ }
+ } finally {
+ if (_didIteratorError4) {
+ throw _iteratorError4;
+ }
+ }
+ }
+ }
+
+ if ("ocsps" in this) certificateChainEngine.ocsps.push(...this.ocsps);
+ return certificateChainEngine.verify({
+ passedWhenNotRevValues
+ }).then(verificationResult => {
+ if ("certificatePath" in verificationResult) certificatePath = verificationResult.certificatePath;
+ if (verificationResult.result === true) return Promise.resolve(true);
+
+ if (extendedMode) {
+ return Promise.reject({
+ date: checkDate,
+ code: 5,
+ message: `Validation of signer's certificate failed: ${verificationResult.resultMessage}`,
+ signatureVerified: null,
+ signerCertificate,
+ signerCertificateVerified: false
+ });
+ }
+
+ return Promise.reject("Validation of signer's certificate failed");
+ }, error => {
+ if (extendedMode) {
+ return Promise.reject({
+ date: checkDate,
+ code: 5,
+ message: `Validation of signer's certificate failed with error: ${error instanceof Object ? error.resultMessage : error}`,
+ signatureVerified: null,
+ signerCertificate,
+ signerCertificateVerified: false
+ });
+ }
+
+ return Promise.reject(`Validation of signer's certificate failed with error: ${error instanceof Object ? error.resultMessage : error}`);
+ });
+ });
+ } //endregion
+ //region Find signer's hashing algorithm
+
+
+ sequence = sequence.then(result => {
+ //region Verify result of previous operation
+ if (result === false) return false; //endregion
+
+ const signerInfoHashAlgorithm = (0, _common.getAlgorithmByOID)(this.signerInfos[signer].digestAlgorithm.algorithmId);
+
+ if ("name" in signerInfoHashAlgorithm === false) {
+ if (extendedMode) {
+ return Promise.reject({
+ date: checkDate,
+ code: 7,
+ message: `Unsupported signature algorithm: ${this.signerInfos[signer].digestAlgorithm.algorithmId}`,
+ signatureVerified: null,
+ signerCertificate,
+ signerCertificateVerified: true
+ });
+ }
+
+ return Promise.reject(`Unsupported signature algorithm: ${this.signerInfos[signer].digestAlgorithm.algorithmId}`);
+ }
+
+ shaAlgorithm = signerInfoHashAlgorithm.name;
+ return true;
+ }); //endregion
+ //region Create correct data block for verification
+
+ sequence = sequence.then(result => {
+ //region Verify result of previous operation
+ if (result === false) return false; //endregion
+
+ if ("eContent" in this.encapContentInfo) // Attached data
+ {
+ if (this.encapContentInfo.eContent.idBlock.tagClass === 1 && this.encapContentInfo.eContent.idBlock.tagNumber === 4) {
+ if (this.encapContentInfo.eContent.idBlock.isConstructed === false) data = this.encapContentInfo.eContent.valueBlock.valueHex;else {
+ var _iteratorNormalCompletion5 = true;
+ var _didIteratorError5 = false;
+ var _iteratorError5 = undefined;
+
+ try {
+ for (var _iterator5 = this.encapContentInfo.eContent.valueBlock.value[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
+ const contentValue = _step5.value;
+ data = (0, _pvutils.utilConcatBuf)(data, contentValue.valueBlock.valueHex);
+ }
+ } catch (err) {
+ _didIteratorError5 = true;
+ _iteratorError5 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion5 && _iterator5.return != null) {
+ _iterator5.return();
+ }
+ } finally {
+ if (_didIteratorError5) {
+ throw _iteratorError5;
+ }
+ }
+ }
+ }
+ } else data = this.encapContentInfo.eContent.valueBlock.valueBeforeDecode;
+ } else // Detached data
+ {
+ if (data.byteLength === 0) // Check that "data" already provided by function parameter
+ {
+ if (extendedMode) {
+ return Promise.reject({
+ date: checkDate,
+ code: 8,
+ message: "Missed detached data input array",
+ signatureVerified: null,
+ signerCertificate,
+ signerCertificateVerified: true
+ });
+ }
+
+ return Promise.reject("Missed detached data input array");
+ }
+ }
+
+ if ("signedAttrs" in this.signerInfos[signer]) {
+ //region Check mandatory attributes
+ let foundContentType = false;
+ let foundMessageDigest = false;
+ var _iteratorNormalCompletion6 = true;
+ var _didIteratorError6 = false;
+ var _iteratorError6 = undefined;
+
+ try {
+ for (var _iterator6 = this.signerInfos[signer].signedAttrs.attributes[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
+ const attribute = _step6.value;
+ //region Check that "content-type" attribute exists
+ if (attribute.type === "1.2.840.113549.1.9.3") foundContentType = true; //endregion
+ //region Check that "message-digest" attribute exists
+
+ if (attribute.type === "1.2.840.113549.1.9.4") {
+ foundMessageDigest = true;
+ messageDigestValue = attribute.values[0].valueBlock.valueHex;
+ } //endregion
+ //region Speed-up searching
+
+
+ if (foundContentType && foundMessageDigest) break; //endregion
+ }
+ } catch (err) {
+ _didIteratorError6 = true;
+ _iteratorError6 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion6 && _iterator6.return != null) {
+ _iterator6.return();
+ }
+ } finally {
+ if (_didIteratorError6) {
+ throw _iteratorError6;
+ }
+ }
+ }
+
+ if (foundContentType === false) {
+ if (extendedMode) {
+ return Promise.reject({
+ date: checkDate,
+ code: 9,
+ message: "Attribute \"content-type\" is a mandatory attribute for \"signed attributes\"",
+ signatureVerified: null,
+ signerCertificate,
+ signerCertificateVerified: true
+ });
+ }
+
+ return Promise.reject("Attribute \"content-type\" is a mandatory attribute for \"signed attributes\"");
+ }
+
+ if (foundMessageDigest === false) {
+ if (extendedMode) {
+ return Promise.reject({
+ date: checkDate,
+ code: 10,
+ message: "Attribute \"message-digest\" is a mandatory attribute for \"signed attributes\"",
+ signatureVerified: null,
+ signerCertificate,
+ signerCertificateVerified: true
+ });
+ }
+
+ return Promise.reject("Attribute \"message-digest\" is a mandatory attribute for \"signed attributes\"");
+ } //endregion
+
+ }
+
+ return true;
+ }); //endregion
+ //region Verify "message-digest" attribute in case of "signedAttrs"
+
+ sequence = sequence.then(result => {
+ //region Verify result of previous operation
+ if (result === false) return false; //endregion
+
+ if ("signedAttrs" in this.signerInfos[signer]) return crypto.digest(shaAlgorithm, new Uint8Array(data));
+ return true;
+ }).then(
+ /**
+ * @param {ArrayBuffer} result
+ */
+ result => {
+ //region Verify result of previous operation
+ if (result === false) return false; //endregion
+
+ if ("signedAttrs" in this.signerInfos[signer]) {
+ if ((0, _pvutils.isEqualBuffer)(result, messageDigestValue)) {
+ data = this.signerInfos[signer].signedAttrs.encodedValue;
+ return true;
+ }
+
+ return false;
+ }
+
+ return true;
+ }); //endregion
+
+ sequence = sequence.then(result => {
+ //region Verify result of previous operation
+ if (result === false) return false; //endregion
+
+ return engine.subtle.verifyWithPublicKey(data, this.signerInfos[signer].signature, signerCertificate.subjectPublicKeyInfo, signerCertificate.signatureAlgorithm, shaAlgorithm);
+ }); //region Make a final result
+
+ sequence = sequence.then(result => {
+ if (extendedMode) {
+ return {
+ date: checkDate,
+ code: 14,
+ message: "",
+ signatureVerified: result,
+ signerCertificate,
+ timestampSerial,
+ signerCertificateVerified: true,
+ certificatePath
+ };
+ }
+
+ return result;
+ }, error => {
+ if (extendedMode) {
+ if ("code" in error) return Promise.reject(error);
+ return Promise.reject({
+ date: checkDate,
+ code: 15,
+ message: `Error during verification: ${error.message}`,
+ signatureVerified: null,
+ signerCertificate,
+ timestampSerial,
+ signerCertificateVerified: true
+ });
+ }
+
+ return Promise.reject(error);
+ }); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+ /**
+ * Signing current SignedData
+ * @param {key} privateKey Private key for "subjectPublicKeyInfo" structure
+ * @param {number} signerIndex Index number (starting from 0) of signer index to make signature for
+ * @param {string} [hashAlgorithm="SHA-1"] Hashing algorithm. Default SHA-1
+ * @param {ArrayBuffer} [data] Detached data
+ * @returns {*}
+ */
+
+
+ sign(privateKey, signerIndex, hashAlgorithm = "SHA-1", data = new ArrayBuffer(0)) {
+ //region Initial checking
+ if (typeof privateKey === "undefined") return Promise.reject("Need to provide a private key for signing"); //endregion
+ //region Initial variables
+
+ let sequence = Promise.resolve();
+ let parameters;
+ const engine = (0, _common.getEngine)(); //endregion
+ //region Simple check for supported algorithm
+
+ const hashAlgorithmOID = (0, _common.getOIDByAlgorithm)({
+ name: hashAlgorithm
+ });
+ if (hashAlgorithmOID === "") return Promise.reject(`Unsupported hash algorithm: ${hashAlgorithm}`); //endregion
+ //region Append information about hash algorithm
+
+ if (this.digestAlgorithms.filter(algorithm => algorithm.algorithmId === hashAlgorithmOID).length === 0) {
+ this.digestAlgorithms.push(new _AlgorithmIdentifier.default({
+ algorithmId: hashAlgorithmOID,
+ algorithmParams: new asn1js.Null()
+ }));
+ }
+
+ this.signerInfos[signerIndex].digestAlgorithm = new _AlgorithmIdentifier.default({
+ algorithmId: hashAlgorithmOID,
+ algorithmParams: new asn1js.Null()
+ }); //endregion
+ //region Get a "default parameters" for current algorithm and set correct signature algorithm
+
+ sequence = sequence.then(() => engine.subtle.getSignatureParameters(privateKey, hashAlgorithm));
+ sequence = sequence.then(result => {
+ parameters = result.parameters;
+ this.signerInfos[signerIndex].signatureAlgorithm = result.signatureAlgorithm;
+ }); //endregion
+ //region Create TBS data for signing
+
+ sequence = sequence.then(() => {
+ if ("signedAttrs" in this.signerInfos[signerIndex]) {
+ if (this.signerInfos[signerIndex].signedAttrs.encodedValue.byteLength !== 0) data = this.signerInfos[signerIndex].signedAttrs.encodedValue;else {
+ data = this.signerInfos[signerIndex].signedAttrs.toSchema(true).toBER(false); //region Change type from "[0]" to "SET" acordingly to standard
+
+ const view = new Uint8Array(data);
+ view[0] = 0x31; //endregion
+ }
+ } else {
+ if ("eContent" in this.encapContentInfo) // Attached data
+ {
+ if (this.encapContentInfo.eContent.idBlock.tagClass === 1 && this.encapContentInfo.eContent.idBlock.tagNumber === 4) {
+ if (this.encapContentInfo.eContent.idBlock.isConstructed === false) data = this.encapContentInfo.eContent.valueBlock.valueHex;else {
+ var _iteratorNormalCompletion7 = true;
+ var _didIteratorError7 = false;
+ var _iteratorError7 = undefined;
+
+ try {
+ for (var _iterator7 = this.encapContentInfo.eContent.valueBlock.value[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
+ const content = _step7.value;
+ data = (0, _pvutils.utilConcatBuf)(data, content.valueBlock.valueHex);
+ }
+ } catch (err) {
+ _didIteratorError7 = true;
+ _iteratorError7 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion7 && _iterator7.return != null) {
+ _iterator7.return();
+ }
+ } finally {
+ if (_didIteratorError7) {
+ throw _iteratorError7;
+ }
+ }
+ }
+ }
+ } else data = this.encapContentInfo.eContent.valueBlock.valueBeforeDecode;
+ } else // Detached data
+ {
+ if (data.byteLength === 0) // Check that "data" already provided by function parameter
+ return Promise.reject("Missed detached data input array");
+ }
+ }
+
+ return Promise.resolve();
+ }); //endregion
+ //region Signing TBS data on provided private key
+
+ sequence = sequence.then(() => engine.subtle.signWithPrivateKey(data, privateKey, parameters));
+ sequence = sequence.then(result => {
+ this.signerInfos[signerIndex].signature = new asn1js.OctetString({
+ valueHex: result
+ });
+ return result;
+ }); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = SignedData;
+
+},{"./AlgorithmIdentifier.js":4,"./BasicOCSPResponse.js":13,"./Certificate.js":19,"./CertificateChainValidationEngine.js":20,"./CertificateRevocationList.js":22,"./CertificateSet.js":23,"./EncapsulatedContentInfo.js":33,"./IssuerAndSerialNumber.js":44,"./OtherRevocationInfoFormat.js":64,"./RevocationInfoChoices.js":93,"./SignerInfo.js":102,"./TSTInfo.js":106,"./common.js":110,"asn1js":112,"pvutils":113}],102:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _SignedAndUnsignedAttributes = _interopRequireDefault(require("./SignedAndUnsignedAttributes.js"));
+
+var _IssuerAndSerialNumber = _interopRequireDefault(require("./IssuerAndSerialNumber.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5652
+ */
+class SignerInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for SignerInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {string}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", SignerInfo.defaultValues("version"));
+ /**
+ * @type {Object}
+ * @desc sid
+ */
+
+ this.sid = (0, _pvutils.getParametersValue)(parameters, "sid", SignerInfo.defaultValues("sid"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc digestAlgorithm
+ */
+
+ this.digestAlgorithm = (0, _pvutils.getParametersValue)(parameters, "digestAlgorithm", SignerInfo.defaultValues("digestAlgorithm"));
+ if ("signedAttrs" in parameters)
+ /**
+ * @type {SignedAndUnsignedAttributes}
+ * @desc signedAttrs
+ */
+ this.signedAttrs = (0, _pvutils.getParametersValue)(parameters, "signedAttrs", SignerInfo.defaultValues("signedAttrs"));
+ /**
+ * @type {AlgorithmIdentifier}
+ * @desc digestAlgorithm
+ */
+
+ this.signatureAlgorithm = (0, _pvutils.getParametersValue)(parameters, "signatureAlgorithm", SignerInfo.defaultValues("signatureAlgorithm"));
+ /**
+ * @type {OctetString}
+ * @desc signature
+ */
+
+ this.signature = (0, _pvutils.getParametersValue)(parameters, "signature", SignerInfo.defaultValues("signature"));
+ if ("unsignedAttrs" in parameters)
+ /**
+ * @type {SignedAndUnsignedAttributes}
+ * @desc unsignedAttrs
+ */
+ this.unsignedAttrs = (0, _pvutils.getParametersValue)(parameters, "unsignedAttrs", SignerInfo.defaultValues("unsignedAttrs")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return 0;
+
+ case "sid":
+ return new asn1js.Any();
+
+ case "digestAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "signedAttrs":
+ return new _SignedAndUnsignedAttributes.default({
+ type: 0
+ });
+
+ case "signatureAlgorithm":
+ return new _AlgorithmIdentifier.default();
+
+ case "signature":
+ return new asn1js.OctetString();
+
+ case "unsignedAttrs":
+ return new _SignedAndUnsignedAttributes.default({
+ type: 1
+ });
+
+ default:
+ throw new Error(`Invalid member name for SignerInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "version":
+ return SignerInfo.defaultValues("version") === memberValue;
+
+ case "sid":
+ return memberValue instanceof asn1js.Any;
+
+ case "digestAlgorithm":
+ if (memberValue instanceof _AlgorithmIdentifier.default === false) return false;
+ return memberValue.isEqual(SignerInfo.defaultValues("digestAlgorithm"));
+
+ case "signedAttrs":
+ return _SignedAndUnsignedAttributes.default.compareWithDefault("type", memberValue.type) && _SignedAndUnsignedAttributes.default.compareWithDefault("attributes", memberValue.attributes) && _SignedAndUnsignedAttributes.default.compareWithDefault("encodedValue", memberValue.encodedValue);
+
+ case "signatureAlgorithm":
+ if (memberValue instanceof _AlgorithmIdentifier.default === false) return false;
+ return memberValue.isEqual(SignerInfo.defaultValues("signatureAlgorithm"));
+
+ case "signature":
+ case "unsignedAttrs":
+ return _SignedAndUnsignedAttributes.default.compareWithDefault("type", memberValue.type) && _SignedAndUnsignedAttributes.default.compareWithDefault("attributes", memberValue.attributes) && _SignedAndUnsignedAttributes.default.compareWithDefault("encodedValue", memberValue.encodedValue);
+
+ default:
+ throw new Error(`Invalid member name for SignerInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * SignerInfo ::= SEQUENCE {
+ * version CMSVersion,
+ * sid SignerIdentifier,
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
+ * signatureAlgorithm SignatureAlgorithmIdentifier,
+ * signature SignatureValue,
+ * unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL }
+ *
+ * SignerIdentifier ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * subjectKeyIdentifier [0] SubjectKeyIdentifier }
+ *
+ * SubjectKeyIdentifier ::= OCTET STRING
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [version]
+ * @property {string} [sid]
+ * @property {string} [digestAlgorithm]
+ * @property {string} [signedAttrs]
+ * @property {string} [signatureAlgorithm]
+ * @property {string} [signature]
+ * @property {string} [unsignedAttrs]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: "SignerInfo",
+ value: [new asn1js.Integer({
+ name: names.version || "SignerInfo.version"
+ }), new asn1js.Choice({
+ value: [_IssuerAndSerialNumber.default.schema(names.sid || {
+ names: {
+ blockName: "SignerInfo.sid"
+ }
+ }), new asn1js.Constructed({
+ optional: true,
+ name: names.sid || "SignerInfo.sid",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.OctetString()]
+ })]
+ }), _AlgorithmIdentifier.default.schema(names.digestAlgorithm || {
+ names: {
+ blockName: "SignerInfo.digestAlgorithm"
+ }
+ }), _SignedAndUnsignedAttributes.default.schema(names.signedAttrs || {
+ names: {
+ blockName: "SignerInfo.signedAttrs",
+ tagNumber: 0
+ }
+ }), _AlgorithmIdentifier.default.schema(names.signatureAlgorithm || {
+ names: {
+ blockName: "SignerInfo.signatureAlgorithm"
+ }
+ }), new asn1js.OctetString({
+ name: names.signature || "SignerInfo.signature"
+ }), _SignedAndUnsignedAttributes.default.schema(names.unsignedAttrs || {
+ names: {
+ blockName: "SignerInfo.unsignedAttrs",
+ tagNumber: 1
+ }
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["SignerInfo.version", "SignerInfo.sid", "SignerInfo.digestAlgorithm", "SignerInfo.signedAttrs", "SignerInfo.signatureAlgorithm", "SignerInfo.signature", "SignerInfo.unsignedAttrs"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, SignerInfo.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for SignerInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.version = asn1.result["SignerInfo.version"].valueBlock.valueDec;
+ const currentSid = asn1.result["SignerInfo.sid"];
+ if (currentSid.idBlock.tagClass === 1) this.sid = new _IssuerAndSerialNumber.default({
+ schema: currentSid
+ });else this.sid = currentSid;
+ this.digestAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result["SignerInfo.digestAlgorithm"]
+ });
+ if ("SignerInfo.signedAttrs" in asn1.result) this.signedAttrs = new _SignedAndUnsignedAttributes.default({
+ type: 0,
+ schema: asn1.result["SignerInfo.signedAttrs"]
+ });
+ this.signatureAlgorithm = new _AlgorithmIdentifier.default({
+ schema: asn1.result["SignerInfo.signatureAlgorithm"]
+ });
+ this.signature = asn1.result["SignerInfo.signature"];
+ if ("SignerInfo.unsignedAttrs" in asn1.result) this.unsignedAttrs = new _SignedAndUnsignedAttributes.default({
+ type: 1,
+ schema: asn1.result["SignerInfo.unsignedAttrs"]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ if (SignerInfo.compareWithDefault("sid", this.sid)) throw new Error("Incorrectly initialized \"SignerInfo\" class"); //region Create array for output sequence
+
+ const outputArray = [];
+ outputArray.push(new asn1js.Integer({
+ value: this.version
+ }));
+ if (this.sid instanceof _IssuerAndSerialNumber.default) outputArray.push(this.sid.toSchema());else outputArray.push(this.sid);
+ outputArray.push(this.digestAlgorithm.toSchema());
+
+ if ("signedAttrs" in this) {
+ if (SignerInfo.compareWithDefault("signedAttrs", this.signedAttrs) === false) outputArray.push(this.signedAttrs.toSchema());
+ }
+
+ outputArray.push(this.signatureAlgorithm.toSchema());
+ outputArray.push(this.signature);
+
+ if ("unsignedAttrs" in this) {
+ if (SignerInfo.compareWithDefault("unsignedAttrs", this.unsignedAttrs) === false) outputArray.push(this.unsignedAttrs.toSchema());
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ if (SignerInfo.compareWithDefault("sid", this.sid)) throw new Error("Incorrectly initialized \"SignerInfo\" class");
+ const _object = {
+ version: this.version
+ };
+ if (!(this.sid instanceof asn1js.Any)) _object.sid = this.sid.toJSON();
+ _object.digestAlgorithm = this.digestAlgorithm.toJSON();
+ if (SignerInfo.compareWithDefault("signedAttrs", this.signedAttrs) === false) _object.signedAttrs = this.signedAttrs.toJSON();
+ _object.signatureAlgorithm = this.signatureAlgorithm.toJSON();
+ _object.signature = this.signature.toJSON();
+ if (SignerInfo.compareWithDefault("unsignedAttrs", this.unsignedAttrs) === false) _object.unsignedAttrs = this.unsignedAttrs.toJSON();
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = SignerInfo;
+
+},{"./AlgorithmIdentifier.js":4,"./IssuerAndSerialNumber.js":44,"./SignedAndUnsignedAttributes.js":99,"asn1js":112,"pvutils":113}],103:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _CertID = _interopRequireDefault(require("./CertID.js"));
+
+var _Extension = _interopRequireDefault(require("./Extension.js"));
+
+var _Extensions = _interopRequireDefault(require("./Extensions.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC6960
+ */
+class SingleResponse {
+ //**********************************************************************************
+
+ /**
+ * Constructor for SingleResponse class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {CertID}
+ * @desc certID
+ */
+ this.certID = (0, _pvutils.getParametersValue)(parameters, "certID", SingleResponse.defaultValues("certID"));
+ /**
+ * @type {Object}
+ * @desc certStatus
+ */
+
+ this.certStatus = (0, _pvutils.getParametersValue)(parameters, "certStatus", SingleResponse.defaultValues("certStatus"));
+ /**
+ * @type {Date}
+ * @desc thisUpdate
+ */
+
+ this.thisUpdate = (0, _pvutils.getParametersValue)(parameters, "thisUpdate", SingleResponse.defaultValues("thisUpdate"));
+ if ("nextUpdate" in parameters)
+ /**
+ * @type {Date}
+ * @desc nextUpdate
+ */
+ this.nextUpdate = (0, _pvutils.getParametersValue)(parameters, "nextUpdate", SingleResponse.defaultValues("nextUpdate"));
+ if ("singleExtensions" in parameters)
+ /**
+ * @type {Array.<Extension>}
+ * @desc singleExtensions
+ */
+ this.singleExtensions = (0, _pvutils.getParametersValue)(parameters, "singleExtensions", SingleResponse.defaultValues("singleExtensions")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "certID":
+ return new _CertID.default();
+
+ case "certStatus":
+ return {};
+
+ case "thisUpdate":
+ case "nextUpdate":
+ return new Date(0, 0, 0);
+
+ case "singleExtensions":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for SingleResponse class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "certID":
+ // noinspection OverlyComplexBooleanExpressionJS
+ return _CertID.default.compareWithDefault("hashAlgorithm", memberValue.hashAlgorithm) && _CertID.default.compareWithDefault("issuerNameHash", memberValue.issuerNameHash) && _CertID.default.compareWithDefault("issuerKeyHash", memberValue.issuerKeyHash) && _CertID.default.compareWithDefault("serialNumber", memberValue.serialNumber);
+
+ case "certStatus":
+ return Object.keys(memberValue).length === 0;
+
+ case "thisUpdate":
+ case "nextUpdate":
+ return memberValue === SingleResponse.defaultValues(memberName);
+
+ default:
+ throw new Error(`Invalid member name for SingleResponse class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * SingleResponse ::= SEQUENCE {
+ * certID CertID,
+ * certStatus CertStatus,
+ * thisUpdate GeneralizedTime,
+ * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
+ * singleExtensions [1] EXPLICIT Extensions OPTIONAL }
+ *
+ * CertStatus ::= CHOICE {
+ * good [0] IMPLICIT NULL,
+ * revoked [1] IMPLICIT RevokedInfo,
+ * unknown [2] IMPLICIT UnknownInfo }
+ *
+ * RevokedInfo ::= SEQUENCE {
+ * revocationTime GeneralizedTime,
+ * revocationReason [0] EXPLICIT CRLReason OPTIONAL }
+ *
+ * UnknownInfo ::= NULL
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [certID]
+ * @property {string} [certStatus]
+ * @property {string} [thisUpdate]
+ * @property {string} [nextUpdate]
+ * @property {string} [singleExtensions]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [_CertID.default.schema(names.certID || {}), new asn1js.Choice({
+ value: [new asn1js.Primitive({
+ name: names.certStatus || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ lenBlockLength: 1 // The length contains one byte 0x00
+
+ }), // IMPLICIT NULL (no "valueBlock")
+ new asn1js.Constructed({
+ name: names.certStatus || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [new asn1js.GeneralizedTime(), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Enumerated()]
+ })]
+ }), new asn1js.Primitive({
+ name: names.certStatus || "",
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ lenBlock: {
+ length: 1
+ }
+ }) // IMPLICIT NULL (no "valueBlock")
+ ]
+ }), new asn1js.GeneralizedTime({
+ name: names.thisUpdate || ""
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.GeneralizedTime({
+ name: names.nextUpdate || ""
+ })]
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [_Extensions.default.schema(names.singleExtensions || {})]
+ }) // EXPLICIT SEQUENCE value
+ ]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["certID", "certStatus", "thisUpdate", "nextUpdate", "singleExtensions"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, SingleResponse.schema({
+ names: {
+ certID: {
+ names: {
+ blockName: "certID"
+ }
+ },
+ certStatus: "certStatus",
+ thisUpdate: "thisUpdate",
+ nextUpdate: "nextUpdate",
+ singleExtensions: {
+ names: {
+ blockName: "singleExtensions"
+ }
+ }
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for SingleResponse"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.certID = new _CertID.default({
+ schema: asn1.result.certID
+ });
+ this.certStatus = asn1.result.certStatus;
+ this.thisUpdate = asn1.result.thisUpdate.toDate();
+ if ("nextUpdate" in asn1.result) this.nextUpdate = asn1.result.nextUpdate.toDate();
+ if ("singleExtensions" in asn1.result) this.singleExtensions = Array.from(asn1.result.singleExtensions.valueBlock.value, element => new _Extension.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create value array for output sequence
+ const outputArray = [];
+ outputArray.push(this.certID.toSchema());
+ outputArray.push(this.certStatus);
+ outputArray.push(new asn1js.GeneralizedTime({
+ valueDate: this.thisUpdate
+ }));
+
+ if ("nextUpdate" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.GeneralizedTime({
+ valueDate: this.nextUpdate
+ })]
+ }));
+ }
+
+ if ("singleExtensions" in this) {
+ outputArray.push(new asn1js.Sequence({
+ value: Array.from(this.singleExtensions, element => element.toSchema())
+ }));
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ certID: this.certID.toJSON(),
+ certStatus: this.certStatus.toJSON(),
+ thisUpdate: this.thisUpdate
+ };
+ if ("nextUpdate" in this) _object.nextUpdate = this.nextUpdate;
+ if ("singleExtensions" in this) _object.singleExtensions = Array.from(this.singleExtensions, element => element.toJSON());
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = SingleResponse;
+
+},{"./CertID.js":18,"./Extension.js":38,"./Extensions.js":39,"asn1js":112,"pvutils":113}],104:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _Attribute = _interopRequireDefault(require("./Attribute.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class SubjectDirectoryAttributes {
+ //**********************************************************************************
+
+ /**
+ * Constructor for SubjectDirectoryAttributes class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {Array.<Attribute>}
+ * @desc attributes
+ */
+ this.attributes = (0, _pvutils.getParametersValue)(parameters, "attributes", SubjectDirectoryAttributes.defaultValues("attributes")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "attributes":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for SubjectDirectoryAttributes class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * SubjectDirectoryAttributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [utcTimeName] Name for "utcTimeName" choice
+ * @property {string} [generalTimeName] Name for "generalTimeName" choice
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "",
+ value: [new asn1js.Repeated({
+ name: names.attributes || "",
+ value: _Attribute.default.schema()
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["attributes"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, SubjectDirectoryAttributes.schema({
+ names: {
+ attributes: "attributes"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for SubjectDirectoryAttributes"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.attributes = Array.from(asn1.result.attributes, element => new _Attribute.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ return new asn1js.Sequence({
+ value: Array.from(this.attributes, element => element.toSchema())
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ attributes: Array.from(this.attributes, element => element.toJSON())
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = SubjectDirectoryAttributes;
+
+},{"./Attribute.js":6,"asn1js":112,"pvutils":113}],105:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _GeneralName = _interopRequireDefault(require("./GeneralName.js"));
+
+var _Request = _interopRequireDefault(require("./Request.js"));
+
+var _Extension = _interopRequireDefault(require("./Extension.js"));
+
+var _Extensions = _interopRequireDefault(require("./Extensions.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC6960
+ */
+class TBSRequest {
+ //**********************************************************************************
+
+ /**
+ * Constructor for TBSRequest class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {ArrayBuffer}
+ * @desc tbs
+ */
+ this.tbs = (0, _pvutils.getParametersValue)(parameters, "tbs", TBSRequest.defaultValues("tbs"));
+ if ("version" in parameters)
+ /**
+ * @type {number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", TBSRequest.defaultValues("version"));
+ if ("requestorName" in parameters)
+ /**
+ * @type {GeneralName}
+ * @desc requestorName
+ */
+ this.requestorName = (0, _pvutils.getParametersValue)(parameters, "requestorName", TBSRequest.defaultValues("requestorName"));
+ /**
+ * @type {Array.<Request>}
+ * @desc requestList
+ */
+
+ this.requestList = (0, _pvutils.getParametersValue)(parameters, "requestList", TBSRequest.defaultValues("requestList"));
+ if ("requestExtensions" in parameters)
+ /**
+ * @type {Array.<Extension>}
+ * @desc requestExtensions
+ */
+ this.requestExtensions = (0, _pvutils.getParametersValue)(parameters, "requestExtensions", TBSRequest.defaultValues("requestExtensions")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "tbs":
+ return new ArrayBuffer(0);
+
+ case "version":
+ return 0;
+
+ case "requestorName":
+ return new _GeneralName.default();
+
+ case "requestList":
+ case "requestExtensions":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for TBSRequest class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "tbs":
+ return memberValue.byteLength === 0;
+
+ case "version":
+ return memberValue === TBSRequest.defaultValues(memberName);
+
+ case "requestorName":
+ return memberValue.type === _GeneralName.default.defaultValues("type") && Object.keys(memberValue.value).length === 0;
+
+ case "requestList":
+ case "requestExtensions":
+ return memberValue.length === 0;
+
+ default:
+ throw new Error(`Invalid member name for TBSRequest class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * TBSRequest ::= SEQUENCE {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * requestorName [1] EXPLICIT GeneralName OPTIONAL,
+ * requestList SEQUENCE OF Request,
+ * requestExtensions [2] EXPLICIT Extensions OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [TBSRequestVersion]
+ * @property {string} [requestorName]
+ * @property {string} [requestList]
+ * @property {string} [requests]
+ * @property {string} [requestNames]
+ * @property {string} [extensions]
+ * @property {string} [requestExtensions]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "TBSRequest",
+ value: [new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Integer({
+ name: names.TBSRequestVersion || "TBSRequest.version"
+ })]
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [_GeneralName.default.schema(names.requestorName || {
+ names: {
+ blockName: "TBSRequest.requestorName"
+ }
+ })]
+ }), new asn1js.Sequence({
+ name: names.requestList || "TBSRequest.requestList",
+ value: [new asn1js.Repeated({
+ name: names.requests || "TBSRequest.requests",
+ value: _Request.default.schema(names.requestNames || {})
+ })]
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ value: [_Extensions.default.schema(names.extensions || {
+ names: {
+ blockName: names.requestExtensions || "TBSRequest.requestExtensions"
+ }
+ })]
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["TBSRequest", "TBSRequest.version", "TBSRequest.requestorName", "TBSRequest.requests", "TBSRequest.requestExtensions"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, TBSRequest.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for TBSRequest"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.tbs = asn1.result.TBSRequest.valueBeforeDecode;
+ if ("TBSRequest.version" in asn1.result) this.version = asn1.result["TBSRequest.version"].valueBlock.valueDec;
+ if ("TBSRequest.requestorName" in asn1.result) this.requestorName = new _GeneralName.default({
+ schema: asn1.result["TBSRequest.requestorName"]
+ });
+ this.requestList = Array.from(asn1.result["TBSRequest.requests"], element => new _Request.default({
+ schema: element
+ }));
+ if ("TBSRequest.requestExtensions" in asn1.result) this.requestExtensions = Array.from(asn1.result["TBSRequest.requestExtensions"].valueBlock.value, element => new _Extension.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @param {boolean} encodeFlag If param equal to false then create TBS schema via decoding stored value. In othe case create TBS schema via assembling from TBS parts.
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema(encodeFlag = false) {
+ //region Decode stored TBS value
+ let tbsSchema;
+
+ if (encodeFlag === false) {
+ if (this.tbs.byteLength === 0) // No stored TBS part
+ return TBSRequest.schema();
+ tbsSchema = asn1js.fromBER(this.tbs).result;
+ } //endregion
+ //region Create TBS schema via assembling from TBS parts
+ else {
+ const outputArray = [];
+
+ if ("version" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Integer({
+ value: this.version
+ })]
+ }));
+ }
+
+ if ("requestorName" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [this.requestorName.toSchema()]
+ }));
+ }
+
+ outputArray.push(new asn1js.Sequence({
+ value: Array.from(this.requestList, element => element.toSchema())
+ }));
+
+ if ("requestExtensions" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 2 // [2]
+
+ },
+ value: [new asn1js.Sequence({
+ value: Array.from(this.requestExtensions, element => element.toSchema())
+ })]
+ }));
+ }
+
+ tbsSchema = new asn1js.Sequence({
+ value: outputArray
+ });
+ } //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return tbsSchema; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {};
+ if ("version" in this) _object.version = this.version;
+ if ("requestorName" in this) _object.requestorName = this.requestorName.toJSON();
+ _object.requestList = Array.from(this.requestList, element => element.toJSON());
+ if ("requestExtensions" in this) _object.requestExtensions = Array.from(this.requestExtensions, element => element.toJSON());
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = TBSRequest;
+
+},{"./Extension.js":38,"./Extensions.js":39,"./GeneralName.js":40,"./Request.js":90,"asn1js":112,"pvutils":113}],106:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _common = require("./common.js");
+
+var _MessageImprint = _interopRequireDefault(require("./MessageImprint.js"));
+
+var _Accuracy = _interopRequireDefault(require("./Accuracy.js"));
+
+var _GeneralName = _interopRequireDefault(require("./GeneralName.js"));
+
+var _Extension = _interopRequireDefault(require("./Extension.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC3161
+ */
+class TSTInfo {
+ //**********************************************************************************
+
+ /**
+ * Constructor for TSTInfo class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", TSTInfo.defaultValues("version"));
+ /**
+ * @type {string}
+ * @desc policy
+ */
+
+ this.policy = (0, _pvutils.getParametersValue)(parameters, "policy", TSTInfo.defaultValues("policy"));
+ /**
+ * @type {MessageImprint}
+ * @desc messageImprint
+ */
+
+ this.messageImprint = (0, _pvutils.getParametersValue)(parameters, "messageImprint", TSTInfo.defaultValues("messageImprint"));
+ /**
+ * @type {Integer}
+ * @desc serialNumber
+ */
+
+ this.serialNumber = (0, _pvutils.getParametersValue)(parameters, "serialNumber", TSTInfo.defaultValues("serialNumber"));
+ /**
+ * @type {Date}
+ * @desc genTime
+ */
+
+ this.genTime = (0, _pvutils.getParametersValue)(parameters, "genTime", TSTInfo.defaultValues("genTime"));
+ if ("accuracy" in parameters)
+ /**
+ * @type {Accuracy}
+ * @desc accuracy
+ */
+ this.accuracy = (0, _pvutils.getParametersValue)(parameters, "accuracy", TSTInfo.defaultValues("accuracy"));
+ if ("ordering" in parameters)
+ /**
+ * @type {boolean}
+ * @desc ordering
+ */
+ this.ordering = (0, _pvutils.getParametersValue)(parameters, "ordering", TSTInfo.defaultValues("ordering"));
+ if ("nonce" in parameters)
+ /**
+ * @type {Integer}
+ * @desc nonce
+ */
+ this.nonce = (0, _pvutils.getParametersValue)(parameters, "nonce", TSTInfo.defaultValues("nonce"));
+ if ("tsa" in parameters)
+ /**
+ * @type {GeneralName}
+ * @desc tsa
+ */
+ this.tsa = (0, _pvutils.getParametersValue)(parameters, "tsa", TSTInfo.defaultValues("tsa"));
+ if ("extensions" in parameters)
+ /**
+ * @type {Array.<Extension>}
+ * @desc extensions
+ */
+ this.extensions = (0, _pvutils.getParametersValue)(parameters, "extensions", TSTInfo.defaultValues("extensions")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return 0;
+
+ case "policy":
+ return "";
+
+ case "messageImprint":
+ return new _MessageImprint.default();
+
+ case "serialNumber":
+ return new asn1js.Integer();
+
+ case "genTime":
+ return new Date(0, 0, 0);
+
+ case "accuracy":
+ return new _Accuracy.default();
+
+ case "ordering":
+ return false;
+
+ case "nonce":
+ return new asn1js.Integer();
+
+ case "tsa":
+ return new _GeneralName.default();
+
+ case "extensions":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for TSTInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "version":
+ case "policy":
+ case "genTime":
+ case "ordering":
+ return memberValue === TSTInfo.defaultValues(memberName);
+
+ case "messageImprint":
+ return _MessageImprint.default.compareWithDefault("hashAlgorithm", memberValue.hashAlgorithm) && _MessageImprint.default.compareWithDefault("hashedMessage", memberValue.hashedMessage);
+
+ case "serialNumber":
+ case "nonce":
+ return memberValue.isEqual(TSTInfo.defaultValues(memberName));
+
+ case "accuracy":
+ return _Accuracy.default.compareWithDefault("seconds", memberValue.seconds) && _Accuracy.default.compareWithDefault("millis", memberValue.millis) && _Accuracy.default.compareWithDefault("micros", memberValue.micros);
+
+ case "tsa":
+ return _GeneralName.default.compareWithDefault("type", memberValue.type) && _GeneralName.default.compareWithDefault("value", memberValue.value);
+
+ case "extensions":
+ return memberValue.length === 0;
+
+ default:
+ throw new Error(`Invalid member name for TSTInfo class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * TSTInfo ::= SEQUENCE {
+ * version INTEGER { v1(1) },
+ * policy TSAPolicyId,
+ * messageImprint MessageImprint,
+ * serialNumber INTEGER,
+ * genTime GeneralizedTime,
+ * accuracy Accuracy OPTIONAL,
+ * ordering BOOLEAN DEFAULT FALSE,
+ * nonce INTEGER OPTIONAL,
+ * tsa [0] GeneralName OPTIONAL,
+ * extensions [1] IMPLICIT Extensions OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [version]
+ * @property {string} [policy]
+ * @property {string} [messageImprint]
+ * @property {string} [serialNumber]
+ * @property {string} [genTime]
+ * @property {string} [accuracy]
+ * @property {string} [ordering]
+ * @property {string} [nonce]
+ * @property {string} [tsa]
+ * @property {string} [extensions]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "TSTInfo",
+ value: [new asn1js.Integer({
+ name: names.version || "TSTInfo.version"
+ }), new asn1js.ObjectIdentifier({
+ name: names.policy || "TSTInfo.policy"
+ }), _MessageImprint.default.schema(names.messageImprint || {
+ names: {
+ blockName: "TSTInfo.messageImprint"
+ }
+ }), new asn1js.Integer({
+ name: names.serialNumber || "TSTInfo.serialNumber"
+ }), new asn1js.GeneralizedTime({
+ name: names.genTime || "TSTInfo.genTime"
+ }), _Accuracy.default.schema(names.accuracy || {
+ names: {
+ blockName: "TSTInfo.accuracy"
+ }
+ }), new asn1js.Boolean({
+ name: names.ordering || "TSTInfo.ordering",
+ optional: true
+ }), new asn1js.Integer({
+ name: names.nonce || "TSTInfo.nonce",
+ optional: true
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [_GeneralName.default.schema(names.tsa || {
+ names: {
+ blockName: "TSTInfo.tsa"
+ }
+ })]
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: [new asn1js.Repeated({
+ name: names.extensions || "TSTInfo.extensions",
+ value: _Extension.default.schema(names.extension || {})
+ })]
+ }) // IMPLICIT Extensions
+ ]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["TSTInfo.version", "TSTInfo.policy", "TSTInfo.messageImprint", "TSTInfo.serialNumber", "TSTInfo.genTime", "TSTInfo.accuracy", "TSTInfo.ordering", "TSTInfo.nonce", "TSTInfo.tsa", "TSTInfo.extensions"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, TSTInfo.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for TSTInfo"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.version = asn1.result["TSTInfo.version"].valueBlock.valueDec;
+ this.policy = asn1.result["TSTInfo.policy"].valueBlock.toString();
+ this.messageImprint = new _MessageImprint.default({
+ schema: asn1.result["TSTInfo.messageImprint"]
+ });
+ this.serialNumber = asn1.result["TSTInfo.serialNumber"];
+ this.genTime = asn1.result["TSTInfo.genTime"].toDate();
+ if ("TSTInfo.accuracy" in asn1.result) this.accuracy = new _Accuracy.default({
+ schema: asn1.result["TSTInfo.accuracy"]
+ });
+ if ("TSTInfo.ordering" in asn1.result) this.ordering = asn1.result["TSTInfo.ordering"].valueBlock.value;
+ if ("TSTInfo.nonce" in asn1.result) this.nonce = asn1.result["TSTInfo.nonce"];
+ if ("TSTInfo.tsa" in asn1.result) this.tsa = new _GeneralName.default({
+ schema: asn1.result["TSTInfo.tsa"]
+ });
+ if ("TSTInfo.extensions" in asn1.result) this.extensions = Array.from(asn1.result["TSTInfo.extensions"], element => new _Extension.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(new asn1js.Integer({
+ value: this.version
+ }));
+ outputArray.push(new asn1js.ObjectIdentifier({
+ value: this.policy
+ }));
+ outputArray.push(this.messageImprint.toSchema());
+ outputArray.push(this.serialNumber);
+ outputArray.push(new asn1js.GeneralizedTime({
+ valueDate: this.genTime
+ }));
+ if ("accuracy" in this) outputArray.push(this.accuracy.toSchema());
+ if ("ordering" in this) outputArray.push(new asn1js.Boolean({
+ value: this.ordering
+ }));
+ if ("nonce" in this) outputArray.push(this.nonce);
+
+ if ("tsa" in this) {
+ outputArray.push(new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [this.tsa.toSchema()]
+ }));
+ } //region Create array of extensions
+
+
+ if ("extensions" in this) {
+ outputArray.push(new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 1 // [1]
+
+ },
+ value: Array.from(this.extensions, element => element.toSchema())
+ }));
+ } //endregion
+ //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ version: this.version,
+ policy: this.policy,
+ messageImprint: this.messageImprint.toJSON(),
+ serialNumber: this.serialNumber.toJSON(),
+ genTime: this.genTime
+ };
+ if ("accuracy" in this) _object.accuracy = this.accuracy.toJSON();
+ if ("ordering" in this) _object.ordering = this.ordering;
+ if ("nonce" in this) _object.nonce = this.nonce.toJSON();
+ if ("tsa" in this) _object.tsa = this.tsa.toJSON();
+ if ("extensions" in this) _object.extensions = Array.from(this.extensions, element => element.toJSON());
+ return _object;
+ } //**********************************************************************************
+
+ /**
+ * Verify current TST Info value
+ * @param {{data: ArrayBuffer, notBefore: Date, notAfter: Date}} parameters Input parameters
+ * @returns {Promise}
+ */
+
+
+ verify(parameters = {}) {
+ //region Initial variables
+ let sequence = Promise.resolve();
+ let data;
+ let notBefore = null;
+ let notAfter = null; //endregion
+ //region Get a "crypto" extension
+
+ const crypto = (0, _common.getCrypto)();
+ if (typeof crypto === "undefined") return Promise.reject("Unable to create WebCrypto object"); //endregion
+ //region Get initial parameters
+
+ if ("data" in parameters) data = parameters.data;else return Promise.reject("\"data\" is a mandatory attribute for TST_INFO verification");
+ if ("notBefore" in parameters) notBefore = parameters.notBefore;
+ if ("notAfter" in parameters) notAfter = parameters.notAfter; //endregion
+ //region Check date
+
+ if (notBefore !== null) {
+ if (this.genTime < notBefore) return Promise.reject("Generation time for TSTInfo object is less than notBefore value");
+ }
+
+ if (notAfter !== null) {
+ if (this.genTime > notAfter) return Promise.reject("Generation time for TSTInfo object is more than notAfter value");
+ } //endregion
+ //region Find hashing algorithm
+
+
+ const shaAlgorithm = (0, _common.getAlgorithmByOID)(this.messageImprint.hashAlgorithm.algorithmId);
+ if ("name" in shaAlgorithm === false) return Promise.reject(`Unsupported signature algorithm: ${this.messageImprint.hashAlgorithm.algorithmId}`); //endregion
+ //region Calculate message digest for input "data" buffer
+ // noinspection JSCheckFunctionSignatures
+
+ sequence = sequence.then(() => crypto.digest(shaAlgorithm.name, new Uint8Array(data))).then(result => (0, _pvutils.isEqualBuffer)(result, this.messageImprint.hashedMessage.valueBlock.valueHex)); //endregion
+
+ return sequence;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = TSTInfo;
+
+},{"./Accuracy.js":3,"./Extension.js":38,"./GeneralName.js":40,"./MessageImprint.js":53,"./common.js":110,"asn1js":112,"pvutils":113}],107:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC5280
+ */
+class Time {
+ //**********************************************************************************
+
+ /**
+ * Constructor for Time class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ * @property {number} [type] 0 - UTCTime; 1 - GeneralizedTime; 2 - empty value
+ * @property {Date} [value] Value of the TIME class
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc 0 - UTCTime; 1 - GeneralizedTime; 2 - empty value
+ */
+ this.type = (0, _pvutils.getParametersValue)(parameters, "type", Time.defaultValues("type"));
+ /**
+ * @type {Date}
+ * @desc Value of the TIME class
+ */
+
+ this.value = (0, _pvutils.getParametersValue)(parameters, "value", Time.defaultValues("value")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "type":
+ return 0;
+
+ case "value":
+ return new Date(0, 0, 0);
+
+ default:
+ throw new Error(`Invalid member name for Time class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @param {boolean} optional Flag that current schema should be optional
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}, optional = false) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [utcTimeName] Name for "utcTimeName" choice
+ * @property {string} [generalTimeName] Name for "generalTimeName" choice
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Choice({
+ optional,
+ value: [new asn1js.UTCTime({
+ name: names.utcTimeName || ""
+ }), new asn1js.GeneralizedTime({
+ name: names.generalTimeName || ""
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["utcTimeName", "generalTimeName"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, Time.schema({
+ names: {
+ utcTimeName: "utcTimeName",
+ generalTimeName: "generalTimeName"
+ }
+ }));
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for Time"); //endregion
+ //region Get internal properties from parsed schema
+
+ if ("utcTimeName" in asn1.result) {
+ this.type = 0;
+ this.value = asn1.result.utcTimeName.toDate();
+ }
+
+ if ("generalTimeName" in asn1.result) {
+ this.type = 1;
+ this.value = asn1.result.generalTimeName.toDate();
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Construct and return new ASN.1 schema for this object
+ let result = {};
+ if (this.type === 0) result = new asn1js.UTCTime({
+ valueDate: this.value
+ });
+ if (this.type === 1) result = new asn1js.GeneralizedTime({
+ valueDate: this.value
+ });
+ return result; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ return {
+ type: this.type,
+ value: this.value
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = Time;
+
+},{"asn1js":112,"pvutils":113}],108:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _MessageImprint = _interopRequireDefault(require("./MessageImprint.js"));
+
+var _Extension = _interopRequireDefault(require("./Extension.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC3161
+ */
+class TimeStampReq {
+ //**********************************************************************************
+
+ /**
+ * Constructor for TimeStampReq class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {number}
+ * @desc version
+ */
+ this.version = (0, _pvutils.getParametersValue)(parameters, "version", TimeStampReq.defaultValues("version"));
+ /**
+ * @type {MessageImprint}
+ * @desc messageImprint
+ */
+
+ this.messageImprint = (0, _pvutils.getParametersValue)(parameters, "messageImprint", TimeStampReq.defaultValues("messageImprint"));
+ if ("reqPolicy" in parameters)
+ /**
+ * @type {string}
+ * @desc reqPolicy
+ */
+ this.reqPolicy = (0, _pvutils.getParametersValue)(parameters, "reqPolicy", TimeStampReq.defaultValues("reqPolicy"));
+ if ("nonce" in parameters)
+ /**
+ * @type {Integer}
+ * @desc nonce
+ */
+ this.nonce = (0, _pvutils.getParametersValue)(parameters, "nonce", TimeStampReq.defaultValues("nonce"));
+ if ("certReq" in parameters)
+ /**
+ * @type {boolean}
+ * @desc certReq
+ */
+ this.certReq = (0, _pvutils.getParametersValue)(parameters, "certReq", TimeStampReq.defaultValues("certReq"));
+ if ("extensions" in parameters)
+ /**
+ * @type {Array.<Extension>}
+ * @desc extensions
+ */
+ this.extensions = (0, _pvutils.getParametersValue)(parameters, "extensions", TimeStampReq.defaultValues("extensions")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "version":
+ return 0;
+
+ case "messageImprint":
+ return new _MessageImprint.default();
+
+ case "reqPolicy":
+ return "";
+
+ case "nonce":
+ return new asn1js.Integer();
+
+ case "certReq":
+ return false;
+
+ case "extensions":
+ return [];
+
+ default:
+ throw new Error(`Invalid member name for TimeStampReq class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "version":
+ case "reqPolicy":
+ case "certReq":
+ return memberValue === TimeStampReq.defaultValues(memberName);
+
+ case "messageImprint":
+ return _MessageImprint.default.compareWithDefault("hashAlgorithm", memberValue.hashAlgorithm) && _MessageImprint.default.compareWithDefault("hashedMessage", memberValue.hashedMessage);
+
+ case "nonce":
+ return memberValue.isEqual(TimeStampReq.defaultValues(memberName));
+
+ case "extensions":
+ return memberValue.length === 0;
+
+ default:
+ throw new Error(`Invalid member name for TimeStampReq class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * TimeStampReq ::= SEQUENCE {
+ * version INTEGER { v1(1) },
+ * messageImprint MessageImprint,
+ * reqPolicy TSAPolicyId OPTIONAL,
+ * nonce INTEGER OPTIONAL,
+ * certReq BOOLEAN DEFAULT FALSE,
+ * extensions [0] IMPLICIT Extensions OPTIONAL }
+ *
+ * TSAPolicyId ::= OBJECT IDENTIFIER
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [type]
+ * @property {string} [setName]
+ * @property {string} [values]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "TimeStampReq",
+ value: [new asn1js.Integer({
+ name: names.version || "TimeStampReq.version"
+ }), _MessageImprint.default.schema(names.messageImprint || {
+ names: {
+ blockName: "TimeStampReq.messageImprint"
+ }
+ }), new asn1js.ObjectIdentifier({
+ name: names.reqPolicy || "TimeStampReq.reqPolicy",
+ optional: true
+ }), new asn1js.Integer({
+ name: names.nonce || "TimeStampReq.nonce",
+ optional: true
+ }), new asn1js.Boolean({
+ name: names.certReq || "TimeStampReq.certReq",
+ optional: true
+ }), new asn1js.Constructed({
+ optional: true,
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: [new asn1js.Repeated({
+ name: names.extensions || "TimeStampReq.extensions",
+ value: _Extension.default.schema()
+ })]
+ }) // IMPLICIT SEQUENCE value
+ ]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["TimeStampReq.version", "TimeStampReq.messageImprint", "TimeStampReq.reqPolicy", "TimeStampReq.nonce", "TimeStampReq.certReq", "TimeStampReq.extensions"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, TimeStampReq.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for TimeStampReq"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.version = asn1.result["TimeStampReq.version"].valueBlock.valueDec;
+ this.messageImprint = new _MessageImprint.default({
+ schema: asn1.result["TimeStampReq.messageImprint"]
+ });
+ if ("TimeStampReq.reqPolicy" in asn1.result) this.reqPolicy = asn1.result["TimeStampReq.reqPolicy"].valueBlock.toString();
+ if ("TimeStampReq.nonce" in asn1.result) this.nonce = asn1.result["TimeStampReq.nonce"];
+ if ("TimeStampReq.certReq" in asn1.result) this.certReq = asn1.result["TimeStampReq.certReq"].valueBlock.value;
+ if ("TimeStampReq.extensions" in asn1.result) this.extensions = Array.from(asn1.result["TimeStampReq.extensions"], element => new _Extension.default({
+ schema: element
+ })); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(new asn1js.Integer({
+ value: this.version
+ }));
+ outputArray.push(this.messageImprint.toSchema());
+ if ("reqPolicy" in this) outputArray.push(new asn1js.ObjectIdentifier({
+ value: this.reqPolicy
+ }));
+ if ("nonce" in this) outputArray.push(this.nonce);
+ if ("certReq" in this && TimeStampReq.compareWithDefault("certReq", this.certReq) === false) outputArray.push(new asn1js.Boolean({
+ value: this.certReq
+ })); //region Create array of extensions
+
+ if ("extensions" in this) {
+ outputArray.push(new asn1js.Constructed({
+ idBlock: {
+ tagClass: 3,
+ // CONTEXT-SPECIFIC
+ tagNumber: 0 // [0]
+
+ },
+ value: Array.from(this.extensions, element => element.toSchema())
+ }));
+ } //endregion
+ //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ version: this.version,
+ messageImprint: this.messageImprint.toJSON()
+ };
+ if ("reqPolicy" in this) _object.reqPolicy = this.reqPolicy;
+ if ("nonce" in this) _object.nonce = this.nonce.toJSON();
+ if ("certReq" in this && TimeStampReq.compareWithDefault("certReq", this.certReq) === false) _object.certReq = this.certReq;
+ if ("extensions" in this) _object.extensions = Array.from(this.extensions, element => element.toJSON());
+ return _object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = TimeStampReq;
+
+},{"./Extension.js":38,"./MessageImprint.js":53,"asn1js":112,"pvutils":113}],109:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _PKIStatusInfo = _interopRequireDefault(require("./PKIStatusInfo.js"));
+
+var _ContentInfo = _interopRequireDefault(require("./ContentInfo.js"));
+
+var _SignedData = _interopRequireDefault(require("./SignedData.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+
+/**
+ * Class from RFC3161
+ */
+class TimeStampResp {
+ //**********************************************************************************
+
+ /**
+ * Constructor for TimeStampResp class
+ * @param {Object} [parameters={}]
+ * @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
+ */
+ constructor(parameters = {}) {
+ //region Internal properties of the object
+
+ /**
+ * @type {PKIStatusInfo}
+ * @desc status
+ */
+ this.status = (0, _pvutils.getParametersValue)(parameters, "status", TimeStampResp.defaultValues("status"));
+ if ("timeStampToken" in parameters)
+ /**
+ * @type {ContentInfo}
+ * @desc timeStampToken
+ */
+ this.timeStampToken = (0, _pvutils.getParametersValue)(parameters, "timeStampToken", TimeStampResp.defaultValues("timeStampToken")); //endregion
+ //region If input argument array contains "schema" for this object
+
+ if ("schema" in parameters) this.fromSchema(parameters.schema); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Return default values for all class members
+ * @param {string} memberName String name for a class member
+ */
+
+
+ static defaultValues(memberName) {
+ switch (memberName) {
+ case "status":
+ return new _PKIStatusInfo.default();
+
+ case "timeStampToken":
+ return new _ContentInfo.default();
+
+ default:
+ throw new Error(`Invalid member name for TimeStampResp class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Compare values with default values for all class members
+ * @param {string} memberName String name for a class member
+ * @param {*} memberValue Value to compare with default value
+ */
+
+
+ static compareWithDefault(memberName, memberValue) {
+ switch (memberName) {
+ case "status":
+ return _PKIStatusInfo.default.compareWithDefault("status", memberValue.status) && "statusStrings" in memberValue === false && "failInfo" in memberValue === false;
+
+ case "timeStampToken":
+ return memberValue.contentType === "" && memberValue.content instanceof asn1js.Any;
+
+ default:
+ throw new Error(`Invalid member name for TimeStampResp class: ${memberName}`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Return value of pre-defined ASN.1 schema for current class
+ *
+ * ASN.1 schema:
+ * ```asn1
+ * TimeStampResp ::= SEQUENCE {
+ * status PKIStatusInfo,
+ * timeStampToken TimeStampToken OPTIONAL }
+ * ```
+ *
+ * @param {Object} parameters Input parameters for the schema
+ * @returns {Object} asn1js schema object
+ */
+
+
+ static schema(parameters = {}) {
+ /**
+ * @type {Object}
+ * @property {string} [blockName]
+ * @property {string} [status]
+ * @property {string} [timeStampToken]
+ */
+ const names = (0, _pvutils.getParametersValue)(parameters, "names", {});
+ return new asn1js.Sequence({
+ name: names.blockName || "TimeStampResp",
+ value: [_PKIStatusInfo.default.schema(names.status || {
+ names: {
+ blockName: "TimeStampResp.status"
+ }
+ }), _ContentInfo.default.schema(names.timeStampToken || {
+ names: {
+ blockName: "TimeStampResp.timeStampToken",
+ optional: true
+ }
+ })]
+ });
+ } //**********************************************************************************
+
+ /**
+ * Convert parsed asn1js object into current class
+ * @param {!Object} schema
+ */
+
+
+ fromSchema(schema) {
+ //region Clear input data first
+ (0, _pvutils.clearProps)(schema, ["TimeStampResp.status", "TimeStampResp.timeStampToken"]); //endregion
+ //region Check the schema is valid
+
+ const asn1 = asn1js.compareSchema(schema, schema, TimeStampResp.schema());
+ if (asn1.verified === false) throw new Error("Object's schema was not verified against input data for TimeStampResp"); //endregion
+ //region Get internal properties from parsed schema
+
+ this.status = new _PKIStatusInfo.default({
+ schema: asn1.result["TimeStampResp.status"]
+ });
+ if ("TimeStampResp.timeStampToken" in asn1.result) this.timeStampToken = new _ContentInfo.default({
+ schema: asn1.result["TimeStampResp.timeStampToken"]
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convert current object to asn1js object and set correct values
+ * @returns {Object} asn1js object
+ */
+
+
+ toSchema() {
+ //region Create array for output sequence
+ const outputArray = [];
+ outputArray.push(this.status.toSchema());
+ if ("timeStampToken" in this) outputArray.push(this.timeStampToken.toSchema()); //endregion
+ //region Construct and return new ASN.1 schema for this object
+
+ return new asn1js.Sequence({
+ value: outputArray
+ }); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the class to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ const _object = {
+ status: this.status
+ };
+ if ("timeStampToken" in this) _object.timeStampToken = this.timeStampToken.toJSON();
+ return _object;
+ } //**********************************************************************************
+
+ /**
+ * Sign current TSP Response
+ * @param {Object} privateKey Private key for "subjectPublicKeyInfo" structure
+ * @param {string} [hashAlgorithm] Hashing algorithm. Default SHA-1
+ * @returns {Promise}
+ */
+
+
+ sign(privateKey, hashAlgorithm) {
+ //region Check that "timeStampToken" exists
+ if ("timeStampToken" in this === false) return Promise.reject("timeStampToken is absent in TSP response"); //endregion
+ //region Check that "timeStampToken" has a right internal format
+
+ if (this.timeStampToken.contentType !== "1.2.840.113549.1.7.2") // Must be a CMS signed data
+ return Promise.reject(`Wrong format of timeStampToken: ${this.timeStampToken.contentType}`); //endregion
+ //region Sign internal signed data value
+
+ const signed = new _ContentInfo.default({
+ schema: this.timeStampToken.content
+ });
+ return signed.sign(privateKey, 0, hashAlgorithm); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Verify current TSP Response
+ * @param {Object} verificationParameters Input parameters for verification
+ * @returns {Promise}
+ */
+
+
+ verify(verificationParameters = {
+ signer: 0,
+ trustedCerts: [],
+ data: new ArrayBuffer(0)
+ }) {
+ //region Check that "timeStampToken" exists
+ if ("timeStampToken" in this === false) return Promise.reject("timeStampToken is absent in TSP response"); //endregion
+ //region Check that "timeStampToken" has a right internal format
+
+ if (this.timeStampToken.contentType !== "1.2.840.113549.1.7.2") // Must be a CMS signed data
+ return Promise.reject(`Wrong format of timeStampToken: ${this.timeStampToken.contentType}`); //endregion
+ //region Verify internal signed data value
+
+ const signed = new _SignedData.default({
+ schema: this.timeStampToken.content
+ });
+ return signed.verify(verificationParameters); //endregion
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.default = TimeStampResp;
+
+},{"./ContentInfo.js":26,"./PKIStatusInfo.js":69,"./SignedData.js":101,"asn1js":112,"pvutils":113}],110:[function(require,module,exports){
+(function (process,global){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.setEngine = setEngine;
+exports.getEngine = getEngine;
+exports.getCrypto = getCrypto;
+exports.getRandomValues = getRandomValues;
+exports.getOIDByAlgorithm = getOIDByAlgorithm;
+exports.getAlgorithmParameters = getAlgorithmParameters;
+exports.createCMSECDSASignature = createCMSECDSASignature;
+exports.stringPrep = stringPrep;
+exports.createECDSASignatureFromCMS = createECDSASignatureFromCMS;
+exports.getAlgorithmByOID = getAlgorithmByOID;
+exports.getHashAlgorithm = getHashAlgorithm;
+exports.kdfWithCounter = kdfWithCounter;
+exports.kdf = kdf;
+
+var asn1js = _interopRequireWildcard(require("asn1js"));
+
+var _pvutils = require("pvutils");
+
+var _CryptoEngine = _interopRequireDefault(require("./CryptoEngine.js"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+//**************************************************************************************
+//region Crypto engine related function
+//**************************************************************************************
+let engine = {
+ name: "none",
+ crypto: null,
+ subtle: null
+}; //**************************************************************************************
+
+function setEngine(name, crypto, subtle) {
+ //region We are in Node
+ // noinspection JSUnresolvedVariable
+ if (typeof process !== "undefined" && "pid" in process && typeof global !== "undefined" && typeof window === "undefined") {
+ // noinspection ES6ModulesDependencies, JSUnresolvedVariable
+ if (typeof global[process.pid] === "undefined") {
+ // noinspection JSUnresolvedVariable
+ global[process.pid] = {};
+ } else {
+ // noinspection JSUnresolvedVariable
+ if (typeof global[process.pid] !== "object") {
+ // noinspection JSUnresolvedVariable
+ throw new Error(`Name global.${process.pid} already exists and it is not an object`);
+ }
+ } // noinspection JSUnresolvedVariable
+
+
+ if (typeof global[process.pid].pkijs === "undefined") {
+ // noinspection JSUnresolvedVariable
+ global[process.pid].pkijs = {};
+ } else {
+ // noinspection JSUnresolvedVariable
+ if (typeof global[process.pid].pkijs !== "object") {
+ // noinspection JSUnresolvedVariable
+ throw new Error(`Name global.${process.pid}.pkijs already exists and it is not an object`);
+ }
+ } // noinspection JSUnresolvedVariable
+
+
+ global[process.pid].pkijs.engine = {
+ name: name,
+ crypto: crypto,
+ subtle: subtle
+ };
+ } //endregion
+ //region We are in browser
+ else {
+ engine = {
+ name: name,
+ crypto: crypto,
+ subtle: subtle
+ };
+ } //endregion
+
+} //**************************************************************************************
+
+
+function getEngine() {
+ //region We are in Node
+ // noinspection JSUnresolvedVariable
+ if (typeof process !== "undefined" && "pid" in process && typeof global !== "undefined" && typeof window === "undefined") {
+ let _engine;
+
+ try {
+ // noinspection JSUnresolvedVariable
+ _engine = global[process.pid].pkijs.engine;
+ } catch (ex) {
+ throw new Error("Please call \"setEngine\" before call to \"getEngine\"");
+ }
+
+ return _engine;
+ } //endregion
+
+
+ return engine;
+} //**************************************************************************************
+
+
+(function initCryptoEngine() {
+ if (typeof self !== "undefined") {
+ if ("crypto" in self) {
+ let engineName = "webcrypto";
+ /**
+ * Standard crypto object
+ * @type {Object}
+ * @property {Object} [webkitSubtle] Subtle object from Apple
+ */
+
+ const cryptoObject = self.crypto;
+ let subtleObject; // Apple Safari support
+
+ if ("webkitSubtle" in self.crypto) {
+ try {
+ subtleObject = self.crypto.webkitSubtle;
+ } catch (ex) {
+ subtleObject = self.crypto.subtle;
+ }
+
+ engineName = "safari";
+ }
+
+ if ("subtle" in self.crypto) subtleObject = self.crypto.subtle;
+
+ if (typeof subtleObject === "undefined") {
+ engine = {
+ name: engineName,
+ crypto: cryptoObject,
+ subtle: null
+ };
+ } else {
+ engine = {
+ name: engineName,
+ crypto: cryptoObject,
+ subtle: new _CryptoEngine.default({
+ name: engineName,
+ crypto: self.crypto,
+ subtle: subtleObject
+ })
+ };
+ }
+ }
+ }
+
+ setEngine(engine.name, engine.crypto, engine.subtle);
+})(); //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of common functions
+//**************************************************************************************
+
+/**
+ * Get crypto subtle from current "crypto engine" or "undefined"
+ * @returns {({decrypt, deriveKey, digest, encrypt, exportKey, generateKey, importKey, sign, unwrapKey, verify, wrapKey}|null)}
+ */
+
+
+function getCrypto() {
+ const _engine = getEngine();
+
+ if (_engine.subtle !== null) return _engine.subtle;
+ return undefined;
+} //**************************************************************************************
+
+/**
+ * Initialize input Uint8Array by random values (with help from current "crypto engine")
+ * @param {!Uint8Array} view
+ * @returns {*}
+ */
+
+
+function getRandomValues(view) {
+ return getEngine().subtle.getRandomValues(view);
+} //**************************************************************************************
+
+/**
+ * Get OID for each specific algorithm
+ * @param {Object} algorithm
+ * @returns {string}
+ */
+
+
+function getOIDByAlgorithm(algorithm) {
+ return getEngine().subtle.getOIDByAlgorithm(algorithm);
+} //**************************************************************************************
+
+/**
+ * Get default algorithm parameters for each kind of operation
+ * @param {string} algorithmName Algorithm name to get common parameters for
+ * @param {string} operation Kind of operation: "sign", "encrypt", "generatekey", "importkey", "exportkey", "verify"
+ * @returns {*}
+ */
+
+
+function getAlgorithmParameters(algorithmName, operation) {
+ return getEngine().subtle.getAlgorithmParameters(algorithmName, operation);
+} //**************************************************************************************
+
+/**
+ * Create CMS ECDSA signature from WebCrypto ECDSA signature
+ * @param {ArrayBuffer} signatureBuffer WebCrypto result of "sign" function
+ * @returns {ArrayBuffer}
+ */
+
+
+function createCMSECDSASignature(signatureBuffer) {
+ //region Initial check for correct length
+ if (signatureBuffer.byteLength % 2 !== 0) return new ArrayBuffer(0); //endregion
+ //region Initial variables
+
+ const length = signatureBuffer.byteLength / 2; // There are two equal parts inside incoming ArrayBuffer
+
+ const rBuffer = new ArrayBuffer(length);
+ const rView = new Uint8Array(rBuffer);
+ rView.set(new Uint8Array(signatureBuffer, 0, length));
+ const rInteger = new asn1js.Integer({
+ valueHex: rBuffer
+ });
+ const sBuffer = new ArrayBuffer(length);
+ const sView = new Uint8Array(sBuffer);
+ sView.set(new Uint8Array(signatureBuffer, length, length));
+ const sInteger = new asn1js.Integer({
+ valueHex: sBuffer
+ }); //endregion
+
+ return new asn1js.Sequence({
+ value: [rInteger.convertToDER(), sInteger.convertToDER()]
+ }).toBER(false);
+} //**************************************************************************************
+
+/**
+ * String preparation function. In a future here will be realization of algorithm from RFC4518
+ * @param {string} inputString JavaScript string. As soon as for each ASN.1 string type we have a specific transformation function here we will work with pure JavaScript string
+ * @returns {string} Formated string
+ */
+
+
+function stringPrep(inputString) {
+ //region Initial variables
+ let isSpace = false;
+ let cuttedResult = ""; //endregion
+
+ const result = inputString.trim(); // Trim input string
+ //region Change all sequence of SPACE down to SPACE char
+
+ for (let i = 0; i < result.length; i++) {
+ if (result.charCodeAt(i) === 32) {
+ if (isSpace === false) isSpace = true;
+ } else {
+ if (isSpace) {
+ cuttedResult += " ";
+ isSpace = false;
+ }
+
+ cuttedResult += result[i];
+ }
+ } //endregion
+
+
+ return cuttedResult.toLowerCase();
+} //**************************************************************************************
+
+/**
+ * Create a single ArrayBuffer from CMS ECDSA signature
+ * @param {Sequence} cmsSignature ASN.1 SEQUENCE contains CMS ECDSA signature
+ * @returns {ArrayBuffer}
+ */
+
+
+function createECDSASignatureFromCMS(cmsSignature) {
+ //region Check input variables
+ if (cmsSignature instanceof asn1js.Sequence === false) return new ArrayBuffer(0);
+ if (cmsSignature.valueBlock.value.length !== 2) return new ArrayBuffer(0);
+ if (cmsSignature.valueBlock.value[0] instanceof asn1js.Integer === false) return new ArrayBuffer(0);
+ if (cmsSignature.valueBlock.value[1] instanceof asn1js.Integer === false) return new ArrayBuffer(0); //endregion
+
+ const rValue = cmsSignature.valueBlock.value[0].convertFromDER();
+ const sValue = cmsSignature.valueBlock.value[1].convertFromDER(); //region Check the lengths of two parts are equal
+
+ switch (true) {
+ case rValue.valueBlock.valueHex.byteLength < sValue.valueBlock.valueHex.byteLength:
+ {
+ if (sValue.valueBlock.valueHex.byteLength - rValue.valueBlock.valueHex.byteLength !== 1) throw new Error("Incorrect DER integer decoding");
+ const correctedLength = sValue.valueBlock.valueHex.byteLength;
+ const rValueView = new Uint8Array(rValue.valueBlock.valueHex);
+ const rValueBufferCorrected = new ArrayBuffer(correctedLength);
+ const rValueViewCorrected = new Uint8Array(rValueBufferCorrected);
+ rValueViewCorrected.set(rValueView, 1);
+ rValueViewCorrected[0] = 0x00; // In order to be sure we do not have any garbage here
+
+ return (0, _pvutils.utilConcatBuf)(rValueBufferCorrected, sValue.valueBlock.valueHex);
+ }
+
+ case rValue.valueBlock.valueHex.byteLength > sValue.valueBlock.valueHex.byteLength:
+ {
+ if (rValue.valueBlock.valueHex.byteLength - sValue.valueBlock.valueHex.byteLength !== 1) throw new Error("Incorrect DER integer decoding");
+ const correctedLength = rValue.valueBlock.valueHex.byteLength;
+ const sValueView = new Uint8Array(sValue.valueBlock.valueHex);
+ const sValueBufferCorrected = new ArrayBuffer(correctedLength);
+ const sValueViewCorrected = new Uint8Array(sValueBufferCorrected);
+ sValueViewCorrected.set(sValueView, 1);
+ sValueViewCorrected[0] = 0x00; // In order to be sure we do not have any garbage here
+
+ return (0, _pvutils.utilConcatBuf)(rValue.valueBlock.valueHex, sValueBufferCorrected);
+ }
+
+ default:
+ {
+ //region In case we have equal length and the length is not even with 2
+ if (rValue.valueBlock.valueHex.byteLength % 2) {
+ const correctedLength = rValue.valueBlock.valueHex.byteLength + 1;
+ const rValueView = new Uint8Array(rValue.valueBlock.valueHex);
+ const rValueBufferCorrected = new ArrayBuffer(correctedLength);
+ const rValueViewCorrected = new Uint8Array(rValueBufferCorrected);
+ rValueViewCorrected.set(rValueView, 1);
+ rValueViewCorrected[0] = 0x00; // In order to be sure we do not have any garbage here
+
+ const sValueView = new Uint8Array(sValue.valueBlock.valueHex);
+ const sValueBufferCorrected = new ArrayBuffer(correctedLength);
+ const sValueViewCorrected = new Uint8Array(sValueBufferCorrected);
+ sValueViewCorrected.set(sValueView, 1);
+ sValueViewCorrected[0] = 0x00; // In order to be sure we do not have any garbage here
+
+ return (0, _pvutils.utilConcatBuf)(rValueBufferCorrected, sValueBufferCorrected);
+ } //endregion
+
+ }
+ } //endregion
+
+
+ return (0, _pvutils.utilConcatBuf)(rValue.valueBlock.valueHex, sValue.valueBlock.valueHex);
+} //**************************************************************************************
+
+/**
+ * Get WebCrypto algorithm by wel-known OID
+ * @param {string} oid well-known OID to search for
+ * @returns {Object}
+ */
+
+
+function getAlgorithmByOID(oid) {
+ return getEngine().subtle.getAlgorithmByOID(oid);
+} //**************************************************************************************
+
+/**
+ * Getting hash algorithm by signature algorithm
+ * @param {AlgorithmIdentifier} signatureAlgorithm Signature algorithm
+ * @returns {string}
+ */
+
+
+function getHashAlgorithm(signatureAlgorithm) {
+ return getEngine().subtle.getHashAlgorithm(signatureAlgorithm);
+} //**************************************************************************************
+
+/**
+ * ANS X9.63 Key Derivation Function having a "Counter" as a parameter
+ * @param {string} hashFunction Used hash function
+ * @param {ArrayBuffer} Zbuffer ArrayBuffer containing ECDH shared secret to derive from
+ * @param {number} Counter
+ * @param {ArrayBuffer} SharedInfo Usually DER encoded "ECC_CMS_SharedInfo" structure
+ */
+
+
+function kdfWithCounter(hashFunction, Zbuffer, Counter, SharedInfo) {
+ //region Check of input parameters
+ switch (hashFunction.toUpperCase()) {
+ case "SHA-1":
+ case "SHA-256":
+ case "SHA-384":
+ case "SHA-512":
+ break;
+
+ default:
+ return Promise.reject(`Unknown hash function: ${hashFunction}`);
+ }
+
+ if (Zbuffer instanceof ArrayBuffer === false) return Promise.reject("Please set \"Zbuffer\" as \"ArrayBuffer\"");
+ if (Zbuffer.byteLength === 0) return Promise.reject("\"Zbuffer\" has zero length, error");
+ if (SharedInfo instanceof ArrayBuffer === false) return Promise.reject("Please set \"SharedInfo\" as \"ArrayBuffer\"");
+ if (Counter > 255) return Promise.reject("Please set \"Counter\" variable to value less or equal to 255"); //endregion
+ //region Initial variables
+
+ const counterBuffer = new ArrayBuffer(4);
+ const counterView = new Uint8Array(counterBuffer);
+ counterView[0] = 0x00;
+ counterView[1] = 0x00;
+ counterView[2] = 0x00;
+ counterView[3] = Counter;
+ let combinedBuffer = new ArrayBuffer(0); //endregion
+ //region Get a "crypto" extension
+
+ const crypto = getCrypto();
+ if (typeof crypto === "undefined") return Promise.reject("Unable to create WebCrypto object"); //endregion
+ //region Create a combined ArrayBuffer for digesting
+
+ combinedBuffer = (0, _pvutils.utilConcatBuf)(combinedBuffer, Zbuffer);
+ combinedBuffer = (0, _pvutils.utilConcatBuf)(combinedBuffer, counterBuffer);
+ combinedBuffer = (0, _pvutils.utilConcatBuf)(combinedBuffer, SharedInfo); //endregion
+ //region Return digest of combined ArrayBuffer and information about current counter
+
+ return crypto.digest({
+ name: hashFunction
+ }, combinedBuffer).then(result => ({
+ counter: Counter,
+ result
+ })); //endregion
+} //**************************************************************************************
+
+/**
+ * ANS X9.63 Key Derivation Function
+ * @param {string} hashFunction Used hash function
+ * @param {ArrayBuffer} Zbuffer ArrayBuffer containing ECDH shared secret to derive from
+ * @param {number} keydatalen Length (!!! in BITS !!!) of used kew derivation function
+ * @param {ArrayBuffer} SharedInfo Usually DER encoded "ECC_CMS_SharedInfo" structure
+ */
+
+
+function kdf(hashFunction, Zbuffer, keydatalen, SharedInfo) {
+ //region Initial variables
+ let hashLength = 0;
+ let maxCounter = 1;
+ const kdfArray = []; //endregion
+ //region Check of input parameters
+
+ switch (hashFunction.toUpperCase()) {
+ case "SHA-1":
+ hashLength = 160; // In bits
+
+ break;
+
+ case "SHA-256":
+ hashLength = 256; // In bits
+
+ break;
+
+ case "SHA-384":
+ hashLength = 384; // In bits
+
+ break;
+
+ case "SHA-512":
+ hashLength = 512; // In bits
+
+ break;
+
+ default:
+ return Promise.reject(`Unknown hash function: ${hashFunction}`);
+ }
+
+ if (Zbuffer instanceof ArrayBuffer === false) return Promise.reject("Please set \"Zbuffer\" as \"ArrayBuffer\"");
+ if (Zbuffer.byteLength === 0) return Promise.reject("\"Zbuffer\" has zero length, error");
+ if (SharedInfo instanceof ArrayBuffer === false) return Promise.reject("Please set \"SharedInfo\" as \"ArrayBuffer\""); //endregion
+ //region Calculated maximum value of "Counter" variable
+
+ const quotient = keydatalen / hashLength;
+
+ if (Math.floor(quotient) > 0) {
+ maxCounter = Math.floor(quotient);
+ if (quotient - maxCounter > 0) maxCounter++;
+ } //endregion
+ //region Create an array of "kdfWithCounter"
+
+
+ for (let i = 1; i <= maxCounter; i++) kdfArray.push(kdfWithCounter(hashFunction, Zbuffer, i, SharedInfo)); //endregion
+ //region Return combined digest with specified length
+
+
+ return Promise.all(kdfArray).then(incomingResult => {
+ //region Initial variables
+ let combinedBuffer = new ArrayBuffer(0);
+ let currentCounter = 1;
+ let found = true; //endregion
+ //region Combine all buffer together
+
+ while (found) {
+ found = false;
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = incomingResult[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ const result = _step.value;
+
+ if (result.counter === currentCounter) {
+ combinedBuffer = (0, _pvutils.utilConcatBuf)(combinedBuffer, result.result);
+ found = true;
+ break;
+ }
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+
+ currentCounter++;
+ } //endregion
+ //region Create output buffer with specified length
+
+
+ keydatalen >>= 3; // Divide by 8 since "keydatalen" is in bits
+
+ if (combinedBuffer.byteLength > keydatalen) {
+ const newBuffer = new ArrayBuffer(keydatalen);
+ const newView = new Uint8Array(newBuffer);
+ const combinedView = new Uint8Array(combinedBuffer);
+
+ for (let i = 0; i < keydatalen; i++) newView[i] = combinedView[i];
+
+ return newBuffer;
+ }
+
+ return combinedBuffer; // Since the situation when "combinedBuffer.byteLength < keydatalen" here we have only "combinedBuffer.byteLength === keydatalen"
+ //endregion
+ }); //endregion
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+
+}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"./CryptoEngine.js":27,"_process":114,"asn1js":112,"pvutils":113}],111:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+Object.defineProperty(exports, "setEngine", {
+ enumerable: true,
+ get: function get() {
+ return _common.setEngine;
+ }
+});
+Object.defineProperty(exports, "getEngine", {
+ enumerable: true,
+ get: function get() {
+ return _common.getEngine;
+ }
+});
+Object.defineProperty(exports, "getCrypto", {
+ enumerable: true,
+ get: function get() {
+ return _common.getCrypto;
+ }
+});
+Object.defineProperty(exports, "getRandomValues", {
+ enumerable: true,
+ get: function get() {
+ return _common.getRandomValues;
+ }
+});
+Object.defineProperty(exports, "getOIDByAlgorithm", {
+ enumerable: true,
+ get: function get() {
+ return _common.getOIDByAlgorithm;
+ }
+});
+Object.defineProperty(exports, "getAlgorithmParameters", {
+ enumerable: true,
+ get: function get() {
+ return _common.getAlgorithmParameters;
+ }
+});
+Object.defineProperty(exports, "createCMSECDSASignature", {
+ enumerable: true,
+ get: function get() {
+ return _common.createCMSECDSASignature;
+ }
+});
+Object.defineProperty(exports, "stringPrep", {
+ enumerable: true,
+ get: function get() {
+ return _common.stringPrep;
+ }
+});
+Object.defineProperty(exports, "createECDSASignatureFromCMS", {
+ enumerable: true,
+ get: function get() {
+ return _common.createECDSASignatureFromCMS;
+ }
+});
+Object.defineProperty(exports, "getAlgorithmByOID", {
+ enumerable: true,
+ get: function get() {
+ return _common.getAlgorithmByOID;
+ }
+});
+Object.defineProperty(exports, "getHashAlgorithm", {
+ enumerable: true,
+ get: function get() {
+ return _common.getHashAlgorithm;
+ }
+});
+Object.defineProperty(exports, "kdfWithCounter", {
+ enumerable: true,
+ get: function get() {
+ return _common.kdfWithCounter;
+ }
+});
+Object.defineProperty(exports, "kdf", {
+ enumerable: true,
+ get: function get() {
+ return _common.kdf;
+ }
+});
+Object.defineProperty(exports, "AccessDescription", {
+ enumerable: true,
+ get: function get() {
+ return _AccessDescription.default;
+ }
+});
+Object.defineProperty(exports, "Accuracy", {
+ enumerable: true,
+ get: function get() {
+ return _Accuracy.default;
+ }
+});
+Object.defineProperty(exports, "AlgorithmIdentifier", {
+ enumerable: true,
+ get: function get() {
+ return _AlgorithmIdentifier.default;
+ }
+});
+Object.defineProperty(exports, "AltName", {
+ enumerable: true,
+ get: function get() {
+ return _AltName.default;
+ }
+});
+Object.defineProperty(exports, "Attribute", {
+ enumerable: true,
+ get: function get() {
+ return _Attribute.default;
+ }
+});
+Object.defineProperty(exports, "AttributeTypeAndValue", {
+ enumerable: true,
+ get: function get() {
+ return _AttributeTypeAndValue.default;
+ }
+});
+Object.defineProperty(exports, "AuthenticatedSafe", {
+ enumerable: true,
+ get: function get() {
+ return _AuthenticatedSafe.default;
+ }
+});
+Object.defineProperty(exports, "AuthorityKeyIdentifier", {
+ enumerable: true,
+ get: function get() {
+ return _AuthorityKeyIdentifier.default;
+ }
+});
+Object.defineProperty(exports, "BasicConstraints", {
+ enumerable: true,
+ get: function get() {
+ return _BasicConstraints.default;
+ }
+});
+Object.defineProperty(exports, "BasicOCSPResponse", {
+ enumerable: true,
+ get: function get() {
+ return _BasicOCSPResponse.default;
+ }
+});
+Object.defineProperty(exports, "CRLBag", {
+ enumerable: true,
+ get: function get() {
+ return _CRLBag.default;
+ }
+});
+Object.defineProperty(exports, "CRLDistributionPoints", {
+ enumerable: true,
+ get: function get() {
+ return _CRLDistributionPoints.default;
+ }
+});
+Object.defineProperty(exports, "CertBag", {
+ enumerable: true,
+ get: function get() {
+ return _CertBag.default;
+ }
+});
+Object.defineProperty(exports, "CertID", {
+ enumerable: true,
+ get: function get() {
+ return _CertID.default;
+ }
+});
+Object.defineProperty(exports, "Certificate", {
+ enumerable: true,
+ get: function get() {
+ return _Certificate.default;
+ }
+});
+Object.defineProperty(exports, "CertificateChainValidationEngine", {
+ enumerable: true,
+ get: function get() {
+ return _CertificateChainValidationEngine.default;
+ }
+});
+Object.defineProperty(exports, "CertificatePolicies", {
+ enumerable: true,
+ get: function get() {
+ return _CertificatePolicies.default;
+ }
+});
+Object.defineProperty(exports, "CertificateRevocationList", {
+ enumerable: true,
+ get: function get() {
+ return _CertificateRevocationList.default;
+ }
+});
+Object.defineProperty(exports, "CertificateSet", {
+ enumerable: true,
+ get: function get() {
+ return _CertificateSet.default;
+ }
+});
+Object.defineProperty(exports, "CertificationRequest", {
+ enumerable: true,
+ get: function get() {
+ return _CertificationRequest.default;
+ }
+});
+Object.defineProperty(exports, "ContentInfo", {
+ enumerable: true,
+ get: function get() {
+ return _ContentInfo.default;
+ }
+});
+Object.defineProperty(exports, "CryptoEngine", {
+ enumerable: true,
+ get: function get() {
+ return _CryptoEngine.default;
+ }
+});
+Object.defineProperty(exports, "DigestInfo", {
+ enumerable: true,
+ get: function get() {
+ return _DigestInfo.default;
+ }
+});
+Object.defineProperty(exports, "DistributionPoint", {
+ enumerable: true,
+ get: function get() {
+ return _DistributionPoint.default;
+ }
+});
+Object.defineProperty(exports, "ECCCMSSharedInfo", {
+ enumerable: true,
+ get: function get() {
+ return _ECCCMSSharedInfo.default;
+ }
+});
+Object.defineProperty(exports, "ECPrivateKey", {
+ enumerable: true,
+ get: function get() {
+ return _ECPrivateKey.default;
+ }
+});
+Object.defineProperty(exports, "ECPublicKey", {
+ enumerable: true,
+ get: function get() {
+ return _ECPublicKey.default;
+ }
+});
+Object.defineProperty(exports, "EncapsulatedContentInfo", {
+ enumerable: true,
+ get: function get() {
+ return _EncapsulatedContentInfo.default;
+ }
+});
+Object.defineProperty(exports, "EncryptedContentInfo", {
+ enumerable: true,
+ get: function get() {
+ return _EncryptedContentInfo.default;
+ }
+});
+Object.defineProperty(exports, "EncryptedData", {
+ enumerable: true,
+ get: function get() {
+ return _EncryptedData.default;
+ }
+});
+Object.defineProperty(exports, "EnvelopedData", {
+ enumerable: true,
+ get: function get() {
+ return _EnvelopedData.default;
+ }
+});
+Object.defineProperty(exports, "ExtKeyUsage", {
+ enumerable: true,
+ get: function get() {
+ return _ExtKeyUsage.default;
+ }
+});
+Object.defineProperty(exports, "Extension", {
+ enumerable: true,
+ get: function get() {
+ return _Extension.default;
+ }
+});
+Object.defineProperty(exports, "Extensions", {
+ enumerable: true,
+ get: function get() {
+ return _Extensions.default;
+ }
+});
+Object.defineProperty(exports, "GeneralName", {
+ enumerable: true,
+ get: function get() {
+ return _GeneralName.default;
+ }
+});
+Object.defineProperty(exports, "GeneralNames", {
+ enumerable: true,
+ get: function get() {
+ return _GeneralNames.default;
+ }
+});
+Object.defineProperty(exports, "GeneralSubtree", {
+ enumerable: true,
+ get: function get() {
+ return _GeneralSubtree.default;
+ }
+});
+Object.defineProperty(exports, "InfoAccess", {
+ enumerable: true,
+ get: function get() {
+ return _InfoAccess.default;
+ }
+});
+Object.defineProperty(exports, "IssuerAndSerialNumber", {
+ enumerable: true,
+ get: function get() {
+ return _IssuerAndSerialNumber.default;
+ }
+});
+Object.defineProperty(exports, "IssuingDistributionPoint", {
+ enumerable: true,
+ get: function get() {
+ return _IssuingDistributionPoint.default;
+ }
+});
+Object.defineProperty(exports, "KEKIdentifier", {
+ enumerable: true,
+ get: function get() {
+ return _KEKIdentifier.default;
+ }
+});
+Object.defineProperty(exports, "KEKRecipientInfo", {
+ enumerable: true,
+ get: function get() {
+ return _KEKRecipientInfo.default;
+ }
+});
+Object.defineProperty(exports, "KeyAgreeRecipientIdentifier", {
+ enumerable: true,
+ get: function get() {
+ return _KeyAgreeRecipientIdentifier.default;
+ }
+});
+Object.defineProperty(exports, "KeyAgreeRecipientInfo", {
+ enumerable: true,
+ get: function get() {
+ return _KeyAgreeRecipientInfo.default;
+ }
+});
+Object.defineProperty(exports, "KeyBag", {
+ enumerable: true,
+ get: function get() {
+ return _KeyBag.default;
+ }
+});
+Object.defineProperty(exports, "KeyTransRecipientInfo", {
+ enumerable: true,
+ get: function get() {
+ return _KeyTransRecipientInfo.default;
+ }
+});
+Object.defineProperty(exports, "MacData", {
+ enumerable: true,
+ get: function get() {
+ return _MacData.default;
+ }
+});
+Object.defineProperty(exports, "MessageImprint", {
+ enumerable: true,
+ get: function get() {
+ return _MessageImprint.default;
+ }
+});
+Object.defineProperty(exports, "NameConstraints", {
+ enumerable: true,
+ get: function get() {
+ return _NameConstraints.default;
+ }
+});
+Object.defineProperty(exports, "OCSPRequest", {
+ enumerable: true,
+ get: function get() {
+ return _OCSPRequest.default;
+ }
+});
+Object.defineProperty(exports, "OCSPResponse", {
+ enumerable: true,
+ get: function get() {
+ return _OCSPResponse.default;
+ }
+});
+Object.defineProperty(exports, "OriginatorIdentifierOrKey", {
+ enumerable: true,
+ get: function get() {
+ return _OriginatorIdentifierOrKey.default;
+ }
+});
+Object.defineProperty(exports, "OriginatorInfo", {
+ enumerable: true,
+ get: function get() {
+ return _OriginatorInfo.default;
+ }
+});
+Object.defineProperty(exports, "OriginatorPublicKey", {
+ enumerable: true,
+ get: function get() {
+ return _OriginatorPublicKey.default;
+ }
+});
+Object.defineProperty(exports, "OtherCertificateFormat", {
+ enumerable: true,
+ get: function get() {
+ return _OtherCertificateFormat.default;
+ }
+});
+Object.defineProperty(exports, "OtherKeyAttribute", {
+ enumerable: true,
+ get: function get() {
+ return _OtherKeyAttribute.default;
+ }
+});
+Object.defineProperty(exports, "OtherPrimeInfo", {
+ enumerable: true,
+ get: function get() {
+ return _OtherPrimeInfo.default;
+ }
+});
+Object.defineProperty(exports, "OtherRecipientInfo", {
+ enumerable: true,
+ get: function get() {
+ return _OtherRecipientInfo.default;
+ }
+});
+Object.defineProperty(exports, "OtherRevocationInfoFormat", {
+ enumerable: true,
+ get: function get() {
+ return _OtherRevocationInfoFormat.default;
+ }
+});
+Object.defineProperty(exports, "PBES2Params", {
+ enumerable: true,
+ get: function get() {
+ return _PBES2Params.default;
+ }
+});
+Object.defineProperty(exports, "PBKDF2Params", {
+ enumerable: true,
+ get: function get() {
+ return _PBKDF2Params.default;
+ }
+});
+Object.defineProperty(exports, "PFX", {
+ enumerable: true,
+ get: function get() {
+ return _PFX.default;
+ }
+});
+Object.defineProperty(exports, "PKCS8ShroudedKeyBag", {
+ enumerable: true,
+ get: function get() {
+ return _PKCS8ShroudedKeyBag.default;
+ }
+});
+Object.defineProperty(exports, "PKIStatusInfo", {
+ enumerable: true,
+ get: function get() {
+ return _PKIStatusInfo.default;
+ }
+});
+Object.defineProperty(exports, "PasswordRecipientinfo", {
+ enumerable: true,
+ get: function get() {
+ return _PasswordRecipientinfo.default;
+ }
+});
+Object.defineProperty(exports, "PolicyConstraints", {
+ enumerable: true,
+ get: function get() {
+ return _PolicyConstraints.default;
+ }
+});
+Object.defineProperty(exports, "PolicyInformation", {
+ enumerable: true,
+ get: function get() {
+ return _PolicyInformation.default;
+ }
+});
+Object.defineProperty(exports, "PolicyMapping", {
+ enumerable: true,
+ get: function get() {
+ return _PolicyMapping.default;
+ }
+});
+Object.defineProperty(exports, "PolicyMappings", {
+ enumerable: true,
+ get: function get() {
+ return _PolicyMappings.default;
+ }
+});
+Object.defineProperty(exports, "PolicyQualifierInfo", {
+ enumerable: true,
+ get: function get() {
+ return _PolicyQualifierInfo.default;
+ }
+});
+Object.defineProperty(exports, "PrivateKeyInfo", {
+ enumerable: true,
+ get: function get() {
+ return _PrivateKeyInfo.default;
+ }
+});
+Object.defineProperty(exports, "PrivateKeyUsagePeriod", {
+ enumerable: true,
+ get: function get() {
+ return _PrivateKeyUsagePeriod.default;
+ }
+});
+Object.defineProperty(exports, "PublicKeyInfo", {
+ enumerable: true,
+ get: function get() {
+ return _PublicKeyInfo.default;
+ }
+});
+Object.defineProperty(exports, "RSAESOAEPParams", {
+ enumerable: true,
+ get: function get() {
+ return _RSAESOAEPParams.default;
+ }
+});
+Object.defineProperty(exports, "RSAPrivateKey", {
+ enumerable: true,
+ get: function get() {
+ return _RSAPrivateKey.default;
+ }
+});
+Object.defineProperty(exports, "RSAPublicKey", {
+ enumerable: true,
+ get: function get() {
+ return _RSAPublicKey.default;
+ }
+});
+Object.defineProperty(exports, "RSASSAPSSParams", {
+ enumerable: true,
+ get: function get() {
+ return _RSASSAPSSParams.default;
+ }
+});
+Object.defineProperty(exports, "RecipientEncryptedKey", {
+ enumerable: true,
+ get: function get() {
+ return _RecipientEncryptedKey.default;
+ }
+});
+Object.defineProperty(exports, "RecipientEncryptedKeys", {
+ enumerable: true,
+ get: function get() {
+ return _RecipientEncryptedKeys.default;
+ }
+});
+Object.defineProperty(exports, "RecipientIdentifier", {
+ enumerable: true,
+ get: function get() {
+ return _RecipientIdentifier.default;
+ }
+});
+Object.defineProperty(exports, "RecipientInfo", {
+ enumerable: true,
+ get: function get() {
+ return _RecipientInfo.default;
+ }
+});
+Object.defineProperty(exports, "RecipientKeyIdentifier", {
+ enumerable: true,
+ get: function get() {
+ return _RecipientKeyIdentifier.default;
+ }
+});
+Object.defineProperty(exports, "RelativeDistinguishedNames", {
+ enumerable: true,
+ get: function get() {
+ return _RelativeDistinguishedNames.default;
+ }
+});
+Object.defineProperty(exports, "Request", {
+ enumerable: true,
+ get: function get() {
+ return _Request.default;
+ }
+});
+Object.defineProperty(exports, "ResponseBytes", {
+ enumerable: true,
+ get: function get() {
+ return _ResponseBytes.default;
+ }
+});
+Object.defineProperty(exports, "ResponseData", {
+ enumerable: true,
+ get: function get() {
+ return _ResponseData.default;
+ }
+});
+Object.defineProperty(exports, "RevocationInfoChoices", {
+ enumerable: true,
+ get: function get() {
+ return _RevocationInfoChoices.default;
+ }
+});
+Object.defineProperty(exports, "RevokedCertificate", {
+ enumerable: true,
+ get: function get() {
+ return _RevokedCertificate.default;
+ }
+});
+Object.defineProperty(exports, "SafeBag", {
+ enumerable: true,
+ get: function get() {
+ return _SafeBag.default;
+ }
+});
+Object.defineProperty(exports, "SafeContents", {
+ enumerable: true,
+ get: function get() {
+ return _SafeContents.default;
+ }
+});
+Object.defineProperty(exports, "SecretBag", {
+ enumerable: true,
+ get: function get() {
+ return _SecretBag.default;
+ }
+});
+Object.defineProperty(exports, "Signature", {
+ enumerable: true,
+ get: function get() {
+ return _Signature.default;
+ }
+});
+Object.defineProperty(exports, "SignedAndUnsignedAttributes", {
+ enumerable: true,
+ get: function get() {
+ return _SignedAndUnsignedAttributes.default;
+ }
+});
+Object.defineProperty(exports, "SignedData", {
+ enumerable: true,
+ get: function get() {
+ return _SignedData.default;
+ }
+});
+Object.defineProperty(exports, "SignerInfo", {
+ enumerable: true,
+ get: function get() {
+ return _SignerInfo.default;
+ }
+});
+Object.defineProperty(exports, "SingleResponse", {
+ enumerable: true,
+ get: function get() {
+ return _SingleResponse.default;
+ }
+});
+Object.defineProperty(exports, "SubjectDirectoryAttributes", {
+ enumerable: true,
+ get: function get() {
+ return _SubjectDirectoryAttributes.default;
+ }
+});
+Object.defineProperty(exports, "TBSRequest", {
+ enumerable: true,
+ get: function get() {
+ return _TBSRequest.default;
+ }
+});
+Object.defineProperty(exports, "TSTInfo", {
+ enumerable: true,
+ get: function get() {
+ return _TSTInfo.default;
+ }
+});
+Object.defineProperty(exports, "Time", {
+ enumerable: true,
+ get: function get() {
+ return _Time.default;
+ }
+});
+Object.defineProperty(exports, "TimeStampReq", {
+ enumerable: true,
+ get: function get() {
+ return _TimeStampReq.default;
+ }
+});
+Object.defineProperty(exports, "TimeStampResp", {
+ enumerable: true,
+ get: function get() {
+ return _TimeStampResp.default;
+ }
+});
+Object.defineProperty(exports, "SignedCertificateTimestampList", {
+ enumerable: true,
+ get: function get() {
+ return _SignedCertificateTimestampList.default;
+ }
+});
+Object.defineProperty(exports, "SignedCertificateTimestamp", {
+ enumerable: true,
+ get: function get() {
+ return _SignedCertificateTimestampList.SignedCertificateTimestamp;
+ }
+});
+Object.defineProperty(exports, "verifySCTsForCertificate", {
+ enumerable: true,
+ get: function get() {
+ return _SignedCertificateTimestampList.verifySCTsForCertificate;
+ }
+});
+Object.defineProperty(exports, "CertificateTemplate", {
+ enumerable: true,
+ get: function get() {
+ return _CertificateTemplate.default;
+ }
+});
+Object.defineProperty(exports, "CAVersion", {
+ enumerable: true,
+ get: function get() {
+ return _CAVersion.default;
+ }
+});
+Object.defineProperty(exports, "QCStatements", {
+ enumerable: true,
+ get: function get() {
+ return _CAVersion.default;
+ }
+});
+Object.defineProperty(exports, "QCStatement", {
+ enumerable: true,
+ get: function get() {
+ return _QCStatements.QCStatement;
+ }
+});
+
+var _common = require("./common.js");
+
+var _AccessDescription = _interopRequireDefault(require("./AccessDescription.js"));
+
+var _Accuracy = _interopRequireDefault(require("./Accuracy.js"));
+
+var _AlgorithmIdentifier = _interopRequireDefault(require("./AlgorithmIdentifier.js"));
+
+var _AltName = _interopRequireDefault(require("./AltName.js"));
+
+var _Attribute = _interopRequireDefault(require("./Attribute.js"));
+
+var _AttributeTypeAndValue = _interopRequireDefault(require("./AttributeTypeAndValue.js"));
+
+var _AuthenticatedSafe = _interopRequireDefault(require("./AuthenticatedSafe.js"));
+
+var _AuthorityKeyIdentifier = _interopRequireDefault(require("./AuthorityKeyIdentifier.js"));
+
+var _BasicConstraints = _interopRequireDefault(require("./BasicConstraints.js"));
+
+var _BasicOCSPResponse = _interopRequireDefault(require("./BasicOCSPResponse.js"));
+
+var _CRLBag = _interopRequireDefault(require("./CRLBag.js"));
+
+var _CRLDistributionPoints = _interopRequireDefault(require("./CRLDistributionPoints.js"));
+
+var _CertBag = _interopRequireDefault(require("./CertBag.js"));
+
+var _CertID = _interopRequireDefault(require("./CertID.js"));
+
+var _Certificate = _interopRequireDefault(require("./Certificate.js"));
+
+var _CertificateChainValidationEngine = _interopRequireDefault(require("./CertificateChainValidationEngine.js"));
+
+var _CertificatePolicies = _interopRequireDefault(require("./CertificatePolicies.js"));
+
+var _CertificateRevocationList = _interopRequireDefault(require("./CertificateRevocationList.js"));
+
+var _CertificateSet = _interopRequireDefault(require("./CertificateSet.js"));
+
+var _CertificationRequest = _interopRequireDefault(require("./CertificationRequest.js"));
+
+var _ContentInfo = _interopRequireDefault(require("./ContentInfo.js"));
+
+var _CryptoEngine = _interopRequireDefault(require("./CryptoEngine.js"));
+
+var _DigestInfo = _interopRequireDefault(require("./DigestInfo.js"));
+
+var _DistributionPoint = _interopRequireDefault(require("./DistributionPoint.js"));
+
+var _ECCCMSSharedInfo = _interopRequireDefault(require("./ECCCMSSharedInfo.js"));
+
+var _ECPrivateKey = _interopRequireDefault(require("./ECPrivateKey.js"));
+
+var _ECPublicKey = _interopRequireDefault(require("./ECPublicKey.js"));
+
+var _EncapsulatedContentInfo = _interopRequireDefault(require("./EncapsulatedContentInfo.js"));
+
+var _EncryptedContentInfo = _interopRequireDefault(require("./EncryptedContentInfo.js"));
+
+var _EncryptedData = _interopRequireDefault(require("./EncryptedData.js"));
+
+var _EnvelopedData = _interopRequireDefault(require("./EnvelopedData.js"));
+
+var _ExtKeyUsage = _interopRequireDefault(require("./ExtKeyUsage.js"));
+
+var _Extension = _interopRequireDefault(require("./Extension.js"));
+
+var _Extensions = _interopRequireDefault(require("./Extensions.js"));
+
+var _GeneralName = _interopRequireDefault(require("./GeneralName.js"));
+
+var _GeneralNames = _interopRequireDefault(require("./GeneralNames.js"));
+
+var _GeneralSubtree = _interopRequireDefault(require("./GeneralSubtree.js"));
+
+var _InfoAccess = _interopRequireDefault(require("./InfoAccess.js"));
+
+var _IssuerAndSerialNumber = _interopRequireDefault(require("./IssuerAndSerialNumber.js"));
+
+var _IssuingDistributionPoint = _interopRequireDefault(require("./IssuingDistributionPoint.js"));
+
+var _KEKIdentifier = _interopRequireDefault(require("./KEKIdentifier.js"));
+
+var _KEKRecipientInfo = _interopRequireDefault(require("./KEKRecipientInfo.js"));
+
+var _KeyAgreeRecipientIdentifier = _interopRequireDefault(require("./KeyAgreeRecipientIdentifier.js"));
+
+var _KeyAgreeRecipientInfo = _interopRequireDefault(require("./KeyAgreeRecipientInfo.js"));
+
+var _KeyBag = _interopRequireDefault(require("./KeyBag.js"));
+
+var _KeyTransRecipientInfo = _interopRequireDefault(require("./KeyTransRecipientInfo.js"));
+
+var _MacData = _interopRequireDefault(require("./MacData.js"));
+
+var _MessageImprint = _interopRequireDefault(require("./MessageImprint.js"));
+
+var _NameConstraints = _interopRequireDefault(require("./NameConstraints.js"));
+
+var _OCSPRequest = _interopRequireDefault(require("./OCSPRequest.js"));
+
+var _OCSPResponse = _interopRequireDefault(require("./OCSPResponse.js"));
+
+var _OriginatorIdentifierOrKey = _interopRequireDefault(require("./OriginatorIdentifierOrKey.js"));
+
+var _OriginatorInfo = _interopRequireDefault(require("./OriginatorInfo.js"));
+
+var _OriginatorPublicKey = _interopRequireDefault(require("./OriginatorPublicKey.js"));
+
+var _OtherCertificateFormat = _interopRequireDefault(require("./OtherCertificateFormat.js"));
+
+var _OtherKeyAttribute = _interopRequireDefault(require("./OtherKeyAttribute.js"));
+
+var _OtherPrimeInfo = _interopRequireDefault(require("./OtherPrimeInfo.js"));
+
+var _OtherRecipientInfo = _interopRequireDefault(require("./OtherRecipientInfo.js"));
+
+var _OtherRevocationInfoFormat = _interopRequireDefault(require("./OtherRevocationInfoFormat.js"));
+
+var _PBES2Params = _interopRequireDefault(require("./PBES2Params.js"));
+
+var _PBKDF2Params = _interopRequireDefault(require("./PBKDF2Params.js"));
+
+var _PFX = _interopRequireDefault(require("./PFX.js"));
+
+var _PKCS8ShroudedKeyBag = _interopRequireDefault(require("./PKCS8ShroudedKeyBag.js"));
+
+var _PKIStatusInfo = _interopRequireDefault(require("./PKIStatusInfo.js"));
+
+var _PasswordRecipientinfo = _interopRequireDefault(require("./PasswordRecipientinfo.js"));
+
+var _PolicyConstraints = _interopRequireDefault(require("./PolicyConstraints.js"));
+
+var _PolicyInformation = _interopRequireDefault(require("./PolicyInformation.js"));
+
+var _PolicyMapping = _interopRequireDefault(require("./PolicyMapping.js"));
+
+var _PolicyMappings = _interopRequireDefault(require("./PolicyMappings.js"));
+
+var _PolicyQualifierInfo = _interopRequireDefault(require("./PolicyQualifierInfo.js"));
+
+var _PrivateKeyInfo = _interopRequireDefault(require("./PrivateKeyInfo.js"));
+
+var _PrivateKeyUsagePeriod = _interopRequireDefault(require("./PrivateKeyUsagePeriod.js"));
+
+var _PublicKeyInfo = _interopRequireDefault(require("./PublicKeyInfo.js"));
+
+var _RSAESOAEPParams = _interopRequireDefault(require("./RSAESOAEPParams.js"));
+
+var _RSAPrivateKey = _interopRequireDefault(require("./RSAPrivateKey.js"));
+
+var _RSAPublicKey = _interopRequireDefault(require("./RSAPublicKey.js"));
+
+var _RSASSAPSSParams = _interopRequireDefault(require("./RSASSAPSSParams.js"));
+
+var _RecipientEncryptedKey = _interopRequireDefault(require("./RecipientEncryptedKey.js"));
+
+var _RecipientEncryptedKeys = _interopRequireDefault(require("./RecipientEncryptedKeys.js"));
+
+var _RecipientIdentifier = _interopRequireDefault(require("./RecipientIdentifier.js"));
+
+var _RecipientInfo = _interopRequireDefault(require("./RecipientInfo.js"));
+
+var _RecipientKeyIdentifier = _interopRequireDefault(require("./RecipientKeyIdentifier.js"));
+
+var _RelativeDistinguishedNames = _interopRequireDefault(require("./RelativeDistinguishedNames.js"));
+
+var _Request = _interopRequireDefault(require("./Request.js"));
+
+var _ResponseBytes = _interopRequireDefault(require("./ResponseBytes.js"));
+
+var _ResponseData = _interopRequireDefault(require("./ResponseData.js"));
+
+var _RevocationInfoChoices = _interopRequireDefault(require("./RevocationInfoChoices.js"));
+
+var _RevokedCertificate = _interopRequireDefault(require("./RevokedCertificate.js"));
+
+var _SafeBag = _interopRequireDefault(require("./SafeBag.js"));
+
+var _SafeContents = _interopRequireDefault(require("./SafeContents.js"));
+
+var _SecretBag = _interopRequireDefault(require("./SecretBag.js"));
+
+var _Signature = _interopRequireDefault(require("./Signature.js"));
+
+var _SignedAndUnsignedAttributes = _interopRequireDefault(require("./SignedAndUnsignedAttributes.js"));
+
+var _SignedData = _interopRequireDefault(require("./SignedData.js"));
+
+var _SignerInfo = _interopRequireDefault(require("./SignerInfo.js"));
+
+var _SingleResponse = _interopRequireDefault(require("./SingleResponse.js"));
+
+var _SubjectDirectoryAttributes = _interopRequireDefault(require("./SubjectDirectoryAttributes.js"));
+
+var _TBSRequest = _interopRequireDefault(require("./TBSRequest.js"));
+
+var _TSTInfo = _interopRequireDefault(require("./TSTInfo.js"));
+
+var _Time = _interopRequireDefault(require("./Time.js"));
+
+var _TimeStampReq = _interopRequireDefault(require("./TimeStampReq.js"));
+
+var _TimeStampResp = _interopRequireDefault(require("./TimeStampResp.js"));
+
+var _SignedCertificateTimestampList = _interopRequireWildcard(require("./SignedCertificateTimestampList.js"));
+
+var _CertificateTemplate = _interopRequireDefault(require("./CertificateTemplate.js"));
+
+var _CAVersion = _interopRequireDefault(require("./CAVersion.js"));
+
+var _QCStatements = require("./QCStatements.js");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+},{"./AccessDescription.js":2,"./Accuracy.js":3,"./AlgorithmIdentifier.js":4,"./AltName.js":5,"./Attribute.js":6,"./AttributeTypeAndValue.js":9,"./AuthenticatedSafe.js":10,"./AuthorityKeyIdentifier.js":11,"./BasicConstraints.js":12,"./BasicOCSPResponse.js":13,"./CAVersion.js":14,"./CRLBag.js":15,"./CRLDistributionPoints.js":16,"./CertBag.js":17,"./CertID.js":18,"./Certificate.js":19,"./CertificateChainValidationEngine.js":20,"./CertificatePolicies.js":21,"./CertificateRevocationList.js":22,"./CertificateSet.js":23,"./CertificateTemplate.js":24,"./CertificationRequest.js":25,"./ContentInfo.js":26,"./CryptoEngine.js":27,"./DigestInfo.js":28,"./DistributionPoint.js":29,"./ECCCMSSharedInfo.js":30,"./ECPrivateKey.js":31,"./ECPublicKey.js":32,"./EncapsulatedContentInfo.js":33,"./EncryptedContentInfo.js":34,"./EncryptedData.js":35,"./EnvelopedData.js":36,"./ExtKeyUsage.js":37,"./Extension.js":38,"./Extensions.js":39,"./GeneralName.js":40,"./GeneralNames.js":41,"./GeneralSubtree.js":42,"./InfoAccess.js":43,"./IssuerAndSerialNumber.js":44,"./IssuingDistributionPoint.js":45,"./KEKIdentifier.js":46,"./KEKRecipientInfo.js":47,"./KeyAgreeRecipientIdentifier.js":48,"./KeyAgreeRecipientInfo.js":49,"./KeyBag.js":50,"./KeyTransRecipientInfo.js":51,"./MacData.js":52,"./MessageImprint.js":53,"./NameConstraints.js":54,"./OCSPRequest.js":55,"./OCSPResponse.js":56,"./OriginatorIdentifierOrKey.js":57,"./OriginatorInfo.js":58,"./OriginatorPublicKey.js":59,"./OtherCertificateFormat.js":60,"./OtherKeyAttribute.js":61,"./OtherPrimeInfo.js":62,"./OtherRecipientInfo.js":63,"./OtherRevocationInfoFormat.js":64,"./PBES2Params.js":65,"./PBKDF2Params.js":66,"./PFX.js":67,"./PKCS8ShroudedKeyBag.js":68,"./PKIStatusInfo.js":69,"./PasswordRecipientinfo.js":70,"./PolicyConstraints.js":71,"./PolicyInformation.js":72,"./PolicyMapping.js":73,"./PolicyMappings.js":74,"./PolicyQualifierInfo.js":75,"./PrivateKeyInfo.js":76,"./PrivateKeyUsagePeriod.js":77,"./PublicKeyInfo.js":78,"./QCStatements.js":79,"./RSAESOAEPParams.js":80,"./RSAPrivateKey.js":81,"./RSAPublicKey.js":82,"./RSASSAPSSParams.js":83,"./RecipientEncryptedKey.js":84,"./RecipientEncryptedKeys.js":85,"./RecipientIdentifier.js":86,"./RecipientInfo.js":87,"./RecipientKeyIdentifier.js":88,"./RelativeDistinguishedNames.js":89,"./Request.js":90,"./ResponseBytes.js":91,"./ResponseData.js":92,"./RevocationInfoChoices.js":93,"./RevokedCertificate.js":94,"./SafeBag.js":95,"./SafeContents.js":96,"./SecretBag.js":97,"./Signature.js":98,"./SignedAndUnsignedAttributes.js":99,"./SignedCertificateTimestampList.js":100,"./SignedData.js":101,"./SignerInfo.js":102,"./SingleResponse.js":103,"./SubjectDirectoryAttributes.js":104,"./TBSRequest.js":105,"./TSTInfo.js":106,"./Time.js":107,"./TimeStampReq.js":108,"./TimeStampResp.js":109,"./common.js":110}],112:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.fromBER = fromBER;
+exports.compareSchema = compareSchema;
+exports.verifySchema = verifySchema;
+exports.fromJSON = fromJSON;
+exports.RawData = exports.Repeated = exports.Any = exports.Choice = exports.TIME = exports.Duration = exports.DateTime = exports.TimeOfDay = exports.DATE = exports.GeneralizedTime = exports.UTCTime = exports.CharacterString = exports.GeneralString = exports.VisibleString = exports.GraphicString = exports.IA5String = exports.VideotexString = exports.TeletexString = exports.PrintableString = exports.NumericString = exports.UniversalString = exports.BmpString = exports.RelativeObjectIdentifier = exports.Utf8String = exports.ObjectIdentifier = exports.Enumerated = exports.Integer = exports.BitString = exports.OctetString = exports.Null = exports.Set = exports.Sequence = exports.Boolean = exports.EndOfContent = exports.Constructed = exports.Primitive = exports.BaseBlock = exports.ValueBlock = exports.HexBlock = void 0;
+
+var _pvutils = require("pvutils");
+
+/* eslint-disable indent */
+
+/*
+ * Copyright (c) 2016-2018, Peculiar Ventures
+ * All rights reserved.
+ *
+ * Author 2016-2018, Yury Strozhevsky <www.strozhevsky.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ */
+//**************************************************************************************
+//**************************************************************************************
+//region Declaration of global variables
+//**************************************************************************************
+const powers2 = [new Uint8Array([1])];
+const digitsString = "0123456789"; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration for "LocalBaseBlock" class
+//**************************************************************************************
+
+/**
+ * Class used as a base block for all remaining ASN.1 classes
+ * @typedef LocalBaseBlock
+ * @interface
+ * @property {number} blockLength
+ * @property {string} error
+ * @property {Array.<string>} warnings
+ * @property {ArrayBuffer} valueBeforeDecode
+ */
+
+class LocalBaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalBaseBlock" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueBeforeDecode]
+ */
+ constructor(parameters = {}) {
+ /**
+ * @type {number} blockLength
+ */
+ this.blockLength = (0, _pvutils.getParametersValue)(parameters, "blockLength", 0);
+ /**
+ * @type {string} error
+ */
+
+ this.error = (0, _pvutils.getParametersValue)(parameters, "error", "");
+ /**
+ * @type {Array.<string>} warnings
+ */
+
+ this.warnings = (0, _pvutils.getParametersValue)(parameters, "warnings", []); //noinspection JSCheckFunctionSignatures
+
+ /**
+ * @type {ArrayBuffer} valueBeforeDecode
+ */
+
+ if ("valueBeforeDecode" in parameters) this.valueBeforeDecode = parameters.valueBeforeDecode.slice(0);else this.valueBeforeDecode = new ArrayBuffer(0);
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "baseBlock";
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
+ */
+
+
+ toJSON() {
+ return {
+ blockName: this.constructor.blockName(),
+ blockLength: this.blockLength,
+ error: this.error,
+ warnings: this.warnings,
+ valueBeforeDecode: (0, _pvutils.bufferToHexCodes)(this.valueBeforeDecode, 0, this.valueBeforeDecode.byteLength)
+ };
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Description for "HexBlock" class
+//**************************************************************************************
+
+/**
+ * Class used as a base block for all remaining ASN.1 classes
+ * @extends LocalBaseBlock
+ * @typedef HexBlock
+ * @property {number} blockLength
+ * @property {string} error
+ * @property {Array.<string>} warnings
+ * @property {ArrayBuffer} valueBeforeDecode
+ * @property {boolean} isHexOnly
+ * @property {ArrayBuffer} valueHex
+ */
+//noinspection JSUnusedLocalSymbols
+
+
+const HexBlock = BaseClass => class LocalHexBlockMixin extends BaseClass {
+ //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+
+ /**
+ * Constructor for "HexBlock" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ /**
+ * @type {boolean}
+ */
+
+ this.isHexOnly = (0, _pvutils.getParametersValue)(parameters, "isHexOnly", false);
+ /**
+ * @type {ArrayBuffer}
+ */
+
+ if ("valueHex" in parameters) this.valueHex = parameters.valueHex.slice(0);else this.valueHex = new ArrayBuffer(0);
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "hexBlock";
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
+ //region Getting Uint8Array from ArrayBuffer
+
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength); //endregion
+ //region Initial checks
+
+ if (intBuffer.length === 0) {
+ this.warnings.push("Zero buffer length");
+ return inputOffset;
+ } //endregion
+ //region Copy input buffer to internal buffer
+
+
+ this.valueHex = inputBuffer.slice(inputOffset, inputOffset + inputLength); //endregion
+
+ this.blockLength = inputLength;
+ return inputOffset + inputLength;
+ } //**********************************************************************************
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ if (this.isHexOnly !== true) {
+ this.error = "Flag \"isHexOnly\" is not set, abort";
+ return new ArrayBuffer(0);
+ }
+
+ if (sizeOnly === true) return new ArrayBuffer(this.valueHex.byteLength); //noinspection JSCheckFunctionSignatures
+
+ return this.valueHex.slice(0);
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.blockName = this.constructor.blockName();
+ object.isHexOnly = this.isHexOnly;
+ object.valueHex = (0, _pvutils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
+ return object;
+ } //**********************************************************************************
+
+
+}; //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of identification block class
+//**************************************************************************************
+
+
+exports.HexBlock = HexBlock;
+
+class LocalIdentificationBlock extends HexBlock(LocalBaseBlock) {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalBaseBlock" class
+ * @param {Object} [parameters={}]
+ * @property {Object} [idBlock]
+ */
+ constructor(parameters = {}) {
+ super();
+
+ if ("idBlock" in parameters) {
+ //region Properties from hexBlock class
+ this.isHexOnly = (0, _pvutils.getParametersValue)(parameters.idBlock, "isHexOnly", false);
+ this.valueHex = (0, _pvutils.getParametersValue)(parameters.idBlock, "valueHex", new ArrayBuffer(0)); //endregion
+
+ this.tagClass = (0, _pvutils.getParametersValue)(parameters.idBlock, "tagClass", -1);
+ this.tagNumber = (0, _pvutils.getParametersValue)(parameters.idBlock, "tagNumber", -1);
+ this.isConstructed = (0, _pvutils.getParametersValue)(parameters.idBlock, "isConstructed", false);
+ } else {
+ this.tagClass = -1;
+ this.tagNumber = -1;
+ this.isConstructed = false;
+ }
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "identificationBlock";
+ } //**********************************************************************************
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ //region Initial variables
+ let firstOctet = 0;
+ let retBuf;
+ let retView; //endregion
+
+ switch (this.tagClass) {
+ case 1:
+ firstOctet |= 0x00; // UNIVERSAL
+
+ break;
+
+ case 2:
+ firstOctet |= 0x40; // APPLICATION
+
+ break;
+
+ case 3:
+ firstOctet |= 0x80; // CONTEXT-SPECIFIC
+
+ break;
+
+ case 4:
+ firstOctet |= 0xC0; // PRIVATE
+
+ break;
+
+ default:
+ this.error = "Unknown tag class";
+ return new ArrayBuffer(0);
+ }
+
+ if (this.isConstructed) firstOctet |= 0x20;
+
+ if (this.tagNumber < 31 && !this.isHexOnly) {
+ retBuf = new ArrayBuffer(1);
+ retView = new Uint8Array(retBuf);
+
+ if (!sizeOnly) {
+ let number = this.tagNumber;
+ number &= 0x1F;
+ firstOctet |= number;
+ retView[0] = firstOctet;
+ }
+
+ return retBuf;
+ }
+
+ if (this.isHexOnly === false) {
+ const encodedBuf = (0, _pvutils.utilToBase)(this.tagNumber, 7);
+ const encodedView = new Uint8Array(encodedBuf);
+ const size = encodedBuf.byteLength;
+ retBuf = new ArrayBuffer(size + 1);
+ retView = new Uint8Array(retBuf);
+ retView[0] = firstOctet | 0x1F;
+
+ if (!sizeOnly) {
+ for (let i = 0; i < size - 1; i++) retView[i + 1] = encodedView[i] | 0x80;
+
+ retView[size] = encodedView[size - 1];
+ }
+
+ return retBuf;
+ }
+
+ retBuf = new ArrayBuffer(this.valueHex.byteLength + 1);
+ retView = new Uint8Array(retBuf);
+ retView[0] = firstOctet | 0x1F;
+
+ if (sizeOnly === false) {
+ const curView = new Uint8Array(this.valueHex);
+
+ for (let i = 0; i < curView.length - 1; i++) retView[i + 1] = curView[i] | 0x80;
+
+ retView[this.valueHex.byteLength] = curView[curView.length - 1];
+ }
+
+ return retBuf;
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number}
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
+ //region Getting Uint8Array from ArrayBuffer
+
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength); //endregion
+ //region Initial checks
+
+ if (intBuffer.length === 0) {
+ this.error = "Zero buffer length";
+ return -1;
+ } //endregion
+ //region Find tag class
+
+
+ const tagClassMask = intBuffer[0] & 0xC0;
+
+ switch (tagClassMask) {
+ case 0x00:
+ this.tagClass = 1; // UNIVERSAL
+
+ break;
+
+ case 0x40:
+ this.tagClass = 2; // APPLICATION
+
+ break;
+
+ case 0x80:
+ this.tagClass = 3; // CONTEXT-SPECIFIC
+
+ break;
+
+ case 0xC0:
+ this.tagClass = 4; // PRIVATE
+
+ break;
+
+ default:
+ this.error = "Unknown tag class";
+ return -1;
+ } //endregion
+ //region Find it's constructed or not
+
+
+ this.isConstructed = (intBuffer[0] & 0x20) === 0x20; //endregion
+ //region Find tag number
+
+ this.isHexOnly = false;
+ const tagNumberMask = intBuffer[0] & 0x1F; //region Simple case (tag number < 31)
+
+ if (tagNumberMask !== 0x1F) {
+ this.tagNumber = tagNumberMask;
+ this.blockLength = 1;
+ } //endregion
+ //region Tag number bigger or equal to 31
+ else {
+ let count = 1;
+ this.valueHex = new ArrayBuffer(255);
+ let tagNumberBufferMaxLength = 255;
+ let intTagNumberBuffer = new Uint8Array(this.valueHex); //noinspection JSBitwiseOperatorUsage
+
+ while (intBuffer[count] & 0x80) {
+ intTagNumberBuffer[count - 1] = intBuffer[count] & 0x7F;
+ count++;
+
+ if (count >= intBuffer.length) {
+ this.error = "End of input reached before message was fully decoded";
+ return -1;
+ } //region In case if tag number length is greater than 255 bytes (rare but possible case)
+
+
+ if (count === tagNumberBufferMaxLength) {
+ tagNumberBufferMaxLength += 255;
+ const tempBuffer = new ArrayBuffer(tagNumberBufferMaxLength);
+ const tempBufferView = new Uint8Array(tempBuffer);
+
+ for (let i = 0; i < intTagNumberBuffer.length; i++) tempBufferView[i] = intTagNumberBuffer[i];
+
+ this.valueHex = new ArrayBuffer(tagNumberBufferMaxLength);
+ intTagNumberBuffer = new Uint8Array(this.valueHex);
+ } //endregion
+
+ }
+
+ this.blockLength = count + 1;
+ intTagNumberBuffer[count - 1] = intBuffer[count] & 0x7F; // Write last byte to buffer
+ //region Cut buffer
+
+ const tempBuffer = new ArrayBuffer(count);
+ const tempBufferView = new Uint8Array(tempBuffer);
+
+ for (let i = 0; i < count; i++) tempBufferView[i] = intTagNumberBuffer[i];
+
+ this.valueHex = new ArrayBuffer(count);
+ intTagNumberBuffer = new Uint8Array(this.valueHex);
+ intTagNumberBuffer.set(tempBufferView); //endregion
+ //region Try to convert long tag number to short form
+
+ if (this.blockLength <= 9) this.tagNumber = (0, _pvutils.utilFromBase)(intTagNumberBuffer, 7);else {
+ this.isHexOnly = true;
+ this.warnings.push("Tag too long, represented as hex-coded");
+ } //endregion
+ } //endregion
+ //endregion
+ //region Check if constructed encoding was using for primitive type
+
+
+ if (this.tagClass === 1 && this.isConstructed) {
+ switch (this.tagNumber) {
+ case 1: // Boolean
+
+ case 2: // REAL
+
+ case 5: // Null
+
+ case 6: // OBJECT IDENTIFIER
+
+ case 9: // REAL
+
+ case 13: // RELATIVE OBJECT IDENTIFIER
+
+ case 14: // Time
+
+ case 23:
+ case 24:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ this.error = "Constructed encoding used for primitive type";
+ return -1;
+
+ default:
+ }
+ } //endregion
+
+
+ return inputOffset + this.blockLength; // Return current offset in input buffer
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {{blockName: string,
+ * tagClass: number,
+ * tagNumber: number,
+ * isConstructed: boolean,
+ * isHexOnly: boolean,
+ * valueHex: ArrayBuffer,
+ * blockLength: number,
+ * error: string, warnings: Array.<string>,
+ * valueBeforeDecode: string}}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.blockName = this.constructor.blockName();
+ object.tagClass = this.tagClass;
+ object.tagNumber = this.tagNumber;
+ object.isConstructed = this.isConstructed;
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of length block class
+//**************************************************************************************
+
+
+class LocalLengthBlock extends LocalBaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalLengthBlock" class
+ * @param {Object} [parameters={}]
+ * @property {Object} [lenBlock]
+ */
+ constructor(parameters = {}) {
+ super();
+
+ if ("lenBlock" in parameters) {
+ this.isIndefiniteForm = (0, _pvutils.getParametersValue)(parameters.lenBlock, "isIndefiniteForm", false);
+ this.longFormUsed = (0, _pvutils.getParametersValue)(parameters.lenBlock, "longFormUsed", false);
+ this.length = (0, _pvutils.getParametersValue)(parameters.lenBlock, "length", 0);
+ } else {
+ this.isIndefiniteForm = false;
+ this.longFormUsed = false;
+ this.length = 0;
+ }
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "lengthBlock";
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number}
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
+ //region Getting Uint8Array from ArrayBuffer
+
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength); //endregion
+ //region Initial checks
+
+ if (intBuffer.length === 0) {
+ this.error = "Zero buffer length";
+ return -1;
+ }
+
+ if (intBuffer[0] === 0xFF) {
+ this.error = "Length block 0xFF is reserved by standard";
+ return -1;
+ } //endregion
+ //region Check for length form type
+
+
+ this.isIndefiniteForm = intBuffer[0] === 0x80; //endregion
+ //region Stop working in case of indefinite length form
+
+ if (this.isIndefiniteForm === true) {
+ this.blockLength = 1;
+ return inputOffset + this.blockLength;
+ } //endregion
+ //region Check is long form of length encoding using
+
+
+ this.longFormUsed = !!(intBuffer[0] & 0x80); //endregion
+ //region Stop working in case of short form of length value
+
+ if (this.longFormUsed === false) {
+ this.length = intBuffer[0];
+ this.blockLength = 1;
+ return inputOffset + this.blockLength;
+ } //endregion
+ //region Calculate length value in case of long form
+
+
+ const count = intBuffer[0] & 0x7F;
+
+ if (count > 8) // Too big length value
+ {
+ this.error = "Too big integer";
+ return -1;
+ }
+
+ if (count + 1 > intBuffer.length) {
+ this.error = "End of input reached before message was fully decoded";
+ return -1;
+ }
+
+ const lengthBufferView = new Uint8Array(count);
+
+ for (let i = 0; i < count; i++) lengthBufferView[i] = intBuffer[i + 1];
+
+ if (lengthBufferView[count - 1] === 0x00) this.warnings.push("Needlessly long encoded length");
+ this.length = (0, _pvutils.utilFromBase)(lengthBufferView, 8);
+ if (this.longFormUsed && this.length <= 127) this.warnings.push("Unneccesary usage of long length form");
+ this.blockLength = count + 1; //endregion
+
+ return inputOffset + this.blockLength; // Return current offset in input buffer
+ } //**********************************************************************************
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ //region Initial variables
+ let retBuf;
+ let retView; //endregion
+
+ if (this.length > 127) this.longFormUsed = true;
+
+ if (this.isIndefiniteForm) {
+ retBuf = new ArrayBuffer(1);
+
+ if (sizeOnly === false) {
+ retView = new Uint8Array(retBuf);
+ retView[0] = 0x80;
+ }
+
+ return retBuf;
+ }
+
+ if (this.longFormUsed === true) {
+ const encodedBuf = (0, _pvutils.utilToBase)(this.length, 8);
+
+ if (encodedBuf.byteLength > 127) {
+ this.error = "Too big length";
+ return new ArrayBuffer(0);
+ }
+
+ retBuf = new ArrayBuffer(encodedBuf.byteLength + 1);
+ if (sizeOnly === true) return retBuf;
+ const encodedView = new Uint8Array(encodedBuf);
+ retView = new Uint8Array(retBuf);
+ retView[0] = encodedBuf.byteLength | 0x80;
+
+ for (let i = 0; i < encodedBuf.byteLength; i++) retView[i + 1] = encodedView[i];
+
+ return retBuf;
+ }
+
+ retBuf = new ArrayBuffer(1);
+
+ if (sizeOnly === false) {
+ retView = new Uint8Array(retBuf);
+ retView[0] = this.length;
+ }
+
+ return retBuf;
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.blockName = this.constructor.blockName();
+ object.isIndefiniteForm = this.isIndefiniteForm;
+ object.longFormUsed = this.longFormUsed;
+ object.length = this.length;
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of value block class
+//**************************************************************************************
+
+
+class ValueBlock extends LocalBaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "ValueBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "valueBlock";
+ } //**********************************************************************************
+ //noinspection JSUnusedLocalSymbols,JSUnusedLocalSymbols,JSUnusedLocalSymbols
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number}
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Throw an exception for a function which needs to be specified in extended classes
+ throw TypeError("User need to make a specific function in a class which extends \"ValueBlock\""); //endregion
+ } //**********************************************************************************
+ //noinspection JSUnusedLocalSymbols
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ //region Throw an exception for a function which needs to be specified in extended classes
+ throw TypeError("User need to make a specific function in a class which extends \"ValueBlock\""); //endregion
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of basic ASN.1 block class
+//**************************************************************************************
+
+
+exports.ValueBlock = ValueBlock;
+
+class BaseBlock extends LocalBaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "BaseBlock" class
+ * @param {Object} [parameters={}]
+ * @property {Object} [primitiveSchema]
+ * @property {string} [name]
+ * @property {boolean} [optional]
+ * @param valueBlockType Type of value block
+ */
+ constructor(parameters = {}, valueBlockType = ValueBlock) {
+ super(parameters);
+ if ("name" in parameters) this.name = parameters.name;
+ if ("optional" in parameters) this.optional = parameters.optional;
+ if ("primitiveSchema" in parameters) this.primitiveSchema = parameters.primitiveSchema;
+ this.idBlock = new LocalIdentificationBlock(parameters);
+ this.lenBlock = new LocalLengthBlock(parameters);
+ this.valueBlock = new valueBlockType(parameters);
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "BaseBlock";
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number}
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
+
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+ return resultOffset;
+ }
+
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+ if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
+ return resultOffset;
+ } //**********************************************************************************
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ let retBuf;
+ const idBlockBuf = this.idBlock.toBER(sizeOnly);
+ const valueBlockSizeBuf = this.valueBlock.toBER(true);
+ this.lenBlock.length = valueBlockSizeBuf.byteLength;
+ const lenBlockBuf = this.lenBlock.toBER(sizeOnly);
+ retBuf = (0, _pvutils.utilConcatBuf)(idBlockBuf, lenBlockBuf);
+ let valueBlockBuf;
+ if (sizeOnly === false) valueBlockBuf = this.valueBlock.toBER(sizeOnly);else valueBlockBuf = new ArrayBuffer(this.lenBlock.length);
+ retBuf = (0, _pvutils.utilConcatBuf)(retBuf, valueBlockBuf);
+
+ if (this.lenBlock.isIndefiniteForm === true) {
+ const indefBuf = new ArrayBuffer(2);
+
+ if (sizeOnly === false) {
+ const indefView = new Uint8Array(indefBuf);
+ indefView[0] = 0x00;
+ indefView[1] = 0x00;
+ }
+
+ retBuf = (0, _pvutils.utilConcatBuf)(retBuf, indefBuf);
+ }
+
+ return retBuf;
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.idBlock = this.idBlock.toJSON();
+ object.lenBlock = this.lenBlock.toJSON();
+ object.valueBlock = this.valueBlock.toJSON();
+ if ("name" in this) object.name = this.name;
+ if ("optional" in this) object.optional = this.optional;
+ if ("primitiveSchema" in this) object.primitiveSchema = this.primitiveSchema.toJSON();
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of basic block for all PRIMITIVE types
+//**************************************************************************************
+
+
+exports.BaseBlock = BaseBlock;
+
+class LocalPrimitiveValueBlock extends ValueBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalPrimitiveValueBlock" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueBeforeDecode]
+ */
+ constructor(parameters = {}) {
+ super(parameters); //region Variables from "hexBlock" class
+
+ if ("valueHex" in parameters) this.valueHex = parameters.valueHex.slice(0);else this.valueHex = new ArrayBuffer(0);
+ this.isHexOnly = (0, _pvutils.getParametersValue)(parameters, "isHexOnly", true); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number}
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
+ //region Getting Uint8Array from ArrayBuffer
+
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength); //endregion
+ //region Initial checks
+
+ if (intBuffer.length === 0) {
+ this.warnings.push("Zero buffer length");
+ return inputOffset;
+ } //endregion
+ //region Copy input buffer into internal buffer
+
+
+ this.valueHex = new ArrayBuffer(intBuffer.length);
+ const valueHexView = new Uint8Array(this.valueHex);
+
+ for (let i = 0; i < intBuffer.length; i++) valueHexView[i] = intBuffer[i]; //endregion
+
+
+ this.blockLength = inputLength;
+ return inputOffset + inputLength;
+ } //**********************************************************************************
+ //noinspection JSUnusedLocalSymbols
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ return this.valueHex.slice(0);
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "PrimitiveValueBlock";
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.valueHex = (0, _pvutils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
+ object.isHexOnly = this.isHexOnly;
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+class Primitive extends BaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "Primitive" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalPrimitiveValueBlock);
+ this.idBlock.isConstructed = false;
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "PRIMITIVE";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of basic block for all CONSTRUCTED types
+//**************************************************************************************
+
+
+exports.Primitive = Primitive;
+
+class LocalConstructedValueBlock extends ValueBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalConstructedValueBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.value = (0, _pvutils.getParametersValue)(parameters, "value", []);
+ this.isIndefiniteForm = (0, _pvutils.getParametersValue)(parameters, "isIndefiniteForm", false);
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number}
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Store initial offset and length
+ const initialOffset = inputOffset;
+ const initialLength = inputLength; //endregion
+ //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
+ //region Getting Uint8Array from ArrayBuffer
+
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength); //endregion
+ //region Initial checks
+
+ if (intBuffer.length === 0) {
+ this.warnings.push("Zero buffer length");
+ return inputOffset;
+ } //endregion
+ //region Aux function
+
+
+ function checkLen(indefiniteLength, length) {
+ if (indefiniteLength === true) return 1;
+ return length;
+ } //endregion
+
+
+ let currentOffset = inputOffset;
+
+ while (checkLen(this.isIndefiniteForm, inputLength) > 0) {
+ const returnObject = LocalFromBER(inputBuffer, currentOffset, inputLength);
+
+ if (returnObject.offset === -1) {
+ this.error = returnObject.result.error;
+ this.warnings.concat(returnObject.result.warnings);
+ return -1;
+ }
+
+ currentOffset = returnObject.offset;
+ this.blockLength += returnObject.result.blockLength;
+ inputLength -= returnObject.result.blockLength;
+ this.value.push(returnObject.result);
+ if (this.isIndefiniteForm === true && returnObject.result.constructor.blockName() === EndOfContent.blockName()) break;
+ }
+
+ if (this.isIndefiniteForm === true) {
+ if (this.value[this.value.length - 1].constructor.blockName() === EndOfContent.blockName()) this.value.pop();else this.warnings.push("No EndOfContent block encoded");
+ } //region Copy "inputBuffer" to "valueBeforeDecode"
+
+
+ this.valueBeforeDecode = inputBuffer.slice(initialOffset, initialOffset + initialLength); //endregion
+
+ return currentOffset;
+ } //**********************************************************************************
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ let retBuf = new ArrayBuffer(0);
+
+ for (let i = 0; i < this.value.length; i++) {
+ const valueBuf = this.value[i].toBER(sizeOnly);
+ retBuf = (0, _pvutils.utilConcatBuf)(retBuf, valueBuf);
+ }
+
+ return retBuf;
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "ConstructedValueBlock";
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.isIndefiniteForm = this.isIndefiniteForm;
+ object.value = [];
+
+ for (let i = 0; i < this.value.length; i++) object.value.push(this.value[i].toJSON());
+
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+class Constructed extends BaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "Constructed" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalConstructedValueBlock);
+ this.idBlock.isConstructed = true;
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "CONSTRUCTED";
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number}
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ this.valueBlock.isIndefiniteForm = this.lenBlock.isIndefiniteForm;
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
+
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+ return resultOffset;
+ }
+
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+ if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
+ return resultOffset;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 EndOfContent type class
+//**************************************************************************************
+
+
+exports.Constructed = Constructed;
+
+class LocalEndOfContentValueBlock extends ValueBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalEndOfContentValueBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ } //**********************************************************************************
+ //noinspection JSUnusedLocalSymbols,JSUnusedLocalSymbols
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number}
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region There is no "value block" for EndOfContent type and we need to return the same offset
+ return inputOffset; //endregion
+ } //**********************************************************************************
+ //noinspection JSUnusedLocalSymbols
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ return new ArrayBuffer(0);
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "EndOfContentValueBlock";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+class EndOfContent extends BaseBlock {
+ //**********************************************************************************
+ constructor(paramaters = {}) {
+ super(paramaters, LocalEndOfContentValueBlock);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 0; // EndOfContent
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "EndOfContent";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 Boolean type class
+//**************************************************************************************
+
+
+exports.EndOfContent = EndOfContent;
+
+class LocalBooleanValueBlock extends ValueBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalBooleanValueBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.value = (0, _pvutils.getParametersValue)(parameters, "value", false);
+ this.isHexOnly = (0, _pvutils.getParametersValue)(parameters, "isHexOnly", false);
+ if ("valueHex" in parameters) this.valueHex = parameters.valueHex.slice(0);else {
+ this.valueHex = new ArrayBuffer(1);
+
+ if (this.value === true) {
+ const view = new Uint8Array(this.valueHex);
+ view[0] = 0xFF;
+ }
+ }
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
+ //region Getting Uint8Array from ArrayBuffer
+
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength); //endregion
+
+ if (inputLength > 1) this.warnings.push("Boolean value encoded in more then 1 octet");
+ this.isHexOnly = true; //region Copy input buffer to internal array
+
+ this.valueHex = new ArrayBuffer(intBuffer.length);
+ const view = new Uint8Array(this.valueHex);
+
+ for (let i = 0; i < intBuffer.length; i++) view[i] = intBuffer[i]; //endregion
+
+
+ if (_pvutils.utilDecodeTC.call(this) !== 0) this.value = true;else this.value = false;
+ this.blockLength = inputLength;
+ return inputOffset + inputLength;
+ } //**********************************************************************************
+ //noinspection JSUnusedLocalSymbols
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ return this.valueHex;
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "BooleanValueBlock";
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.value = this.value;
+ object.isHexOnly = this.isHexOnly;
+ object.valueHex = (0, _pvutils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+class Boolean extends BaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "Boolean" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalBooleanValueBlock);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 1; // Boolean
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "Boolean";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 Sequence and Set type classes
+//**************************************************************************************
+
+
+exports.Boolean = Boolean;
+
+class Sequence extends Constructed {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "Sequence" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 16; // Sequence
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "Sequence";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.Sequence = Sequence;
+
+class Set extends Constructed {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "Set" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 17; // Set
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "Set";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 Null type class
+//**************************************************************************************
+
+
+exports.Set = Set;
+
+class Null extends BaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "Null" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalBaseBlock); // We will not have a call to "Null value block" because of specified "fromBER" and "toBER" functions
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 5; // Null
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "Null";
+ } //**********************************************************************************
+ //noinspection JSUnusedLocalSymbols
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ if (this.lenBlock.length > 0) this.warnings.push("Non-zero length of value block for Null type");
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+ this.blockLength += inputLength;
+
+ if (inputOffset + inputLength > inputBuffer.byteLength) {
+ this.error = "End of input reached before message was fully decoded (inconsistent offset and length values)";
+ return -1;
+ }
+
+ return inputOffset + inputLength;
+ } //**********************************************************************************
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ const retBuf = new ArrayBuffer(2);
+ if (sizeOnly === true) return retBuf;
+ const retView = new Uint8Array(retBuf);
+ retView[0] = 0x05;
+ retView[1] = 0x00;
+ return retBuf;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 OctetString type class
+//**************************************************************************************
+
+
+exports.Null = Null;
+
+class LocalOctetStringValueBlock extends HexBlock(LocalConstructedValueBlock) {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalOctetStringValueBlock" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.isConstructed = (0, _pvutils.getParametersValue)(parameters, "isConstructed", false);
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ let resultOffset = 0;
+
+ if (this.isConstructed === true) {
+ this.isHexOnly = false;
+ resultOffset = LocalConstructedValueBlock.prototype.fromBER.call(this, inputBuffer, inputOffset, inputLength);
+ if (resultOffset === -1) return resultOffset;
+
+ for (let i = 0; i < this.value.length; i++) {
+ const currentBlockName = this.value[i].constructor.blockName();
+
+ if (currentBlockName === EndOfContent.blockName()) {
+ if (this.isIndefiniteForm === true) break;else {
+ this.error = "EndOfContent is unexpected, OCTET STRING may consists of OCTET STRINGs only";
+ return -1;
+ }
+ }
+
+ if (currentBlockName !== OctetString.blockName()) {
+ this.error = "OCTET STRING may consists of OCTET STRINGs only";
+ return -1;
+ }
+ }
+ } else {
+ this.isHexOnly = true;
+ resultOffset = super.fromBER(inputBuffer, inputOffset, inputLength);
+ this.blockLength = inputLength;
+ }
+
+ return resultOffset;
+ } //**********************************************************************************
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ if (this.isConstructed === true) return LocalConstructedValueBlock.prototype.toBER.call(this, sizeOnly);
+ let retBuf = new ArrayBuffer(this.valueHex.byteLength);
+ if (sizeOnly === true) return retBuf;
+ if (this.valueHex.byteLength === 0) return retBuf;
+ retBuf = this.valueHex.slice(0);
+ return retBuf;
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "OctetStringValueBlock";
+ } //**********************************************************************************
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.isConstructed = this.isConstructed;
+ object.isHexOnly = this.isHexOnly;
+ object.valueHex = (0, _pvutils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+class OctetString extends BaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "OctetString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalOctetStringValueBlock);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 4; // OctetString
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ this.valueBlock.isConstructed = this.idBlock.isConstructed;
+ this.valueBlock.isIndefiniteForm = this.lenBlock.isIndefiniteForm; //region Ability to encode empty OCTET STRING
+
+ if (inputLength === 0) {
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+ return inputOffset;
+ } //endregion
+
+
+ return super.fromBER(inputBuffer, inputOffset, inputLength);
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "OctetString";
+ } //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+
+ /**
+ * Checking that two OCTETSTRINGs are equal
+ * @param {OctetString} octetString
+ */
+
+
+ isEqual(octetString) {
+ //region Check input type
+ if (octetString instanceof OctetString === false) return false; //endregion
+ //region Compare two JSON strings
+
+ if (JSON.stringify(this) !== JSON.stringify(octetString)) return false; //endregion
+
+ return true;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 BitString type class
+//**************************************************************************************
+
+
+exports.OctetString = OctetString;
+
+class LocalBitStringValueBlock extends HexBlock(LocalConstructedValueBlock) {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalBitStringValueBlock" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.unusedBits = (0, _pvutils.getParametersValue)(parameters, "unusedBits", 0);
+ this.isConstructed = (0, _pvutils.getParametersValue)(parameters, "isConstructed", false);
+ this.blockLength = this.valueHex.byteLength;
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Ability to decode zero-length BitString value
+ if (inputLength === 0) return inputOffset; //endregion
+
+ let resultOffset = -1; //region If the BISTRING supposed to be a constructed value
+
+ if (this.isConstructed === true) {
+ resultOffset = LocalConstructedValueBlock.prototype.fromBER.call(this, inputBuffer, inputOffset, inputLength);
+ if (resultOffset === -1) return resultOffset;
+
+ for (let i = 0; i < this.value.length; i++) {
+ const currentBlockName = this.value[i].constructor.blockName();
+
+ if (currentBlockName === EndOfContent.blockName()) {
+ if (this.isIndefiniteForm === true) break;else {
+ this.error = "EndOfContent is unexpected, BIT STRING may consists of BIT STRINGs only";
+ return -1;
+ }
+ }
+
+ if (currentBlockName !== BitString.blockName()) {
+ this.error = "BIT STRING may consists of BIT STRINGs only";
+ return -1;
+ }
+
+ if (this.unusedBits > 0 && this.value[i].valueBlock.unusedBits > 0) {
+ this.error = "Usign of \"unused bits\" inside constructive BIT STRING allowed for least one only";
+ return -1;
+ }
+
+ this.unusedBits = this.value[i].valueBlock.unusedBits;
+
+ if (this.unusedBits > 7) {
+ this.error = "Unused bits for BitString must be in range 0-7";
+ return -1;
+ }
+ }
+
+ return resultOffset;
+ } //endregion
+ //region If the BitString supposed to be a primitive value
+ //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+
+
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
+
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
+ this.unusedBits = intBuffer[0];
+
+ if (this.unusedBits > 7) {
+ this.error = "Unused bits for BitString must be in range 0-7";
+ return -1;
+ } //region Copy input buffer to internal buffer
+
+
+ this.valueHex = new ArrayBuffer(intBuffer.length - 1);
+ const view = new Uint8Array(this.valueHex);
+
+ for (let i = 0; i < inputLength - 1; i++) view[i] = intBuffer[i + 1]; //endregion
+
+
+ this.blockLength = intBuffer.length;
+ return inputOffset + inputLength; //endregion
+ } //**********************************************************************************
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ if (this.isConstructed === true) return LocalConstructedValueBlock.prototype.toBER.call(this, sizeOnly);
+ if (sizeOnly === true) return new ArrayBuffer(this.valueHex.byteLength + 1);
+ if (this.valueHex.byteLength === 0) return new ArrayBuffer(0);
+ const curView = new Uint8Array(this.valueHex);
+ const retBuf = new ArrayBuffer(this.valueHex.byteLength + 1);
+ const retView = new Uint8Array(retBuf);
+ retView[0] = this.unusedBits;
+
+ for (let i = 0; i < this.valueHex.byteLength; i++) retView[i + 1] = curView[i];
+
+ return retBuf;
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "BitStringValueBlock";
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {{blockName, blockLength, error, warnings, valueBeforeDecode}|{blockName: string, blockLength: number, error: string, warnings: Array.<string>, valueBeforeDecode: string}}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.unusedBits = this.unusedBits;
+ object.isConstructed = this.isConstructed;
+ object.isHexOnly = this.isHexOnly;
+ object.valueHex = (0, _pvutils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+class BitString extends BaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "BitString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalBitStringValueBlock);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 3; // BitString
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "BitString";
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ //region Ability to encode empty BitString
+ if (inputLength === 0) return inputOffset; //endregion
+
+ this.valueBlock.isConstructed = this.idBlock.isConstructed;
+ this.valueBlock.isIndefiniteForm = this.lenBlock.isIndefiniteForm;
+ return super.fromBER(inputBuffer, inputOffset, inputLength);
+ } //**********************************************************************************
+
+ /**
+ * Checking that two BITSTRINGs are equal
+ * @param {BitString} bitString
+ */
+
+
+ isEqual(bitString) {
+ //region Check input type
+ if (bitString instanceof BitString === false) return false; //endregion
+ //region Compare two JSON strings
+
+ if (JSON.stringify(this) !== JSON.stringify(bitString)) return false; //endregion
+
+ return true;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 Integer type class
+//**************************************************************************************
+
+/**
+ * @extends ValueBlock
+ */
+
+
+exports.BitString = BitString;
+
+class LocalIntegerValueBlock extends HexBlock(ValueBlock) {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalIntegerValueBlock" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ if ("value" in parameters) this.valueDec = parameters.value;
+ } //**********************************************************************************
+
+ /**
+ * Setter for "valueHex"
+ * @param {ArrayBuffer} _value
+ */
+
+
+ set valueHex(_value) {
+ this._valueHex = _value.slice(0);
+
+ if (_value.byteLength >= 4) {
+ this.warnings.push("Too big Integer for decoding, hex only");
+ this.isHexOnly = true;
+ this._valueDec = 0;
+ } else {
+ this.isHexOnly = false;
+ if (_value.byteLength > 0) this._valueDec = _pvutils.utilDecodeTC.call(this);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Getter for "valueHex"
+ * @returns {ArrayBuffer}
+ */
+
+
+ get valueHex() {
+ return this._valueHex;
+ } //**********************************************************************************
+
+ /**
+ * Getter for "valueDec"
+ * @param {number} _value
+ */
+
+
+ set valueDec(_value) {
+ this._valueDec = _value;
+ this.isHexOnly = false;
+ this._valueHex = (0, _pvutils.utilEncodeTC)(_value);
+ } //**********************************************************************************
+
+ /**
+ * Getter for "valueDec"
+ * @returns {number}
+ */
+
+
+ get valueDec() {
+ return this._valueDec;
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from DER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 DER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 DER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @param {number} [expectedLength=0] Expected length of converted "valueHex" buffer
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromDER(inputBuffer, inputOffset, inputLength, expectedLength = 0) {
+ const offset = this.fromBER(inputBuffer, inputOffset, inputLength);
+ if (offset === -1) return offset;
+ const view = new Uint8Array(this._valueHex);
+
+ if (view[0] === 0x00 && (view[1] & 0x80) !== 0) {
+ const updatedValueHex = new ArrayBuffer(this._valueHex.byteLength - 1);
+ const updatedView = new Uint8Array(updatedValueHex);
+ updatedView.set(new Uint8Array(this._valueHex, 1, this._valueHex.byteLength - 1));
+ this._valueHex = updatedValueHex.slice(0);
+ } else {
+ if (expectedLength !== 0) {
+ if (this._valueHex.byteLength < expectedLength) {
+ if (expectedLength - this._valueHex.byteLength > 1) expectedLength = this._valueHex.byteLength + 1;
+ const updatedValueHex = new ArrayBuffer(expectedLength);
+ const updatedView = new Uint8Array(updatedValueHex);
+ updatedView.set(view, expectedLength - this._valueHex.byteLength);
+ this._valueHex = updatedValueHex.slice(0);
+ }
+ }
+ }
+
+ return offset;
+ } //**********************************************************************************
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (DER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toDER(sizeOnly = false) {
+ const view = new Uint8Array(this._valueHex);
+
+ switch (true) {
+ case (view[0] & 0x80) !== 0:
+ {
+ const updatedValueHex = new ArrayBuffer(this._valueHex.byteLength + 1);
+ const updatedView = new Uint8Array(updatedValueHex);
+ updatedView[0] = 0x00;
+ updatedView.set(view, 1);
+ this._valueHex = updatedValueHex.slice(0);
+ }
+ break;
+
+ case view[0] === 0x00 && (view[1] & 0x80) === 0:
+ {
+ const updatedValueHex = new ArrayBuffer(this._valueHex.byteLength - 1);
+ const updatedView = new Uint8Array(updatedValueHex);
+ updatedView.set(new Uint8Array(this._valueHex, 1, this._valueHex.byteLength - 1));
+ this._valueHex = updatedValueHex.slice(0);
+ }
+ break;
+
+ default:
+ }
+
+ return this.toBER(sizeOnly);
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ const resultOffset = super.fromBER(inputBuffer, inputOffset, inputLength);
+ if (resultOffset === -1) return resultOffset;
+ this.blockLength = inputLength;
+ return inputOffset + inputLength;
+ } //**********************************************************************************
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ //noinspection JSCheckFunctionSignatures
+ return this.valueHex.slice(0);
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "IntegerValueBlock";
+ } //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.valueDec = this.valueDec;
+ return object;
+ } //**********************************************************************************
+
+ /**
+ * Convert current value to decimal string representation
+ */
+
+
+ toString() {
+ //region Aux functions
+ function viewAdd(first, second) {
+ //region Initial variables
+ const c = new Uint8Array([0]);
+ let firstView = new Uint8Array(first);
+ let secondView = new Uint8Array(second);
+ let firstViewCopy = firstView.slice(0);
+ const firstViewCopyLength = firstViewCopy.length - 1;
+ let secondViewCopy = secondView.slice(0);
+ const secondViewCopyLength = secondViewCopy.length - 1;
+ let value = 0;
+ const max = secondViewCopyLength < firstViewCopyLength ? firstViewCopyLength : secondViewCopyLength;
+ let counter = 0; //endregion
+
+ for (let i = max; i >= 0; i--, counter++) {
+ switch (true) {
+ case counter < secondViewCopy.length:
+ value = firstViewCopy[firstViewCopyLength - counter] + secondViewCopy[secondViewCopyLength - counter] + c[0];
+ break;
+
+ default:
+ value = firstViewCopy[firstViewCopyLength - counter] + c[0];
+ }
+
+ c[0] = value / 10;
+
+ switch (true) {
+ case counter >= firstViewCopy.length:
+ firstViewCopy = (0, _pvutils.utilConcatView)(new Uint8Array([value % 10]), firstViewCopy);
+ break;
+
+ default:
+ firstViewCopy[firstViewCopyLength - counter] = value % 10;
+ }
+ }
+
+ if (c[0] > 0) firstViewCopy = (0, _pvutils.utilConcatView)(c, firstViewCopy);
+ return firstViewCopy.slice(0);
+ }
+
+ function power2(n) {
+ if (n >= powers2.length) {
+ for (let p = powers2.length; p <= n; p++) {
+ const c = new Uint8Array([0]);
+ let digits = powers2[p - 1].slice(0);
+
+ for (let i = digits.length - 1; i >= 0; i--) {
+ const newValue = new Uint8Array([(digits[i] << 1) + c[0]]);
+ c[0] = newValue[0] / 10;
+ digits[i] = newValue[0] % 10;
+ }
+
+ if (c[0] > 0) digits = (0, _pvutils.utilConcatView)(c, digits);
+ powers2.push(digits);
+ }
+ }
+
+ return powers2[n];
+ }
+
+ function viewSub(first, second) {
+ //region Initial variables
+ let b = 0;
+ let firstView = new Uint8Array(first);
+ let secondView = new Uint8Array(second);
+ let firstViewCopy = firstView.slice(0);
+ const firstViewCopyLength = firstViewCopy.length - 1;
+ let secondViewCopy = secondView.slice(0);
+ const secondViewCopyLength = secondViewCopy.length - 1;
+ let value;
+ let counter = 0; //endregion
+
+ for (let i = secondViewCopyLength; i >= 0; i--, counter++) {
+ value = firstViewCopy[firstViewCopyLength - counter] - secondViewCopy[secondViewCopyLength - counter] - b;
+
+ switch (true) {
+ case value < 0:
+ b = 1;
+ firstViewCopy[firstViewCopyLength - counter] = value + 10;
+ break;
+
+ default:
+ b = 0;
+ firstViewCopy[firstViewCopyLength - counter] = value;
+ }
+ }
+
+ if (b > 0) {
+ for (let i = firstViewCopyLength - secondViewCopyLength + 1; i >= 0; i--, counter++) {
+ value = firstViewCopy[firstViewCopyLength - counter] - b;
+
+ if (value < 0) {
+ b = 1;
+ firstViewCopy[firstViewCopyLength - counter] = value + 10;
+ } else {
+ b = 0;
+ firstViewCopy[firstViewCopyLength - counter] = value;
+ break;
+ }
+ }
+ }
+
+ return firstViewCopy.slice();
+ } //endregion
+ //region Initial variables
+
+
+ const firstBit = this._valueHex.byteLength * 8 - 1;
+ let digits = new Uint8Array(this._valueHex.byteLength * 8 / 3);
+ let bitNumber = 0;
+ let currentByte;
+ const asn1View = new Uint8Array(this._valueHex);
+ let result = "";
+ let flag = false; //endregion
+ //region Calculate number
+
+ for (let byteNumber = this._valueHex.byteLength - 1; byteNumber >= 0; byteNumber--) {
+ currentByte = asn1View[byteNumber];
+
+ for (let i = 0; i < 8; i++) {
+ if ((currentByte & 1) === 1) {
+ switch (bitNumber) {
+ case firstBit:
+ digits = viewSub(power2(bitNumber), digits);
+ result = "-";
+ break;
+
+ default:
+ digits = viewAdd(digits, power2(bitNumber));
+ }
+ }
+
+ bitNumber++;
+ currentByte >>= 1;
+ }
+ } //endregion
+ //region Print number
+
+
+ for (let i = 0; i < digits.length; i++) {
+ if (digits[i]) flag = true;
+ if (flag) result += digitsString.charAt(digits[i]);
+ }
+
+ if (flag === false) result += digitsString.charAt(0); //endregion
+
+ return result;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+class Integer extends BaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "Integer" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalIntegerValueBlock);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 2; // Integer
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "Integer";
+ } //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+
+ /**
+ * Compare two Integer object, or Integer and ArrayBuffer objects
+ * @param {!Integer|ArrayBuffer} otherValue
+ * @returns {boolean}
+ */
+
+
+ isEqual(otherValue) {
+ if (otherValue instanceof Integer) {
+ if (this.valueBlock.isHexOnly && otherValue.valueBlock.isHexOnly) // Compare two ArrayBuffers
+ return (0, _pvutils.isEqualBuffer)(this.valueBlock.valueHex, otherValue.valueBlock.valueHex);
+ if (this.valueBlock.isHexOnly === otherValue.valueBlock.isHexOnly) return this.valueBlock.valueDec === otherValue.valueBlock.valueDec;
+ return false;
+ }
+
+ if (otherValue instanceof ArrayBuffer) return (0, _pvutils.isEqualBuffer)(this.valueBlock.valueHex, otherValue);
+ return false;
+ } //**********************************************************************************
+
+ /**
+ * Convert current Integer value from BER into DER format
+ * @returns {Integer}
+ */
+
+
+ convertToDER() {
+ const integer = new Integer({
+ valueHex: this.valueBlock.valueHex
+ });
+ integer.valueBlock.toDER();
+ return integer;
+ } //**********************************************************************************
+
+ /**
+ * Convert current Integer value from DER to BER format
+ * @returns {Integer}
+ */
+
+
+ convertFromDER() {
+ const expectedLength = this.valueBlock.valueHex.byteLength % 2 ? this.valueBlock.valueHex.byteLength + 1 : this.valueBlock.valueHex.byteLength;
+ const integer = new Integer({
+ valueHex: this.valueBlock.valueHex
+ });
+ integer.valueBlock.fromDER(integer.valueBlock.valueHex, 0, integer.valueBlock.valueHex.byteLength, expectedLength);
+ return integer;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 Enumerated type class
+//**************************************************************************************
+
+
+exports.Integer = Integer;
+
+class Enumerated extends Integer {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "Enumerated" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 10; // Enumerated
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "Enumerated";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of ASN.1 ObjectIdentifier type class
+//**************************************************************************************
+
+
+exports.Enumerated = Enumerated;
+
+class LocalSidValueBlock extends HexBlock(LocalBaseBlock) {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalSidValueBlock" class
+ * @param {Object} [parameters={}]
+ * @property {number} [valueDec]
+ * @property {boolean} [isFirstSid]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.valueDec = (0, _pvutils.getParametersValue)(parameters, "valueDec", -1);
+ this.isFirstSid = (0, _pvutils.getParametersValue)(parameters, "isFirstSid", false);
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "sidBlock";
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ if (inputLength === 0) return inputOffset; //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
+
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
+ this.valueHex = new ArrayBuffer(inputLength);
+ let view = new Uint8Array(this.valueHex);
+
+ for (let i = 0; i < inputLength; i++) {
+ view[i] = intBuffer[i] & 0x7F;
+ this.blockLength++;
+ if ((intBuffer[i] & 0x80) === 0x00) break;
+ } //region Ajust size of valueHex buffer
+
+
+ const tempValueHex = new ArrayBuffer(this.blockLength);
+ const tempView = new Uint8Array(tempValueHex);
+
+ for (let i = 0; i < this.blockLength; i++) tempView[i] = view[i]; //noinspection JSCheckFunctionSignatures
+
+
+ this.valueHex = tempValueHex.slice(0);
+ view = new Uint8Array(this.valueHex); //endregion
+
+ if ((intBuffer[this.blockLength - 1] & 0x80) !== 0x00) {
+ this.error = "End of input reached before message was fully decoded";
+ return -1;
+ }
+
+ if (view[0] === 0x00) this.warnings.push("Needlessly long format of SID encoding");
+ if (this.blockLength <= 8) this.valueDec = (0, _pvutils.utilFromBase)(view, 7);else {
+ this.isHexOnly = true;
+ this.warnings.push("Too big SID for decoding, hex only");
+ }
+ return inputOffset + this.blockLength;
+ } //**********************************************************************************
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ //region Initial variables
+ let retBuf;
+ let retView; //endregion
+
+ if (this.isHexOnly) {
+ if (sizeOnly === true) return new ArrayBuffer(this.valueHex.byteLength);
+ const curView = new Uint8Array(this.valueHex);
+ retBuf = new ArrayBuffer(this.blockLength);
+ retView = new Uint8Array(retBuf);
+
+ for (let i = 0; i < this.blockLength - 1; i++) retView[i] = curView[i] | 0x80;
+
+ retView[this.blockLength - 1] = curView[this.blockLength - 1];
+ return retBuf;
+ }
+
+ const encodedBuf = (0, _pvutils.utilToBase)(this.valueDec, 7);
+
+ if (encodedBuf.byteLength === 0) {
+ this.error = "Error during encoding SID value";
+ return new ArrayBuffer(0);
+ }
+
+ retBuf = new ArrayBuffer(encodedBuf.byteLength);
+
+ if (sizeOnly === false) {
+ const encodedView = new Uint8Array(encodedBuf);
+ retView = new Uint8Array(retBuf);
+
+ for (let i = 0; i < encodedBuf.byteLength - 1; i++) retView[i] = encodedView[i] | 0x80;
+
+ retView[encodedBuf.byteLength - 1] = encodedView[encodedBuf.byteLength - 1];
+ }
+
+ return retBuf;
+ } //**********************************************************************************
+
+ /**
+ * Create string representation of current SID block
+ * @returns {string}
+ */
+
+
+ toString() {
+ let result = "";
+ if (this.isHexOnly === true) result = (0, _pvutils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);else {
+ if (this.isFirstSid) {
+ let sidValue = this.valueDec;
+ if (this.valueDec <= 39) result = "0.";else {
+ if (this.valueDec <= 79) {
+ result = "1.";
+ sidValue -= 40;
+ } else {
+ result = "2.";
+ sidValue -= 80;
+ }
+ }
+ result += sidValue.toString();
+ } else result = this.valueDec.toString();
+ }
+ return result;
+ } //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.valueDec = this.valueDec;
+ object.isFirstSid = this.isFirstSid;
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+class LocalObjectIdentifierValueBlock extends ValueBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalObjectIdentifierValueBlock" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.fromString((0, _pvutils.getParametersValue)(parameters, "value", ""));
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ let resultOffset = inputOffset;
+
+ while (inputLength > 0) {
+ const sidBlock = new LocalSidValueBlock();
+ resultOffset = sidBlock.fromBER(inputBuffer, resultOffset, inputLength);
+
+ if (resultOffset === -1) {
+ this.blockLength = 0;
+ this.error = sidBlock.error;
+ return resultOffset;
+ }
+
+ if (this.value.length === 0) sidBlock.isFirstSid = true;
+ this.blockLength += sidBlock.blockLength;
+ inputLength -= sidBlock.blockLength;
+ this.value.push(sidBlock);
+ }
+
+ return resultOffset;
+ } //**********************************************************************************
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ let retBuf = new ArrayBuffer(0);
+
+ for (let i = 0; i < this.value.length; i++) {
+ const valueBuf = this.value[i].toBER(sizeOnly);
+
+ if (valueBuf.byteLength === 0) {
+ this.error = this.value[i].error;
+ return new ArrayBuffer(0);
+ }
+
+ retBuf = (0, _pvutils.utilConcatBuf)(retBuf, valueBuf);
+ }
+
+ return retBuf;
+ } //**********************************************************************************
+
+ /**
+ * Create "LocalObjectIdentifierValueBlock" class from string
+ * @param {string} string Input string to convert from
+ * @returns {boolean}
+ */
+
+
+ fromString(string) {
+ this.value = []; // Clear existing SID values
+
+ let pos1 = 0;
+ let pos2 = 0;
+ let sid = "";
+ let flag = false;
+
+ do {
+ pos2 = string.indexOf(".", pos1);
+ if (pos2 === -1) sid = string.substr(pos1);else sid = string.substr(pos1, pos2 - pos1);
+ pos1 = pos2 + 1;
+
+ if (flag) {
+ const sidBlock = this.value[0];
+ let plus = 0;
+
+ switch (sidBlock.valueDec) {
+ case 0:
+ break;
+
+ case 1:
+ plus = 40;
+ break;
+
+ case 2:
+ plus = 80;
+ break;
+
+ default:
+ this.value = []; // clear SID array
+
+ return false;
+ // ???
+ }
+
+ const parsedSID = parseInt(sid, 10);
+ if (isNaN(parsedSID)) return true;
+ sidBlock.valueDec = parsedSID + plus;
+ flag = false;
+ } else {
+ const sidBlock = new LocalSidValueBlock();
+ sidBlock.valueDec = parseInt(sid, 10);
+ if (isNaN(sidBlock.valueDec)) return true;
+
+ if (this.value.length === 0) {
+ sidBlock.isFirstSid = true;
+ flag = true;
+ }
+
+ this.value.push(sidBlock);
+ }
+ } while (pos2 !== -1);
+
+ return true;
+ } //**********************************************************************************
+
+ /**
+ * Converts "LocalObjectIdentifierValueBlock" class to string
+ * @returns {string}
+ */
+
+
+ toString() {
+ let result = "";
+ let isHexOnly = false;
+
+ for (let i = 0; i < this.value.length; i++) {
+ isHexOnly = this.value[i].isHexOnly;
+ let sidStr = this.value[i].toString();
+ if (i !== 0) result = `${result}.`;
+
+ if (isHexOnly) {
+ sidStr = `{${sidStr}}`;
+ if (this.value[i].isFirstSid) result = `2.{${sidStr} - 80}`;else result += sidStr;
+ } else result += sidStr;
+ }
+
+ return result;
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "ObjectIdentifierValueBlock";
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.value = this.toString();
+ object.sidArray = [];
+
+ for (let i = 0; i < this.value.length; i++) object.sidArray.push(this.value[i].toJSON());
+
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends BaseBlock
+ */
+
+
+class ObjectIdentifier extends BaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "ObjectIdentifier" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalObjectIdentifierValueBlock);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 6; // OBJECT IDENTIFIER
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "ObjectIdentifier";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of all string's classes
+//**************************************************************************************
+
+
+exports.ObjectIdentifier = ObjectIdentifier;
+
+class LocalUtf8StringValueBlock extends HexBlock(LocalBaseBlock) {
+ //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+
+ /**
+ * Constructor for "LocalUtf8StringValueBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.isHexOnly = true;
+ this.value = ""; // String representation of decoded ArrayBuffer
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "Utf8StringValueBlock";
+ } //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.value = this.value;
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends BaseBlock
+ */
+
+
+class Utf8String extends BaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "Utf8String" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalUtf8StringValueBlock);
+ if ("value" in parameters) this.fromString(parameters.value);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 12; // Utf8String
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "Utf8String";
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
+
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+ return resultOffset;
+ }
+
+ this.fromBuffer(this.valueBlock.valueHex);
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+ if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
+ return resultOffset;
+ } //**********************************************************************************
+
+ /**
+ * Function converting ArrayBuffer into ASN.1 internal string
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ */
+
+
+ fromBuffer(inputBuffer) {
+ this.valueBlock.value = String.fromCharCode.apply(null, new Uint8Array(inputBuffer));
+
+ try {
+ //noinspection JSDeprecatedSymbols
+ this.valueBlock.value = decodeURIComponent(escape(this.valueBlock.value));
+ } catch (ex) {
+ this.warnings.push(`Error during "decodeURIComponent": ${ex}, using raw string`);
+ }
+ } //**********************************************************************************
+
+ /**
+ * Function converting JavaScript string into ASN.1 internal class
+ * @param {!string} inputString ASN.1 BER encoded array
+ */
+
+
+ fromString(inputString) {
+ //noinspection JSDeprecatedSymbols
+ const str = unescape(encodeURIComponent(inputString));
+ const strLen = str.length;
+ this.valueBlock.valueHex = new ArrayBuffer(strLen);
+ const view = new Uint8Array(this.valueBlock.valueHex);
+
+ for (let i = 0; i < strLen; i++) view[i] = str.charCodeAt(i);
+
+ this.valueBlock.value = inputString;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//region Declaration of ASN.1 RelativeObjectIdentifier type class
+//**************************************************************************************
+
+
+exports.Utf8String = Utf8String;
+
+class LocalRelativeSidValueBlock extends HexBlock(LocalBaseBlock) {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalRelativeSidValueBlock" class
+ * @param {Object} [parameters={}]
+ * @property {number} [valueDec]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.valueDec = (0, _pvutils.getParametersValue)(parameters, "valueDec", -1);
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "relativeSidBlock";
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ if (inputLength === 0) return inputOffset; //region Basic check for parameters
+ //noinspection JSCheckFunctionSignatures
+
+ if ((0, _pvutils.checkBufferParams)(this, inputBuffer, inputOffset, inputLength) === false) return -1; //endregion
+
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength);
+ this.valueHex = new ArrayBuffer(inputLength);
+ let view = new Uint8Array(this.valueHex);
+
+ for (let i = 0; i < inputLength; i++) {
+ view[i] = intBuffer[i] & 0x7F;
+ this.blockLength++;
+ if ((intBuffer[i] & 0x80) === 0x00) break;
+ } //region Ajust size of valueHex buffer
+
+
+ const tempValueHex = new ArrayBuffer(this.blockLength);
+ const tempView = new Uint8Array(tempValueHex);
+
+ for (let i = 0; i < this.blockLength; i++) tempView[i] = view[i]; //noinspection JSCheckFunctionSignatures
+
+
+ this.valueHex = tempValueHex.slice(0);
+ view = new Uint8Array(this.valueHex); //endregion
+
+ if ((intBuffer[this.blockLength - 1] & 0x80) !== 0x00) {
+ this.error = "End of input reached before message was fully decoded";
+ return -1;
+ }
+
+ if (view[0] === 0x00) this.warnings.push("Needlessly long format of SID encoding");
+ if (this.blockLength <= 8) this.valueDec = (0, _pvutils.utilFromBase)(view, 7);else {
+ this.isHexOnly = true;
+ this.warnings.push("Too big SID for decoding, hex only");
+ }
+ return inputOffset + this.blockLength;
+ } //**********************************************************************************
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ //region Initial variables
+ let retBuf;
+ let retView; //endregion
+
+ if (this.isHexOnly) {
+ if (sizeOnly === true) return new ArrayBuffer(this.valueHex.byteLength);
+ const curView = new Uint8Array(this.valueHex);
+ retBuf = new ArrayBuffer(this.blockLength);
+ retView = new Uint8Array(retBuf);
+
+ for (let i = 0; i < this.blockLength - 1; i++) retView[i] = curView[i] | 0x80;
+
+ retView[this.blockLength - 1] = curView[this.blockLength - 1];
+ return retBuf;
+ }
+
+ const encodedBuf = (0, _pvutils.utilToBase)(this.valueDec, 7);
+
+ if (encodedBuf.byteLength === 0) {
+ this.error = "Error during encoding SID value";
+ return new ArrayBuffer(0);
+ }
+
+ retBuf = new ArrayBuffer(encodedBuf.byteLength);
+
+ if (sizeOnly === false) {
+ const encodedView = new Uint8Array(encodedBuf);
+ retView = new Uint8Array(retBuf);
+
+ for (let i = 0; i < encodedBuf.byteLength - 1; i++) retView[i] = encodedView[i] | 0x80;
+
+ retView[encodedBuf.byteLength - 1] = encodedView[encodedBuf.byteLength - 1];
+ }
+
+ return retBuf;
+ } //**********************************************************************************
+
+ /**
+ * Create string representation of current SID block
+ * @returns {string}
+ */
+
+
+ toString() {
+ let result = "";
+ if (this.isHexOnly === true) result = (0, _pvutils.bufferToHexCodes)(this.valueHex, 0, this.valueHex.byteLength);else {
+ result = this.valueDec.toString();
+ }
+ return result;
+ } //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.valueDec = this.valueDec;
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+class LocalRelativeObjectIdentifierValueBlock extends ValueBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalRelativeObjectIdentifierValueBlock" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.fromString((0, _pvutils.getParametersValue)(parameters, "value", ""));
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ let resultOffset = inputOffset;
+
+ while (inputLength > 0) {
+ const sidBlock = new LocalRelativeSidValueBlock();
+ resultOffset = sidBlock.fromBER(inputBuffer, resultOffset, inputLength);
+
+ if (resultOffset === -1) {
+ this.blockLength = 0;
+ this.error = sidBlock.error;
+ return resultOffset;
+ }
+
+ this.blockLength += sidBlock.blockLength;
+ inputLength -= sidBlock.blockLength;
+ this.value.push(sidBlock);
+ }
+
+ return resultOffset;
+ } //**********************************************************************************
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ let retBuf = new ArrayBuffer(0);
+
+ for (let i = 0; i < this.value.length; i++) {
+ const valueBuf = this.value[i].toBER(sizeOnly);
+
+ if (valueBuf.byteLength === 0) {
+ this.error = this.value[i].error;
+ return new ArrayBuffer(0);
+ }
+
+ retBuf = (0, _pvutils.utilConcatBuf)(retBuf, valueBuf);
+ }
+
+ return retBuf;
+ } //**********************************************************************************
+
+ /**
+ * Create "LocalRelativeObjectIdentifierValueBlock" class from string
+ * @param {string} string Input string to convert from
+ * @returns {boolean}
+ */
+
+
+ fromString(string) {
+ this.value = []; // Clear existing SID values
+
+ let pos1 = 0;
+ let pos2 = 0;
+ let sid = "";
+
+ do {
+ pos2 = string.indexOf(".", pos1);
+ if (pos2 === -1) sid = string.substr(pos1);else sid = string.substr(pos1, pos2 - pos1);
+ pos1 = pos2 + 1;
+ const sidBlock = new LocalRelativeSidValueBlock();
+ sidBlock.valueDec = parseInt(sid, 10);
+ if (isNaN(sidBlock.valueDec)) return true;
+ this.value.push(sidBlock);
+ } while (pos2 !== -1);
+
+ return true;
+ } //**********************************************************************************
+
+ /**
+ * Converts "LocalRelativeObjectIdentifierValueBlock" class to string
+ * @returns {string}
+ */
+
+
+ toString() {
+ let result = "";
+ let isHexOnly = false;
+
+ for (let i = 0; i < this.value.length; i++) {
+ isHexOnly = this.value[i].isHexOnly;
+ let sidStr = this.value[i].toString();
+ if (i !== 0) result = `${result}.`;
+
+ if (isHexOnly) {
+ sidStr = `{${sidStr}}`;
+ result += sidStr;
+ } else result += sidStr;
+ }
+
+ return result;
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "RelativeObjectIdentifierValueBlock";
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.value = this.toString();
+ object.sidArray = [];
+
+ for (let i = 0; i < this.value.length; i++) object.sidArray.push(this.value[i].toJSON());
+
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends BaseBlock
+ */
+
+
+class RelativeObjectIdentifier extends BaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "RelativeObjectIdentifier" class
+ * @param {Object} [parameters={}]
+ * @property {ArrayBuffer} [valueHex]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalRelativeObjectIdentifierValueBlock);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 13; // RELATIVE OBJECT IDENTIFIER
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "RelativeObjectIdentifier";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+
+/**
+ * @extends LocalBaseBlock
+ * @extends HexBlock
+ */
+
+
+exports.RelativeObjectIdentifier = RelativeObjectIdentifier;
+
+class LocalBmpStringValueBlock extends HexBlock(LocalBaseBlock) {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalBmpStringValueBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.isHexOnly = true;
+ this.value = "";
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "BmpStringValueBlock";
+ } //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.value = this.value;
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends BaseBlock
+ */
+
+
+class BmpString extends BaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "BmpString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalBmpStringValueBlock);
+ if ("value" in parameters) this.fromString(parameters.value);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 30; // BmpString
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "BmpString";
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
+
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+ return resultOffset;
+ }
+
+ this.fromBuffer(this.valueBlock.valueHex);
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+ if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
+ return resultOffset;
+ } //**********************************************************************************
+
+ /**
+ * Function converting ArrayBuffer into ASN.1 internal string
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ */
+
+
+ fromBuffer(inputBuffer) {
+ //noinspection JSCheckFunctionSignatures
+ const copyBuffer = inputBuffer.slice(0);
+ const valueView = new Uint8Array(copyBuffer);
+
+ for (let i = 0; i < valueView.length; i += 2) {
+ const temp = valueView[i];
+ valueView[i] = valueView[i + 1];
+ valueView[i + 1] = temp;
+ }
+
+ this.valueBlock.value = String.fromCharCode.apply(null, new Uint16Array(copyBuffer));
+ } //**********************************************************************************
+
+ /**
+ * Function converting JavaScript string into ASN.1 internal class
+ * @param {!string} inputString ASN.1 BER encoded array
+ */
+
+
+ fromString(inputString) {
+ const strLength = inputString.length;
+ this.valueBlock.valueHex = new ArrayBuffer(strLength * 2);
+ const valueHexView = new Uint8Array(this.valueBlock.valueHex);
+
+ for (let i = 0; i < strLength; i++) {
+ const codeBuf = (0, _pvutils.utilToBase)(inputString.charCodeAt(i), 8);
+ const codeView = new Uint8Array(codeBuf);
+ if (codeView.length > 2) continue;
+ const dif = 2 - codeView.length;
+
+ for (let j = codeView.length - 1; j >= 0; j--) valueHexView[i * 2 + j + dif] = codeView[j];
+ }
+
+ this.valueBlock.value = inputString;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.BmpString = BmpString;
+
+class LocalUniversalStringValueBlock extends HexBlock(LocalBaseBlock) {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalUniversalStringValueBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.isHexOnly = true;
+ this.value = "";
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "UniversalStringValueBlock";
+ } //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.value = this.value;
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends BaseBlock
+ */
+
+
+class UniversalString extends BaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "UniversalString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalUniversalStringValueBlock);
+ if ("value" in parameters) this.fromString(parameters.value);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 28; // UniversalString
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "UniversalString";
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
+
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+ return resultOffset;
+ }
+
+ this.fromBuffer(this.valueBlock.valueHex);
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+ if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
+ return resultOffset;
+ } //**********************************************************************************
+
+ /**
+ * Function converting ArrayBuffer into ASN.1 internal string
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ */
+
+
+ fromBuffer(inputBuffer) {
+ //noinspection JSCheckFunctionSignatures
+ const copyBuffer = inputBuffer.slice(0);
+ const valueView = new Uint8Array(copyBuffer);
+
+ for (let i = 0; i < valueView.length; i += 4) {
+ valueView[i] = valueView[i + 3];
+ valueView[i + 1] = valueView[i + 2];
+ valueView[i + 2] = 0x00;
+ valueView[i + 3] = 0x00;
+ }
+
+ this.valueBlock.value = String.fromCharCode.apply(null, new Uint32Array(copyBuffer));
+ } //**********************************************************************************
+
+ /**
+ * Function converting JavaScript string into ASN.1 internal class
+ * @param {!string} inputString ASN.1 BER encoded array
+ */
+
+
+ fromString(inputString) {
+ const strLength = inputString.length;
+ this.valueBlock.valueHex = new ArrayBuffer(strLength * 4);
+ const valueHexView = new Uint8Array(this.valueBlock.valueHex);
+
+ for (let i = 0; i < strLength; i++) {
+ const codeBuf = (0, _pvutils.utilToBase)(inputString.charCodeAt(i), 8);
+ const codeView = new Uint8Array(codeBuf);
+ if (codeView.length > 4) continue;
+ const dif = 4 - codeView.length;
+
+ for (let j = codeView.length - 1; j >= 0; j--) valueHexView[i * 4 + j + dif] = codeView[j];
+ }
+
+ this.valueBlock.value = inputString;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+
+exports.UniversalString = UniversalString;
+
+class LocalSimpleStringValueBlock extends HexBlock(LocalBaseBlock) {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalSimpleStringValueBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.value = "";
+ this.isHexOnly = true;
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "SimpleStringValueBlock";
+ } //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.value = this.value;
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends BaseBlock
+ */
+
+
+class LocalSimpleStringBlock extends BaseBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "LocalSimpleStringBlock" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters, LocalSimpleStringValueBlock);
+ if ("value" in parameters) this.fromString(parameters.value);
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "SIMPLESTRING";
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
+
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+ return resultOffset;
+ }
+
+ this.fromBuffer(this.valueBlock.valueHex);
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+ if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
+ return resultOffset;
+ } //**********************************************************************************
+
+ /**
+ * Function converting ArrayBuffer into ASN.1 internal string
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ */
+
+
+ fromBuffer(inputBuffer) {
+ this.valueBlock.value = String.fromCharCode.apply(null, new Uint8Array(inputBuffer));
+ } //**********************************************************************************
+
+ /**
+ * Function converting JavaScript string into ASN.1 internal class
+ * @param {!string} inputString ASN.1 BER encoded array
+ */
+
+
+ fromString(inputString) {
+ const strLen = inputString.length;
+ this.valueBlock.valueHex = new ArrayBuffer(strLen);
+ const view = new Uint8Array(this.valueBlock.valueHex);
+
+ for (let i = 0; i < strLen; i++) view[i] = inputString.charCodeAt(i);
+
+ this.valueBlock.value = inputString;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+
+class NumericString extends LocalSimpleStringBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "NumericString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 18; // NumericString
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "NumericString";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+
+exports.NumericString = NumericString;
+
+class PrintableString extends LocalSimpleStringBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "PrintableString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 19; // PrintableString
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "PrintableString";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+
+exports.PrintableString = PrintableString;
+
+class TeletexString extends LocalSimpleStringBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "TeletexString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 20; // TeletexString
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "TeletexString";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+
+exports.TeletexString = TeletexString;
+
+class VideotexString extends LocalSimpleStringBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "VideotexString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 21; // VideotexString
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "VideotexString";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+
+exports.VideotexString = VideotexString;
+
+class IA5String extends LocalSimpleStringBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "IA5String" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 22; // IA5String
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "IA5String";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+
+exports.IA5String = IA5String;
+
+class GraphicString extends LocalSimpleStringBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "GraphicString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 25; // GraphicString
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "GraphicString";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+
+exports.GraphicString = GraphicString;
+
+class VisibleString extends LocalSimpleStringBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "VisibleString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 26; // VisibleString
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "VisibleString";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+
+exports.VisibleString = VisibleString;
+
+class GeneralString extends LocalSimpleStringBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "GeneralString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 27; // GeneralString
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "GeneralString";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends LocalSimpleStringBlock
+ */
+
+
+exports.GeneralString = GeneralString;
+
+class CharacterString extends LocalSimpleStringBlock {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "CharacterString" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 29; // CharacterString
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "CharacterString";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of all date and time classes
+//**************************************************************************************
+
+/**
+ * @extends VisibleString
+ */
+
+
+exports.CharacterString = CharacterString;
+
+class UTCTime extends VisibleString {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "UTCTime" class
+ * @param {Object} [parameters={}]
+ * @property {string} [value] String representatio of the date
+ * @property {Date} [valueDate] JavaScript "Date" object
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.year = 0;
+ this.month = 0;
+ this.day = 0;
+ this.hour = 0;
+ this.minute = 0;
+ this.second = 0; //region Create UTCTime from ASN.1 UTC string value
+
+ if ("value" in parameters) {
+ this.fromString(parameters.value);
+ this.valueBlock.valueHex = new ArrayBuffer(parameters.value.length);
+ const view = new Uint8Array(this.valueBlock.valueHex);
+
+ for (let i = 0; i < parameters.value.length; i++) view[i] = parameters.value.charCodeAt(i);
+ } //endregion
+ //region Create GeneralizedTime from JavaScript Date type
+
+
+ if ("valueDate" in parameters) {
+ this.fromDate(parameters.valueDate);
+ this.valueBlock.valueHex = this.toBuffer();
+ } //endregion
+
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 23; // UTCTime
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
+
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+ return resultOffset;
+ }
+
+ this.fromBuffer(this.valueBlock.valueHex);
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+ if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
+ return resultOffset;
+ } //**********************************************************************************
+
+ /**
+ * Function converting ArrayBuffer into ASN.1 internal string
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ */
+
+
+ fromBuffer(inputBuffer) {
+ this.fromString(String.fromCharCode.apply(null, new Uint8Array(inputBuffer)));
+ } //**********************************************************************************
+
+ /**
+ * Function converting ASN.1 internal string into ArrayBuffer
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBuffer() {
+ const str = this.toString();
+ const buffer = new ArrayBuffer(str.length);
+ const view = new Uint8Array(buffer);
+
+ for (let i = 0; i < str.length; i++) view[i] = str.charCodeAt(i);
+
+ return buffer;
+ } //**********************************************************************************
+
+ /**
+ * Function converting "Date" object into ASN.1 internal string
+ * @param {!Date} inputDate JavaScript "Date" object
+ */
+
+
+ fromDate(inputDate) {
+ this.year = inputDate.getUTCFullYear();
+ this.month = inputDate.getUTCMonth() + 1;
+ this.day = inputDate.getUTCDate();
+ this.hour = inputDate.getUTCHours();
+ this.minute = inputDate.getUTCMinutes();
+ this.second = inputDate.getUTCSeconds();
+ } //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+
+ /**
+ * Function converting ASN.1 internal string into "Date" object
+ * @returns {Date}
+ */
+
+
+ toDate() {
+ return new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second));
+ } //**********************************************************************************
+
+ /**
+ * Function converting JavaScript string into ASN.1 internal class
+ * @param {!string} inputString ASN.1 BER encoded array
+ */
+
+
+ fromString(inputString) {
+ //region Parse input string
+ const parser = /(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})Z/ig;
+ const parserArray = parser.exec(inputString);
+
+ if (parserArray === null) {
+ this.error = "Wrong input string for convertion";
+ return;
+ } //endregion
+ //region Store parsed values
+
+
+ const year = parseInt(parserArray[1], 10);
+ if (year >= 50) this.year = 1900 + year;else this.year = 2000 + year;
+ this.month = parseInt(parserArray[2], 10);
+ this.day = parseInt(parserArray[3], 10);
+ this.hour = parseInt(parserArray[4], 10);
+ this.minute = parseInt(parserArray[5], 10);
+ this.second = parseInt(parserArray[6], 10); //endregion
+ } //**********************************************************************************
+
+ /**
+ * Function converting ASN.1 internal class into JavaScript string
+ * @returns {string}
+ */
+
+
+ toString() {
+ const outputArray = new Array(7);
+ outputArray[0] = (0, _pvutils.padNumber)(this.year < 2000 ? this.year - 1900 : this.year - 2000, 2);
+ outputArray[1] = (0, _pvutils.padNumber)(this.month, 2);
+ outputArray[2] = (0, _pvutils.padNumber)(this.day, 2);
+ outputArray[3] = (0, _pvutils.padNumber)(this.hour, 2);
+ outputArray[4] = (0, _pvutils.padNumber)(this.minute, 2);
+ outputArray[5] = (0, _pvutils.padNumber)(this.second, 2);
+ outputArray[6] = "Z";
+ return outputArray.join("");
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "UTCTime";
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.year = this.year;
+ object.month = this.month;
+ object.day = this.day;
+ object.hour = this.hour;
+ object.minute = this.minute;
+ object.second = this.second;
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends VisibleString
+ */
+
+
+exports.UTCTime = UTCTime;
+
+class GeneralizedTime extends VisibleString {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "GeneralizedTime" class
+ * @param {Object} [parameters={}]
+ * @property {string} [value] String representatio of the date
+ * @property {Date} [valueDate] JavaScript "Date" object
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.year = 0;
+ this.month = 0;
+ this.day = 0;
+ this.hour = 0;
+ this.minute = 0;
+ this.second = 0;
+ this.millisecond = 0; //region Create UTCTime from ASN.1 UTC string value
+
+ if ("value" in parameters) {
+ this.fromString(parameters.value);
+ this.valueBlock.valueHex = new ArrayBuffer(parameters.value.length);
+ const view = new Uint8Array(this.valueBlock.valueHex);
+
+ for (let i = 0; i < parameters.value.length; i++) view[i] = parameters.value.charCodeAt(i);
+ } //endregion
+ //region Create GeneralizedTime from JavaScript Date type
+
+
+ if ("valueDate" in parameters) {
+ this.fromDate(parameters.valueDate);
+ this.valueBlock.valueHex = this.toBuffer();
+ } //endregion
+
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 24; // GeneralizedTime
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm === true ? inputLength : this.lenBlock.length);
+
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+ return resultOffset;
+ }
+
+ this.fromBuffer(this.valueBlock.valueHex);
+ if (this.idBlock.error.length === 0) this.blockLength += this.idBlock.blockLength;
+ if (this.lenBlock.error.length === 0) this.blockLength += this.lenBlock.blockLength;
+ if (this.valueBlock.error.length === 0) this.blockLength += this.valueBlock.blockLength;
+ return resultOffset;
+ } //**********************************************************************************
+
+ /**
+ * Function converting ArrayBuffer into ASN.1 internal string
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ */
+
+
+ fromBuffer(inputBuffer) {
+ this.fromString(String.fromCharCode.apply(null, new Uint8Array(inputBuffer)));
+ } //**********************************************************************************
+
+ /**
+ * Function converting ASN.1 internal string into ArrayBuffer
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBuffer() {
+ const str = this.toString();
+ const buffer = new ArrayBuffer(str.length);
+ const view = new Uint8Array(buffer);
+
+ for (let i = 0; i < str.length; i++) view[i] = str.charCodeAt(i);
+
+ return buffer;
+ } //**********************************************************************************
+
+ /**
+ * Function converting "Date" object into ASN.1 internal string
+ * @param {!Date} inputDate JavaScript "Date" object
+ */
+
+
+ fromDate(inputDate) {
+ this.year = inputDate.getUTCFullYear();
+ this.month = inputDate.getUTCMonth() + 1;
+ this.day = inputDate.getUTCDate();
+ this.hour = inputDate.getUTCHours();
+ this.minute = inputDate.getUTCMinutes();
+ this.second = inputDate.getUTCSeconds();
+ this.millisecond = inputDate.getUTCMilliseconds();
+ } //**********************************************************************************
+ //noinspection JSUnusedGlobalSymbols
+
+ /**
+ * Function converting ASN.1 internal string into "Date" object
+ * @returns {Date}
+ */
+
+
+ toDate() {
+ return new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second, this.millisecond));
+ } //**********************************************************************************
+
+ /**
+ * Function converting JavaScript string into ASN.1 internal class
+ * @param {!string} inputString ASN.1 BER encoded array
+ */
+
+
+ fromString(inputString) {
+ //region Initial variables
+ let isUTC = false;
+ let timeString = "";
+ let dateTimeString = "";
+ let fractionPart = 0;
+ let parser;
+ let hourDifference = 0;
+ let minuteDifference = 0; //endregion
+ //region Convert as UTC time
+
+ if (inputString[inputString.length - 1] === "Z") {
+ timeString = inputString.substr(0, inputString.length - 1);
+ isUTC = true;
+ } //endregion
+ //region Convert as local time
+ else {
+ //noinspection JSPrimitiveTypeWrapperUsage
+ const number = new Number(inputString[inputString.length - 1]);
+ if (isNaN(number.valueOf())) throw new Error("Wrong input string for convertion");
+ timeString = inputString;
+ } //endregion
+ //region Check that we do not have a "+" and "-" symbols inside UTC time
+
+
+ if (isUTC) {
+ if (timeString.indexOf("+") !== -1) throw new Error("Wrong input string for convertion");
+ if (timeString.indexOf("-") !== -1) throw new Error("Wrong input string for convertion");
+ } //endregion
+ //region Get "UTC time difference" in case of local time
+ else {
+ let multiplier = 1;
+ let differencePosition = timeString.indexOf("+");
+ let differenceString = "";
+
+ if (differencePosition === -1) {
+ differencePosition = timeString.indexOf("-");
+ multiplier = -1;
+ }
+
+ if (differencePosition !== -1) {
+ differenceString = timeString.substr(differencePosition + 1);
+ timeString = timeString.substr(0, differencePosition);
+ if (differenceString.length !== 2 && differenceString.length !== 4) throw new Error("Wrong input string for convertion"); //noinspection JSPrimitiveTypeWrapperUsage
+
+ let number = new Number(differenceString.substr(0, 2));
+ if (isNaN(number.valueOf())) throw new Error("Wrong input string for convertion");
+ hourDifference = multiplier * number;
+
+ if (differenceString.length === 4) {
+ //noinspection JSPrimitiveTypeWrapperUsage
+ number = new Number(differenceString.substr(2, 2));
+ if (isNaN(number.valueOf())) throw new Error("Wrong input string for convertion");
+ minuteDifference = multiplier * number;
+ }
+ }
+ } //endregion
+ //region Get position of fraction point
+
+
+ let fractionPointPosition = timeString.indexOf("."); // Check for "full stop" symbol
+
+ if (fractionPointPosition === -1) fractionPointPosition = timeString.indexOf(","); // Check for "comma" symbol
+ //endregion
+ //region Get fraction part
+
+ if (fractionPointPosition !== -1) {
+ //noinspection JSPrimitiveTypeWrapperUsage
+ const fractionPartCheck = new Number(`0${timeString.substr(fractionPointPosition)}`);
+ if (isNaN(fractionPartCheck.valueOf())) throw new Error("Wrong input string for convertion");
+ fractionPart = fractionPartCheck.valueOf();
+ dateTimeString = timeString.substr(0, fractionPointPosition);
+ } else dateTimeString = timeString; //endregion
+ //region Parse internal date
+
+
+ switch (true) {
+ case dateTimeString.length === 8:
+ // "YYYYMMDD"
+ parser = /(\d{4})(\d{2})(\d{2})/ig;
+ if (fractionPointPosition !== -1) throw new Error("Wrong input string for convertion"); // Here we should not have a "fraction point"
+
+ break;
+
+ case dateTimeString.length === 10:
+ // "YYYYMMDDHH"
+ parser = /(\d{4})(\d{2})(\d{2})(\d{2})/ig;
+
+ if (fractionPointPosition !== -1) {
+ let fractionResult = 60 * fractionPart;
+ this.minute = Math.floor(fractionResult);
+ fractionResult = 60 * (fractionResult - this.minute);
+ this.second = Math.floor(fractionResult);
+ fractionResult = 1000 * (fractionResult - this.second);
+ this.millisecond = Math.floor(fractionResult);
+ }
+
+ break;
+
+ case dateTimeString.length === 12:
+ // "YYYYMMDDHHMM"
+ parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/ig;
+
+ if (fractionPointPosition !== -1) {
+ let fractionResult = 60 * fractionPart;
+ this.second = Math.floor(fractionResult);
+ fractionResult = 1000 * (fractionResult - this.second);
+ this.millisecond = Math.floor(fractionResult);
+ }
+
+ break;
+
+ case dateTimeString.length === 14:
+ // "YYYYMMDDHHMMSS"
+ parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/ig;
+
+ if (fractionPointPosition !== -1) {
+ const fractionResult = 1000 * fractionPart;
+ this.millisecond = Math.floor(fractionResult);
+ }
+
+ break;
+
+ default:
+ throw new Error("Wrong input string for convertion");
+ } //endregion
+ //region Put parsed values at right places
+
+
+ const parserArray = parser.exec(dateTimeString);
+ if (parserArray === null) throw new Error("Wrong input string for convertion");
+
+ for (let j = 1; j < parserArray.length; j++) {
+ switch (j) {
+ case 1:
+ this.year = parseInt(parserArray[j], 10);
+ break;
+
+ case 2:
+ this.month = parseInt(parserArray[j], 10);
+ break;
+
+ case 3:
+ this.day = parseInt(parserArray[j], 10);
+ break;
+
+ case 4:
+ this.hour = parseInt(parserArray[j], 10) + hourDifference;
+ break;
+
+ case 5:
+ this.minute = parseInt(parserArray[j], 10) + minuteDifference;
+ break;
+
+ case 6:
+ this.second = parseInt(parserArray[j], 10);
+ break;
+
+ default:
+ throw new Error("Wrong input string for convertion");
+ }
+ } //endregion
+ //region Get final date
+
+
+ if (isUTC === false) {
+ const tempDate = new Date(this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond);
+ this.year = tempDate.getUTCFullYear();
+ this.month = tempDate.getUTCMonth();
+ this.day = tempDate.getUTCDay();
+ this.hour = tempDate.getUTCHours();
+ this.minute = tempDate.getUTCMinutes();
+ this.second = tempDate.getUTCSeconds();
+ this.millisecond = tempDate.getUTCMilliseconds();
+ } //endregion
+
+ } //**********************************************************************************
+
+ /**
+ * Function converting ASN.1 internal class into JavaScript string
+ * @returns {string}
+ */
+
+
+ toString() {
+ const outputArray = [];
+ outputArray.push((0, _pvutils.padNumber)(this.year, 4));
+ outputArray.push((0, _pvutils.padNumber)(this.month, 2));
+ outputArray.push((0, _pvutils.padNumber)(this.day, 2));
+ outputArray.push((0, _pvutils.padNumber)(this.hour, 2));
+ outputArray.push((0, _pvutils.padNumber)(this.minute, 2));
+ outputArray.push((0, _pvutils.padNumber)(this.second, 2));
+
+ if (this.millisecond !== 0) {
+ outputArray.push(".");
+ outputArray.push((0, _pvutils.padNumber)(this.millisecond, 3));
+ }
+
+ outputArray.push("Z");
+ return outputArray.join("");
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "GeneralizedTime";
+ } //**********************************************************************************
+
+ /**
+ * Convertion for the block to JSON object
+ * @returns {Object}
+ */
+
+
+ toJSON() {
+ let object = {}; //region Seems at the moment (Sep 2016) there is no way how to check method is supported in "super" object
+
+ try {
+ object = super.toJSON();
+ } catch (ex) {} //endregion
+
+
+ object.year = this.year;
+ object.month = this.month;
+ object.day = this.day;
+ object.hour = this.hour;
+ object.minute = this.minute;
+ object.second = this.second;
+ object.millisecond = this.millisecond;
+ return object;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends Utf8String
+ */
+
+
+exports.GeneralizedTime = GeneralizedTime;
+
+class DATE extends Utf8String {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "DATE" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 31; // DATE
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "DATE";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends Utf8String
+ */
+
+
+exports.DATE = DATE;
+
+class TimeOfDay extends Utf8String {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "TimeOfDay" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 32; // TimeOfDay
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "TimeOfDay";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends Utf8String
+ */
+
+
+exports.TimeOfDay = TimeOfDay;
+
+class DateTime extends Utf8String {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "DateTime" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 33; // DateTime
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "DateTime";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends Utf8String
+ */
+
+
+exports.DateTime = DateTime;
+
+class Duration extends Utf8String {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "Duration" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 34; // Duration
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "Duration";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+
+/**
+ * @extends Utf8String
+ */
+
+
+exports.Duration = Duration;
+
+class TIME extends Utf8String {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "Time" class
+ * @param {Object} [parameters={}]
+ */
+ constructor(parameters = {}) {
+ super(parameters);
+ this.idBlock.tagClass = 1; // UNIVERSAL
+
+ this.idBlock.tagNumber = 14; // Time
+ } //**********************************************************************************
+
+ /**
+ * Aux function, need to get a block name. Need to have it here for inhiritence
+ * @returns {string}
+ */
+
+
+ static blockName() {
+ return "TIME";
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of special ASN.1 schema type Choice
+//**************************************************************************************
+
+
+exports.TIME = TIME;
+
+class Choice {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "Choice" class
+ * @param {Object} [parameters={}]
+ * @property {Array} [value] Array of ASN.1 types for make a choice from
+ * @property {boolean} [optional]
+ */
+ constructor(parameters = {}) {
+ this.value = (0, _pvutils.getParametersValue)(parameters, "value", []);
+ this.optional = (0, _pvutils.getParametersValue)(parameters, "optional", false);
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of special ASN.1 schema type Any
+//**************************************************************************************
+
+
+exports.Choice = Choice;
+
+class Any {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "Any" class
+ * @param {Object} [parameters={}]
+ * @property {string} [name]
+ * @property {boolean} [optional]
+ */
+ constructor(parameters = {}) {
+ this.name = (0, _pvutils.getParametersValue)(parameters, "name", "");
+ this.optional = (0, _pvutils.getParametersValue)(parameters, "optional", false);
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of special ASN.1 schema type Repeated
+//**************************************************************************************
+
+
+exports.Any = Any;
+
+class Repeated {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "Repeated" class
+ * @param {Object} [parameters={}]
+ * @property {string} [name]
+ * @property {boolean} [optional]
+ */
+ constructor(parameters = {}) {
+ this.name = (0, _pvutils.getParametersValue)(parameters, "name", "");
+ this.optional = (0, _pvutils.getParametersValue)(parameters, "optional", false);
+ this.value = (0, _pvutils.getParametersValue)(parameters, "value", new Any());
+ this.local = (0, _pvutils.getParametersValue)(parameters, "local", false); // Could local or global array to store elements
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Declaration of special ASN.1 schema type RawData
+//**************************************************************************************
+
+/**
+ * @description Special class providing ability to have "toBER/fromBER" for raw ArrayBuffer
+ */
+
+
+exports.Repeated = Repeated;
+
+class RawData {
+ //**********************************************************************************
+
+ /**
+ * Constructor for "Repeated" class
+ * @param {Object} [parameters={}]
+ * @property {string} [name]
+ * @property {boolean} [optional]
+ */
+ constructor(parameters = {}) {
+ this.data = (0, _pvutils.getParametersValue)(parameters, "data", new ArrayBuffer(0));
+ } //**********************************************************************************
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {number} Offset after least decoded byte
+ */
+
+
+ fromBER(inputBuffer, inputOffset, inputLength) {
+ this.data = inputBuffer.slice(inputOffset, inputLength);
+ return inputOffset + inputLength;
+ } //**********************************************************************************
+
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param {boolean} [sizeOnly=false] Flag that we need only a size of encoding, not a real array of bytes
+ * @returns {ArrayBuffer}
+ */
+
+
+ toBER(sizeOnly = false) {
+ return this.data;
+ } //**********************************************************************************
+
+
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Major ASN.1 BER decoding function
+//**************************************************************************************
+
+/**
+ * Internal library function for decoding ASN.1 BER
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array
+ * @param {!number} inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param {!number} inputLength Maximum length of array of bytes which can be using in this function
+ * @returns {{offset: number, result: Object}}
+ */
+
+
+exports.RawData = RawData;
+
+function LocalFromBER(inputBuffer, inputOffset, inputLength) {
+ const incomingOffset = inputOffset; // Need to store initial offset since "inputOffset" is changing in the function
+ //region Local function changing a type for ASN.1 classes
+
+ function localChangeType(inputObject, newType) {
+ if (inputObject instanceof newType) return inputObject;
+ const newObject = new newType();
+ newObject.idBlock = inputObject.idBlock;
+ newObject.lenBlock = inputObject.lenBlock;
+ newObject.warnings = inputObject.warnings; //noinspection JSCheckFunctionSignatures
+
+ newObject.valueBeforeDecode = inputObject.valueBeforeDecode.slice(0);
+ return newObject;
+ } //endregion
+ //region Create a basic ASN.1 type since we need to return errors and warnings from the function
+
+
+ let returnObject = new BaseBlock({}, Object); //endregion
+ //region Basic check for parameters
+
+ const baseBlock = new LocalBaseBlock();
+
+ if ((0, _pvutils.checkBufferParams)(baseBlock, inputBuffer, inputOffset, inputLength) === false) {
+ returnObject.error = baseBlock.error;
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ } //endregion
+ //region Getting Uint8Array from ArrayBuffer
+
+
+ const intBuffer = new Uint8Array(inputBuffer, inputOffset, inputLength); //endregion
+ //region Initial checks
+
+ if (intBuffer.length === 0) {
+ this.error = "Zero buffer length";
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ } //endregion
+ //region Decode indentifcation block of ASN.1 BER structure
+
+
+ let resultOffset = returnObject.idBlock.fromBER(inputBuffer, inputOffset, inputLength);
+ returnObject.warnings.concat(returnObject.idBlock.warnings);
+
+ if (resultOffset === -1) {
+ returnObject.error = returnObject.idBlock.error;
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ }
+
+ inputOffset = resultOffset;
+ inputLength -= returnObject.idBlock.blockLength; //endregion
+ //region Decode length block of ASN.1 BER structure
+
+ resultOffset = returnObject.lenBlock.fromBER(inputBuffer, inputOffset, inputLength);
+ returnObject.warnings.concat(returnObject.lenBlock.warnings);
+
+ if (resultOffset === -1) {
+ returnObject.error = returnObject.lenBlock.error;
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ }
+
+ inputOffset = resultOffset;
+ inputLength -= returnObject.lenBlock.blockLength; //endregion
+ //region Check for usign indefinite length form in encoding for primitive types
+
+ if (returnObject.idBlock.isConstructed === false && returnObject.lenBlock.isIndefiniteForm === true) {
+ returnObject.error = "Indefinite length form used for primitive encoding form";
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ } //endregion
+ //region Switch ASN.1 block type
+
+
+ let newASN1Type = BaseBlock;
+
+ switch (returnObject.idBlock.tagClass) {
+ //region UNIVERSAL
+ case 1:
+ //region Check for reserved tag numbers
+ if (returnObject.idBlock.tagNumber >= 37 && returnObject.idBlock.isHexOnly === false) {
+ returnObject.error = "UNIVERSAL 37 and upper tags are reserved by ASN.1 standard";
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ } //endregion
+
+
+ switch (returnObject.idBlock.tagNumber) {
+ //region EndOfContent type
+ case 0:
+ //region Check for EndOfContent type
+ if (returnObject.idBlock.isConstructed === true && returnObject.lenBlock.length > 0) {
+ returnObject.error = "Type [UNIVERSAL 0] is reserved";
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ } //endregion
+
+
+ newASN1Type = EndOfContent;
+ break;
+ //endregion
+ //region Boolean type
+
+ case 1:
+ newASN1Type = Boolean;
+ break;
+ //endregion
+ //region Integer type
+
+ case 2:
+ newASN1Type = Integer;
+ break;
+ //endregion
+ //region BitString type
+
+ case 3:
+ newASN1Type = BitString;
+ break;
+ //endregion
+ //region OctetString type
+
+ case 4:
+ newASN1Type = OctetString;
+ break;
+ //endregion
+ //region Null type
+
+ case 5:
+ newASN1Type = Null;
+ break;
+ //endregion
+ //region OBJECT IDENTIFIER type
+
+ case 6:
+ newASN1Type = ObjectIdentifier;
+ break;
+ //endregion
+ //region Enumerated type
+
+ case 10:
+ newASN1Type = Enumerated;
+ break;
+ //endregion
+ //region Utf8String type
+
+ case 12:
+ newASN1Type = Utf8String;
+ break;
+ //endregion
+ //region Time type
+ //region RELATIVE OBJECT IDENTIFIER type
+
+ case 13:
+ newASN1Type = RelativeObjectIdentifier;
+ break;
+ //endregion
+
+ case 14:
+ newASN1Type = TIME;
+ break;
+ //endregion
+ //region ASN.1 reserved type
+
+ case 15:
+ returnObject.error = "[UNIVERSAL 15] is reserved by ASN.1 standard";
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ //endregion
+ //region Sequence type
+
+ case 16:
+ newASN1Type = Sequence;
+ break;
+ //endregion
+ //region Set type
+
+ case 17:
+ newASN1Type = Set;
+ break;
+ //endregion
+ //region NumericString type
+
+ case 18:
+ newASN1Type = NumericString;
+ break;
+ //endregion
+ //region PrintableString type
+
+ case 19:
+ newASN1Type = PrintableString;
+ break;
+ //endregion
+ //region TeletexString type
+
+ case 20:
+ newASN1Type = TeletexString;
+ break;
+ //endregion
+ //region VideotexString type
+
+ case 21:
+ newASN1Type = VideotexString;
+ break;
+ //endregion
+ //region IA5String type
+
+ case 22:
+ newASN1Type = IA5String;
+ break;
+ //endregion
+ //region UTCTime type
+
+ case 23:
+ newASN1Type = UTCTime;
+ break;
+ //endregion
+ //region GeneralizedTime type
+
+ case 24:
+ newASN1Type = GeneralizedTime;
+ break;
+ //endregion
+ //region GraphicString type
+
+ case 25:
+ newASN1Type = GraphicString;
+ break;
+ //endregion
+ //region VisibleString type
+
+ case 26:
+ newASN1Type = VisibleString;
+ break;
+ //endregion
+ //region GeneralString type
+
+ case 27:
+ newASN1Type = GeneralString;
+ break;
+ //endregion
+ //region UniversalString type
+
+ case 28:
+ newASN1Type = UniversalString;
+ break;
+ //endregion
+ //region CharacterString type
+
+ case 29:
+ newASN1Type = CharacterString;
+ break;
+ //endregion
+ //region BmpString type
+
+ case 30:
+ newASN1Type = BmpString;
+ break;
+ //endregion
+ //region DATE type
+
+ case 31:
+ newASN1Type = DATE;
+ break;
+ //endregion
+ //region TimeOfDay type
+
+ case 32:
+ newASN1Type = TimeOfDay;
+ break;
+ //endregion
+ //region Date-Time type
+
+ case 33:
+ newASN1Type = DateTime;
+ break;
+ //endregion
+ //region Duration type
+
+ case 34:
+ newASN1Type = Duration;
+ break;
+ //endregion
+ //region default
+
+ default:
+ {
+ let newObject;
+ if (returnObject.idBlock.isConstructed === true) newObject = new Constructed();else newObject = new Primitive();
+ newObject.idBlock = returnObject.idBlock;
+ newObject.lenBlock = returnObject.lenBlock;
+ newObject.warnings = returnObject.warnings;
+ returnObject = newObject;
+ resultOffset = returnObject.fromBER(inputBuffer, inputOffset, inputLength);
+ }
+ //endregion
+ }
+
+ break;
+ //endregion
+ //region All other tag classes
+
+ case 2: // APPLICATION
+
+ case 3: // CONTEXT-SPECIFIC
+
+ case 4: // PRIVATE
+
+ default:
+ {
+ if (returnObject.idBlock.isConstructed === true) newASN1Type = Constructed;else newASN1Type = Primitive;
+ }
+ //endregion
+ } //endregion
+ //region Change type and perform BER decoding
+
+
+ returnObject = localChangeType(returnObject, newASN1Type);
+ resultOffset = returnObject.fromBER(inputBuffer, inputOffset, returnObject.lenBlock.isIndefiniteForm === true ? inputLength : returnObject.lenBlock.length); //endregion
+ //region Coping incoming buffer for entire ASN.1 block
+
+ returnObject.valueBeforeDecode = inputBuffer.slice(incomingOffset, incomingOffset + returnObject.blockLength); //endregion
+
+ return {
+ offset: resultOffset,
+ result: returnObject
+ };
+} //**************************************************************************************
+
+/**
+ * Major function for decoding ASN.1 BER array into internal library structuries
+ * @param {!ArrayBuffer} inputBuffer ASN.1 BER encoded array of bytes
+ */
+
+
+function fromBER(inputBuffer) {
+ if (inputBuffer.byteLength === 0) {
+ const result = new BaseBlock({}, Object);
+ result.error = "Input buffer has zero length";
+ return {
+ offset: -1,
+ result
+ };
+ }
+
+ return LocalFromBER(inputBuffer, 0, inputBuffer.byteLength);
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Major scheme verification function
+//**************************************************************************************
+
+/**
+ * Compare of two ASN.1 object trees
+ * @param {!Object} root Root of input ASN.1 object tree
+ * @param {!Object} inputData Input ASN.1 object tree
+ * @param {!Object} inputSchema Input ASN.1 schema to compare with
+ * @return {{verified: boolean}|{verified:boolean, result: Object}}
+ */
+
+
+function compareSchema(root, inputData, inputSchema) {
+ //region Special case for Choice schema element type
+ if (inputSchema instanceof Choice) {
+ const choiceResult = false;
+
+ for (let j = 0; j < inputSchema.value.length; j++) {
+ const result = compareSchema(root, inputData, inputSchema.value[j]);
+
+ if (result.verified === true) {
+ return {
+ verified: true,
+ result: root
+ };
+ }
+ }
+
+ if (choiceResult === false) {
+ const _result = {
+ verified: false,
+ result: {
+ error: "Wrong values for Choice type"
+ }
+ };
+ if (inputSchema.hasOwnProperty("name")) _result.name = inputSchema.name;
+ return _result;
+ }
+ } //endregion
+ //region Special case for Any schema element type
+
+
+ if (inputSchema instanceof Any) {
+ //region Add named component of ASN.1 schema
+ if (inputSchema.hasOwnProperty("name")) root[inputSchema.name] = inputData; //endregion
+
+ return {
+ verified: true,
+ result: root
+ };
+ } //endregion
+ //region Initial check
+
+
+ if (root instanceof Object === false) {
+ return {
+ verified: false,
+ result: {
+ error: "Wrong root object"
+ }
+ };
+ }
+
+ if (inputData instanceof Object === false) {
+ return {
+ verified: false,
+ result: {
+ error: "Wrong ASN.1 data"
+ }
+ };
+ }
+
+ if (inputSchema instanceof Object === false) {
+ return {
+ verified: false,
+ result: {
+ error: "Wrong ASN.1 schema"
+ }
+ };
+ }
+
+ if ("idBlock" in inputSchema === false) {
+ return {
+ verified: false,
+ result: {
+ error: "Wrong ASN.1 schema"
+ }
+ };
+ } //endregion
+ //region Comparing idBlock properties in ASN.1 data and ASN.1 schema
+ //region Encode and decode ASN.1 schema idBlock
+ /// <remarks>This encoding/decoding is neccessary because could be an errors in schema definition</remarks>
+
+
+ if ("fromBER" in inputSchema.idBlock === false) {
+ return {
+ verified: false,
+ result: {
+ error: "Wrong ASN.1 schema"
+ }
+ };
+ }
+
+ if ("toBER" in inputSchema.idBlock === false) {
+ return {
+ verified: false,
+ result: {
+ error: "Wrong ASN.1 schema"
+ }
+ };
+ }
+
+ const encodedId = inputSchema.idBlock.toBER(false);
+
+ if (encodedId.byteLength === 0) {
+ return {
+ verified: false,
+ result: {
+ error: "Error encoding idBlock for ASN.1 schema"
+ }
+ };
+ }
+
+ const decodedOffset = inputSchema.idBlock.fromBER(encodedId, 0, encodedId.byteLength);
+
+ if (decodedOffset === -1) {
+ return {
+ verified: false,
+ result: {
+ error: "Error decoding idBlock for ASN.1 schema"
+ }
+ };
+ } //endregion
+ //region tagClass
+
+
+ if (inputSchema.idBlock.hasOwnProperty("tagClass") === false) {
+ return {
+ verified: false,
+ result: {
+ error: "Wrong ASN.1 schema"
+ }
+ };
+ }
+
+ if (inputSchema.idBlock.tagClass !== inputData.idBlock.tagClass) {
+ return {
+ verified: false,
+ result: root
+ };
+ } //endregion
+ //region tagNumber
+
+
+ if (inputSchema.idBlock.hasOwnProperty("tagNumber") === false) {
+ return {
+ verified: false,
+ result: {
+ error: "Wrong ASN.1 schema"
+ }
+ };
+ }
+
+ if (inputSchema.idBlock.tagNumber !== inputData.idBlock.tagNumber) {
+ return {
+ verified: false,
+ result: root
+ };
+ } //endregion
+ //region isConstructed
+
+
+ if (inputSchema.idBlock.hasOwnProperty("isConstructed") === false) {
+ return {
+ verified: false,
+ result: {
+ error: "Wrong ASN.1 schema"
+ }
+ };
+ }
+
+ if (inputSchema.idBlock.isConstructed !== inputData.idBlock.isConstructed) {
+ return {
+ verified: false,
+ result: root
+ };
+ } //endregion
+ //region isHexOnly
+
+
+ if ("isHexOnly" in inputSchema.idBlock === false) // Since 'isHexOnly' is an inhirited property
+ {
+ return {
+ verified: false,
+ result: {
+ error: "Wrong ASN.1 schema"
+ }
+ };
+ }
+
+ if (inputSchema.idBlock.isHexOnly !== inputData.idBlock.isHexOnly) {
+ return {
+ verified: false,
+ result: root
+ };
+ } //endregion
+ //region valueHex
+
+
+ if (inputSchema.idBlock.isHexOnly === true) {
+ if ("valueHex" in inputSchema.idBlock === false) // Since 'valueHex' is an inhirited property
+ {
+ return {
+ verified: false,
+ result: {
+ error: "Wrong ASN.1 schema"
+ }
+ };
+ }
+
+ const schemaView = new Uint8Array(inputSchema.idBlock.valueHex);
+ const asn1View = new Uint8Array(inputData.idBlock.valueHex);
+
+ if (schemaView.length !== asn1View.length) {
+ return {
+ verified: false,
+ result: root
+ };
+ }
+
+ for (let i = 0; i < schemaView.length; i++) {
+ if (schemaView[i] !== asn1View[1]) {
+ return {
+ verified: false,
+ result: root
+ };
+ }
+ }
+ } //endregion
+ //endregion
+ //region Add named component of ASN.1 schema
+
+
+ if (inputSchema.hasOwnProperty("name")) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
+ if (inputSchema.name !== "") root[inputSchema.name] = inputData;
+ } //endregion
+ //region Getting next ASN.1 block for comparition
+
+
+ if (inputSchema.idBlock.isConstructed === true) {
+ let admission = 0;
+ let result = {
+ verified: false
+ };
+ let maxLength = inputSchema.valueBlock.value.length;
+
+ if (maxLength > 0) {
+ if (inputSchema.valueBlock.value[0] instanceof Repeated) maxLength = inputData.valueBlock.value.length;
+ } //region Special case when constructive value has no elements
+
+
+ if (maxLength === 0) {
+ return {
+ verified: true,
+ result: root
+ };
+ } //endregion
+ //region Special case when "inputData" has no values and "inputSchema" has all optional values
+
+
+ if (inputData.valueBlock.value.length === 0 && inputSchema.valueBlock.value.length !== 0) {
+ let _optional = true;
+
+ for (let i = 0; i < inputSchema.valueBlock.value.length; i++) _optional = _optional && (inputSchema.valueBlock.value[i].optional || false);
+
+ if (_optional === true) {
+ return {
+ verified: true,
+ result: root
+ };
+ } //region Delete early added name of block
+
+
+ if (inputSchema.hasOwnProperty("name")) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
+ if (inputSchema.name !== "") delete root[inputSchema.name];
+ } //endregion
+
+
+ root.error = "Inconsistent object length";
+ return {
+ verified: false,
+ result: root
+ };
+ } //endregion
+
+
+ for (let i = 0; i < maxLength; i++) {
+ //region Special case when there is an "optional" element of ASN.1 schema at the end
+ if (i - admission >= inputData.valueBlock.value.length) {
+ if (inputSchema.valueBlock.value[i].optional === false) {
+ const _result = {
+ verified: false,
+ result: root
+ };
+ root.error = "Inconsistent length between ASN.1 data and schema"; //region Delete early added name of block
+
+ if (inputSchema.hasOwnProperty("name")) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
+
+ if (inputSchema.name !== "") {
+ delete root[inputSchema.name];
+ _result.name = inputSchema.name;
+ }
+ } //endregion
+
+
+ return _result;
+ }
+ } //endregion
+ else {
+ //region Special case for Repeated type of ASN.1 schema element
+ if (inputSchema.valueBlock.value[0] instanceof Repeated) {
+ result = compareSchema(root, inputData.valueBlock.value[i], inputSchema.valueBlock.value[0].value);
+
+ if (result.verified === false) {
+ if (inputSchema.valueBlock.value[0].optional === true) admission++;else {
+ //region Delete early added name of block
+ if (inputSchema.hasOwnProperty("name")) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
+ if (inputSchema.name !== "") delete root[inputSchema.name];
+ } //endregion
+
+
+ return result;
+ }
+ }
+
+ if ("name" in inputSchema.valueBlock.value[0] && inputSchema.valueBlock.value[0].name.length > 0) {
+ let arrayRoot = {};
+ if ("local" in inputSchema.valueBlock.value[0] && inputSchema.valueBlock.value[0].local === true) arrayRoot = inputData;else arrayRoot = root;
+ if (typeof arrayRoot[inputSchema.valueBlock.value[0].name] === "undefined") arrayRoot[inputSchema.valueBlock.value[0].name] = [];
+ arrayRoot[inputSchema.valueBlock.value[0].name].push(inputData.valueBlock.value[i]);
+ }
+ } //endregion
+ else {
+ result = compareSchema(root, inputData.valueBlock.value[i - admission], inputSchema.valueBlock.value[i]);
+
+ if (result.verified === false) {
+ if (inputSchema.valueBlock.value[i].optional === true) admission++;else {
+ //region Delete early added name of block
+ if (inputSchema.hasOwnProperty("name")) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
+ if (inputSchema.name !== "") delete root[inputSchema.name];
+ } //endregion
+
+
+ return result;
+ }
+ }
+ }
+ }
+ }
+
+ if (result.verified === false) // The situation may take place if last element is "optional" and verification failed
+ {
+ const _result = {
+ verified: false,
+ result: root
+ }; //region Delete early added name of block
+
+ if (inputSchema.hasOwnProperty("name")) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
+
+ if (inputSchema.name !== "") {
+ delete root[inputSchema.name];
+ _result.name = inputSchema.name;
+ }
+ } //endregion
+
+
+ return _result;
+ }
+
+ return {
+ verified: true,
+ result: root
+ };
+ } //endregion
+ //region Ability to parse internal value for primitive-encoded value (value of OctetString, for example)
+
+
+ if ("primitiveSchema" in inputSchema && "valueHex" in inputData.valueBlock) {
+ //region Decoding of raw ASN.1 data
+ const asn1 = fromBER(inputData.valueBlock.valueHex);
+
+ if (asn1.offset === -1) {
+ const _result = {
+ verified: false,
+ result: asn1.result
+ }; //region Delete early added name of block
+
+ if (inputSchema.hasOwnProperty("name")) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, "");
+
+ if (inputSchema.name !== "") {
+ delete root[inputSchema.name];
+ _result.name = inputSchema.name;
+ }
+ } //endregion
+
+
+ return _result;
+ } //endregion
+
+
+ return compareSchema(root, asn1.result, inputSchema.primitiveSchema);
+ }
+
+ return {
+ verified: true,
+ result: root
+ }; //endregion
+} //**************************************************************************************
+//noinspection JSUnusedGlobalSymbols
+
+/**
+ * ASN.1 schema verification for ArrayBuffer data
+ * @param {!ArrayBuffer} inputBuffer Input BER-encoded ASN.1 data
+ * @param {!Object} inputSchema Input ASN.1 schema to verify against to
+ * @return {{verified: boolean}|{verified:boolean, result: Object}}
+ */
+
+
+function verifySchema(inputBuffer, inputSchema) {
+ //region Initial check
+ if (inputSchema instanceof Object === false) {
+ return {
+ verified: false,
+ result: {
+ error: "Wrong ASN.1 schema type"
+ }
+ };
+ } //endregion
+ //region Decoding of raw ASN.1 data
+
+
+ const asn1 = fromBER(inputBuffer);
+
+ if (asn1.offset === -1) {
+ return {
+ verified: false,
+ result: asn1.result
+ };
+ } //endregion
+ //region Compare ASN.1 struct with input schema
+
+
+ return compareSchema(asn1.result, asn1.result, inputSchema); //endregion
+} //**************************************************************************************
+//endregion
+//**************************************************************************************
+//region Major function converting JSON to ASN.1 objects
+//**************************************************************************************
+//noinspection JSUnusedGlobalSymbols
+
+/**
+ * Converting from JSON to ASN.1 objects
+ * @param {string|Object} json JSON string or object to convert to ASN.1 objects
+ */
+
+
+function fromJSON(json) {} // TODO Implement
+//**************************************************************************************
+//endregion
+//**************************************************************************************
+
+},{"pvutils":113}],113:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.getUTCDate = getUTCDate;
+exports.getParametersValue = getParametersValue;
+exports.bufferToHexCodes = bufferToHexCodes;
+exports.checkBufferParams = checkBufferParams;
+exports.utilFromBase = utilFromBase;
+exports.utilToBase = utilToBase;
+exports.utilConcatBuf = utilConcatBuf;
+exports.utilConcatView = utilConcatView;
+exports.utilDecodeTC = utilDecodeTC;
+exports.utilEncodeTC = utilEncodeTC;
+exports.isEqualBuffer = isEqualBuffer;
+exports.padNumber = padNumber;
+exports.toBase64 = toBase64;
+exports.fromBase64 = fromBase64;
+exports.arrayBufferToString = arrayBufferToString;
+exports.stringToArrayBuffer = stringToArrayBuffer;
+exports.nearestPowerOf2 = nearestPowerOf2;
+exports.clearProps = clearProps;
+//**************************************************************************************
+/**
+ * Making UTC date from local date
+ * @param {Date} date Date to convert from
+ * @returns {Date}
+ */
+function getUTCDate(date) {
+ // noinspection NestedFunctionCallJS, MagicNumberJS
+ return new Date(date.getTime() + date.getTimezoneOffset() * 60000);
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleReturnPointsJS
+/**
+ * Get value for input parameters, or set a default value
+ * @param {Object} parameters
+ * @param {string} name
+ * @param defaultValue
+ */
+function getParametersValue(parameters, name, defaultValue) {
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS
+ if (parameters instanceof Object === false) return defaultValue;
+
+ // noinspection NonBlockStatementBodyJS
+ if (name in parameters) return parameters[name];
+
+ return defaultValue;
+}
+//**************************************************************************************
+/**
+ * Converts "ArrayBuffer" into a hexdecimal string
+ * @param {ArrayBuffer} inputBuffer
+ * @param {number} [inputOffset=0]
+ * @param {number} [inputLength=inputBuffer.byteLength]
+ * @param {boolean} [insertSpace=false]
+ * @returns {string}
+ */
+function bufferToHexCodes(inputBuffer, inputOffset = 0, inputLength = inputBuffer.byteLength - inputOffset, insertSpace = false) {
+ let result = "";
+
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = new Uint8Array(inputBuffer, inputOffset, inputLength)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ const item = _step.value;
+
+ // noinspection ChainedFunctionCallJS
+ const str = item.toString(16).toUpperCase();
+
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS
+ if (str.length === 1) result += "0";
+
+ result += str;
+
+ // noinspection NonBlockStatementBodyJS
+ if (insertSpace) result += " ";
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+
+ return result.trim();
+}
+//**************************************************************************************
+// noinspection JSValidateJSDoc, FunctionWithMultipleReturnPointsJS
+/**
+ * Check input "ArrayBuffer" for common functions
+ * @param {LocalBaseBlock} baseBlock
+ * @param {ArrayBuffer} inputBuffer
+ * @param {number} inputOffset
+ * @param {number} inputLength
+ * @returns {boolean}
+ */
+function checkBufferParams(baseBlock, inputBuffer, inputOffset, inputLength) {
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (inputBuffer instanceof ArrayBuffer === false) {
+ // noinspection JSUndefinedPropertyAssignment
+ baseBlock.error = "Wrong parameter: inputBuffer must be \"ArrayBuffer\"";
+ return false;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (inputBuffer.byteLength === 0) {
+ // noinspection JSUndefinedPropertyAssignment
+ baseBlock.error = "Wrong parameter: inputBuffer has zero length";
+ return false;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (inputOffset < 0) {
+ // noinspection JSUndefinedPropertyAssignment
+ baseBlock.error = "Wrong parameter: inputOffset less than zero";
+ return false;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (inputLength < 0) {
+ // noinspection JSUndefinedPropertyAssignment
+ baseBlock.error = "Wrong parameter: inputLength less than zero";
+ return false;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (inputBuffer.byteLength - inputOffset - inputLength < 0) {
+ // noinspection JSUndefinedPropertyAssignment
+ baseBlock.error = "End of input reached before message was fully decoded (inconsistent offset and length values)";
+ return false;
+ }
+
+ return true;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleReturnPointsJS
+/**
+ * Convert number from 2^base to 2^10
+ * @param {Uint8Array} inputBuffer
+ * @param {number} inputBase
+ * @returns {number}
+ */
+function utilFromBase(inputBuffer, inputBase) {
+ let result = 0;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS
+ if (inputBuffer.length === 1) return inputBuffer[0];
+
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS
+ for (let i = inputBuffer.length - 1; i >= 0; i--) result += inputBuffer[inputBuffer.length - 1 - i] * Math.pow(2, inputBase * i);
+
+ return result;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS, FunctionWithMultipleReturnPointsJS
+/**
+ * Convert number from 2^10 to 2^base
+ * @param {!number} value The number to convert
+ * @param {!number} base The base for 2^base
+ * @param {number} [reserved=0] Pre-defined number of bytes in output array (-1 = limited by function itself)
+ * @returns {ArrayBuffer}
+ */
+function utilToBase(value, base, reserved = -1) {
+ const internalReserved = reserved;
+ let internalValue = value;
+
+ let result = 0;
+ let biggest = Math.pow(2, base);
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ for (let i = 1; i < 8; i++) {
+ if (value < biggest) {
+ let retBuf;
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (internalReserved < 0) {
+ retBuf = new ArrayBuffer(i);
+ result = i;
+ } else {
+ // noinspection NonBlockStatementBodyJS
+ if (internalReserved < i) return new ArrayBuffer(0);
+
+ retBuf = new ArrayBuffer(internalReserved);
+
+ result = internalReserved;
+ }
+
+ const retView = new Uint8Array(retBuf);
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ for (let j = i - 1; j >= 0; j--) {
+ const basis = Math.pow(2, j * base);
+
+ retView[result - j - 1] = Math.floor(internalValue / basis);
+ internalValue -= retView[result - j - 1] * basis;
+ }
+
+ return retBuf;
+ }
+
+ biggest *= Math.pow(2, base);
+ }
+
+ return new ArrayBuffer(0);
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS
+/**
+ * Concatenate two ArrayBuffers
+ * @param {...ArrayBuffer} buffers Set of ArrayBuffer
+ */
+function utilConcatBuf(...buffers) {
+ //region Initial variables
+ let outputLength = 0;
+ let prevLength = 0;
+ //endregion
+
+ //region Calculate output length
+
+ // noinspection NonBlockStatementBodyJS
+ var _iteratorNormalCompletion2 = true;
+ var _didIteratorError2 = false;
+ var _iteratorError2 = undefined;
+
+ try {
+ for (var _iterator2 = buffers[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+ const buffer = _step2.value;
+
+ outputLength += buffer.byteLength;
+ } //endregion
+ } catch (err) {
+ _didIteratorError2 = true;
+ _iteratorError2 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion2 && _iterator2.return) {
+ _iterator2.return();
+ }
+ } finally {
+ if (_didIteratorError2) {
+ throw _iteratorError2;
+ }
+ }
+ }
+
+ const retBuf = new ArrayBuffer(outputLength);
+ const retView = new Uint8Array(retBuf);
+
+ var _iteratorNormalCompletion3 = true;
+ var _didIteratorError3 = false;
+ var _iteratorError3 = undefined;
+
+ try {
+ for (var _iterator3 = buffers[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
+ const buffer = _step3.value;
+
+ // noinspection NestedFunctionCallJS
+ retView.set(new Uint8Array(buffer), prevLength);
+ prevLength += buffer.byteLength;
+ }
+ } catch (err) {
+ _didIteratorError3 = true;
+ _iteratorError3 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion3 && _iterator3.return) {
+ _iterator3.return();
+ }
+ } finally {
+ if (_didIteratorError3) {
+ throw _iteratorError3;
+ }
+ }
+ }
+
+ return retBuf;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS
+/**
+ * Concatenate two Uint8Array
+ * @param {...Uint8Array} views Set of Uint8Array
+ */
+function utilConcatView(...views) {
+ //region Initial variables
+ let outputLength = 0;
+ let prevLength = 0;
+ //endregion
+
+ //region Calculate output length
+ // noinspection NonBlockStatementBodyJS
+ var _iteratorNormalCompletion4 = true;
+ var _didIteratorError4 = false;
+ var _iteratorError4 = undefined;
+
+ try {
+ for (var _iterator4 = views[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
+ const view = _step4.value;
+
+ outputLength += view.length;
+ } //endregion
+ } catch (err) {
+ _didIteratorError4 = true;
+ _iteratorError4 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion4 && _iterator4.return) {
+ _iterator4.return();
+ }
+ } finally {
+ if (_didIteratorError4) {
+ throw _iteratorError4;
+ }
+ }
+ }
+
+ const retBuf = new ArrayBuffer(outputLength);
+ const retView = new Uint8Array(retBuf);
+
+ var _iteratorNormalCompletion5 = true;
+ var _didIteratorError5 = false;
+ var _iteratorError5 = undefined;
+
+ try {
+ for (var _iterator5 = views[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
+ const view = _step5.value;
+
+ retView.set(view, prevLength);
+ prevLength += view.length;
+ }
+ } catch (err) {
+ _didIteratorError5 = true;
+ _iteratorError5 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion5 && _iterator5.return) {
+ _iterator5.return();
+ }
+ } finally {
+ if (_didIteratorError5) {
+ throw _iteratorError5;
+ }
+ }
+ }
+
+ return retView;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS
+/**
+ * Decoding of "two complement" values
+ * The function must be called in scope of instance of "hexBlock" class ("valueHex" and "warnings" properties must be present)
+ * @returns {number}
+ */
+function utilDecodeTC() {
+ const buf = new Uint8Array(this.valueHex);
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (this.valueHex.byteLength >= 2) {
+ //noinspection JSBitwiseOperatorUsage, ConstantOnRightSideOfComparisonJS, LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const condition1 = buf[0] === 0xFF && buf[1] & 0x80;
+ // noinspection ConstantOnRightSideOfComparisonJS, LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const condition2 = buf[0] === 0x00 && (buf[1] & 0x80) === 0x00;
+
+ // noinspection NonBlockStatementBodyJS
+ if (condition1 || condition2) this.warnings.push("Needlessly long format");
+ }
+
+ //region Create big part of the integer
+ const bigIntBuffer = new ArrayBuffer(this.valueHex.byteLength);
+ const bigIntView = new Uint8Array(bigIntBuffer);
+ // noinspection NonBlockStatementBodyJS
+ for (let i = 0; i < this.valueHex.byteLength; i++) bigIntView[i] = 0;
+
+ // noinspection MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ bigIntView[0] = buf[0] & 0x80; // mask only the biggest bit
+
+ const bigInt = utilFromBase(bigIntView, 8);
+ //endregion
+
+ //region Create small part of the integer
+ const smallIntBuffer = new ArrayBuffer(this.valueHex.byteLength);
+ const smallIntView = new Uint8Array(smallIntBuffer);
+ // noinspection NonBlockStatementBodyJS
+ for (let j = 0; j < this.valueHex.byteLength; j++) smallIntView[j] = buf[j];
+
+ // noinspection MagicNumberJS
+ smallIntView[0] &= 0x7F; // mask biggest bit
+
+ const smallInt = utilFromBase(smallIntView, 8);
+ //endregion
+
+ return smallInt - bigInt;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS, FunctionWithMultipleReturnPointsJS
+/**
+ * Encode integer value to "two complement" format
+ * @param {number} value Value to encode
+ * @returns {ArrayBuffer}
+ */
+function utilEncodeTC(value) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConditionalExpressionJS
+ const modValue = value < 0 ? value * -1 : value;
+ let bigInt = 128;
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ for (let i = 1; i < 8; i++) {
+ if (modValue <= bigInt) {
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (value < 0) {
+ const smallInt = bigInt - modValue;
+
+ const retBuf = utilToBase(smallInt, 8, i);
+ const retView = new Uint8Array(retBuf);
+
+ // noinspection MagicNumberJS
+ retView[0] |= 0x80;
+
+ return retBuf;
+ }
+
+ let retBuf = utilToBase(modValue, 8, i);
+ let retView = new Uint8Array(retBuf);
+
+ //noinspection JSBitwiseOperatorUsage, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ if (retView[0] & 0x80) {
+ //noinspection JSCheckFunctionSignatures
+ const tempBuf = retBuf.slice(0);
+ const tempView = new Uint8Array(tempBuf);
+
+ retBuf = new ArrayBuffer(retBuf.byteLength + 1);
+ // noinspection ReuseOfLocalVariableJS
+ retView = new Uint8Array(retBuf);
+
+ // noinspection NonBlockStatementBodyJS
+ for (let k = 0; k < tempBuf.byteLength; k++) retView[k + 1] = tempView[k];
+
+ // noinspection MagicNumberJS
+ retView[0] = 0x00;
+ }
+
+ return retBuf;
+ }
+
+ bigInt *= Math.pow(2, 8);
+ }
+
+ return new ArrayBuffer(0);
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleReturnPointsJS, ParameterNamingConventionJS
+/**
+ * Compare two array buffers
+ * @param {!ArrayBuffer} inputBuffer1
+ * @param {!ArrayBuffer} inputBuffer2
+ * @returns {boolean}
+ */
+function isEqualBuffer(inputBuffer1, inputBuffer2) {
+ // noinspection NonBlockStatementBodyJS
+ if (inputBuffer1.byteLength !== inputBuffer2.byteLength) return false;
+
+ // noinspection LocalVariableNamingConventionJS
+ const view1 = new Uint8Array(inputBuffer1);
+ // noinspection LocalVariableNamingConventionJS
+ const view2 = new Uint8Array(inputBuffer2);
+
+ for (let i = 0; i < view1.length; i++) {
+ // noinspection NonBlockStatementBodyJS
+ if (view1[i] !== view2[i]) return false;
+ }
+
+ return true;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleReturnPointsJS
+/**
+ * Pad input number with leade "0" if needed
+ * @returns {string}
+ * @param {number} inputNumber
+ * @param {number} fullLength
+ */
+function padNumber(inputNumber, fullLength) {
+ const str = inputNumber.toString(10);
+
+ // noinspection NonBlockStatementBodyJS
+ if (fullLength < str.length) return "";
+
+ const dif = fullLength - str.length;
+
+ const padding = new Array(dif);
+ // noinspection NonBlockStatementBodyJS
+ for (let i = 0; i < dif; i++) padding[i] = "0";
+
+ const paddingString = padding.join("");
+
+ return paddingString.concat(str);
+}
+//**************************************************************************************
+const base64Template = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+const base64UrlTemplate = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=";
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS, OverlyComplexFunctionJS, FunctionTooLongJS, FunctionNamingConventionJS
+/**
+ * Encode string into BASE64 (or "base64url")
+ * @param {string} input
+ * @param {boolean} useUrlTemplate If "true" then output would be encoded using "base64url"
+ * @param {boolean} skipPadding Skip BASE-64 padding or not
+ * @param {boolean} skipLeadingZeros Skip leading zeros in input data or not
+ * @returns {string}
+ */
+function toBase64(input, useUrlTemplate = false, skipPadding = false, skipLeadingZeros = false) {
+ let i = 0;
+
+ // noinspection LocalVariableNamingConventionJS
+ let flag1 = 0;
+ // noinspection LocalVariableNamingConventionJS
+ let flag2 = 0;
+
+ let output = "";
+
+ // noinspection ConditionalExpressionJS
+ const template = useUrlTemplate ? base64UrlTemplate : base64Template;
+
+ if (skipLeadingZeros) {
+ let nonZeroPosition = 0;
+
+ for (let i = 0; i < input.length; i++) {
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (input.charCodeAt(i) !== 0) {
+ nonZeroPosition = i;
+ // noinspection BreakStatementJS
+ break;
+ }
+ }
+
+ // noinspection AssignmentToFunctionParameterJS
+ input = input.slice(nonZeroPosition);
+ }
+
+ while (i < input.length) {
+ // noinspection LocalVariableNamingConventionJS, IncrementDecrementResultUsedJS
+ const chr1 = input.charCodeAt(i++);
+ // noinspection NonBlockStatementBodyJS
+ if (i >= input.length) flag1 = 1;
+ // noinspection LocalVariableNamingConventionJS, IncrementDecrementResultUsedJS
+ const chr2 = input.charCodeAt(i++);
+ // noinspection NonBlockStatementBodyJS
+ if (i >= input.length) flag2 = 1;
+ // noinspection LocalVariableNamingConventionJS, IncrementDecrementResultUsedJS
+ const chr3 = input.charCodeAt(i++);
+
+ // noinspection LocalVariableNamingConventionJS
+ const enc1 = chr1 >> 2;
+ // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const enc2 = (chr1 & 0x03) << 4 | chr2 >> 4;
+ // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ let enc3 = (chr2 & 0x0F) << 2 | chr3 >> 6;
+ // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ let enc4 = chr3 & 0x3F;
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (flag1 === 1) {
+ // noinspection NestedAssignmentJS, AssignmentResultUsedJS, MagicNumberJS
+ enc3 = enc4 = 64;
+ } else {
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (flag2 === 1) {
+ // noinspection MagicNumberJS
+ enc4 = 64;
+ }
+ }
+
+ // noinspection NonBlockStatementBodyJS
+ if (skipPadding) {
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS, MagicNumberJS
+ if (enc3 === 64) output += `${template.charAt(enc1)}${template.charAt(enc2)}`;else {
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS, MagicNumberJS
+ if (enc4 === 64) output += `${template.charAt(enc1)}${template.charAt(enc2)}${template.charAt(enc3)}`;else output += `${template.charAt(enc1)}${template.charAt(enc2)}${template.charAt(enc3)}${template.charAt(enc4)}`;
+ }
+ } else output += `${template.charAt(enc1)}${template.charAt(enc2)}${template.charAt(enc3)}${template.charAt(enc4)}`;
+ }
+
+ return output;
+}
+//**************************************************************************************
+// noinspection FunctionWithMoreThanThreeNegationsJS, FunctionWithMultipleLoopsJS, OverlyComplexFunctionJS, FunctionNamingConventionJS
+/**
+ * Decode string from BASE64 (or "base64url")
+ * @param {string} input
+ * @param {boolean} [useUrlTemplate=false] If "true" then output would be encoded using "base64url"
+ * @param {boolean} [cutTailZeros=false] If "true" then cut tailing zeroz from function result
+ * @returns {string}
+ */
+function fromBase64(input, useUrlTemplate = false, cutTailZeros = false) {
+ // noinspection ConditionalExpressionJS
+ const template = useUrlTemplate ? base64UrlTemplate : base64Template;
+
+ //region Aux functions
+ // noinspection FunctionWithMultipleReturnPointsJS, NestedFunctionJS
+ function indexof(toSearch) {
+ // noinspection ConstantOnRightSideOfComparisonJS, MagicNumberJS
+ for (let i = 0; i < 64; i++) {
+ // noinspection NonBlockStatementBodyJS
+ if (template.charAt(i) === toSearch) return i;
+ }
+
+ // noinspection MagicNumberJS
+ return 64;
+ }
+
+ // noinspection NestedFunctionJS
+ function test(incoming) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConditionalExpressionJS, MagicNumberJS
+ return incoming === 64 ? 0x00 : incoming;
+ }
+ //endregion
+
+ let i = 0;
+
+ let output = "";
+
+ while (i < input.length) {
+ // noinspection NestedFunctionCallJS, LocalVariableNamingConventionJS, IncrementDecrementResultUsedJS
+ const enc1 = indexof(input.charAt(i++));
+ // noinspection NestedFunctionCallJS, LocalVariableNamingConventionJS, ConditionalExpressionJS, MagicNumberJS, IncrementDecrementResultUsedJS
+ const enc2 = i >= input.length ? 0x00 : indexof(input.charAt(i++));
+ // noinspection NestedFunctionCallJS, LocalVariableNamingConventionJS, ConditionalExpressionJS, MagicNumberJS, IncrementDecrementResultUsedJS
+ const enc3 = i >= input.length ? 0x00 : indexof(input.charAt(i++));
+ // noinspection NestedFunctionCallJS, LocalVariableNamingConventionJS, ConditionalExpressionJS, MagicNumberJS, IncrementDecrementResultUsedJS
+ const enc4 = i >= input.length ? 0x00 : indexof(input.charAt(i++));
+
+ // noinspection LocalVariableNamingConventionJS, NonShortCircuitBooleanExpressionJS
+ const chr1 = test(enc1) << 2 | test(enc2) >> 4;
+ // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const chr2 = (test(enc2) & 0x0F) << 4 | test(enc3) >> 2;
+ // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const chr3 = (test(enc3) & 0x03) << 6 | test(enc4);
+
+ output += String.fromCharCode(chr1);
+
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS, MagicNumberJS
+ if (enc3 !== 64) output += String.fromCharCode(chr2);
+
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS, MagicNumberJS
+ if (enc4 !== 64) output += String.fromCharCode(chr3);
+ }
+
+ if (cutTailZeros) {
+ const outputLength = output.length;
+ let nonZeroStart = -1;
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ for (let i = outputLength - 1; i >= 0; i--) {
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (output.charCodeAt(i) !== 0) {
+ nonZeroStart = i;
+ // noinspection BreakStatementJS
+ break;
+ }
+ }
+
+ // noinspection NonBlockStatementBodyJS, NegatedIfStatementJS
+ if (nonZeroStart !== -1) output = output.slice(0, nonZeroStart + 1);else output = "";
+ }
+
+ return output;
+}
+//**************************************************************************************
+function arrayBufferToString(buffer) {
+ let resultString = "";
+ const view = new Uint8Array(buffer);
+
+ // noinspection NonBlockStatementBodyJS
+ var _iteratorNormalCompletion6 = true;
+ var _didIteratorError6 = false;
+ var _iteratorError6 = undefined;
+
+ try {
+ for (var _iterator6 = view[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
+ const element = _step6.value;
+
+ resultString += String.fromCharCode(element);
+ }
+ } catch (err) {
+ _didIteratorError6 = true;
+ _iteratorError6 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion6 && _iterator6.return) {
+ _iterator6.return();
+ }
+ } finally {
+ if (_didIteratorError6) {
+ throw _iteratorError6;
+ }
+ }
+ }
+
+ return resultString;
+}
+//**************************************************************************************
+function stringToArrayBuffer(str) {
+ const stringLength = str.length;
+
+ const resultBuffer = new ArrayBuffer(stringLength);
+ const resultView = new Uint8Array(resultBuffer);
+
+ // noinspection NonBlockStatementBodyJS
+ for (let i = 0; i < stringLength; i++) resultView[i] = str.charCodeAt(i);
+
+ return resultBuffer;
+}
+//**************************************************************************************
+const log2 = Math.log(2);
+//**************************************************************************************
+// noinspection FunctionNamingConventionJS
+/**
+ * Get nearest to input length power of 2
+ * @param {number} length Current length of existing array
+ * @returns {number}
+ */
+function nearestPowerOf2(length) {
+ const base = Math.log(length) / log2;
+
+ const floor = Math.floor(base);
+ const round = Math.round(base);
+
+ // noinspection ConditionalExpressionJS
+ return floor === round ? floor : round;
+}
+//**************************************************************************************
+/**
+ * Delete properties by name from specified object
+ * @param {Object} object Object to delete properties from
+ * @param {Array.<string>} propsArray Array of properties names
+ */
+function clearProps(object, propsArray) {
+ var _iteratorNormalCompletion7 = true;
+ var _didIteratorError7 = false;
+ var _iteratorError7 = undefined;
+
+ try {
+ for (var _iterator7 = propsArray[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
+ const prop = _step7.value;
+
+ delete object[prop];
+ }
+ } catch (err) {
+ _didIteratorError7 = true;
+ _iteratorError7 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion7 && _iterator7.return) {
+ _iterator7.return();
+ }
+ } finally {
+ if (_didIteratorError7) {
+ throw _iteratorError7;
+ }
+ }
+ }
+}
+//**************************************************************************************
+
+},{}],114:[function(require,module,exports){
+// shim for using process in browser
+var process = module.exports = {};
+
+// cached from whatever global is present so that test runners that stub it
+// don't break things. But we need to wrap it in a try catch in case it is
+// wrapped in strict mode code which doesn't define any globals. It's inside a
+// function because try/catches deoptimize in certain engines.
+
+var cachedSetTimeout;
+var cachedClearTimeout;
+
+function defaultSetTimout() {
+ throw new Error('setTimeout has not been defined');
+}
+function defaultClearTimeout () {
+ throw new Error('clearTimeout has not been defined');
+}
+(function () {
+ try {
+ if (typeof setTimeout === 'function') {
+ cachedSetTimeout = setTimeout;
+ } else {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ } catch (e) {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ try {
+ if (typeof clearTimeout === 'function') {
+ cachedClearTimeout = clearTimeout;
+ } else {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+ } catch (e) {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+} ())
+function runTimeout(fun) {
+ if (cachedSetTimeout === setTimeout) {
+ //normal enviroments in sane situations
+ return setTimeout(fun, 0);
+ }
+ // if setTimeout wasn't available but was latter defined
+ if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+ cachedSetTimeout = setTimeout;
+ return setTimeout(fun, 0);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedSetTimeout(fun, 0);
+ } catch(e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedSetTimeout.call(null, fun, 0);
+ } catch(e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+ return cachedSetTimeout.call(this, fun, 0);
+ }
+ }
+
+
+}
+function runClearTimeout(marker) {
+ if (cachedClearTimeout === clearTimeout) {
+ //normal enviroments in sane situations
+ return clearTimeout(marker);
+ }
+ // if clearTimeout wasn't available but was latter defined
+ if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+ cachedClearTimeout = clearTimeout;
+ return clearTimeout(marker);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedClearTimeout(marker);
+ } catch (e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedClearTimeout.call(null, marker);
+ } catch (e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+ // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+ return cachedClearTimeout.call(this, marker);
+ }
+ }
+
+
+
+}
+var queue = [];
+var draining = false;
+var currentQueue;
+var queueIndex = -1;
+
+function cleanUpNextTick() {
+ if (!draining || !currentQueue) {
+ return;
+ }
+ draining = false;
+ if (currentQueue.length) {
+ queue = currentQueue.concat(queue);
+ } else {
+ queueIndex = -1;
+ }
+ if (queue.length) {
+ drainQueue();
+ }
+}
+
+function drainQueue() {
+ if (draining) {
+ return;
+ }
+ var timeout = runTimeout(cleanUpNextTick);
+ draining = true;
+
+ var len = queue.length;
+ while(len) {
+ currentQueue = queue;
+ queue = [];
+ while (++queueIndex < len) {
+ if (currentQueue) {
+ currentQueue[queueIndex].run();
+ }
+ }
+ queueIndex = -1;
+ len = queue.length;
+ }
+ currentQueue = null;
+ draining = false;
+ runClearTimeout(timeout);
+}
+
+process.nextTick = function (fun) {
+ var args = new Array(arguments.length - 1);
+ if (arguments.length > 1) {
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+ }
+ queue.push(new Item(fun, args));
+ if (queue.length === 1 && !draining) {
+ runTimeout(drainQueue);
+ }
+};
+
+// v8 likes predictible objects
+function Item(fun, array) {
+ this.fun = fun;
+ this.array = array;
+}
+Item.prototype.run = function () {
+ this.fun.apply(null, this.array);
+};
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+process.version = ''; // empty string to avoid regexp issues
+process.versions = {};
+
+function noop() {}
+
+process.on = noop;
+process.addListener = noop;
+process.once = noop;
+process.off = noop;
+process.removeListener = noop;
+process.removeAllListeners = noop;
+process.emit = noop;
+process.prependListener = noop;
+process.prependOnceListener = noop;
+
+process.listeners = function (name) { return [] }
+
+process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+};
+
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+};
+process.umask = function() { return 0; };
+
+},{}],115:[function(require,module,exports){
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const pkijs = require("pkijs"); // version 2.1.78
+
+module.exports = {
+ pkijs,
+};
+
+},{"pkijs":111}]},{},[115])(115)
+});
diff --git a/toolkit/components/certviewer/content/vendor/pvutils_bundle.js b/toolkit/components/certviewer/content/vendor/pvutils_bundle.js
new file mode 100644
index 0000000000..4ecec5e223
--- /dev/null
+++ b/toolkit/components/certviewer/content/vendor/pvutils_bundle.js
@@ -0,0 +1,791 @@
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.pvutils = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.getUTCDate = getUTCDate;
+exports.getParametersValue = getParametersValue;
+exports.bufferToHexCodes = bufferToHexCodes;
+exports.checkBufferParams = checkBufferParams;
+exports.utilFromBase = utilFromBase;
+exports.utilToBase = utilToBase;
+exports.utilConcatBuf = utilConcatBuf;
+exports.utilConcatView = utilConcatView;
+exports.utilDecodeTC = utilDecodeTC;
+exports.utilEncodeTC = utilEncodeTC;
+exports.isEqualBuffer = isEqualBuffer;
+exports.padNumber = padNumber;
+exports.toBase64 = toBase64;
+exports.fromBase64 = fromBase64;
+exports.arrayBufferToString = arrayBufferToString;
+exports.stringToArrayBuffer = stringToArrayBuffer;
+exports.nearestPowerOf2 = nearestPowerOf2;
+exports.clearProps = clearProps;
+//**************************************************************************************
+/**
+ * Making UTC date from local date
+ * @param {Date} date Date to convert from
+ * @returns {Date}
+ */
+function getUTCDate(date) {
+ // noinspection NestedFunctionCallJS, MagicNumberJS
+ return new Date(date.getTime() + date.getTimezoneOffset() * 60000);
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleReturnPointsJS
+/**
+ * Get value for input parameters, or set a default value
+ * @param {Object} parameters
+ * @param {string} name
+ * @param defaultValue
+ */
+function getParametersValue(parameters, name, defaultValue) {
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS
+ if (parameters instanceof Object === false) return defaultValue;
+
+ // noinspection NonBlockStatementBodyJS
+ if (name in parameters) return parameters[name];
+
+ return defaultValue;
+}
+//**************************************************************************************
+/**
+ * Converts "ArrayBuffer" into a hexdecimal string
+ * @param {ArrayBuffer} inputBuffer
+ * @param {number} [inputOffset=0]
+ * @param {number} [inputLength=inputBuffer.byteLength]
+ * @param {boolean} [insertSpace=false]
+ * @returns {string}
+ */
+function bufferToHexCodes(inputBuffer, inputOffset = 0, inputLength = inputBuffer.byteLength - inputOffset, insertSpace = false) {
+ let result = "";
+
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = new Uint8Array(inputBuffer, inputOffset, inputLength)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ const item = _step.value;
+
+ // noinspection ChainedFunctionCallJS
+ const str = item.toString(16).toUpperCase();
+
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS
+ if (str.length === 1) result += "0";
+
+ result += str;
+
+ // noinspection NonBlockStatementBodyJS
+ if (insertSpace) result += " ";
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+
+ return result.trim();
+}
+//**************************************************************************************
+// noinspection JSValidateJSDoc, FunctionWithMultipleReturnPointsJS
+/**
+ * Check input "ArrayBuffer" for common functions
+ * @param {LocalBaseBlock} baseBlock
+ * @param {ArrayBuffer} inputBuffer
+ * @param {number} inputOffset
+ * @param {number} inputLength
+ * @returns {boolean}
+ */
+function checkBufferParams(baseBlock, inputBuffer, inputOffset, inputLength) {
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (inputBuffer instanceof ArrayBuffer === false) {
+ // noinspection JSUndefinedPropertyAssignment
+ baseBlock.error = "Wrong parameter: inputBuffer must be \"ArrayBuffer\"";
+ return false;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (inputBuffer.byteLength === 0) {
+ // noinspection JSUndefinedPropertyAssignment
+ baseBlock.error = "Wrong parameter: inputBuffer has zero length";
+ return false;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (inputOffset < 0) {
+ // noinspection JSUndefinedPropertyAssignment
+ baseBlock.error = "Wrong parameter: inputOffset less than zero";
+ return false;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (inputLength < 0) {
+ // noinspection JSUndefinedPropertyAssignment
+ baseBlock.error = "Wrong parameter: inputLength less than zero";
+ return false;
+ }
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (inputBuffer.byteLength - inputOffset - inputLength < 0) {
+ // noinspection JSUndefinedPropertyAssignment
+ baseBlock.error = "End of input reached before message was fully decoded (inconsistent offset and length values)";
+ return false;
+ }
+
+ return true;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleReturnPointsJS
+/**
+ * Convert number from 2^base to 2^10
+ * @param {Uint8Array} inputBuffer
+ * @param {number} inputBase
+ * @returns {number}
+ */
+function utilFromBase(inputBuffer, inputBase) {
+ let result = 0;
+
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS
+ if (inputBuffer.length === 1) return inputBuffer[0];
+
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS
+ for (let i = inputBuffer.length - 1; i >= 0; i--) result += inputBuffer[inputBuffer.length - 1 - i] * Math.pow(2, inputBase * i);
+
+ return result;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS, FunctionWithMultipleReturnPointsJS
+/**
+ * Convert number from 2^10 to 2^base
+ * @param {!number} value The number to convert
+ * @param {!number} base The base for 2^base
+ * @param {number} [reserved=0] Pre-defined number of bytes in output array (-1 = limited by function itself)
+ * @returns {ArrayBuffer}
+ */
+function utilToBase(value, base, reserved = -1) {
+ const internalReserved = reserved;
+ let internalValue = value;
+
+ let result = 0;
+ let biggest = Math.pow(2, base);
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ for (let i = 1; i < 8; i++) {
+ if (value < biggest) {
+ let retBuf;
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (internalReserved < 0) {
+ retBuf = new ArrayBuffer(i);
+ result = i;
+ } else {
+ // noinspection NonBlockStatementBodyJS
+ if (internalReserved < i) return new ArrayBuffer(0);
+
+ retBuf = new ArrayBuffer(internalReserved);
+
+ result = internalReserved;
+ }
+
+ const retView = new Uint8Array(retBuf);
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ for (let j = i - 1; j >= 0; j--) {
+ const basis = Math.pow(2, j * base);
+
+ retView[result - j - 1] = Math.floor(internalValue / basis);
+ internalValue -= retView[result - j - 1] * basis;
+ }
+
+ return retBuf;
+ }
+
+ biggest *= Math.pow(2, base);
+ }
+
+ return new ArrayBuffer(0);
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS
+/**
+ * Concatenate two ArrayBuffers
+ * @param {...ArrayBuffer} buffers Set of ArrayBuffer
+ */
+function utilConcatBuf(...buffers) {
+ //region Initial variables
+ let outputLength = 0;
+ let prevLength = 0;
+ //endregion
+
+ //region Calculate output length
+
+ // noinspection NonBlockStatementBodyJS
+ var _iteratorNormalCompletion2 = true;
+ var _didIteratorError2 = false;
+ var _iteratorError2 = undefined;
+
+ try {
+ for (var _iterator2 = buffers[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+ const buffer = _step2.value;
+
+ outputLength += buffer.byteLength;
+ } //endregion
+ } catch (err) {
+ _didIteratorError2 = true;
+ _iteratorError2 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion2 && _iterator2.return) {
+ _iterator2.return();
+ }
+ } finally {
+ if (_didIteratorError2) {
+ throw _iteratorError2;
+ }
+ }
+ }
+
+ const retBuf = new ArrayBuffer(outputLength);
+ const retView = new Uint8Array(retBuf);
+
+ var _iteratorNormalCompletion3 = true;
+ var _didIteratorError3 = false;
+ var _iteratorError3 = undefined;
+
+ try {
+ for (var _iterator3 = buffers[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
+ const buffer = _step3.value;
+
+ // noinspection NestedFunctionCallJS
+ retView.set(new Uint8Array(buffer), prevLength);
+ prevLength += buffer.byteLength;
+ }
+ } catch (err) {
+ _didIteratorError3 = true;
+ _iteratorError3 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion3 && _iterator3.return) {
+ _iterator3.return();
+ }
+ } finally {
+ if (_didIteratorError3) {
+ throw _iteratorError3;
+ }
+ }
+ }
+
+ return retBuf;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS
+/**
+ * Concatenate two Uint8Array
+ * @param {...Uint8Array} views Set of Uint8Array
+ */
+function utilConcatView(...views) {
+ //region Initial variables
+ let outputLength = 0;
+ let prevLength = 0;
+ //endregion
+
+ //region Calculate output length
+ // noinspection NonBlockStatementBodyJS
+ var _iteratorNormalCompletion4 = true;
+ var _didIteratorError4 = false;
+ var _iteratorError4 = undefined;
+
+ try {
+ for (var _iterator4 = views[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
+ const view = _step4.value;
+
+ outputLength += view.length;
+ } //endregion
+ } catch (err) {
+ _didIteratorError4 = true;
+ _iteratorError4 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion4 && _iterator4.return) {
+ _iterator4.return();
+ }
+ } finally {
+ if (_didIteratorError4) {
+ throw _iteratorError4;
+ }
+ }
+ }
+
+ const retBuf = new ArrayBuffer(outputLength);
+ const retView = new Uint8Array(retBuf);
+
+ var _iteratorNormalCompletion5 = true;
+ var _didIteratorError5 = false;
+ var _iteratorError5 = undefined;
+
+ try {
+ for (var _iterator5 = views[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
+ const view = _step5.value;
+
+ retView.set(view, prevLength);
+ prevLength += view.length;
+ }
+ } catch (err) {
+ _didIteratorError5 = true;
+ _iteratorError5 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion5 && _iterator5.return) {
+ _iterator5.return();
+ }
+ } finally {
+ if (_didIteratorError5) {
+ throw _iteratorError5;
+ }
+ }
+ }
+
+ return retView;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS
+/**
+ * Decoding of "two complement" values
+ * The function must be called in scope of instance of "hexBlock" class ("valueHex" and "warnings" properties must be present)
+ * @returns {number}
+ */
+function utilDecodeTC() {
+ const buf = new Uint8Array(this.valueHex);
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (this.valueHex.byteLength >= 2) {
+ //noinspection JSBitwiseOperatorUsage, ConstantOnRightSideOfComparisonJS, LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const condition1 = buf[0] === 0xFF && buf[1] & 0x80;
+ // noinspection ConstantOnRightSideOfComparisonJS, LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const condition2 = buf[0] === 0x00 && (buf[1] & 0x80) === 0x00;
+
+ // noinspection NonBlockStatementBodyJS
+ if (condition1 || condition2) this.warnings.push("Needlessly long format");
+ }
+
+ //region Create big part of the integer
+ const bigIntBuffer = new ArrayBuffer(this.valueHex.byteLength);
+ const bigIntView = new Uint8Array(bigIntBuffer);
+ // noinspection NonBlockStatementBodyJS
+ for (let i = 0; i < this.valueHex.byteLength; i++) bigIntView[i] = 0;
+
+ // noinspection MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ bigIntView[0] = buf[0] & 0x80; // mask only the biggest bit
+
+ const bigInt = utilFromBase(bigIntView, 8);
+ //endregion
+
+ //region Create small part of the integer
+ const smallIntBuffer = new ArrayBuffer(this.valueHex.byteLength);
+ const smallIntView = new Uint8Array(smallIntBuffer);
+ // noinspection NonBlockStatementBodyJS
+ for (let j = 0; j < this.valueHex.byteLength; j++) smallIntView[j] = buf[j];
+
+ // noinspection MagicNumberJS
+ smallIntView[0] &= 0x7F; // mask biggest bit
+
+ const smallInt = utilFromBase(smallIntView, 8);
+ //endregion
+
+ return smallInt - bigInt;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS, FunctionWithMultipleReturnPointsJS
+/**
+ * Encode integer value to "two complement" format
+ * @param {number} value Value to encode
+ * @returns {ArrayBuffer}
+ */
+function utilEncodeTC(value) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConditionalExpressionJS
+ const modValue = value < 0 ? value * -1 : value;
+ let bigInt = 128;
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ for (let i = 1; i < 8; i++) {
+ if (modValue <= bigInt) {
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (value < 0) {
+ const smallInt = bigInt - modValue;
+
+ const retBuf = utilToBase(smallInt, 8, i);
+ const retView = new Uint8Array(retBuf);
+
+ // noinspection MagicNumberJS
+ retView[0] |= 0x80;
+
+ return retBuf;
+ }
+
+ let retBuf = utilToBase(modValue, 8, i);
+ let retView = new Uint8Array(retBuf);
+
+ //noinspection JSBitwiseOperatorUsage, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ if (retView[0] & 0x80) {
+ //noinspection JSCheckFunctionSignatures
+ const tempBuf = retBuf.slice(0);
+ const tempView = new Uint8Array(tempBuf);
+
+ retBuf = new ArrayBuffer(retBuf.byteLength + 1);
+ // noinspection ReuseOfLocalVariableJS
+ retView = new Uint8Array(retBuf);
+
+ // noinspection NonBlockStatementBodyJS
+ for (let k = 0; k < tempBuf.byteLength; k++) retView[k + 1] = tempView[k];
+
+ // noinspection MagicNumberJS
+ retView[0] = 0x00;
+ }
+
+ return retBuf;
+ }
+
+ bigInt *= Math.pow(2, 8);
+ }
+
+ return new ArrayBuffer(0);
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleReturnPointsJS, ParameterNamingConventionJS
+/**
+ * Compare two array buffers
+ * @param {!ArrayBuffer} inputBuffer1
+ * @param {!ArrayBuffer} inputBuffer2
+ * @returns {boolean}
+ */
+function isEqualBuffer(inputBuffer1, inputBuffer2) {
+ // noinspection NonBlockStatementBodyJS
+ if (inputBuffer1.byteLength !== inputBuffer2.byteLength) return false;
+
+ // noinspection LocalVariableNamingConventionJS
+ const view1 = new Uint8Array(inputBuffer1);
+ // noinspection LocalVariableNamingConventionJS
+ const view2 = new Uint8Array(inputBuffer2);
+
+ for (let i = 0; i < view1.length; i++) {
+ // noinspection NonBlockStatementBodyJS
+ if (view1[i] !== view2[i]) return false;
+ }
+
+ return true;
+}
+//**************************************************************************************
+// noinspection FunctionWithMultipleReturnPointsJS
+/**
+ * Pad input number with leade "0" if needed
+ * @returns {string}
+ * @param {number} inputNumber
+ * @param {number} fullLength
+ */
+function padNumber(inputNumber, fullLength) {
+ const str = inputNumber.toString(10);
+
+ // noinspection NonBlockStatementBodyJS
+ if (fullLength < str.length) return "";
+
+ const dif = fullLength - str.length;
+
+ const padding = new Array(dif);
+ // noinspection NonBlockStatementBodyJS
+ for (let i = 0; i < dif; i++) padding[i] = "0";
+
+ const paddingString = padding.join("");
+
+ return paddingString.concat(str);
+}
+//**************************************************************************************
+const base64Template = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+const base64UrlTemplate = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=";
+//**************************************************************************************
+// noinspection FunctionWithMultipleLoopsJS, OverlyComplexFunctionJS, FunctionTooLongJS, FunctionNamingConventionJS
+/**
+ * Encode string into BASE64 (or "base64url")
+ * @param {string} input
+ * @param {boolean} useUrlTemplate If "true" then output would be encoded using "base64url"
+ * @param {boolean} skipPadding Skip BASE-64 padding or not
+ * @param {boolean} skipLeadingZeros Skip leading zeros in input data or not
+ * @returns {string}
+ */
+function toBase64(input, useUrlTemplate = false, skipPadding = false, skipLeadingZeros = false) {
+ let i = 0;
+
+ // noinspection LocalVariableNamingConventionJS
+ let flag1 = 0;
+ // noinspection LocalVariableNamingConventionJS
+ let flag2 = 0;
+
+ let output = "";
+
+ // noinspection ConditionalExpressionJS
+ const template = useUrlTemplate ? base64UrlTemplate : base64Template;
+
+ if (skipLeadingZeros) {
+ let nonZeroPosition = 0;
+
+ for (let i = 0; i < input.length; i++) {
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (input.charCodeAt(i) !== 0) {
+ nonZeroPosition = i;
+ // noinspection BreakStatementJS
+ break;
+ }
+ }
+
+ // noinspection AssignmentToFunctionParameterJS
+ input = input.slice(nonZeroPosition);
+ }
+
+ while (i < input.length) {
+ // noinspection LocalVariableNamingConventionJS, IncrementDecrementResultUsedJS
+ const chr1 = input.charCodeAt(i++);
+ // noinspection NonBlockStatementBodyJS
+ if (i >= input.length) flag1 = 1;
+ // noinspection LocalVariableNamingConventionJS, IncrementDecrementResultUsedJS
+ const chr2 = input.charCodeAt(i++);
+ // noinspection NonBlockStatementBodyJS
+ if (i >= input.length) flag2 = 1;
+ // noinspection LocalVariableNamingConventionJS, IncrementDecrementResultUsedJS
+ const chr3 = input.charCodeAt(i++);
+
+ // noinspection LocalVariableNamingConventionJS
+ const enc1 = chr1 >> 2;
+ // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const enc2 = (chr1 & 0x03) << 4 | chr2 >> 4;
+ // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ let enc3 = (chr2 & 0x0F) << 2 | chr3 >> 6;
+ // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ let enc4 = chr3 & 0x3F;
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (flag1 === 1) {
+ // noinspection NestedAssignmentJS, AssignmentResultUsedJS, MagicNumberJS
+ enc3 = enc4 = 64;
+ } else {
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (flag2 === 1) {
+ // noinspection MagicNumberJS
+ enc4 = 64;
+ }
+ }
+
+ // noinspection NonBlockStatementBodyJS
+ if (skipPadding) {
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS, MagicNumberJS
+ if (enc3 === 64) output += `${template.charAt(enc1)}${template.charAt(enc2)}`;else {
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS, MagicNumberJS
+ if (enc4 === 64) output += `${template.charAt(enc1)}${template.charAt(enc2)}${template.charAt(enc3)}`;else output += `${template.charAt(enc1)}${template.charAt(enc2)}${template.charAt(enc3)}${template.charAt(enc4)}`;
+ }
+ } else output += `${template.charAt(enc1)}${template.charAt(enc2)}${template.charAt(enc3)}${template.charAt(enc4)}`;
+ }
+
+ return output;
+}
+//**************************************************************************************
+// noinspection FunctionWithMoreThanThreeNegationsJS, FunctionWithMultipleLoopsJS, OverlyComplexFunctionJS, FunctionNamingConventionJS
+/**
+ * Decode string from BASE64 (or "base64url")
+ * @param {string} input
+ * @param {boolean} [useUrlTemplate=false] If "true" then output would be encoded using "base64url"
+ * @param {boolean} [cutTailZeros=false] If "true" then cut tailing zeroz from function result
+ * @returns {string}
+ */
+function fromBase64(input, useUrlTemplate = false, cutTailZeros = false) {
+ // noinspection ConditionalExpressionJS
+ const template = useUrlTemplate ? base64UrlTemplate : base64Template;
+
+ //region Aux functions
+ // noinspection FunctionWithMultipleReturnPointsJS, NestedFunctionJS
+ function indexof(toSearch) {
+ // noinspection ConstantOnRightSideOfComparisonJS, MagicNumberJS
+ for (let i = 0; i < 64; i++) {
+ // noinspection NonBlockStatementBodyJS
+ if (template.charAt(i) === toSearch) return i;
+ }
+
+ // noinspection MagicNumberJS
+ return 64;
+ }
+
+ // noinspection NestedFunctionJS
+ function test(incoming) {
+ // noinspection ConstantOnRightSideOfComparisonJS, ConditionalExpressionJS, MagicNumberJS
+ return incoming === 64 ? 0x00 : incoming;
+ }
+ //endregion
+
+ let i = 0;
+
+ let output = "";
+
+ while (i < input.length) {
+ // noinspection NestedFunctionCallJS, LocalVariableNamingConventionJS, IncrementDecrementResultUsedJS
+ const enc1 = indexof(input.charAt(i++));
+ // noinspection NestedFunctionCallJS, LocalVariableNamingConventionJS, ConditionalExpressionJS, MagicNumberJS, IncrementDecrementResultUsedJS
+ const enc2 = i >= input.length ? 0x00 : indexof(input.charAt(i++));
+ // noinspection NestedFunctionCallJS, LocalVariableNamingConventionJS, ConditionalExpressionJS, MagicNumberJS, IncrementDecrementResultUsedJS
+ const enc3 = i >= input.length ? 0x00 : indexof(input.charAt(i++));
+ // noinspection NestedFunctionCallJS, LocalVariableNamingConventionJS, ConditionalExpressionJS, MagicNumberJS, IncrementDecrementResultUsedJS
+ const enc4 = i >= input.length ? 0x00 : indexof(input.charAt(i++));
+
+ // noinspection LocalVariableNamingConventionJS, NonShortCircuitBooleanExpressionJS
+ const chr1 = test(enc1) << 2 | test(enc2) >> 4;
+ // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const chr2 = (test(enc2) & 0x0F) << 4 | test(enc3) >> 2;
+ // noinspection LocalVariableNamingConventionJS, MagicNumberJS, NonShortCircuitBooleanExpressionJS
+ const chr3 = (test(enc3) & 0x03) << 6 | test(enc4);
+
+ output += String.fromCharCode(chr1);
+
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS, MagicNumberJS
+ if (enc3 !== 64) output += String.fromCharCode(chr2);
+
+ // noinspection ConstantOnRightSideOfComparisonJS, NonBlockStatementBodyJS, MagicNumberJS
+ if (enc4 !== 64) output += String.fromCharCode(chr3);
+ }
+
+ if (cutTailZeros) {
+ const outputLength = output.length;
+ let nonZeroStart = -1;
+
+ // noinspection ConstantOnRightSideOfComparisonJS
+ for (let i = outputLength - 1; i >= 0; i--) {
+ // noinspection ConstantOnRightSideOfComparisonJS
+ if (output.charCodeAt(i) !== 0) {
+ nonZeroStart = i;
+ // noinspection BreakStatementJS
+ break;
+ }
+ }
+
+ // noinspection NonBlockStatementBodyJS, NegatedIfStatementJS
+ if (nonZeroStart !== -1) output = output.slice(0, nonZeroStart + 1);else output = "";
+ }
+
+ return output;
+}
+//**************************************************************************************
+function arrayBufferToString(buffer) {
+ let resultString = "";
+ const view = new Uint8Array(buffer);
+
+ // noinspection NonBlockStatementBodyJS
+ var _iteratorNormalCompletion6 = true;
+ var _didIteratorError6 = false;
+ var _iteratorError6 = undefined;
+
+ try {
+ for (var _iterator6 = view[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
+ const element = _step6.value;
+
+ resultString += String.fromCharCode(element);
+ }
+ } catch (err) {
+ _didIteratorError6 = true;
+ _iteratorError6 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion6 && _iterator6.return) {
+ _iterator6.return();
+ }
+ } finally {
+ if (_didIteratorError6) {
+ throw _iteratorError6;
+ }
+ }
+ }
+
+ return resultString;
+}
+//**************************************************************************************
+function stringToArrayBuffer(str) {
+ const stringLength = str.length;
+
+ const resultBuffer = new ArrayBuffer(stringLength);
+ const resultView = new Uint8Array(resultBuffer);
+
+ // noinspection NonBlockStatementBodyJS
+ for (let i = 0; i < stringLength; i++) resultView[i] = str.charCodeAt(i);
+
+ return resultBuffer;
+}
+//**************************************************************************************
+const log2 = Math.log(2);
+//**************************************************************************************
+// noinspection FunctionNamingConventionJS
+/**
+ * Get nearest to input length power of 2
+ * @param {number} length Current length of existing array
+ * @returns {number}
+ */
+function nearestPowerOf2(length) {
+ const base = Math.log(length) / log2;
+
+ const floor = Math.floor(base);
+ const round = Math.round(base);
+
+ // noinspection ConditionalExpressionJS
+ return floor === round ? floor : round;
+}
+//**************************************************************************************
+/**
+ * Delete properties by name from specified object
+ * @param {Object} object Object to delete properties from
+ * @param {Array.<string>} propsArray Array of properties names
+ */
+function clearProps(object, propsArray) {
+ var _iteratorNormalCompletion7 = true;
+ var _didIteratorError7 = false;
+ var _iteratorError7 = undefined;
+
+ try {
+ for (var _iterator7 = propsArray[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
+ const prop = _step7.value;
+
+ delete object[prop];
+ }
+ } catch (err) {
+ _didIteratorError7 = true;
+ _iteratorError7 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion7 && _iterator7.return) {
+ _iterator7.return();
+ }
+ } finally {
+ if (_didIteratorError7) {
+ throw _iteratorError7;
+ }
+ }
+ }
+}
+//**************************************************************************************
+
+},{}],2:[function(require,module,exports){
+/* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const pvutils = require("pvutils"); // version 1.0.17
+
+module.exports = {
+ pvutils,
+};
+
+},{"pvutils":1}]},{},[2])(2)
+});
diff --git a/toolkit/components/certviewer/jar.mn b/toolkit/components/certviewer/jar.mn
new file mode 100644
index 0000000000..f4a1e23aa5
--- /dev/null
+++ b/toolkit/components/certviewer/jar.mn
@@ -0,0 +1,30 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+toolkit.jar:
+ content/global/certviewer/certviewer.html (content/certviewer.html)
+ content/global/certviewer/certviewer.css (content/certviewer.css)
+ content/global/certviewer/certviewer.js (content/certviewer.js)
+ content/global/certviewer/components/about-certificate-section.js (content/components/about-certificate-section.js)
+ content/global/certviewer/components/about-certificate-section.css (content/components/about-certificate-section.css)
+ content/global/certviewer/components/about-certificate-items.js (content/components/about-certificate-items.js)
+ content/global/certviewer/components/certificate-section.js (content/components/certificate-section.js)
+ content/global/certviewer/components/certificate-tabs-section.js (content/components/certificate-tabs-section.js)
+ content/global/certviewer/components/certificate-section.css (content/components/certificate-section.css)
+ content/global/certviewer/components/error-section.js (content/components/error-section.js)
+ content/global/certviewer/components/error-section.css (content/components/error-section.css)
+ content/global/certviewer/components/info-group.js (content/components/info-group.js)
+ content/global/certviewer/components/info-group.css (content/components/info-group.css)
+ content/global/certviewer/components/info-group-container.js (content/components/info-group-container.js)
+ content/global/certviewer/components/info-item.js (content/components/info-item.js)
+ content/global/certviewer/components/info-item.css (content/components/info-item.css)
+ content/global/certviewer/components/list-item.js (content/components/list-item.js)
+ content/global/certviewer/components/list-item.css (content/components/list-item.css)
+ content/global/certviewer/certDecoder.js (content/certDecoder.js)
+ content/global/certviewer/strings.js (content/strings.js)
+ content/global/certviewer/ctlognames.js (content/ctlognames.js)
+ content/global/certviewer/utils.js (content/utils.js)
+ content/global/certviewer/pvutils_bundle.js (content/vendor/pvutils_bundle.js)
+ content/global/certviewer/asn1js_bundle.js (content/vendor/asn1js_bundle.js)
+ content/global/certviewer/pkijs_bundle.js (content/vendor/pkijs_bundle.js)
diff --git a/toolkit/components/certviewer/moz.build b/toolkit/components/certviewer/moz.build
new file mode 100644
index 0000000000..a81677ef85
--- /dev/null
+++ b/toolkit/components/certviewer/moz.build
@@ -0,0 +1,19 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+JAR_MANIFESTS += ["jar.mn"]
+
+BROWSER_CHROME_MANIFESTS += ["tests/browser/browser.ini"]
+
+MOCHITEST_CHROME_MANIFESTS += ["tests/chrome/chrome.ini"]
+
+EXTRA_JS_MODULES += [
+ "AboutCertViewerChild.jsm",
+ "AboutCertViewerParent.jsm",
+]
+
+with Files("**"):
+ BUG_COMPONENT = ("Firefox", "Security")
diff --git a/toolkit/components/certviewer/tests/browser/adjustedCerts.js b/toolkit/components/certviewer/tests/browser/adjustedCerts.js
new file mode 100644
index 0000000000..d6939ac291
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/adjustedCerts.js
@@ -0,0 +1,267 @@
+"use strict";
+
+/*
+To change this file you will have to add a function to download a file in toolkit/components/certviewer/content/certviewer.js (e.g: https://ourcodeworld.com/articles/read/189/how-to-create-a-file-and-generate-a-download-with-javascript-in-the-browser-without-a-server),
+download adjustedCerts (e.g: download("out.txt", JSON.stringify(adjustedCerts)), do it after this line https://searchfox.org/mozilla-central/rev/e3fc8f8970491aef14d3212b2d052942f4d29818/toolkit/components/certviewer/content/certviewer.js#428),
+then open Nightly and go to about:certificate?cert=MIIHQjCCBiqgAwIBAgIQCgYwQn9bvO1pVzllk7ZFHzANBgkqhkiG9w0BAQsFADB1MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTQwMgYDVQQDEytEaWdpQ2VydCBTSEEyIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VydmVyIENBMB4XDTE4MDUwODAwMDAwMFoXDTIwMDYwMzEyMDAwMFowgccxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQITCERlbGF3YXJlMRAwDgYDVQQFEwc1MTU3NTUwMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRMwEQYDVQQDEwpnaXRodWIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxjyq8jyXDDrBTyitcnB90865tWBzpHSbindG%2FXqYQkzFMBlXmqkzC%2BFdTRBYyneZw5Pz%2BXWQvL%2B74JW6LsWNc2EF0xCEqLOJuC9zjPAqbr7uroNLghGxYf13YdqbG5oj%2F4x%2BogEG3dF%2FU5YIwVr658DKyESMV6eoYV9mDVfTuJastkqcwero%2B5ZAKfYVMLUEsMwFtoTDJFmVf6JlkOWwsxp1WcQ%2FMRQK1cyqOoUFUgYylgdh3yeCDPeF22Ax8AlQxbcaI%2BGwfQL1FB7Jy%2Bh%2BKjME9lE%2FUpgV6Qt2R1xNSmvFCBWu%2BNFX6epwFP%2FJRbkMfLz0beYFUvmMgLtwVpEPSwIDAQABo4IDeTCCA3UwHwYDVR0jBBgwFoAUPdNQpdagre7zSmAKZdMh1Pj41g8wHQYDVR0OBBYEFMnCU2FmnV%2BrJfQmzQ84mqhJ6kipMCUGA1UdEQQeMByCCmdpdGh1Yi5jb22CDnd3dy5naXRodWIuY29tMA4GA1UdDwEB%2FwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0fBG4wbDA0oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItZXYtc2VydmVyLWcyLmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItZXYtc2VydmVyLWcyLmNybDBLBgNVHSAERDBCMDcGCWCGSAGG%2FWwCATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAcGBWeBDAEBMIGIBggrBgEFBQcBAQR8MHowJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBSBggrBgEFBQcwAoZGaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkV4dGVuZGVkVmFsaWRhdGlvblNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAAMIIBfgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdgCkuQmQtBhYFIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAWNBYm0KAAAEAwBHMEUCIQDRZp38cTWsWH2GdBpe%2FuPTWnsu%2Fm4BEC2%2BdIcvSykZYgIgCP5gGv6yzaazxBK2NwGdmmyuEFNSg2pARbMJlUFgU5UAdgBWFAaaL9fC7NP14b1Esj7HRna5vJkRXMDvlJhV1onQ3QAAAWNBYm0tAAAEAwBHMEUCIQCi7omUvYLm0b2LobtEeRAYnlIo7n6JxbYdrtYdmPUWJQIgVgw1AZ51vK9ENinBg22FPxb82TvNDO05T17hxXRC2IYAdgC72d%2B8H4pxtZOUI5eqkntHOFeVCqtS6BqQlmQ2jh7RhQAAAWNBYm3fAAAEAwBHMEUCIQChzdTKUU2N%2BXcqcK0OJYrN8EYynloVxho4yPk6Dq3EPgIgdNH5u8rC3UcslQV4B9o0a0w204omDREGKTVuEpxGeOQwDQYJKoZIhvcNAQELBQADggEBAHAPWpanWOW%2Fip2oJ5grAH8mqQfaunuCVE%2Bvac%2B88lkDK%2FLVdFgl2B6kIHZiYClzKtfczG93hWvKbST4NRNHP9LiaQqdNC17e5vNHnXVUGw%2ByxyjMLGqkgepOnZ2Rb14kcTOGp4i5AuJuuaMwXmCo7jUwPwfLe1NUlVBKqg6LK0Hcq4K0sZnxE8HFxiZ92WpV2AVWjRMEc%2F2z2shNoDvxvFUYyY1Oe67xINkmyQKc%2BygSBZzyLnXSFVWmHr3u5dcaaQGGAR42v6Ydr4iL38Hd4dOiBma%2BFXsXBIqWUjbST4VXmdaol7uzFMojA4zkxQDZAvF5XgJlAFadfySna%2Fteik%3D
+open the file, and finally copy and paste it here like
+
+const adjustedCerts = <what you just copied>;
+*/
+
+const adjustedCerts = [
+ {
+ certItems: [
+ {
+ sectionId: "subject-name",
+ sectionItems: [
+ { labelId: "business-category", info: "Private Organization" },
+ { labelId: "inc-country", info: "US" },
+ { labelId: "inc-state-province", info: "Delaware" },
+ { labelId: "serial-number", info: "5157550" },
+ { labelId: "country", info: "US" },
+ { labelId: "state-province", info: "California" },
+ { labelId: "locality", info: "San Francisco" },
+ { labelId: "organization", info: "GitHub, Inc." },
+ { labelId: "common-name", info: "github.com" },
+ ],
+ Critical: false,
+ },
+ {
+ sectionId: "issuer-name",
+ sectionItems: [
+ { labelId: "country", info: "US" },
+ { labelId: "organization", info: "DigiCert Inc" },
+ { labelId: "organizational-unit", info: "www.digicert.com" },
+ {
+ labelId: "common-name",
+ info: "DigiCert SHA2 Extended Validation Server CA",
+ },
+ ],
+ Critical: false,
+ },
+ {
+ sectionId: "validity",
+ sectionItems: [
+ {
+ labelId: "not-before",
+ info: {
+ local: "5/7/2018, 9:00:00 PM (Brasilia Standard Time)",
+ utc: "Tue, 08 May 2018 00:00:00 GMT",
+ },
+ },
+ {
+ labelId: "not-after",
+ info: {
+ local: "6/3/2020, 9:00:00 AM (Brasilia Standard Time)",
+ utc: "Wed, 03 Jun 2020 12:00:00 GMT",
+ },
+ },
+ ],
+ Critical: false,
+ },
+ {
+ sectionId: "subject-alt-names",
+ sectionItems: [
+ { labelId: "dns-name", info: "github.com" },
+ { labelId: "dns-name", info: "www.github.com" },
+ ],
+ Critical: false,
+ },
+ {
+ sectionId: "public-key-info",
+ sectionItems: [
+ { labelId: "algorithm", info: "RSA" },
+ { labelId: "key-size", info: 2048 },
+ { labelId: "exponent", info: 65537 },
+ {
+ labelId: "modulus",
+ info:
+ "C6:3C:AA:F2:3C:97:0C:3A:C1:4F:28:AD:72:70:7D:D3:CE:B9:B5:60:73:A4:74:9B:8A:77:46:FD:7A:98:42:4C:C5:30:19:57:9A:A9:33:0B:E1:5D:4D:10:58:CA:77:99:C3:93:F3:F9:75:90:BC:BF:BB:E0:95:BA:2E:C5:8D:73:61:05:D3:10:84:A8:B3:89:B8:2F:73:8C:F0:2A:6E:BE:EE:AE:83:4B:82:11:B1:61:FD:77:61:DA:9B:1B:9A:23:FF:8C:7E:A2:01:06:DD:D1:7F:53:96:08:C1:5A:FA:E7:C0:CA:C8:44:8C:57:A7:A8:61:5F:66:0D:57:D3:B8:96:AC:B6:4A:9C:C1:EA:E8:FB:96:40:29:F6:15:30:B5:04:B0:CC:05:B6:84:C3:24:59:95:7F:A2:65:90:E5:B0:B3:1A:75:59:C4:3F:31:14:0A:D5:CC:AA:3A:85:05:52:06:32:96:07:61:DF:27:82:0C:F7:85:DB:60:31:F0:09:50:C5:B7:1A:23:E1:B0:7D:02:F5:14:1E:C9:CB:E8:7E:2A:33:04:F6:51:3F:52:98:15:E9:0B:76:47:5C:4D:4A:6B:C5:08:15:AE:F8:D1:57:E9:EA:70:14:FF:C9:45:B9:0C:7C:BC:F4:6D:E6:05:52:F9:8C:80:BB:70:56:91:0F:4B",
+ },
+ ],
+ Critical: false,
+ },
+ {
+ sectionId: "miscellaneous",
+ sectionItems: [
+ {
+ labelId: "serial-number",
+ info: "0A:06:30:42:7F:5B:BC:ED:69:57:39:65:93:B6:45:1F",
+ },
+ {
+ labelId: "signature-algorithm",
+ info: "SHA-256 with RSA Encryption",
+ },
+ { labelId: "version", info: "3" },
+ {
+ labelId: "download",
+ info: "PEM (cert)PEM (chain)",
+ },
+ ],
+ Critical: false,
+ },
+ {
+ sectionId: "fingerprints",
+ sectionItems: [
+ {
+ labelId: "sha-256",
+ info:
+ "31:11:50:0C:4A:66:01:2C:DA:E3:33:EC:3F:CA:1C:9D:DE:45:C9:54:44:0E:7E:E4:13:71:6B:FF:36:63:C0:74",
+ },
+ {
+ labelId: "sha-1",
+ info: "CA:06:F5:6B:25:8B:7A:0D:4F:2B:05:47:09:39:47:86:51:15:19:84",
+ },
+ ],
+ Critical: false,
+ },
+ {
+ sectionId: "basic-constraints",
+ sectionItems: [{ labelId: "certificate-authority", info: false }],
+ Critical: true,
+ },
+ {
+ sectionId: "key-usages",
+ sectionItems: [
+ {
+ labelId: "purposes",
+ info: ["Digital Signature", "Key Encipherment"],
+ },
+ ],
+ Critical: true,
+ },
+ {
+ sectionId: "extended-key-usages",
+ sectionItems: [
+ {
+ labelId: "purposes",
+ info: ["Server Authentication", "Client Authentication"],
+ },
+ ],
+ Critical: false,
+ },
+ {
+ sectionId: "subject-key-id",
+ sectionItems: [
+ {
+ labelId: "key-id",
+ info: "C9:C2:53:61:66:9D:5F:AB:25:F4:26:CD:0F:38:9A:A8:49:EA:48:A9",
+ },
+ ],
+ Critical: false,
+ },
+ {
+ sectionId: "authority-key-id",
+ sectionItems: [
+ {
+ labelId: "key-id",
+ info: "3D:D3:50:A5:D6:A0:AD:EE:F3:4A:60:0A:65:D3:21:D4:F8:F8:D6:0F",
+ },
+ ],
+ Critical: false,
+ },
+ {
+ sectionId: "crl-endpoints",
+ sectionItems: [
+ {
+ labelId: "distribution-point",
+ info: "http://crl3.digicert.com/sha2-ev-server-g2.crl",
+ },
+ {
+ labelId: "distribution-point",
+ info: "http://crl4.digicert.com/sha2-ev-server-g2.crl",
+ },
+ ],
+ Critical: false,
+ },
+ {
+ sectionId: "authority-info-aia",
+ sectionItems: [
+ { labelId: "location", info: "http://ocsp.digicert.com" },
+ {
+ labelId: "method",
+ info: "Online Certificate Status Protocol (OCSP)",
+ },
+ {
+ labelId: "location",
+ info:
+ "http://cacerts.digicert.com/DigiCertSHA2ExtendedValidationServerCA.crt",
+ },
+ { labelId: "method", info: "CA Issuers" },
+ ],
+ Critical: false,
+ },
+ {
+ sectionId: "certificate-policies",
+ sectionItems: [
+ {
+ labelId: "policy",
+ info: "ANSI Organizational Identifier ( 2.16.840 )",
+ },
+ { labelId: "value", info: "2.16.840.1.114412.2.1" },
+ {
+ labelId: "qualifier",
+ info: "Practices Statement ( 1.3.6.1.5.5.7.2.1 )",
+ },
+ { labelId: "value", info: "https://www.digicert.com/CPS" },
+ { labelId: "policy", info: "Certificate Type ( 2.23.140.1.1 )" },
+ { labelId: "value", info: "Extended Validation" },
+ ],
+ Critical: false,
+ },
+ {
+ sectionId: "embedded-scts",
+ sectionItems: [
+ {
+ labelId: "logid",
+ info:
+ "A4:B9:09:90:B4:18:58:14:87:BB:13:A2:CC:67:70:0A:3C:35:98:04:F9:1B:DF:B8:E3:77:CD:0E:C8:0D:DC:10",
+ },
+ { labelId: "name", info: "Google “Pilot”" },
+ { labelId: "signaturealgorithm", info: "SHA-256 ECDSA" },
+ { labelId: "version", info: 1 },
+ {
+ labelId: "timestamp",
+ info: {
+ local: "5/8/2018, 5:12:39 PM (Brasilia Standard Time)",
+ utc: "Tue, 08 May 2018 20:12:39 GMT",
+ },
+ },
+ {
+ labelId: "logid",
+ info:
+ "56:14:06:9A:2F:D7:C2:EC:D3:F5:E1:BD:44:B2:3E:C7:46:76:B9:BC:99:11:5C:C0:EF:94:98:55:D6:89:D0:DD",
+ },
+ { labelId: "name", info: "DigiCert Server" },
+ { labelId: "signaturealgorithm", info: "SHA-256 ECDSA" },
+ { labelId: "version", info: 1 },
+ {
+ labelId: "timestamp",
+ info: {
+ local: "5/8/2018, 5:12:39 PM (Brasilia Standard Time)",
+ utc: "Tue, 08 May 2018 20:12:39 GMT",
+ },
+ },
+ {
+ labelId: "logid",
+ info:
+ "BB:D9:DF:BC:1F:8A:71:B5:93:94:23:97:AA:92:7B:47:38:57:95:0A:AB:52:E8:1A:90:96:64:36:8E:1E:D1:85",
+ },
+ { labelId: "name", info: "Google “Skydiver”" },
+ { labelId: "signaturealgorithm", info: "SHA-256 ECDSA" },
+ { labelId: "version", info: 1 },
+ {
+ labelId: "timestamp",
+ info: {
+ local: "5/8/2018, 5:12:39 PM (Brasilia Standard Time)",
+ utc: "Tue, 08 May 2018 20:12:39 GMT",
+ },
+ },
+ ],
+ Critical: false,
+ },
+ ],
+ tabName: "github.com",
+ },
+];
diff --git a/toolkit/components/certviewer/tests/browser/browser.ini b/toolkit/components/certviewer/tests/browser/browser.ini
new file mode 100644
index 0000000000..443cf6c5a3
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser.ini
@@ -0,0 +1,22 @@
+[DEFAULT]
+support-files =
+ head.js
+ adjustedCerts.js
+[browser_aboutcertificateviewer.js]
+[browser_checkLongHex.js]
+[browser_checkMissingCommonName.js]
+[browser_checkNonEmptyFields.js]
+[browser_checkNonRepeatedCertTabs.js]
+[browser_checkNonUndefinedStrings.js]
+[browser_checkOCSP.js]
+[browser_checkStandAlonePage.js]
+[browser_checkAuthorityKeyID.js]
+[browser_checkValiditySection.js]
+[browser_handleMultipleCertsURL.js]
+[browser_openTabAndSendCertInfo.js]
+support-files =
+ dummy_page.html
+[browser_renderCertToUI.js]
+[browser_certificateTabLink.js]
+[browser_downloadLink.js]
+[browser_clickableLink.js]
diff --git a/toolkit/components/certviewer/tests/browser/browser_aboutcertificateviewer.js b/toolkit/components/certviewer/tests/browser/browser_aboutcertificateviewer.js
new file mode 100644
index 0000000000..326237365a
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser_aboutcertificateviewer.js
@@ -0,0 +1,81 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const validCert =
+ "about:certificate?cert=MIIGMDCCBRigAwIBAgIQCa2oS7Nau6nwv1WyRNIJnzANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNzdXJhbmNlIFNlcnZlciBDQTAeFw0xOTA2MDYwMDAwMDBaFw0xOTA5MDQxMjAwMDBaMGExCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTWVubG8gUGFyazEXMBUGA1UEChMORmFjZWJvb2ssIEluYy4xFzAVBgNVBAMMDiouZmFjZWJvb2suY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEALPlfjd8gHkIMDeBOFhRt0e%2B%2F3fdm%2BZdzdM4s1WIHVbYztgmdEy20PUwDCviYKJX4GG%2BT9ivT8kJ%2FvWl1P%2FYqOCA54wggOaMB8GA1UdIwQYMBaAFFFo%2F5CvAgd1PMzZZWRiohK4WXI7MB0GA1UdDgQWBBTsQZVRTuib7KY9w3FfOYsZHvOC9zCBxwYDVR0RBIG%2FMIG8gg4qLmZhY2Vib29rLmNvbYINbWVzc2VuZ2VyLmNvbYILKi5mYmNkbi5uZXSCCCouZmIuY29tghAqLm0uZmFjZWJvb2suY29tggZmYi5jb22CDiouZmFjZWJvb2submV0gg4qLnh4LmZiY2RuLm5ldIIOKi54ei5mYmNkbi5uZXSCDyoubWVzc2VuZ2VyLmNvbYILKi5mYnNieC5jb22CDioueHkuZmJjZG4ubmV0ggxmYWNlYm9vay5jb20wDgYDVR0PAQH%2FBAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzYuY3JsMDSgMqAwhi5odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzYuY3JsMEwGA1UdIARFMEMwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQICMIGDBggrBgEFBQcBAQR3MHUwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBNBggrBgEFBQcwAoZBaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkhpZ2hBc3N1cmFuY2VTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH%2FBAIwADCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB1AKS5CZC0GFgUh7sTosxncAo8NZgE%2BRvfuON3zQ7IDdwQAAABay5CAaUAAAQDAEYwRAIgMwBM6q%2BdBwu2mNtMMjTEwJZZxyoUlHUEYO%2BbfkId%2F9MCIAQ2bxhnxrapYv74fzyoTkt9m%2BELq6%2B43OVpivRVKDKTAHcAdH7agzGtMxCRIZzOJU9CcMK%2F%2FV5CIAjGNzV55hB7zFYAAAFrLkIA%2FAAABAMASDBGAiEA0x1xPWue6RMSE9nbjYBt637CRC86ixrODP%2FEIlI5mCgCIQCHNdqgOlswd0LqaW4QRii2JHN4bnoEj%2FD9j7%2BkqEB7LjANBgkqhkiG9w0BAQsFAAOCAQEAnRdIVNZ850s7IvLgg%2BU9kKxA18kLKVpIF%2FrJHkXTkymvBHKAGOFNfzqF2YxHFhkDMIuoMO2F%2BA1E0Eo8zb1atL6%2FL59broEHTOH6xFmJAlZW0h6mZg8iRJ9Ae0pTN%2FfowaoN9aFVRnVr9ccKhOdqsXYyEZ3Ze39sEwx7Uau9KhzyuJW12Jh3S%2BZJYUdBADeeJNL5ZXSUFIyjgkwSQZPaaWAzSGHZFt3sWhMjdNoBkjRJFlASLDM3m1ZWsKA47vuXvJc%2FDXT35lC1DJmyhYb9qNPR71a1hJ8TS7vUwdDd%2BdEHiJj2wQLV3m7Tn7YvWyJOEyi4n6%2FrPqT44LZmgK7HWw%3D%3D&cert=MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3VyYW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC24C%2FCJAbIbQRf1%2B8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU%2BUDlqUH1VWtMICKq%2FQmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK%2FIHe1NnF9Xt4ZQaJn1itrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j%2F018QsIJzJa9buLnqS9UdAn4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I%2B4G3FhahnSMSTeXXkgisdaScus0Xsh5ENWV%2FUyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcftbZvySC%2FzA%2FWiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH%2FAgEAMA4GA1UdDwEB%2FwQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIGBFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAdBgNVHQ4EFgQUUWj%2FkK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7DaQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwdaOpKj4PWUS%2BNa0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk%2FgNHE%2Br1hspZcX30BJZr01lYPf7TMSVcGDiEo%2Bafgv2MW5gxTs14nhr9hctJqvIni5ly%2FD6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zuxICaEnL6VpPX%2F78whQYwvwt%2FTv9XBZ0k7YXDK%2FumdaisLRbvfXknsuvCnQsH6qqF0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY%2B3sAzm2fTYS5yh%2BRp%2FBIAV0AecPUeybQ%3D&cert=MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm%2B9S75S0tMqbf5YE%2Fyc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG%2B%2BMXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx%2BmM0aBhakaHPQNAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH%2FBAQDAgGGMA8GA1UdEwEB%2FwQFMAMBAf8wHQYDVR0OBBYEFLE%2Bw2kD%2BL9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE%2Bw2kD%2BL9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe%2FEW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9%2BMpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2Yzi9RKR%2F5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2%2FS6cCZdkGCevEsXCS%2B0yx5DaMkHJ8HSXPfqIbloEpw8nL%2Be%2FIBcm2PN7EeqJSdnoDfzAIJ9VNep%2BOkuE6N36B9K";
+
+const invalidCert = "about:certificate?cert=MIIH";
+
+const pem_to_der_error = "about:certificate?cert=MIIHQ";
+
+const error_parsing_cert =
+ "about:certificate?cert=MIIHQjCCBiqgAwIBAgIQCgYwQn9bvO11MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTQwMgYDVQQDEytEaWdpQ2VydCBTSEEyIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VydmVyIENBMB4XDTE4MDUwODAwMDAwMFoXDTIwMDYwMzEyMDAwMFowgccxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQITCERlbGF3YXJlMRAwDgYDVQQFEwc1MTU3NTUwMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRMwEQYDVQQDEwpnaXRodWIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxjyq8jyXDDrBTyitcnB90865tWBzpHSbindG%2FXqYQkzFMBlXmqkzC%2BFdTRBYyneZw5Pz%2BXWQvL%2B74JW6LsWNc2EF0xCEqLOJuC9zjPAqbr7uroNLghGxYf13YdqbG5oj%2F4x%2BogEG3dF%2FU5YIwVr658DKyESMV6eoYV9mDVfTuJastkqcwero%2B5ZAKfYVMLUEsMwFtoTDJFmVf6JlkOWwsxp1WcQ%2FMRQK1cyqOoUFUgYylgdh3yeCDPeF22Ax8AlQxbcaI%2BGwfQL1FB7Jy%2Bh%2BKjME9lE%2FUpgV6Qt2R1xNSmvFCBWu%2BNFX6epwFP%2FJRbkMfLz0beYFUvmMgLtwVpEPSwIDAQABo4IDeTCCA3UwHwYDVR0jBBgwFoAUPdNQpdagre7zSmAKZdMh1Pj41g8wHQYDVR0OBBYEFMnCU2FmnV%2BrJfQmzQ84mqhJ6kipMCUGA1UdEQQeMByCCmdpdGh1Yi5jb22CDnd3dy5naXRodWIuY29tMA4GA1UdDwEB%2FwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0fBG4wbDA0oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItZXYtc2VydmVyLWcyLmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItZXYtc2VydmVyLWcyLmNybDBLBgNVHSAERDBCMDcGCWCGSAGG%2FWwCATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAcGBWeBDAEBMIGIBggrBgEFBQcBAQR8MHowJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBSBggrBgEFBQcwAoZGaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkV4dGVuZGVkVmFsaWRhdGlvblNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAAMIIBfgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdgCkuQmQtBhYFIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAWNBYm0KAAAEAwBHMEUCIQDRZp38cTWsWH2GdBpe%2FuPTWnsu%2Fm4BEC2%2BdIcvSykZYgIgCP5gGv6yzaazxBK2NwGdmmyuEFNSg2pARbMJlUFgU5UAdgBWFAaaL9fC7NP14b1Esj7HRna5vJkRXMDvlJhV1onQ3QAAAWNBYm0tAAAEAwBHMEUCIQCi7omUvYLm0b2LobtEeRAYnlIo7n6JxbYdrtYdmPUWJQIgVgw1AZ51vK9ENinBg22FPxb82TvNDO05T17hxXRC2IYAdgC72d%2B8H4pxtZOUI5eqkntHOFeVCqtS6BqQlmQ2jh7RhQAAAWNBYm3fAAAEAwBHMEUCIQChzdTKUU2N%2BXcqcK0OJYrN8EYynloVxho4yPk6Dq3EPgIgdNH5u8rC3UcslQV4B9o0a0w204omDREGKTVuEpxGeOQwDQYJKoZIhvcNAQELBQADggEBAHAPWpanWOW%2Fip2oJ5grAH8mqQfaunuCVE%2Bvac%2B88lkDK%2FLVdFgl2B6kIHZiYClzKtfczG93hWvKbST4NRNHP9LiaQqdNC17e5vNHnXVUGw%2ByxyjMLGqkgepOnZ2Rb14kcTOGp4i5AuJuuaMwXmCo7jUwPwfLe1NUlVBKqg6LK0Hcq4K0sZnxE8HFxiZ92WpV2AVWjRMEc%2F2z2shNoDvxvFUYyY1Oe67xINkmyQKc%2BygSBZzyLnXSFVWmHr3u5dcaaQGGAR42v6Ydr4iL38Hd4dOiBma%2BFXsXBIqWUjbST4VXmdaol7uzFMojA4zkxQDZAvF5XgJlAFadfySna%2Fteik%3D";
+
+async function checkForErrorSection(infoMessage, url, errorMessage, testType) {
+ info(infoMessage);
+
+ await BrowserTestUtils.withNewTab(url, async function(browser) {
+ await SpecialPowers.spawn(
+ browser,
+ [{ errorMessage, testType }],
+ async function({ errorMessage, testType }) {
+ let errorSection;
+
+ if (testType === "invalid") {
+ await ContentTaskUtils.waitForCondition(() => {
+ return (errorSection = content.document
+ .querySelector("certificate-section")
+ .shadowRoot.querySelector("error-section"));
+ }, errorMessage);
+ ok(errorSection, errorMessage);
+ } else if (testType === "valid") {
+ ok(!errorSection, errorMessage);
+ }
+ }
+ );
+ });
+}
+
+add_task(async function test_checkForErrorSection() {
+ let itemsToTest = [
+ {
+ testType: "valid",
+ url: validCert,
+ infoMessage: "Testing for error when a valid certificate is provided.",
+ errorMessage:
+ "Error section should not be visible when URL contains a valid certificate.",
+ },
+ {
+ testType: "invalid",
+ url: invalidCert,
+ infoMessage: "Testing for error when invalid certificate is provided.",
+ errorMessage:
+ "Error section should be visible when certificate is invalid.",
+ },
+ {
+ testType: "invalid",
+ url: pem_to_der_error,
+ infoMessage: "Testing for error when PEM to DIR error occurs.",
+ errorMessage:
+ "Error section should be visible when PEM to DIR error occurs.",
+ },
+ {
+ testType: "invalid",
+ url: error_parsing_cert,
+ infoMessage: "Testing for error when parsing error occurs.",
+ errorMessage:
+ "Error section should be visible when parsing error occurs.",
+ },
+ ];
+
+ for (let i = 0; i < itemsToTest.length; i++) {
+ let item = itemsToTest[i];
+ await checkForErrorSection(
+ item.infoMessage,
+ item.url,
+ item.errorMessage,
+ item.testType
+ );
+ }
+});
diff --git a/toolkit/components/certviewer/tests/browser/browser_certificateTabLink.js b/toolkit/components/certviewer/tests/browser/browser_certificateTabLink.js
new file mode 100644
index 0000000000..5023097c65
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser_certificateTabLink.js
@@ -0,0 +1,63 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const validCert =
+ "about:certificate?cert=MIIGMDCCBRigAwIBAgIQCa2oS7Nau6nwv1WyRNIJnzANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNzdXJhbmNlIFNlcnZlciBDQTAeFw0xOTA2MDYwMDAwMDBaFw0xOTA5MDQxMjAwMDBaMGExCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTWVubG8gUGFyazEXMBUGA1UEChMORmFjZWJvb2ssIEluYy4xFzAVBgNVBAMMDiouZmFjZWJvb2suY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEALPlfjd8gHkIMDeBOFhRt0e%2B%2F3fdm%2BZdzdM4s1WIHVbYztgmdEy20PUwDCviYKJX4GG%2BT9ivT8kJ%2FvWl1P%2FYqOCA54wggOaMB8GA1UdIwQYMBaAFFFo%2F5CvAgd1PMzZZWRiohK4WXI7MB0GA1UdDgQWBBTsQZVRTuib7KY9w3FfOYsZHvOC9zCBxwYDVR0RBIG%2FMIG8gg4qLmZhY2Vib29rLmNvbYINbWVzc2VuZ2VyLmNvbYILKi5mYmNkbi5uZXSCCCouZmIuY29tghAqLm0uZmFjZWJvb2suY29tggZmYi5jb22CDiouZmFjZWJvb2submV0gg4qLnh4LmZiY2RuLm5ldIIOKi54ei5mYmNkbi5uZXSCDyoubWVzc2VuZ2VyLmNvbYILKi5mYnNieC5jb22CDioueHkuZmJjZG4ubmV0ggxmYWNlYm9vay5jb20wDgYDVR0PAQH%2FBAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzYuY3JsMDSgMqAwhi5odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzYuY3JsMEwGA1UdIARFMEMwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQICMIGDBggrBgEFBQcBAQR3MHUwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBNBggrBgEFBQcwAoZBaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkhpZ2hBc3N1cmFuY2VTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH%2FBAIwADCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB1AKS5CZC0GFgUh7sTosxncAo8NZgE%2BRvfuON3zQ7IDdwQAAABay5CAaUAAAQDAEYwRAIgMwBM6q%2BdBwu2mNtMMjTEwJZZxyoUlHUEYO%2BbfkId%2F9MCIAQ2bxhnxrapYv74fzyoTkt9m%2BELq6%2B43OVpivRVKDKTAHcAdH7agzGtMxCRIZzOJU9CcMK%2F%2FV5CIAjGNzV55hB7zFYAAAFrLkIA%2FAAABAMASDBGAiEA0x1xPWue6RMSE9nbjYBt637CRC86ixrODP%2FEIlI5mCgCIQCHNdqgOlswd0LqaW4QRii2JHN4bnoEj%2FD9j7%2BkqEB7LjANBgkqhkiG9w0BAQsFAAOCAQEAnRdIVNZ850s7IvLgg%2BU9kKxA18kLKVpIF%2FrJHkXTkymvBHKAGOFNfzqF2YxHFhkDMIuoMO2F%2BA1E0Eo8zb1atL6%2FL59broEHTOH6xFmJAlZW0h6mZg8iRJ9Ae0pTN%2FfowaoN9aFVRnVr9ccKhOdqsXYyEZ3Ze39sEwx7Uau9KhzyuJW12Jh3S%2BZJYUdBADeeJNL5ZXSUFIyjgkwSQZPaaWAzSGHZFt3sWhMjdNoBkjRJFlASLDM3m1ZWsKA47vuXvJc%2FDXT35lC1DJmyhYb9qNPR71a1hJ8TS7vUwdDd%2BdEHiJj2wQLV3m7Tn7YvWyJOEyi4n6%2FrPqT44LZmgK7HWw%3D%3D&cert=MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3VyYW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC24C%2FCJAbIbQRf1%2B8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU%2BUDlqUH1VWtMICKq%2FQmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK%2FIHe1NnF9Xt4ZQaJn1itrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j%2F018QsIJzJa9buLnqS9UdAn4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I%2B4G3FhahnSMSTeXXkgisdaScus0Xsh5ENWV%2FUyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcftbZvySC%2FzA%2FWiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH%2FAgEAMA4GA1UdDwEB%2FwQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIGBFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAdBgNVHQ4EFgQUUWj%2FkK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7DaQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwdaOpKj4PWUS%2BNa0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk%2FgNHE%2Br1hspZcX30BJZr01lYPf7TMSVcGDiEo%2Bafgv2MW5gxTs14nhr9hctJqvIni5ly%2FD6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zuxICaEnL6VpPX%2F78whQYwvwt%2FTv9XBZ0k7YXDK%2FumdaisLRbvfXknsuvCnQsH6qqF0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY%2B3sAzm2fTYS5yh%2BRp%2FBIAV0AecPUeybQ%3D&cert=MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm%2B9S75S0tMqbf5YE%2Fyc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG%2B%2BMXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx%2BmM0aBhakaHPQNAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH%2FBAQDAgGGMA8GA1UdEwEB%2FwQFMAMBAf8wHQYDVR0OBBYEFLE%2Bw2kD%2BL9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE%2Bw2kD%2BL9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe%2FEW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9%2BMpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2Yzi9RKR%2F5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2%2FS6cCZdkGCevEsXCS%2B0yx5DaMkHJ8HSXPfqIbloEpw8nL%2Be%2FIBcm2PN7EeqJSdnoDfzAIJ9VNep%2BOkuE6N36B9K";
+
+add_task(async function test_certificateTabLink() {
+ await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
+ gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, validCert);
+ });
+
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function() {
+ let certificateTabs;
+ await ContentTaskUtils.waitForCondition(() => {
+ certificateTabs = content.document
+ .querySelector("certificate-section")
+ .shadowRoot.querySelectorAll(".certificate-tab");
+ return certificateTabs.length;
+ }, "Found certificate tabs.");
+
+ ok(certificateTabs.length, "Certificate tabs should exist.");
+
+ let issuerNameGroups = content.document
+ .querySelector("certificate-section")
+ .shadowRoot.querySelectorAll(".issuer-name");
+ let issuerNames = [];
+ for (let i = 0; i < issuerNameGroups.length; i++) {
+ issuerNames.push(
+ issuerNameGroups[i].shadowRoot.querySelector(".common-name")
+ );
+ }
+
+ for (let i = 0; i < issuerNames.length; i++) {
+ if (i < issuerNames.length - 1) {
+ issuerNames[i].shadowRoot.querySelector("a").click();
+ await ContentTaskUtils.waitForCondition(() => {
+ return (
+ certificateTabs[i + 1].classList.contains("selected"),
+ "Clicking link should select new tab."
+ );
+ });
+ ok(
+ certificateTabs[i + 1].classList.contains("selected"),
+ "Clicking link should select new tab."
+ );
+ } else {
+ await ContentTaskUtils.waitForCondition(() => {
+ return (
+ certificateTabs[i].classList.contains("selected"),
+ "Clicking link should select new tab."
+ );
+ });
+ ok(
+ !issuerNames[i].shadowRoot.querySelector("a"),
+ "Final tab's issuer name should not be link."
+ );
+ }
+ }
+ });
+ gBrowser.removeCurrentTab(); // closes about:certificate
+});
diff --git a/toolkit/components/certviewer/tests/browser/browser_checkAuthorityKeyID.js b/toolkit/components/certviewer/tests/browser/browser_checkAuthorityKeyID.js
new file mode 100644
index 0000000000..79c7a66f6b
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser_checkAuthorityKeyID.js
@@ -0,0 +1,52 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+async function checkAuthorityKeyID(url, expectedKeyId) {
+ await BrowserTestUtils.withNewTab(url, async function(browser) {
+ await SpecialPowers.spawn(browser, [expectedKeyId], async function(
+ expectedKeyId
+ ) {
+ let certificateSection = await ContentTaskUtils.waitForCondition(() => {
+ return content.document.querySelector("certificate-section");
+ }, "Certificate section found");
+ let authorityKeySection = certificateSection.shadowRoot.querySelector(
+ ".authority-key-id"
+ );
+ let subjectNameSection = certificateSection.shadowRoot.querySelector(
+ ".subject-name"
+ );
+ if (!expectedKeyId) {
+ Assert.equal(authorityKeySection, null, "authorityKeySection found");
+ Assert.ok(subjectNameSection, "subjectNameSection found");
+ return;
+ }
+ Assert.ok(authorityKeySection, "authorityKeySection found");
+ let item = authorityKeySection.shadowRoot.querySelector("info-item");
+ Assert.ok(item, "item found");
+ let info = item.shadowRoot.querySelector(".info").textContent;
+ Assert.equal(info, expectedKeyId, "Key IDs must be equal");
+ });
+ });
+}
+
+add_task(async function test() {
+ let tests = [
+ {
+ url:
+ "about:certificate?cert=MIIHQjCCBiqgAwIBAgIQCgYwQn9bvO1pVzllk7ZFHzANBgkqhkiG9w0BAQsFADB1MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTQwMgYDVQQDEytEaWdpQ2VydCBTSEEyIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VydmVyIENBMB4XDTE4MDUwODAwMDAwMFoXDTIwMDYwMzEyMDAwMFowgccxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQITCERlbGF3YXJlMRAwDgYDVQQFEwc1MTU3NTUwMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRMwEQYDVQQDEwpnaXRodWIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxjyq8jyXDDrBTyitcnB90865tWBzpHSbindG%2FXqYQkzFMBlXmqkzC%2BFdTRBYyneZw5Pz%2BXWQvL%2B74JW6LsWNc2EF0xCEqLOJuC9zjPAqbr7uroNLghGxYf13YdqbG5oj%2F4x%2BogEG3dF%2FU5YIwVr658DKyESMV6eoYV9mDVfTuJastkqcwero%2B5ZAKfYVMLUEsMwFtoTDJFmVf6JlkOWwsxp1WcQ%2FMRQK1cyqOoUFUgYylgdh3yeCDPeF22Ax8AlQxbcaI%2BGwfQL1FB7Jy%2Bh%2BKjME9lE%2FUpgV6Qt2R1xNSmvFCBWu%2BNFX6epwFP%2FJRbkMfLz0beYFUvmMgLtwVpEPSwIDAQABo4IDeTCCA3UwHwYDVR0jBBgwFoAUPdNQpdagre7zSmAKZdMh1Pj41g8wHQYDVR0OBBYEFMnCU2FmnV%2BrJfQmzQ84mqhJ6kipMCUGA1UdEQQeMByCCmdpdGh1Yi5jb22CDnd3dy5naXRodWIuY29tMA4GA1UdDwEB%2FwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0fBG4wbDA0oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItZXYtc2VydmVyLWcyLmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItZXYtc2VydmVyLWcyLmNybDBLBgNVHSAERDBCMDcGCWCGSAGG%2FWwCATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAcGBWeBDAEBMIGIBggrBgEFBQcBAQR8MHowJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBSBggrBgEFBQcwAoZGaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkV4dGVuZGVkVmFsaWRhdGlvblNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAAMIIBfgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdgCkuQmQtBhYFIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAWNBYm0KAAAEAwBHMEUCIQDRZp38cTWsWH2GdBpe%2FuPTWnsu%2Fm4BEC2%2BdIcvSykZYgIgCP5gGv6yzaazxBK2NwGdmmyuEFNSg2pARbMJlUFgU5UAdgBWFAaaL9fC7NP14b1Esj7HRna5vJkRXMDvlJhV1onQ3QAAAWNBYm0tAAAEAwBHMEUCIQCi7omUvYLm0b2LobtEeRAYnlIo7n6JxbYdrtYdmPUWJQIgVgw1AZ51vK9ENinBg22FPxb82TvNDO05T17hxXRC2IYAdgC72d%2B8H4pxtZOUI5eqkntHOFeVCqtS6BqQlmQ2jh7RhQAAAWNBYm3fAAAEAwBHMEUCIQChzdTKUU2N%2BXcqcK0OJYrN8EYynloVxho4yPk6Dq3EPgIgdNH5u8rC3UcslQV4B9o0a0w204omDREGKTVuEpxGeOQwDQYJKoZIhvcNAQELBQADggEBAHAPWpanWOW%2Fip2oJ5grAH8mqQfaunuCVE%2Bvac%2B88lkDK%2FLVdFgl2B6kIHZiYClzKtfczG93hWvKbST4NRNHP9LiaQqdNC17e5vNHnXVUGw%2ByxyjMLGqkgepOnZ2Rb14kcTOGp4i5AuJuuaMwXmCo7jUwPwfLe1NUlVBKqg6LK0Hcq4K0sZnxE8HFxiZ92WpV2AVWjRMEc%2F2z2shNoDvxvFUYyY1Oe67xINkmyQKc%2BygSBZzyLnXSFVWmHr3u5dcaaQGGAR42v6Ydr4iL38Hd4dOiBma%2BFXsXBIqWUjbST4VXmdaol7uzFMojA4zkxQDZAvF5XgJlAFadfySna%2Fteik%3D",
+ expectedKeyId:
+ "3D:D3:50:A5:D6:A0:AD:EE:F3:4A:60:0A:65:D3:21:D4:F8:F8:D6:0F",
+ },
+ {
+ url:
+ "about:certificate?cert=MIIGdjCCBF6gAwIBAgIBJjANBgkqhkiG9w0BAQsFADB0MQswCQYDVQQGEwJKRTEPMA0GA1UECAwGSmVyc2V5MRUwEwYDVQQKDAx0Z2hvc3QuY28udWsxFTATBgNVBAMMDHRnaG9zdC5jby51azEmMCQGCSqGSIb3DQEJARYXcG9zdG1hc3RlckB0Z2hvc3QuY28udWswHhcNMTkxMTE4MjE1NjAwWhcNMjAxMTE3MjE1NjAwWjBRMQswCQYDVQQGEwJKRTEPMA0GA1UECAwGSmVyc2V5MRUwEwYDVQQKDAx0Z2hvc3QuY28udWsxGjAYBgNVBAMMEW1haWwudGdob3N0LmNvLnVrMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0CS0dR6hyjv4o6s4%2FI2VT43DCfylcaq%2F6%2B5tUn6xMDtf0tYMXPjG%2FGjtlXQk2Jq7wa%2FlRR%2Fzs8c6037BZ7wzu8Wx2i6tvRLZZSlzM2mRHxaRRDYTeHyovanhCFzKqnvi30bxKugQ3lETBK5eP7ppVpcHz58lx%2B%2BFovPOBx6SRaz4EiceUybZwFpKxUJmlhivT2MJTKM5NHF4n27vszM0dyu2qXLzhpy5dgklMEEhdnHFCT%2F9YPN7uLCvzJnCo9N%2FeWf84odJ%2FjTiEKm5NG6SGDuOZ%2FbY9KwQ8nAk26zeTkw%2BMfMXD2Rl76ZFg%2B07bpckSTiaCtLGGhbgLrqEdgNGTpz1Pu3uFjhR4QsfUsDAaSvgns0PT6eSA152cgOtin2SYo%2B4UVjVdM5d%2ByB0JgEIGHmiCRQkDdCD9%2FNZBhrnG2Xwooe64QzD5OjNS8yQSCPvjfivbSk1ulcIGjgxC0z1Ot4hc%2ByuU8aRE0ekIOf5EUEjZfJ%2FnO4EXT3J5en0CYurswJM7miOsVEiO1OIut022T00MoAF%2F%2FWP73qVW3Jbv6X0pzOBYDY3osyje4n6JRqujhPEOR0MNiaZxfz4JFNPAzi0Tq6qORbXbLgGBqPFvKh2KKIMGysfRqLlETI1lpqsHyhMxgllQW9IK33kwK9y0HgluEZvc58dvle8hOS4NK8CAwEAAaOCATQwggEwMAkGA1UdEwQCMAAwHQYDVR0OBBYEFORJOggtlruQ1S6vzucFiAS86CadMIGQBgNVHSMEgYgwgYWheKR2MHQxCzAJBgNVBAYTAkpFMQ8wDQYDVQQIDAZKZXJzZXkxFTATBgNVBAoMDHRnaG9zdC5jby51azEVMBMGA1UEAwwMdGdob3N0LmNvLnVrMSYwJAYJKoZIhvcNAQkBFhdwb3N0bWFzdGVyQHRnaG9zdC5jby51a4IJAMeNizC6cTabMDMGA1UdHwQsMCowKKAmoCSGImh0dHA6Ly93d3cudGdob3N0LmNvLnVrL2NhL2NybC5wZW0wCwYDVR0PBAQDAgP4MBEGCWCGSAGG%2BEIBAQQEAwIE8DAcBgNVHREEFTATghFtYWlsLnRnaG9zdC5jby51azANBgkqhkiG9w0BAQsFAAOCAgEAKZC9pqgU9MPssbNeJhKeGcCoH49BhfhrJNPkWqlJ%2FVbUB32m8p%2F7exaqFEe%2Fk2YwV8ILMA%2FCvQLgeV36Y9rHcWKqaA8lrklhRkK6%2BfYkAkpw37vVbm8qWsTt4OMa0Ajh%2F7QBy%2FUqak8Gaarl3LkJKLKB3Pj%2Bd2BFNxNm5W3TeFia2s%2B5y0O0eKqSQwRPqlQo3qhNQU1fDimTq8yI3fH9AOByWXHePjSc5h45GHxWoXPqQKtuqCINou6pKeZa1KoTCefB2oYJqamkneL2%2B21JhwkSVkGUfseGc2hiROVLejc%2Fgzq7mpUqudOsyN672BwB6W81w6%2FHCt2cZmCTWAAT5E3b6bHqqTTn9O2uljx2zTxao5Xov4L9EZ3hdccsLJGXHYgGDqY33e6Rrf86Jc%2BV%2F4%2FL8vhGf%2B70ASKLkibUuGwFJ0%2BamQHoHnVXLZ5rnbV3ArXOQcsfegTifmEPn7pGyHm7r5%2BkJ2JIh8wCyl5B%2FUxvNwIfAFEiieU3aqRAgbjnezYXwoLoLJBKSRMXdIfZJldduIkoPaeO0zWWaJSMon3qTAeDuboM4EfYG9Ma3UWdznXVkmgiXFo%2Fz6k%2Bg4jNzaQknI8jNHbp9G5K7M9KPcvUja8hjeGG4RIULKDdkauZUe1hX6m3NrzrJLD3MJPD8YTFeAf%2Fe3HCGwl4stKWHg4%3D&cert=MIIFZDCCA0wCCQDHjYswunE2mzANBgkqhkiG9w0BAQsFADB0MQswCQYDVQQGEwJKRTEPMA0GA1UECAwGSmVyc2V5MRUwEwYDVQQKDAx0Z2hvc3QuY28udWsxFTATBgNVBAMMDHRnaG9zdC5jby51azEmMCQGCSqGSIb3DQEJARYXcG9zdG1hc3RlckB0Z2hvc3QuY28udWswHhcNMTgwNDA4MTIyMjU0WhcNMjMwNDA4MTIyMjU0WjB0MQswCQYDVQQGEwJKRTEPMA0GA1UECAwGSmVyc2V5MRUwEwYDVQQKDAx0Z2hvc3QuY28udWsxFTATBgNVBAMMDHRnaG9zdC5jby51azEmMCQGCSqGSIb3DQEJARYXcG9zdG1hc3RlckB0Z2hvc3QuY28udWswggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCoFbHy44GNOQSymk%2BwAmZmllcAATSM6DrsW7NZgX8vHeP5OAlRaGaOgVmozKcbKSB2KSIvDvY1%2BKEKtfr5meIaeA6r%2BILeUYuNxQomnW3Oy%2B%2B7RFE53pS7R7QIt%2FLVf3k60mdZDLXF1wyFv950noGNrFZfvBvND1%2F88JeC4Gt7dVnJMy9CXOr7V0O%2F7sa5z%2Bvfm2Acufd1RYA3W%2FECbt%2F6z8KV%2FQthAgcYoabQgkmh8AxQ5cG7tBmoEAs%2BNwU%2BR8eMq1f%2B6TBCJiMa07jA1%2BQ663d7YONlk4fTSmvo3lEhXtrR%2BmrkxZAMiAD6NJs3VakcuAED9e1dS3G3%2FmPcNrKsa73aXEC5uvL9y4mKCZLypuSYjlW8cP5JpCG6vtmwL%2FATbcCtwpDwrKLcRWCrZdX0FOJirjWfKL%2BhyIWayQ5u7awdhH430h8rj03fXSMBhtTn73rohSGIANBnqVftvDDPnEQb5p17giaVbJybfA2tdMvJTZg6pEAx9%2B3zHXRECFpWOtaJDjWbmIExPMgiCSFkBPP3MEDVb7VdHKZs0CvBQg6GmpXg9M4OHZylzS6PXXO8qBCtBdKOwdFSZWbeD9E652rkvb5FuQ8laGHcxgMc2YFlVZaqVowXEkVkkld12d4sBipeRpDWNjA2kLfeUmwsXWtugG8c8Jm9IoZY8oeUkwIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCVj6R9C5pE9hkBx7CCr9l4TLoolaEZlKngJHBRRSy5U50MndQ24Jeis2OTxEeYX7DJ%2BOy6QZdaph6FLwALxUWPfQavBcgauKR%2FCdqLQxZc267TMFkRIZvOtHUJ4obJ5qvQAWzNnmRq18b5plznfBfn9b3F2AmHgfsNX6WryQ4geR786VObcUhKTaofcaX%2FE4J9AVzL864fJ%2FDB%2FPSqhYrtskiG6PT9Ngu20ejvgAVk5aJ%2F%2F5Swsjyg6EBl%2BdwJepq2xzI313ZkwCg2pp6oqLDlxf%2Fh585Bsqke39Ax%2B42NWNM14cethcJ7jgyZoEaL3T%2BQ3O%2Bj9XEe5FbvkKtSgMIA6f0FneA4vbF8%2FECPMEi7k3k04gU1gZSR%2FGA63GPEK%2FCLqeh%2BYVgBGKDPinnMEV%2FuBrTUDQFBlDEHlELk7F9o93lxQNs6WOGQSfybfHhySla3nqoYV2phyeZZsJ%2BxMovWWIydJhVN%2F37v0fYTZhnlquGenXHvC5MHrMq2vjUY0Uy637AzXWVNWveNyQmmn9tL4jygELHQu%2Bint4GRybH7rThcslv63D5s4zZza7cITIFjmqZ%2BPrTSVKL%2BlnQLjEMpSdfB86Y2JnMimaOyv%2BbZp1QMB5fYh0PTsjYATi9We%2BDFD42c5H7Su0vFAwCTP11AiKzfbj2oBKVVwwJj3FmkYQ%3D%3D",
+ expectedKeyId: false,
+ },
+ ];
+
+ for (let test of tests) {
+ await checkAuthorityKeyID(test.url, test.expectedKeyId);
+ }
+});
diff --git a/toolkit/components/certviewer/tests/browser/browser_checkLongHex.js b/toolkit/components/certviewer/tests/browser/browser_checkLongHex.js
new file mode 100644
index 0000000000..a17f187a32
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser_checkLongHex.js
@@ -0,0 +1,41 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+async function checkLongHex(url, itemClass) {
+ await BrowserTestUtils.withNewTab(url, async function(browser) {
+ await SpecialPowers.spawn(browser, [itemClass], async function(itemClass) {
+ let certificateSection = await ContentTaskUtils.waitForCondition(() => {
+ return content.document.querySelector("certificate-section");
+ }, "Certificate section found");
+ let publicKeyInfoSection = certificateSection.shadowRoot.querySelector(
+ ".public-key-info"
+ );
+ Assert.ok(publicKeyInfoSection, "publicKeyInfoSection found");
+
+ let item = publicKeyInfoSection.shadowRoot.querySelector(`.${itemClass}`);
+ Assert.ok(item, `item ${itemClass} found`);
+
+ let longHex = item.shadowRoot.querySelector(".long-hex");
+ Assert.ok(longHex, "longHex class name found");
+ });
+ });
+}
+
+add_task(async function test() {
+ let tests = [
+ {
+ url:
+ "about:certificate?cert=MIIHQjCCBiqgAwIBAgIQCgYwQn9bvO1pVzllk7ZFHzANBgkqhkiG9w0BAQsFADB1MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTQwMgYDVQQDEytEaWdpQ2VydCBTSEEyIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VydmVyIENBMB4XDTE4MDUwODAwMDAwMFoXDTIwMDYwMzEyMDAwMFowgccxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQITCERlbGF3YXJlMRAwDgYDVQQFEwc1MTU3NTUwMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRMwEQYDVQQDEwpnaXRodWIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxjyq8jyXDDrBTyitcnB90865tWBzpHSbindG%2FXqYQkzFMBlXmqkzC%2BFdTRBYyneZw5Pz%2BXWQvL%2B74JW6LsWNc2EF0xCEqLOJuC9zjPAqbr7uroNLghGxYf13YdqbG5oj%2F4x%2BogEG3dF%2FU5YIwVr658DKyESMV6eoYV9mDVfTuJastkqcwero%2B5ZAKfYVMLUEsMwFtoTDJFmVf6JlkOWwsxp1WcQ%2FMRQK1cyqOoUFUgYylgdh3yeCDPeF22Ax8AlQxbcaI%2BGwfQL1FB7Jy%2Bh%2BKjME9lE%2FUpgV6Qt2R1xNSmvFCBWu%2BNFX6epwFP%2FJRbkMfLz0beYFUvmMgLtwVpEPSwIDAQABo4IDeTCCA3UwHwYDVR0jBBgwFoAUPdNQpdagre7zSmAKZdMh1Pj41g8wHQYDVR0OBBYEFMnCU2FmnV%2BrJfQmzQ84mqhJ6kipMCUGA1UdEQQeMByCCmdpdGh1Yi5jb22CDnd3dy5naXRodWIuY29tMA4GA1UdDwEB%2FwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0fBG4wbDA0oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItZXYtc2VydmVyLWcyLmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItZXYtc2VydmVyLWcyLmNybDBLBgNVHSAERDBCMDcGCWCGSAGG%2FWwCATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAcGBWeBDAEBMIGIBggrBgEFBQcBAQR8MHowJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBSBggrBgEFBQcwAoZGaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkV4dGVuZGVkVmFsaWRhdGlvblNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAAMIIBfgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdgCkuQmQtBhYFIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAWNBYm0KAAAEAwBHMEUCIQDRZp38cTWsWH2GdBpe%2FuPTWnsu%2Fm4BEC2%2BdIcvSykZYgIgCP5gGv6yzaazxBK2NwGdmmyuEFNSg2pARbMJlUFgU5UAdgBWFAaaL9fC7NP14b1Esj7HRna5vJkRXMDvlJhV1onQ3QAAAWNBYm0tAAAEAwBHMEUCIQCi7omUvYLm0b2LobtEeRAYnlIo7n6JxbYdrtYdmPUWJQIgVgw1AZ51vK9ENinBg22FPxb82TvNDO05T17hxXRC2IYAdgC72d%2B8H4pxtZOUI5eqkntHOFeVCqtS6BqQlmQ2jh7RhQAAAWNBYm3fAAAEAwBHMEUCIQChzdTKUU2N%2BXcqcK0OJYrN8EYynloVxho4yPk6Dq3EPgIgdNH5u8rC3UcslQV4B9o0a0w204omDREGKTVuEpxGeOQwDQYJKoZIhvcNAQELBQADggEBAHAPWpanWOW%2Fip2oJ5grAH8mqQfaunuCVE%2Bvac%2B88lkDK%2FLVdFgl2B6kIHZiYClzKtfczG93hWvKbST4NRNHP9LiaQqdNC17e5vNHnXVUGw%2ByxyjMLGqkgepOnZ2Rb14kcTOGp4i5AuJuuaMwXmCo7jUwPwfLe1NUlVBKqg6LK0Hcq4K0sZnxE8HFxiZ92WpV2AVWjRMEc%2F2z2shNoDvxvFUYyY1Oe67xINkmyQKc%2BygSBZzyLnXSFVWmHr3u5dcaaQGGAR42v6Ydr4iL38Hd4dOiBma%2BFXsXBIqWUjbST4VXmdaol7uzFMojA4zkxQDZAvF5XgJlAFadfySna%2Fteik%3D",
+ itemClass: "modulus",
+ },
+ {
+ url:
+ "about:certificate?cert=MIIIMTCCBxmgAwIBAgIMFkDF1F0uxNlMfXxqMA0GCSqGSIb3DQEBCwUAMGYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTwwOgYDVQQDEzNHbG9iYWxTaWduIE9yZ2FuaXphdGlvbiBWYWxpZGF0aW9uIENBIC0gU0hBMjU2IC0gRzIwHhcNMTgxMTA4MjEyMTA0WhcNMTkxMTIyMDc1OTU5WjB5MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEjMCEGA1UEChMaV2lraW1lZGlhIEZvdW5kYXRpb24sIEluYy4xGDAWBgNVBAMMDyoud2lraXBlZGlhLm9yZzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGd1rS7GauMxJ15BmViShjVMjwQJNjjw%2BOUhnIaqE5QF%2Fq6c%2FLIvVh4N3473a7J52JcfmlfCrXvDthHzaZNEneKjggWVMIIFkTAOBgNVHQ8BAf8EBAMCA4gwgaAGCCsGAQUFBwEBBIGTMIGQME0GCCsGAQUFBzAChkFodHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2NhY2VydC9nc29yZ2FuaXphdGlvbnZhbHNoYTJnMnIxLmNydDA%2FBggrBgEFBQcwAYYzaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL2dzb3JnYW5pemF0aW9udmFsc2hhMmcyMFYGA1UdIARPME0wQQYJKwYBBAGgMgEUMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMAgGBmeBDAECAjAJBgNVHRMEAjAAMEkGA1UdHwRCMEAwPqA8oDqGOGh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vZ3MvZ3Nvcmdhbml6YXRpb252YWxzaGEyZzIuY3JsMIICxQYDVR0RBIICvDCCAriCDyoud2lraXBlZGlhLm9yZ4INd2lraW1lZGlhLm9yZ4INbWVkaWF3aWtpLm9yZ4INd2lraWJvb2tzLm9yZ4IMd2lraWRhdGEub3Jnggx3aWtpbmV3cy5vcmeCDXdpa2lxdW90ZS5vcmeCDndpa2lzb3VyY2Uub3Jngg93aWtpdmVyc2l0eS5vcmeCDndpa2l2b3lhZ2Uub3Jngg53aWt0aW9uYXJ5Lm9yZ4IXd2lraW1lZGlhZm91bmRhdGlvbi5vcmeCBncud2lraYISd21mdXNlcmNvbnRlbnQub3JnghEqLm0ud2lraXBlZGlhLm9yZ4IPKi53aWtpbWVkaWEub3JnghEqLm0ud2lraW1lZGlhLm9yZ4IWKi5wbGFuZXQud2lraW1lZGlhLm9yZ4IPKi5tZWRpYXdpa2kub3JnghEqLm0ubWVkaWF3aWtpLm9yZ4IPKi53aWtpYm9va3Mub3JnghEqLm0ud2lraWJvb2tzLm9yZ4IOKi53aWtpZGF0YS5vcmeCECoubS53aWtpZGF0YS5vcmeCDioud2lraW5ld3Mub3JnghAqLm0ud2lraW5ld3Mub3Jngg8qLndpa2lxdW90ZS5vcmeCESoubS53aWtpcXVvdGUub3JnghAqLndpa2lzb3VyY2Uub3JnghIqLm0ud2lraXNvdXJjZS5vcmeCESoud2lraXZlcnNpdHkub3JnghMqLm0ud2lraXZlcnNpdHkub3JnghAqLndpa2l2b3lhZ2Uub3JnghIqLm0ud2lraXZveWFnZS5vcmeCECoud2lrdGlvbmFyeS5vcmeCEioubS53aWt0aW9uYXJ5Lm9yZ4IZKi53aWtpbWVkaWFmb3VuZGF0aW9uLm9yZ4IUKi53bWZ1c2VyY29udGVudC5vcmeCDXdpa2lwZWRpYS5vcmcwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBSt4NNfC33t2i98DfZjjYpZGMJsijAfBgNVHSMEGDAWgBSW3mHxvRwWKVMcwMx9O4MAQOYafDCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB2AKS5CZC0GFgUh7sTosxncAo8NZgE%2BRvfuON3zQ7IDdwQAAABZvUzN%2FYAAAQDAEcwRQIgBATdvSzbd5NwGdtkmJ5SEvEPn6A8hgAsk6GSP6hzWcgCIQDKfHQNtObs%2FhHPfLgXsVkcnHIbjlNwmWeiukGtGHZFMgB2AG9Tdqwx8DEZ2JkApFEV%2F3cVHBHZAsEAKQaNsgiaN9kTAAABZvUzN8cAAAQDAEcwRQIgYalEnXtd%2FfPhjq9SXPoSPRhaMmeDs0IMN5o5Y6QTKfUCIQClR1uj%2BB56K4tGh%2Fmws4qugG1qSD9zfvmx8roKik3HHDANBgkqhkiG9w0BAQsFAAOCAQEAUEJyg%2FAZo%2BowG5J%2FLIk8EIDnyOcanmfgvdjMg8KnpBvh8l3Wb4HmOudluJhIeIbCUMwzEzSGqYQQ78n4wtjLaLwaDgL4WzHOVec2k%2BrbfmPT6MUCtdlz1PK5%2FWY9JQyQq6vy%2Btm3a6Wijy6M8U%2FTdrJubK5X03SFfRb0pDuFdr2fnkctLRnyCb1w0XHwGXjEcGm1LY42YKwdvbj3WIqumeSEuG4MZtquW6NURKELSil03G%2FhRHRAHHGx3zXes%2FjJcpH2GPX9eY9B%2BR1oHmCE2QF5Y%2FBh%2BuNA2%2B2Iuj%2F6UJAOw%2FZ%2F8%2BqZcnLWWnK2Dwzc34C%2FAUD%2BWb71oUcr60%2BpPg%3D%3D&cert=MIIEYjCCA0qgAwIBAgILBAAAAAABMYnGRMkwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTEwODAyMTAwMDAwWhcNMjIwODAyMTAwMDAwWjBmMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTE8MDoGA1UEAxMzR2xvYmFsU2lnbiBPcmdhbml6YXRpb24gVmFsaWRhdGlvbiBDQSAtIFNIQTI1NiAtIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxw5sPyOTf8xwpZ0gww5TP37ATsKYScpH1SPvAzSFdMijAi5GXAt9yYidT4vw%2BJxsjFU127%2Fys%2Br741bnSkbZEyLKNtWbwajjlkOT8gy85vnm6JnIY0h4f1c2aRoZHVrR1H3CnNR%2F4YASrnrqiOpX2MoKCjoSSaJiGXoNJPc367RzknsFI5sStc7rKd%2BkFAK5AaXUppxDZIje%2BH7%2B4%2FUe5f7co6jkZjHZTCXpGLmJWQmu6Z0cbTcPSh41ICjir9QhiwHERa1uK2OrkmthCk0g7XO6fM7%2BFrXbn4Dw1ots2Qh5Sk94ZdqSvL41%2BbPE%2BSeATv%2BWUuYCIOEHc%2BldK72y8QIDAQABo4IBKTCCASUwDgYDVR0PAQH%2FBAQDAgEGMBIGA1UdEwEB%2FwQIMAYBAf8CAQAwHQYDVR0OBBYEFJbeYfG9HBYpUxzAzH07gwBA5hp8MEcGA1UdIARAMD4wPAYEVR0gADA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzA2BgNVHR8ELzAtMCugKaAnhiVodHRwOi8vY3JsLmdsb2JhbHNpZ24ubmV0L3Jvb3QtcjMuY3JsMD4GCCsGAQUFBwEBBDIwMDAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL3Jvb3RyMzAfBgNVHSMEGDAWgBSP8Et%2FqC5FJK5NUPpjmove4t0bvDANBgkqhkiG9w0BAQsFAAOCAQEAugYpwLQZjCERwJQRnrs91NVDQPafuyULI2i1Gvf6VGTMKxP5IfBEreHoFVjb7v3bok3MGI8Nmm3DawGhMfCNvABAzDlfh2FRbfSV6uoVNT5AhcBi1aE0%2FniqqLJaOfM3Qfuc6D5xSlvr%2BGlYoeDGk3fpumeS62VYkHBzQn2v9CMmeReq%2BqS7meVEb2WB58rrVcj0ticRIXSUvGu3dGIpxM2uR%2FLmQlt4hgVhy5CqeYnfBH6xJnBLjUAfhHvA%2BwfmyLdOkfQ1A%2B3o60EQF0m0YsinLPLhTI8DLPMWN11n8aQ5eUmjwF3MVfkhgA%2F7zuIpalhQ6abX6xwyNrVip8H65g%3D%3D&cert=MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie%2FQV2EcWtiHL8RgJDx7KKnQRfJMsuS%2BFggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ0mpiLx9e%2BpZo34knlTifBtc%2BycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO%2FbLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c%2B9C7v%2FU9AOEGM%2BiCK65TpjoWc4zdQQ4gOsC0p6Hpsk%2BQLjJg6VfLuQSSaGjlOCZgdbKfd%2F%2BRFO%2BuIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH%2FBAQDAgEGMA8GA1UdEwEB%2FwQFMAMBAf8wHQYDVR0OBBYEFI%2FwS3%2BoLkUkrk1Q%2BmOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr%2ByAzv95ZURUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q%2Fc2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj%2B9xTaGdWPoO4zzUhw8lo%2Fs7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj%2B1EbddTKJd%2B82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws%2FzyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9%2BE7gUJTb0o2HLO02JQZR7rkpeDMdmztcpHWD9f",
+ itemClass: "public-value",
+ },
+ ];
+
+ for (let test of tests) {
+ await checkLongHex(test.url, test.itemClass);
+ }
+});
diff --git a/toolkit/components/certviewer/tests/browser/browser_checkMissingCommonName.js b/toolkit/components/certviewer/tests/browser/browser_checkMissingCommonName.js
new file mode 100644
index 0000000000..eae316fe17
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser_checkMissingCommonName.js
@@ -0,0 +1,49 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_check_missing_common_name() {
+ const kURL =
+ "about:certificate?cert=MIIHVDCCBTygAwIBAgIQOBNAgEopyUI1DYLsLmSWejANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ6KGM5pS%2F6ZmiMTUwMwYDVQQDDCzmlL%2FlupzkvLrmnI3lmajmlbjkvY3mhpHorYnnrqHnkIbkuK3lv4MgLSBHMTAeFw0yMDAxMjAwNjExMzBaFw0yMjAxMjAwNjExMzBaMFUxCzAJBgNVBAYTAlRXMQ8wDQYDVQQHDAboh7rngaMxEjAQBgNVBAoMCee4vee1seW6nDEhMB8GA1UEAwwYZW5nbGlzaC5wcmVzaWRlbnQuZ292LnR3MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyxCtEdUsGqr%2FVCNOMpj1TkDzBn6Gs1RBHHERU%2BsJ1q3ri6rJfydTx0rQKUbcGEMyWB2pga4dNSjzxQZ6%2BebP3kctC0H%2F%2BptEnsIOQcyD2yLN5yg8ejx6Y568z3fbU%2FRAVo4q6qGZzlBfzl2AhZMrp3AiNpQZXjLWgNHYZfirDVur7ImSjECq6atLlZ1yn%2B0RC%2FsGsPKalz5iacuxMYIkWeCvm7piA%2FdXPfw%2FVJxbIEkXMSXXxDNGrBZY0wAcmPeDHZxyLDGDOFLV%2Fpics3ZJ4UjFPphwaXuW94K9NKLcfOu7JaYP6JszpBIEiL8GRl8pMdykkKN%2FRkEZ%2F8pE7Tz%2BswIDAQABo4IDGzCCAxcwHwYDVR0jBBgwFoAU1ustnWH%2BK7twiC64B7FZsPSDImowHQYDVR0OBBYEFDxkjGSuIgKbFKTUvadNfX%2B%2BogdCMHUGCCsGAQUFBwEBBGkwZzA1BggrBgEFBQcwAoYpaHR0cDovL2d0bHNjYS5uYXQuZ292LnR3L0NlcnRzL0dUTFNDQS5jcnQwLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3NwLmd0bHNjYS5uYXQuZ292LnR3L09DU1AwIgYDVR0gBBswGTANBgsrBgEEAYG3I2QAAzAIBgZngQwBAgIwIAYDVR0lAQH%2FBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMCMGA1UdEQQcMBqCGGVuZ2xpc2gucHJlc2lkZW50Lmdvdi50dzAgBgNVHQkEGTAXMBUGB2CGdgFkAgExCgYIYIZ2AWQDAwEwQQYDVR0fBDowODA2oDSgMoYwaHR0cDovL2d0bHNjYS5uYXQuZ292LnR3L2NybC9HVExTQ0EtY29tcGxldGUuY3JsMA4GA1UdDwEB%2FwQEAwIFoDCCAXwGCisGAQQB1nkCBAIEggFsBIIBaAFmAHUApLkJkLQYWBSHuxOizGdwCjw1mAT5G9%2B443fNDsgN3BAAAAFvwZRvQAAABAMARjBEAiAWcMYq5U%2BiRndzk4q7XRQ10ykv%2FBlaHelk0SMi8LeXmAIgY%2BJUd3bzT5nSTCYQMOAMLGE52UWhnIRgxdWRtcg60uAAdQDuS723dc5guuFCaR%2Br4Z5mow9%2BX7By2IMAxHuJeqj9ywAAAW%2FBlHdGAAAEAwBGMEQCIAM72FPgBC6JzvE%2BEkvdp9g9Lt19fnJ6KfWQYNN%2BMylsAiBezZw%2FDzsg22O4Tr0QGYoY7HsnPzsHzxEJVUJGl8HXZQB2AG9Tdqwx8DEZ2JkApFEV%2F3cVHBHZAsEAKQaNsgiaN9kTAAABb8GUfQAAAAQDAEcwRQIgXVJY0MInclLEtJ1AoMPtjja0tvBD0zPHSAyxIgZ%2B3EECIQDTj7KrkhXuZqKr6sF0hqwr%2BiMiByMi7gNjK4DOqxJ7YjANBgkqhkiG9w0BAQsFAAOCAgEAeOXA%2FpFjaSlenGSQSMDbbSXM%2BL2nM0M1yQ8WxM2mxRfAxzyuH%2FDo1UGDmbvu1e6f%2FdA6Gr%2BAdx2EFia3FqIBrnB9BAymlMgYKq3pW67b83k8r6iF5UcwxISE4LXplY8iV12a59EUCHr0YnVUzK3gLN9ocPyGHnsRdzuowU7WRtZ2tMFAlVT2dEGPqG2ZKsIiCBRummp1vNF3b%2BB5g4Y5Hc7Vw1%2F1LgPMsaSPj5%2Fl4YdLCIO2tWYqnpA0LE8xuRXFSRA0fmlZQKr01N0%2B1ar2QRH6PcRJE3EJbgdnsIGDMithZ4a2COinwCWNkuj6lwB83RvfGOdwJfVv9ricvRpdMOs3HSQnRk0q1IreY42VVmtOGt6MfuCPaIMZtI0unkd3GHmCDcoe64HIu7sjdTCqWAR60JZpQ4oM%2BOpzfBulhf44BDh33zM7lNAlEtVN%2BtszLA2S3CCoDTHpUGWkes%2BzkI4qjG5Nd1eGZT%2FtqqWyRc799ROCEAI5SkgZgowqRgzMhkazdyDANLTbg2Edt4OT7O6zrdLg70JTZMxdJ5%2BAnDMmDr8NCH63URFJe72ZBOH4uAeZuV%2Bhbh9v1%2BF2kFaqVBh2VaRdY%2FHGpnoD%2By1bJ7FI1erKUJFt%2FP4ZEYjACkmT7Gtw8NifvECY3cw3aiAY7AMg2Bnk72ySxvBcXedVMU8%3D&cert=MIIGtjCCBJ6gAwIBAgIRAJltX%2Bmt4Wzcjs2%2F7bFKMpUwDQYJKoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVFcxIzAhBgNVBAoMGkNodW5naHdhIFRlbGVjb20gQ28uLCBMdGQuMS8wLQYDVQQDDCZlUEtJIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjAeFw0xOTA3MTkwNjQ2NDVaFw0zMTA4MTkwNjQ2NDVaMFgxCzAJBgNVBAYTAlRXMRIwEAYDVQQKDAnooYzmlL%2FpmaIxNTAzBgNVBAMMLOaUv%2BW6nOS8uuacjeWZqOaVuOS9jeaGkeitieeuoeeQhuS4reW%2FgyAtIEcxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwg5R4LGoDj%2BmZIXmcHmRYv501jsSLIm7EoX%2FKAt74uN2yDR436V2EWkFeWhD%2BTS4sx2%2F3JCRW%2BKE%2BIX8NYBKjsWuK9OMY4Gu4FEWJpBu1XCWYjTPKyhHdEhDpxRxv91g3Zk68XgK7j2U5sEzCPx13QjkH7qc%2FMo5BFiro8YsYAfxgCoa%2FrZFEsXyZKXRJeIDw7t%2BiPxVy2cbQ0uNloO9670LGoOVzYVkYABv3IwZo%2BJRtj%2Bj7rLjB7xQKYmfJOA2Jc96yPm6li7zHrIQYfohGPdANmwR9opNNqYOo%2BLtsIYot3%2FcLp9YgAaiGdrAiKrbbEVkYH%2BzKzAHolf5mPBn%2Bh3OElYfygESitWRBp2bwfOGJwAYseTuorQHpyQps1GGcn9vcfnLhvLxa3DMrCAvSJb3SvHCyqahQz0KR0IPcu%2BVLW3icaqlbJausGIGYqp8VSN6FJ0pgmYdbunBLYc1v23VvjmVMl%2BxNJoaSFEUscmSqA4CuYANhkWSANk8HI9rNbvmzuyWhSv7tUXY6UB67mHp4ypGcKYbXrjiKqahv6QLUEb7S8FD71Ds75F2vMeO4O77i6joBs%2FL2E6WZJvSronzJCXL0IwmpYaOAsoFOf0eGVsPBVKn%2Bz4Bq0WA0%2Br7plfWofDbUGmx9Zun%2B%2BrWhoDXrma%2BodubN1Xj1RjlL3sCAwEAAaOCAW4wggFqMB8GA1UdIwQYMBaAFHJbuqpyOO4lkCS1lCL6CYjKiwr7MB0GA1UdDgQWBBTW6y2dYf4ru3CILrgHsVmw9IMiajAOBgNVHQ8BAf8EBAMCAYYwPAYDVR0fBDUwMzAxoC%2BgLYYraHR0cDovL2VjYS5oaW5ldC5uZXQvcmVwb3NpdG9yeS9DUkwyL0NBLmNybDCBggYIKwYBBQUHAQEEdjB0MDsGCCsGAQUFBzAChi9odHRwOi8vZWNhLmhpbmV0Lm5ldC9yZXBvc2l0b3J5L0NlcnRzL2VDQUcyLmNydDA1BggrBgEFBQcwAYYpaHR0cDovL29jc3AuZWNhLmhpbmV0Lm5ldC9PQ1NQL29jc3BHMnNoYTIwEgYDVR0TAQH%2FBAgwBgEB%2FwIBADAiBgNVHSAEGzAZMA0GCysGAQQBgbcjZAADMAgGBmeBDAECAjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggIBAEyrsJ9vUi6nEfwO0vgAoFefXpCRF%2BuDsmG%2F8F6OV9VRnbtzBwazHbxVmaBvDRVofLfoXWr%2BNd8dd3BXVUNxemNrkZa8Hdgdv4s8yFbRs0W6fRTWkhCcc39RpQtSeV7kyxCP1rMTYRSqCA9F%2BFcDMLXJIzZrzl7Tn6guIyqcfZv6sRN7CbbTrYKSc0JX4t26WGFun2zLjzH8kx1TZ457TE4yyjl1oSZdgiWL6Hz7l%2BnbTe6WqPVVm4am2AAmaQaLGncsGLasl7PIHx9Nc4sy7KdOMTc5r0BPCGhAiJ6ueQ6aVd49pra7BDIqFMA7Myy4pXRYfqFnjq9RuROWYiIluzLNUSxlaFtTMUVQnWjJxnlXlBDLX9L4OAxTOvdbtcNNS1GK%2BW1cWiYdTOWF4HTu5pvdUn%2F%2B8yVE4E7MPb0vGuxv3S11QG6JtVPuHkX6BGqRXHo253gY77HZU0g3g9qVs9UaZjWS5UTcqdgLmmOQnH7USaJ9%2F4rXRu%2FP8IWMPG2s6tv1dRVQV5xfq21PQ4y53ytVd0%2B%2Flp0L743%2B1AjnOw0I8t9QxP6c2ti%2Boo43rxM8YE3etVLQBeWsmJc00GOWa%2FXmFACsy8Lkctx0QScAAYwCfB2accfxj9hEX1c6MAeVUVp04YJx4dtjoIFTPI1%2FMFX%2BFkxMq4Fs6k%2BmxSm7tNvv&cert=MIIHZDCCBUygAwIBAgIRAK%2FNjWQsYtZFBn3IV%2F2o8V0wDQYJKoZIhvcNAQELBQAwXjELMAkGA1UEBhMCVFcxIzAhBgNVBAoMGkNodW5naHdhIFRlbGVjb20gQ28uLCBMdGQuMSowKAYDVQQLDCFlUEtJIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTUxMTE3MDg1MTM1WhcNMzQxMjIwMDIzMTI3WjBjMQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xLzAtBgNVBAMMJmVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApFkfoC%2FfvuD76dy1if5alwPJOnenjlyv8uMYOfWq3Q9G0mgPV5ynY2DTWM41wqf2iMJPfxso6dCnAMQXTW3iD8UOJiMgq%2Fc6KKJMCgvMjs7mAJpaQA3UUBqb0Q2clPnb7lzQ8YoHzZorQCxJpF1iX6dr3%2B5WCFDzQhhsMbBe5ZxzkrwO0gx9xThXvLtY2yYZAu3jQ4SKTlZr262hMdnMImeWeP93ncxkxTIgau9OMNUkJf2Iea9xGv7VSxsViLwYcKq9rTgKZjBG5YmF1XYkqamz5llgD7SpU8I6nUUa1q7jd17EYjYzLzDEv5XxLTildejRapMuRYdLSqLfv1gnmspiGape1LGASZbdK%2Bxfj5vgnZeI9YQDo6%2BzpXMtQbrlB7dva3H398lar2mZsy%2FIT0LrbGtxZ3jfCqxP10qFAEYa1c24n%2BqVnQ980cYFheYI3ogXgfbVtW7qoRzXYarjWUKJnFl%2BsXxkNN1hIyo5tRCr%2FIapUxrF62rigE5ZkcA4if6zXdb7kenXsH3ZeAjM9SvMK%2BGh1pRzwf5R9Ix9CrWairn12uDJs9iPqoKDjWlTLf0ABBhKoNpU4XmMiet%2F9YLnoLl3Ta75ugI7iHbrfF2zWhPbfCkWa5nRHeRIIaINXgGI6L7xmE0%2BxxZXHF%2FhCG8cTFhDVveAZYxxDqIEZ08CAwEAAaOCAhYwggISMB8GA1UdIwQYMBaAFB4M97Zn8uGSJglFwFU5Lnc%2FQkqiMB0GA1UdDgQWBBRyW7qqcjjuJZAktZQi%2BgmIyosK%2BzAOBgNVHQ8BAf8EBAMCAQYwQAYDVR0fBDkwNzA1oDOgMYYvaHR0cDovL2VjYS5oaW5ldC5uZXQvcmVwb3NpdG9yeS9DUkxfU0hBMi9DQS5jcmwwgYIGCCsGAQUFBwEBBHYwdDA7BggrBgEFBQcwAoYvaHR0cDovL2VjYS5oaW5ldC5uZXQvcmVwb3NpdG9yeS9DZXJ0cy9lQ0FHMS5jcnQwNQYIKwYBBQUHMAGGKWh0dHA6Ly9vY3NwLmVjYS5oaW5ldC5uZXQvT0NTUC9vY3NwRzFzaGEyMA8GA1UdEwEB%2FwQFMAMBAf8wgecGA1UdIASB3zCB3DANBgsrBgEEAYG3I2QAATANBgsrBgEEAYG3I2QAAjANBgsrBgEEAYG3I2QAAzANBgsrBgEEAYG3I2QABDANBgsrBgEEAYG3I2QACTANBgsrBgEEAYG3I2QAADANBgsrBgEEAYG3I2QEATANBgsrBgEEAYG3I2QEAjANBgsrBgEEAYG3I2QEAzAJBgdghnYBZAABMAkGB2CGdgFkAAIwCQYHYIZ2AWQAAzAJBgdghnYBZAAEMAkGB2CGdgFkAAAwCAYGZ4EMAQIBMAgGBmeBDAECAjAIBgZngQwBAgMwDQYJKoZIhvcNAQELBQADggIBALwy4mxatKA6X%2BUM2IDpnWajNmek00EM4qh5E7eiQY0yZV5Eit9D%2F8q9h0hD77NjVaYPwsOWqWAiVtDAro%2BnWDHfkAG14ptRNBoGjJjzZi%2F%2BOeI2WTc8ZER6C8rAjQ7b%2FRxMzwxfDjRtgCbT2qq01rPiJ%2BqDgyUniDstbyQj08bSo3GJWp6ZsSNDAP26ygODpSgL0Ja806Byk2b4npQevdkmQ0k43S9IU0MeSlWT8hxzluyFlPRl4yuev5le91outdEdpV98KvYcgLAWwW5UcFOM6SRsYTBS2dfSRgKreDnMNdbUHmbAVsb3wLD6WqLoe6LyRNOeXctKPA6%2Be5i%2FJN6NZnqejcMopuS%2BpyWyrNiHlRShGUfTiXrcbT8fbyOswAT8JsX4fWyZYub0kKfFG8hEKQsIxNiyKH4cw6HBih31EYaYS9IEj19NxfHl0KbPm22cpBJoGwkZWgg%2F%2FPflFFHNTdKSalDxPHMKdyZbTBugLtqFVkV%2Bvu1y6WRoGfHwzpa9aQsMWAwLYRnBZnSYzfN9QFZsoHCSDJJVt30Oi6fURJy34%2Bdtvs%2BsQihiN886uYTJ0Cex1R%2BOb9HXCKFrGTumgwD%2Bnitt7hwlB74K9lqrKQrtfgfBFFMG9Tu%2FE%2FOI6JoST2j8KmSN1rpcxoMH3tamxqm3%2BxpLM9HekbBoJ0V2&cert=MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNsIZ5qyNUD9WBpj8zwIuQf5%2FdqIjG3LBXy4P4AakP%2Fh2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKilTza6We%2FCKBk49ZCt0Xvl%2FT29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q%2BRBNGMD%2BXPNjX12ruOzjjK9SXDrkb5wdJfzcq%2BXd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN%2F%2BZ0V0OWQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde%2BS%2FuUWH1%2BETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnaolQ2zepr7BxB4EW%2Fhj8e6DyUadCrlHJhBmd8hh%2BiVBmoKs2pHdmX2Os%2BPYhcZewoozRrSgx4hxyy%2Fvv9haLdnG7t4TY3OZ%2BXkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc%2FQkqiMAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLHClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B01GqZNF5sAFPZn%2FKmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI%2BymBV3QGypzqKOg4ZyYr8dW1P2WT%2BDZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC%2Fgpf36j36%2BuwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2j6%2F7Nu4tCEoduL%2BbXPjqpRugc6bY%2BG7gMwRfaKonh%2B3ZwZCc7b3jajWvY9%2BrGNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS%2FjQ6fbjpKdx2qcgw%2BBRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR%2B2zGp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8%2Fgntsm%2BHbRsZJB%2F9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW%2F2xzQ%2BDhNQ%2BIIX3Sj0rnP0qCglN6oH4EZw%3D";
+
+ await BrowserTestUtils.withNewTab(kURL, async function(browser) {
+ await SpecialPowers.spawn(browser, [], async function() {
+ let certificateSection = await ContentTaskUtils.waitForCondition(() => {
+ return content.document.querySelector("certificate-section");
+ }, "Certificate section found");
+
+ let tabs = certificateSection.shadowRoot.querySelector(
+ ".certificate-tabs"
+ ).children;
+
+ Assert.ok(tabs, "Tabs were found");
+ Assert.equal(tabs.length, 4, "There should be 4 tabs");
+ for (let tab of tabs) {
+ Assert.ok(tab.textContent, "Tab should have non-empty label");
+ Assert.notEqual(
+ tab.dataset.l10nId,
+ "certificate-viewer-unknown-group-label"
+ );
+ // If there is another tab after this one, this tab should link to the
+ // next via its issuer's common name or OU, if available.
+ if (tab.nextElementSibling) {
+ tab.click();
+ let infoGroup = certificateSection.shadowRoot.querySelector(
+ ".selected info-group.issuer-name"
+ );
+ Assert.ok(infoGroup, "infoGroup found");
+ let container =
+ infoGroup.shadowRoot.querySelector(".common-name") ||
+ infoGroup.shadowRoot.querySelector(".organizational-unit");
+ Assert.ok(container, "Should find container for link");
+ Assert.ok(
+ container.shadowRoot.querySelector("a"),
+ "There should be a link in the container for " +
+ container.textContent
+ );
+ }
+ }
+ });
+ });
+});
diff --git a/toolkit/components/certviewer/tests/browser/browser_checkNonEmptyFields.js b/toolkit/components/certviewer/tests/browser/browser_checkNonEmptyFields.js
new file mode 100644
index 0000000000..3077ad3c9e
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser_checkNonEmptyFields.js
@@ -0,0 +1,80 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+async function checkNonEmptyFields(url) {
+ await BrowserTestUtils.withNewTab(url, async function(browser) {
+ await SpecialPowers.spawn(browser, [], async function() {
+ let certificateSection = await ContentTaskUtils.waitForCondition(() => {
+ return content.document.querySelector("certificate-section");
+ }, "Certificate section found");
+
+ let tabs = certificateSection.shadowRoot.querySelector(
+ ".certificate-tabs"
+ ).children;
+
+ Assert.ok(tabs, "Tabs were found");
+ Assert.greater(tabs.length, 0, "There must at least one tab");
+
+ function clickTabAndCheckSelection(tabID) {
+ let selectedTabBefore = 0;
+
+ for (let i = 0; i < tabs.length; i++) {
+ if (tabs[i].className.includes("selected")) {
+ selectedTabBefore = i;
+ break;
+ }
+ }
+
+ let tabButton = certificateSection.shadowRoot.querySelector(
+ `.certificate-tabs .tab[idnumber="${tabID}"]`
+ );
+ tabButton.click();
+
+ if (tabID !== 0) {
+ Assert.notEqual(
+ selectedTabBefore,
+ tabID,
+ "A new tab should be selected now"
+ );
+ }
+ }
+
+ for (let i = 0; i < tabs.length; i++) {
+ clickTabAndCheckSelection(i);
+
+ let infoGroups = certificateSection.shadowRoot.querySelectorAll(
+ "info-group"
+ );
+ Assert.ok(infoGroups, "infoGroups found");
+
+ for (let infoGroup of infoGroups) {
+ let infoItems = infoGroup.shadowRoot.querySelectorAll("info-item");
+ Assert.ok(infoItems, "infoItems found");
+
+ for (let infoItem of infoItems) {
+ let item = infoItem.shadowRoot.querySelector(".info");
+ let info = item.textContent;
+ Assert.notEqual(info, "", "Empty strings shouldn't be rendered");
+ }
+ }
+ }
+ });
+ });
+}
+
+add_task(async function test() {
+ const url1 =
+ "about:certificate?cert=MIIIIDCCBwigAwIBAgIQdFFdOvtZKGMnFerJav62lzANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZpY2VzMSUwIwYDVQQDExxHb29nbGUgSW50ZXJuZXQgQXV0aG9yaXR5IEczMB4XDTE5MDcyOTE4NDQyN1oXDTE5MTAyMTE4MjMwMFowZjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEzARBgNVBAoMCkdvb2dsZSBMTEMxFTATBgNVBAMMDCouZ29vZ2xlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOOufVj7d5UF%2FN49KyXmA0Z0rlQPEicHK5CbO122uECXYbWwepNlWlqM7V1GF0vRutC8YyAlxrCsUmOTrpem7NWjggWlMIIFoTATBgNVHSUEDDAKBggrBgEFBQcDATAOBgNVHQ8BAf8EBAMCB4AwggRqBgNVHREEggRhMIIEXYIMKi5nb29nbGUuY29tgg0qLmFuZHJvaWQuY29tghYqLmFwcGVuZ2luZS5nb29nbGUuY29tghIqLmNsb3VkLmdvb2dsZS5jb22CGCouY3Jvd2Rzb3VyY2UuZ29vZ2xlLmNvbYIGKi5nLmNvgg4qLmdjcC5ndnQyLmNvbYIRKi5nY3BjZG4uZ3Z0MS5jb22CCiouZ2dwaHQuY26CFiouZ29vZ2xlLWFuYWx5dGljcy5jb22CCyouZ29vZ2xlLmNhggsqLmdvb2dsZS5jbIIOKi5nb29nbGUuY28uaW6CDiouZ29vZ2xlLmNvLmpwgg4qLmdvb2dsZS5jby51a4IPKi5nb29nbGUuY29tLmFygg8qLmdvb2dsZS5jb20uYXWCDyouZ29vZ2xlLmNvbS5icoIPKi5nb29nbGUuY29tLmNvgg8qLmdvb2dsZS5jb20ubXiCDyouZ29vZ2xlLmNvbS50coIPKi5nb29nbGUuY29tLnZuggsqLmdvb2dsZS5kZYILKi5nb29nbGUuZXOCCyouZ29vZ2xlLmZyggsqLmdvb2dsZS5odYILKi5nb29nbGUuaXSCCyouZ29vZ2xlLm5sggsqLmdvb2dsZS5wbIILKi5nb29nbGUucHSCEiouZ29vZ2xlYWRhcGlzLmNvbYIPKi5nb29nbGVhcGlzLmNughEqLmdvb2dsZWNuYXBwcy5jboIUKi5nb29nbGVjb21tZXJjZS5jb22CESouZ29vZ2xldmlkZW8uY29tggwqLmdzdGF0aWMuY26CDSouZ3N0YXRpYy5jb22CEiouZ3N0YXRpY2NuYXBwcy5jboIKKi5ndnQxLmNvbYIKKi5ndnQyLmNvbYIUKi5tZXRyaWMuZ3N0YXRpYy5jb22CDCoudXJjaGluLmNvbYIQKi51cmwuZ29vZ2xlLmNvbYIWKi55b3V0dWJlLW5vY29va2llLmNvbYINKi55b3V0dWJlLmNvbYIWKi55b3V0dWJlZWR1Y2F0aW9uLmNvbYIRKi55b3V0dWJla2lkcy5jb22CByoueXQuYmWCCyoueXRpbWcuY29tghphbmRyb2lkLmNsaWVudHMuZ29vZ2xlLmNvbYILYW5kcm9pZC5jb22CG2RldmVsb3Blci5hbmRyb2lkLmdvb2dsZS5jboIcZGV2ZWxvcGVycy5hbmRyb2lkLmdvb2dsZS5jboIEZy5jb4IIZ2dwaHQuY26CBmdvby5nbIIUZ29vZ2xlLWFuYWx5dGljcy5jb22CCmdvb2dsZS5jb22CD2dvb2dsZWNuYXBwcy5jboISZ29vZ2xlY29tbWVyY2UuY29tghhzb3VyY2UuYW5kcm9pZC5nb29nbGUuY26CCnVyY2hpbi5jb22CCnd3dy5nb28uZ2yCCHlvdXR1LmJlggt5b3V0dWJlLmNvbYIUeW91dHViZWVkdWNhdGlvbi5jb22CD3lvdXR1YmVraWRzLmNvbYIFeXQuYmUwaAYIKwYBBQUHAQEEXDBaMC0GCCsGAQUFBzAChiFodHRwOi8vcGtpLmdvb2cvZ3NyMi9HVFNHSUFHMy5jcnQwKQYIKwYBBQUHMAGGHWh0dHA6Ly9vY3NwLnBraS5nb29nL0dUU0dJQUczMB0GA1UdDgQWBBRPZJy%2FftYprTgIqQTFvmZIl%2BXaGTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFHfCuFCaZ3Z2sS3ChtCDoH6mfrpLMCEGA1UdIAQaMBgwDAYKKwYBBAHWeQIFAzAIBgZngQwBAgIwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovL2NybC5wa2kuZ29vZy9HVFNHSUFHMy5jcmwwDQYJKoZIhvcNAQELBQADggEBADc7%2BG7Np83iC8KU6GYSKizr%2F2VbPPpBjR5EzXIdUpUgxWFQ7Faxd1LVhm22QVlmMKjjYe7JUxnaIa5Zay6pBlMr5Fq%2BHbSTuA63GOt4IW1CvB1zAOaJWfxGXaNX1Xg%2F740qWEDoe95h9Xm%2FfIcFLD86FCUITAenFKBOKdaKoBMGoDBOq7jUdn492oGBYi%2BQtXfNjvcZm0yABGTjQOtH8JzyWKx1NvNLw5gSXYH5Vmj%2FQzRBEED3%2BpIJh6vgKIGEhG%2BhCg4tx4k0nnwoHGnL4a2mcemlRIWRCcjbb%2FBoF%2B05EvQvB6PcurckBaPN8r7wWCxefYViIMnHiMmzPdwZYIA%3D&cert=MIIEXDCCA0SgAwIBAgINAeOpMBz8cgY4P5pTHTANBgkqhkiG9w0BAQsFADBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0xNzA2MTUwMDAwNDJaFw0yMTEyMTUwMDAwNDJaMFQxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVHb29nbGUgVHJ1c3QgU2VydmljZXMxJTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5ldCBBdXRob3JpdHkgRzMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDKUkvqHv%2FOJGuo2nIYaNVWXQ5IWi01CXZaz6TIHLGp%2FlOJ%2B600%2F4hbn7vn6AAB3DVzdQOts7G5pH0rJnnOFUAK71G4nzKMfHCGUksW%2Fmona%2BY2emJQ2N%2BaicwJKetPKRSIgAuPOB6Aahh8Hb2XO3h9RUk2T0HNouB2VzxoMXlkyW7XUR5mw6JkLHnA52XDVoRTWkNty5oCINLvGmnRsJ1zouAqYGVQMc%2F7sy%2B%2FEYhALrVJEA8KbtyX%2Br8snwU5C1hUrwaW6MWOARa8qBpNQcWTkaIeoYvy%2FsGIJEmjR0vFEwHdp1cSaWIr6%2F4g72n7OqXwfinu7ZYW97EfoOSQJeAzAgMBAAGjggEzMIIBLzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB%2FwQIMAYBAf8CAQAwHQYDVR0OBBYEFHfCuFCaZ3Z2sS3ChtCDoH6mfrpLMB8GA1UdIwQYMBaAFJviB1dnHB7AagbeWbSaLd%2FcGYYuMDUGCCsGAQUFBwEBBCkwJzAlBggrBgEFBQcwAYYZaHR0cDovL29jc3AucGtpLmdvb2cvZ3NyMjAyBgNVHR8EKzApMCegJaAjhiFodHRwOi8vY3JsLnBraS5nb29nL2dzcjIvZ3NyMi5jcmwwPwYDVR0gBDgwNjA0BgZngQwBAgIwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly9wa2kuZ29vZy9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEAHLeJluRT7bvs26gyAZ8so81trUISd7O45skDUmAge1cnxhG1P2cNmSxbWsoiCt2eux9LSD%2BPAj2LIYRFHW31%2F6xoic1k4tbWXkDCjir37xTTNqRAMPUyFRWSdvt%2BnlPqwnb8Oa2I%2FmaSJukcxDjNSfpDh%2FBd1lZNgdd%2F8cLdsE3%2BwypufJ9uXO1iQpnh9zbuFIwsIONGl1p3A8CgxkqI%2FUAih3JaGOqcpcdaCIzkBaR9uYQ1X4k2Vg5APRLouzVy7a8IVk6wuy6pm%2BT7HT4LY8ibS5FEZlfAFLSW8NwsVz9SBK2Vqn1N0PIMn5xA6NZVc7o835DLAFshEWfC7TIe3g%3D%3D&cert=MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6%2BLm8omUVCxKs%2BIVSbC9N%2FhHD6ErPLv4dfxn%2BG07IwXNb9rfF73OX4YJYJkhD10FPe%2B3t%2Bc4isUoh7SqbKSaZeqKeMWhG8eoLrvozps6yWJQeXSpkqBy%2B0Hne%2Fig%2B1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ%2FgkwpRl4pazq%2Br1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH%2FBAUwAwEB%2FzAdBgNVHQ4EFgQUm%2BIHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0%2FWwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP%2BDTKqttVCL1OmLNIG%2B6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavSot%2B3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h%2Bu%2FN5GJG79G%2BdwfCMNYxdAfvDbbnvRG15RjF%2BCv6pgsH%2F76tuIMRQyV%2BdTZsXjAzlAcmgQWpzU%2FqlULRuJQ%2F7TBj0%2FVLZjmmx6BEP3ojY%2Bx1J96relc8geMJgEtslQIxq%2FH5COEBkEveegeGTLg%3D%3D";
+ const url2 =
+ "about:certificate?cert=MIIDeTCCAmGgAwIBAgIJAPziuikCTox4MA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQKDAZCYWRTU0wxFTATBgNVBAMMDCouYmFkc3NsLmNvbTAeFw0xOTEwMDkyMzQxNTJaFw0yMTEwMDgyMzQxNTJaMGIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQKDAZCYWRTU0wxFTATBgNVBAMMDCouYmFkc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMIE7PiM7gTCs9hQ1XBYzJMY61yoaEmwIrX5lZ6xKyx2PmzAS2BMTOqytMAPgLaw%2BXLJhgL5XEFdEyt%2FccRLvOmULlA3pmccYYz2QULFRtMWhyefdOsKnRFSJiFzbIRMeVXk0WvoBj1IFVKtsyjbqv9u%2F2CVSndrOfEk0TG23U3AxPxTuW1CrbV8%2Fq71FdIzSOciccfCFHpsKOo3St%2FqbLVytH5aohbcabFXRNsKEqveww9HdFxBIuGa%2BRuT5q0iBikusbpJHAwnnqP7i%2FdAcgCskgjZjFeEU4EFy%2Bb%2Ba1SYQCeFxxC7c3DvaRhBB0VVfPlkPz0sw6l865MaTIbRyoUCAwEAAaMyMDAwCQYDVR0TBAIwADAjBgNVHREEHDAaggwqLmJhZHNzbC5jb22CCmJhZHNzbC5jb20wDQYJKoZIhvcNAQELBQADggEBAGlwCdbPxflZfYOaukZGCaxYK6gpincX4Lla4Ui2WdeQxE95w7fChXvP3YkE3UYUE7mupZ0eg4ZILr%2FA0e7JQDsgIu%2FSRTUE0domCKgPZ8v99k3Avka4LpLK51jHJJK7EFgo3ca2nldd97GM0MU41xHFk8qaK1tWJkfrrfcGwDJ4GQPIiLlm6i0yHq1Qg1RypAXJy5dTlRXlCLd8ufWhhiwW0W75Va5AEnJuqpQrKwl3KQVewGj67WWRgLfSr%2B4QG1mNvCZb2CkjZWmxkGPuoP40%2Fy7Yu5OFqxP5tAjj4YixCYTWEVA0pmzIzgBg%2BJIe3PdRy27T0asgQW%2FF4TY61Yk%3D";
+ const url3 =
+ "about:certificate?cert=MIIG7jCCBNagAwIBAgIBDzANBgkqhkiG9w0BAQsFADB5MRAwDgYDVQQKEwdSb290IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNBIENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRAY2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAOBgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEiMCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ8BLPRoZzYLdufujAWGSuzbCtRRcMY%2FpnCujW0r8%2B55jE8Ez64AO7NV1sId6eINm6zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42yfk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz%2BqOqfrU0j36NK2B5jcG8Y0f3%2FJHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN%2FNb5gznZY0dj4kepKwDpUeb%2BagRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE%2F9KTfWgu3YtLq1i6L43qlaegw1SJpfvbi1EinbLDvhG%2BLJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV%2FRRyH9XzQQUxPKZgh%2FTMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivUfslfrejrckzzAeVLIL%2BaplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826YreQQejdIOQpvGQpQsgi3Hia%2F0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAX8wggF7MB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TAPBgNVHRMBAf8EBTADAQH%2FMDQGCWCGSAGG%2BEIBCAQnFiVodHRwOi8vd3d3LmNhY2VydC5vcmcvaW5kZXgucGhwP2lkPTEwMFYGCWCGSAGG%2BEIBDQRJFkdUbyBnZXQgeW91ciBvd24gY2VydGlmaWNhdGUgZm9yIEZSRUUgaGVhZCBvdmVyIHRvIGh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzAxBgNVHR8EKjAoMCagJKAihiBodHRwOi8vY3JsLmNhY2VydC5vcmcvcmV2b2tlLmNybDAzBglghkgBhvhCAQQEJhYkVVJJOmh0dHA6Ly9jcmwuY2FjZXJ0Lm9yZy9yZXZva2UuY3JsMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYWaHR0cDovL29jc3AuY2FjZXJ0Lm9yZzAfBgNVHSMEGDAWgBQWtTIb1Mfz4OaO873SsDrusjkY0TANBgkqhkiG9w0BAQsFAAOCAgEAR5zXs6IX01JTt7Rq3b%2BbNRUhbO9vGBMggczo7R0qIh1kdhS6WzcrDoO6PkpuRg0L3qM7YQB6pw2V%2BubzF7xl4C0HWltfzPTbzAHdJtjaJQw7QaBlmAYpN2CLB6Jeg8q%2F1Xpgdw%2F%2BIP1GRwdg7xUpReUA482l4MH1kf0W0ad94SuIfNWQHcdLApmno%2FSUh1bpZyeWrMnlhkGNDKMxCCQXQ360TwFHc8dfEAaq5ry6cZzm1oetrkSviE2qofxvv1VFiQ%2B9TX3%2FzkECCsUB%2FEjPM0lxFBmu9T5Ih%2BEqns9ivmrEIQDv9tNyJHuLsDNqbUBal7OoiPZnXk9LH%2Bqb%2BpLf1ofv5noy5vX2a5OKebHe%2B0Ex%2FA7e%2BG%2FHuOjVNqhZ9j5Nispfq9zNyOHGWD8ofj8DHwB50L1Xh5H%2BEbIoga%2FhJCQnRtxWkHP699T1JpLFYwapgplivF4TFv4fqp0nHTKC1x9gGrIgvuYJl1txIKmxXdfJzgscMzqpabhtHOMXOiwQBpWzyJkofF%2Fw55e0LttZDBkEsilV%2FvW0CJsPs3eNaQF%2BiMWscGOkgLFlWsAS3HwyiYLNJo26aqyWPaIdc8E4ck7Sk08WrFrHIK3EHr4n1FZwmLpFAvucKqgl0hr%2B2jypyh5puA3KksHF3CsUzjMUvzxMhykh9zrMxQAHLBVrGwc%3D";
+
+ let urls = [url1, url2, url3];
+
+ for (let url of urls) {
+ await checkNonEmptyFields(url);
+ }
+});
diff --git a/toolkit/components/certviewer/tests/browser/browser_checkNonRepeatedCertTabs.js b/toolkit/components/certviewer/tests/browser/browser_checkNonRepeatedCertTabs.js
new file mode 100644
index 0000000000..21c56ad209
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser_checkNonRepeatedCertTabs.js
@@ -0,0 +1,129 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+function checkCertTabs() {
+ let certificatePages = 0;
+ for (let tab of gBrowser.tabs) {
+ let spec = tab.linkedBrowser.documentURI.spec;
+ if (spec.includes("about:certificate")) {
+ certificatePages++;
+ }
+ }
+ Assert.equal(certificatePages, 1, "Do not open repeated certificate pages!");
+}
+
+add_task(async function testBadCert() {
+ info("Testing bad cert");
+
+ let tab = await openErrorPage();
+
+ let loaded = BrowserTestUtils.waitForNewTab(gBrowser, null, true);
+ for (let i = 0; i < 2; i++) {
+ // try opening two certificates that are the same
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function() {
+ let advancedButton = content.document.getElementById("advancedButton");
+ Assert.ok(advancedButton, "advancedButton found");
+ Assert.equal(
+ advancedButton.hasAttribute("disabled"),
+ false,
+ "advancedButton should be clickable"
+ );
+ advancedButton.click();
+ let viewCertificate = content.document.getElementById("viewCertificate");
+ Assert.ok(viewCertificate, "viewCertificate found");
+ Assert.equal(
+ viewCertificate.hasAttribute("disabled"),
+ false,
+ "viewCertificate should be clickable"
+ );
+
+ viewCertificate.click();
+ });
+ await loaded;
+ }
+ checkCertTabs();
+
+ gBrowser.removeCurrentTab(); // closes about:certificate
+ gBrowser.removeCurrentTab(); // closes https://expired.example.com/
+});
+
+add_task(async function testGoodCert() {
+ info("Testing page info");
+ let url = "https://example.com/";
+
+ info(`Loading ${url}`);
+ await BrowserTestUtils.withNewTab({ gBrowser, url }, async function() {
+ info("Opening pageinfo");
+ let pageInfo = BrowserPageInfo(url, "securityTab", {});
+ await BrowserTestUtils.waitForEvent(pageInfo, "load");
+
+ let securityTab = pageInfo.document.getElementById("securityTab");
+ await TestUtils.waitForCondition(
+ () => BrowserTestUtils.is_visible(securityTab),
+ "Security tab should be visible."
+ );
+ Assert.ok(securityTab, "Security tab is available");
+ let viewCertButton = pageInfo.document.getElementById("security-view-cert");
+ await TestUtils.waitForCondition(
+ () => BrowserTestUtils.is_visible(viewCertButton),
+ "view cert button should be visible."
+ );
+
+ let loaded = BrowserTestUtils.waitForNewTab(gBrowser, null, true);
+ for (let i = 0; i < 2; i++) {
+ checkAndClickButton(pageInfo.document, "security-view-cert");
+ await loaded;
+ }
+
+ pageInfo.close();
+ checkCertTabs();
+ });
+
+ gBrowser.removeCurrentTab();
+});
+
+add_task(async function testPreferencesCert() {
+ info("Testing preferences cert");
+ let url = "about:preferences#privacy";
+
+ info(`Loading ${url}`);
+ await BrowserTestUtils.withNewTab({ gBrowser, url }, async function(browser) {
+ checkAndClickButton(browser.contentDocument, "viewCertificatesButton");
+
+ let certDialogLoaded = promiseLoadSubDialog(
+ "chrome://pippki/content/certManager.xhtml"
+ );
+ let dialogWin = await certDialogLoaded;
+ let doc = dialogWin.document;
+ Assert.ok(doc, "doc loaded");
+
+ doc.getElementById("certmanagertabs").selectedTab = doc.getElementById(
+ "ca_tab"
+ );
+ let treeView = doc.getElementById("ca-tree").view;
+ let selectedCert;
+
+ for (let i = 0; i < treeView.rowCount; i++) {
+ treeView.selection.select(i);
+ dialogWin.getSelectedCerts();
+ let certs = dialogWin.selected_certs;
+ if (certs && certs.length == 1 && certs[0]) {
+ selectedCert = certs[0];
+ break;
+ }
+ }
+ Assert.ok(selectedCert, "A cert should be selected");
+ let viewButton = doc.getElementById("ca_viewButton");
+ Assert.equal(viewButton.disabled, false, "Should enable view button");
+
+ let loaded = BrowserTestUtils.waitForNewTab(gBrowser, null, true);
+ for (let i = 0; i < 2; i++) {
+ viewButton.click();
+ await loaded;
+ }
+ checkCertTabs();
+ });
+ gBrowser.removeCurrentTab(); // closes about:certificate
+});
diff --git a/toolkit/components/certviewer/tests/browser/browser_checkNonUndefinedStrings.js b/toolkit/components/certviewer/tests/browser/browser_checkNonUndefinedStrings.js
new file mode 100644
index 0000000000..2a4119f4c7
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser_checkNonUndefinedStrings.js
@@ -0,0 +1,49 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const url =
+ "about:certificate?cert=MIIGRjCCBS6gAwIBAgIQDJduPkI49CDWPd%2BG7%2Bu6kDANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5EaWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgxMTA1MDAwMDAwWhcNMTkxMTEzMTIwMDAwWjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxHDAaBgNVBAoTE01vemlsbGEgQ29ycG9yYXRpb24xDzANBgNVBAsTBldlYk9wczEYMBYGA1UEAxMPd3d3Lm1vemlsbGEub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuKruymkkmkqCJh7QjmXlUOBcLFRyw5LG%2FvUUWVrsxC2gsbR8WJq%2BcYoYBpoNVStKrO4U2rBh1GEbccvT6qKOQI%2BpjjDxx9cmRdubGTGp8L0MF1ohVvhIvYLumOEoRDDPU4PvGJjGhek%2FojvedPWe8dhciHkxOC2qPFZvVFMwg1%2Fo%2Fb80147BwZQmzB18mnHsmcyKlpsCN8pxw86uao9Iun8gZQrsllW64rTZlRR56pHdAcuGAoZjYZxwS9Z%2BlvrSjEgrddemWyGGalqyFp1rXlVM1Tf4%2FIYWAQXTgTUN303u3xMjss7QK7eUDsACRxiWPLW9XQDd1c%2ByvaYJKzgJ2wIDAQABo4IC6TCCAuUwHwYDVR0jBBgwFoAUD4BhHIIxYdUvKOeNRji0LOHG2eIwHQYDVR0OBBYEFNpSvSGcN2VT%2FB9TdQ8eXwebo60%2FMCcGA1UdEQQgMB6CD3d3dy5tb3ppbGxhLm9yZ4ILbW96aWxsYS5vcmcwDgYDVR0PAQH%2FBAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBrBgNVHR8EZDBiMC%2BgLaArhilodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc3NjYS1zaGEyLWc2LmNybDAvoC2gK4YpaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nNi5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBAgIwfAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH%2FBAIwADCCAQIGCisGAQQB1nkCBAIEgfMEgfAA7gB1AKS5CZC0GFgUh7sTosxncAo8NZgE%2BRvfuON3zQ7IDdwQAAABZuYWiHwAAAQDAEYwRAIgZnMSH1JdG6NASHWTwD0mlP%2Fzbr0hzP263c02Ym0DU64CIEe4QHJDP47j0b6oTFu6RrZz1NQ9cq8Az1KnMKRuaFAlAHUAh3W%2F51l8%2BIxDmV%2B9827%2FVo1HVjb%2FSrVgwbTq%2F16ggw8AAAFm5haJAgAABAMARjBEAiAxGLXkUaOAkZhXNeNR3pWyahZeKmSaMXadgu18SfK1ZAIgKtwu5eGxK76rgaszLCZ9edBIjuU0DKorzPUuxUXFY0QwDQYJKoZIhvcNAQELBQADggEBAKLJAFO3wuaP5MM%2Fed1lhk5Uc2aDokhcM7XyvdhEKSHbgPhcgMoT9YIVoPa70gNC6KHcwoXu0g8wt7X6Vm1ql%2F68G5q844kFuC6JPl4LVT9mciD%2BVW6bHUSXD9xifL9DqdJ0Ic0SllTlM%2Boq5aAeOxUQGXhXIqj6fSQv9fQN6mXxQIoc%2Fgjxteskq%2FVl8YmY1FIZP9Bh7g27kxZ9GAAGQtjTL03RzKAuSg6yeImYVdQWasc7UPnBXlRAzZ8%2BOJThUbzK16a2CI3Rg4agKSJk%2BuA47h1%2FImmngpFLRb%2FMvRX6H1oWcUuyH6O7PZdl0YpwTpw1THIuqCGl%2FwpPgyQgcTM%3D&cert=MIIElDCCA3ygAwIBAgIQAf2j627KdciIQ4tyS8%2B8kTANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0xMzAzMDgxMjAwMDBaFw0yMzAzMDgxMjAwMDBaME0xCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJzAlBgNVBAMTHkRpZ2lDZXJ0IFNIQTIgU2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANyuWJBNwcQwFZA1W248ghX1LFy949v%2FcUP6ZCWA1O4Yok3wZtAKc24RmDYXZK83nf36QYSvx6%2BM%2FhpzTc8zl5CilodTgyu5pnVILR1WN3vaMTIa16yrBvSqXUu3R0bdKpPDkC55gIDvEwRqFDu1m5K%2BwgdlTvza%2FP96rtxcflUxDOg5B6TXvi%2FTC2rSsd9f%2Fld0Uzs1gN2ujkSYs58O09rg1%2FRrKatEp0tYhG2SS4HD2nOLEpdIkARFdRrdNzGXkujNVA075ME%2FOV4uuPNcfhCOhkEAjUVmR7ChZc6gqikJTvOX6%2Bguqw9ypzAO%2Bsf0%2FRR3w6RbKFfCs%2FmC%2FbdFWJsCAwEAAaOCAVowggFWMBIGA1UdEwEB%2FwQIMAYBAf8CAQAwDgYDVR0PAQH%2FBAQDAgGGMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMHsGA1UdHwR0MHIwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RDQS5jcmwwN6A1oDOGMWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RDQS5jcmwwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwHQYDVR0OBBYEFA%2BAYRyCMWHVLyjnjUY4tCzhxtniMB8GA1UdIwQYMBaAFAPeUDVW0Uy7ZvCj4hsbw5eyPdFVMA0GCSqGSIb3DQEBCwUAA4IBAQAjPt9L0jFCpbZ%2BQlwaRMxp0Wi0XUvgBCFsS%2BJtzLHgl4%2BmUwnNqipl5TlPHoOlblyYoiQm5vuh7ZPHLgLGTUq%2FsELfeNqzqPlt%2FyGFUzZgTHbO7Djc1lGA8MXW5dRNJ2Srm8c%2BcftIl7gzbckTB%2B6WohsYFfZcTEDts8Ls%2F3HB40f%2F1LkAtDdC2iDJ6m6K7hQGrn2iWZiIqBtvLfTyyRRfJs8sjX7tN8Cp1Tm5gr8ZDOo0rwAhaPitc%2BLJMto4JQtV05od8GiG7S5BNO98pVAdvzr508EIDObtHopYJeS4d60tbvVS3bR0j6tJLp07kzQoH3jOlOrHvdPJbRzeXDLz&cert=MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOnTjC3U%2FdDxGkAV53ijSLdhwZAAIEJzs4bg7%2FfzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5BmV%2FSl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C%2FdxC%2F%2FAH2hdmoRBBYMql1GNXRor5H4idq9Joz%2BEkIYIvUX7Q6hL%2BhqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv%2BzbMUZBfHWymeMr%2Fy7vrTC0LUq7dBMtoM1O%2F4gdW7jVg%2FtRvoSSiicNoxBN33shbyTApOB6jtSj1etX%2BjkMOvJwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH%2FBAUwAwEB%2FzAdBgNVHQ4EFgQUA95QNVbRTLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK%2Bt1EnE9SsPTfrgT1eXkIoyQY%2FEsrhMAtudXH%2FvTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp%2F2PV5Adg06O%2FnVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp%2BdWOIrWcBAI%2B0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU%2BKrk2U886UAb3LujEV0lsYSEY1QSteDwsOoBrp%2BuvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQkCAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4%3D";
+
+add_task(async function test() {
+ await BrowserTestUtils.withNewTab(url, async function(browser) {
+ await SpecialPowers.spawn(browser, [], async function() {
+ let certificateSection = await ContentTaskUtils.waitForCondition(() => {
+ return content.document.querySelector("certificate-section");
+ }, "Certificate section found");
+
+ let tabs = certificateSection.shadowRoot.querySelector(
+ ".certificate-tabs"
+ ).children;
+
+ Assert.ok(tabs, "Tabs were found");
+
+ for (let i = 0; i < tabs.length; i++) {
+ let tabButton = certificateSection.shadowRoot.querySelector(
+ `.certificate-tabs .tab[idnumber="${i}"]`
+ );
+ tabButton.click();
+
+ let infoGroups = certificateSection.shadowRoot.querySelectorAll(
+ "info-group"
+ );
+ Assert.ok(infoGroups, "infoGroups found");
+
+ for (let infoGroup of infoGroups) {
+ let infoItems = infoGroup.shadowRoot.querySelectorAll("info-item");
+ Assert.ok(infoItems, "infoItems found");
+
+ for (let infoItem of infoItems) {
+ let info = infoItem.shadowRoot.children[2].textContent;
+ Assert.equal(
+ info.includes("undefined"),
+ false,
+ "Empty strings shouldn't be rendered"
+ );
+ }
+ }
+ }
+ });
+ });
+});
diff --git a/toolkit/components/certviewer/tests/browser/browser_checkOCSP.js b/toolkit/components/certviewer/tests/browser/browser_checkOCSP.js
new file mode 100644
index 0000000000..c5ef2684ec
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser_checkOCSP.js
@@ -0,0 +1,47 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+async function checkOCSP(url, shouldBeRendered) {
+ await BrowserTestUtils.withNewTab(url, async function(browser) {
+ await SpecialPowers.spawn(browser, [shouldBeRendered], async function(
+ shouldBeRendered
+ ) {
+ let certificateSection = await ContentTaskUtils.waitForCondition(() => {
+ return content.document.querySelector("certificate-section");
+ }, "Certificate section found");
+ let OCSPSection = certificateSection.shadowRoot.querySelector(
+ ".ocsp-stapling"
+ );
+ if (!shouldBeRendered) {
+ Assert.equal(OCSPSection, null, "OCSPSection found");
+ return;
+ }
+ Assert.ok(OCSPSection, "OCSPSection found");
+ let item = OCSPSection.shadowRoot.querySelector("info-item");
+ Assert.ok(item, "item found");
+ let info = item.shadowRoot.querySelector(".info").textContent;
+ Assert.equal(info, "Yes", "OCSP is required");
+ });
+ });
+}
+
+add_task(async function test() {
+ let tests = [
+ {
+ url:
+ "about:certificate?cert=MIIE1jCCA76gAwIBAgISA8ud4ZkTgHyRgFEI060JNN%2FFMA0GCSqGSIb3DQEBCwUAMEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xOTEwMjAwODUzMTFaFw0yMDAxMTgwODUzMTFaMB0xGzAZBgNVBAMTEmRtNHByb2R1Y3Rpb25zLmNvbTB2MBAGByqGSM49AgEGBSuBBAAiA2IABAaBrphEFb0WufNLet5XJDrjo3UYUnEhNJZ5LKbbdaMeRHU%2BamVcM%2B%2Fyddoeq56%2FbeZF0p8oKptxg0TQpeVz4b5ZONe17S6Bp17DN0HLqeX6FXLKyVqRTfoesv7XR1KtW6OCAo8wggKLMA4GA1UdDwEB%2FwQEAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH%2FBAIwADAdBgNVHQ4EFgQUNXKbW53h63%2Bz%2FBCOyd4pilpoFc8wHwYDVR0jBBgwFoAUqEpqYwR93brm0Tm3pkVl7%2FOo7KEwbwYIKwYBBQUHAQEEYzBhMC4GCCsGAQUFBzABhiJodHRwOi8vb2NzcC5pbnQteDMubGV0c2VuY3J5cHQub3JnMC8GCCsGAQUFBzAChiNodHRwOi8vY2VydC5pbnQteDMubGV0c2VuY3J5cHQub3JnLzAzBgNVHREELDAqghQqLmRtNHByb2R1Y3Rpb25zLmNvbYISZG00cHJvZHVjdGlvbnMuY29tMBEGCCsGAQUFBwEYBAUwAwIBBTBMBgNVHSAERTBDMAgGBmeBDAECATA3BgsrBgEEAYLfEwEBATAoMCYGCCsGAQUFBwIBFhpodHRwOi8vY3BzLmxldHNlbmNyeXB0Lm9yZzCCAQMGCisGAQQB1nkCBAIEgfQEgfEA7wB1ALIeBcyLos2KIE6HZvkruYolIGdr2vpw57JJUy3vi5BeAAABbeiVw3YAAAQDAEYwRAIgHUJgZEK9S5grlRSnDiZMZUWllQ1Ki10T2ldH1XgRfuUCICfKCcvcMas9Wb09athc6kPrD9WxVCi%2FTPfOWVmFv4EdAHYAb1N2rDHwMRnYmQCkURX%2FdxUcEdkCwQApBo2yCJo32RMAAAFt6JXE7wAABAMARzBFAiEAm4lY7Jsj1c%2F%2FzAES61A7hi9jJ5bqQpE1x9KCALQqd4sCIAablaGWv6L3uksVpDH1KDxj1Df9iDPGO2CJSzKjSKdNMA0GCSqGSIb3DQEBCwUAA4IBAQBjP5pR%2Fnj%2FCOZy3Z2LfqN7z%2Fcb87rz0CY7iR5p6PvdvwOs0JPq%2F1pVf4V3JTPmEduP7Z4cYIAoOp2%2BFBE0kZar0zzhp6uXcoBagrlxanG9KvgeWr1hfyJjYbnsteake8Z3vqfjdnlhB5ZFmQudHQh7QAoxtswNbdxjy%2FNwBIR5pKIDxleebVwe%2FneH%2BtokDYSPmH2vsmto0z72VM1KlFjgXC79XDIKMl83R2U%2F1B9wq23EHeFFY38cBUFKEjO67eC9q1Xxsv%2FpYAKrXVkdwwsvHfoY7evFRu%2Fj%2BsS3fWcf8uPrApaoqqJgjxpJ2jHjcXniad47iTffJUmwHqmyeigZ&cert=MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA%2FMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0NlowSjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMTGkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EFq6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan%2FPQeGdxyGkOlZHP%2FuaZ6WA8SMx%2Byk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0Z8h%2FpZq4UmEUEz9l6YKHy9v6Dlb2honzhT%2BXhq%2Bw3Brvaw2VFn3EK6BlspkENnWAa6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB%2FonkxEz0tNvjj%2FPIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0TAQH%2FBAgwBgEB%2FwIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIGCCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNvbTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9kc3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf%2FEFWCFiRAwVAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcCARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwuY3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsFAAOCAQEA3TPXEfNjWDjdGBX7CVW%2Bdla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJouM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg%2BVyOeph4EYpr%2F1wXKtx8%2FwApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so%2FjoWUoHOUgwuX4Po1QYz%2B3dszkDqMp4fklxBwXRsW10KXzPMTZ%2BsOPAveyxindmjkW8lGy%2BQsRlGPfZ%2BG6Z6h7mjem0Y%2BiWlkYcV4PIWL1iwBi8saCbGS5jN2p8M%2BX%2BQ7UNKEkROb3N6KOqkqm57TH2H3eDJAkSnh6%2FDNFu0Qg%3D%3D&cert=MIIDSjCCAjKgAwIBAgIQRK%2BwgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA%2FMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN%2Bv6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi%2BDoM3ZJKuM%2FIUmTrE4Orz5Iy2Xu%2FNMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9UL2AZd%2B3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRyxXtqqzTWMIn%2F5WgTe1QLyNau7Fqckh49ZLOMxt%2B%2FyUFw7BZy1SbsOFU5Q9D8%2FRhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4%2BU9m5%2FwAl0CAwEAAaNCMEAwDwYDVR0TAQH%2FBAUwAwEB%2FzAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62%2BFLkHX%2FxBVghYkQMA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or%2BDxz9LwwmglSBd49lZRNI%2BDT69ikugdB%2FOEIKcdBodfpga3csTS7MgROSR6cz8faXbauX%2B5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK%2BrlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir%2Fmd2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL%2BT0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ",
+ shouldBeRendered: true,
+ },
+ {
+ url:
+ "about:certificate?cert=MIIE0DCCBHegAwIBAgIQCP0zdXA01ESx6eTjfitzfzAKBggqhkjOPQQDAjBvMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xGTAXBgNVBAoTEENsb3VkRmxhcmUsIEluYy4xIDAeBgNVBAMTF0Nsb3VkRmxhcmUgSW5jIEVDQyBDQS0yMB4XDTE5MDUwMzAwMDAwMFoXDTIwMDUwMzEyMDAwMFowaDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRkwFwYDVQQKExBDbG91ZEZsYXJlLCBJbmMuMRkwFwYDVQQDExBzY290dGhlbG1lLmNvLnVrMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYQYIOYOkA0SNAxlrsvTnr7BIOoNmUaBFG2oXXyKfphkc%2F5wXXMU1Ez1%2BpqjFHSwaAtCkgTzTNEEOxkuDicJLqKOCAvowggL2MB8GA1UdIwQYMBaAFD50LR%2FPRXUEfj%2FAooc%2BTEODURPGMB0GA1UdDgQWBBSlm2TM83mhbWzqLL2SZRmdHbh%2FWDAvBgNVHREEKDAmghBzY290dGhlbG1lLmNvLnVrghIqLnNjb3R0aGVsbWUuY28udWswDgYDVR0PAQH%2FBAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB5BgNVHR8EcjBwMDagNKAyhjBodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vQ2xvdWRGbGFyZUluY0VDQ0NBMi5jcmwwNqA0oDKGMGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9DbG91ZEZsYXJlSW5jRUNDQ0EyLmNybDBMBgNVHSAERTBDMDcGCWCGSAGG%2FWwBATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeBDAECAjB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBABggrBgEFBQcwAoY0aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0Nsb3VkRmxhcmVJbmNFQ0NDQS0yLmNydDAMBgNVHRMBAf8EAjAAMIIBAwYKKwYBBAHWeQIEAgSB9ASB8QDvAHUA7ku9t3XOYLrhQmkfq%2BGeZqMPfl%2BwctiDAMR7iXqo%2FcsAAAFqfaV7eQAABAMARjBEAiAcD2ch9qAysZxlIFqrYjElyv%2B6fPbwBZ%2BCFSgJW7d4cgIgUnpOdauBy9OXIeQerY0ElxqlPDFo0qTx34NBoPmfyOYAdgBep3P531bA57U2SH3QSeAyepGaDIShEhKEGHWWgXFFWAAAAWp9pXsQAAAEAwBHMEUCIQDlDcpBkwV225tooGiDmWX4bwvpko6nmXnQ8RBeSltUGAIgXUCskAznLKPcqf7e55eEj9xwago28rJZny6stP9NqakwCgYIKoZIzj0EAwIDRwAwRAIfVXERnB1UkKpq73xsv0H3o0SC%2FVGdyuIizTc1HHeP6gIhAKSIp4zfgOLP3l46y2yHzir9PdeCc%2BRGUVg4P4IgAANv&cert=MIIDozCCAougAwIBAgIQD%2FPmFjmqPRoSZfQfizTltjANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTE1MTAxNDEyMDAwMFoXDTIwMTAwOTEyMDAwMFowbzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRkwFwYDVQQKExBDbG91ZEZsYXJlLCBJbmMuMSAwHgYDVQQDExdDbG91ZEZsYXJlIEluYyBFQ0MgQ0EtMjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNFW9Jy25DGg9aRSz%2BOaeob%2F8oayXsy1WcwRx07dZP1VnGDjoEvZeFT%2FSFC6ouGhWHWPx2A3RBZNVZns7tQzeiOjggEZMIIBFTASBgNVHRMBAf8ECDAGAQH%2FAgEAMA4GA1UdDwEB%2FwQEAwIBhjA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTA6BgNVHR8EMzAxMC%2BgLaArhilodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vT21uaXJvb3QyMDI1LmNybDA9BgNVHSAENjA0MDIGBFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAdBgNVHQ4EFgQUPnQtH89FdQR%2BP8Cihz5MQ4NRE8YwHwYDVR0jBBgwFoAU5Z1ZMIJHWMys%2BghUNoZ7OrUETfAwDQYJKoZIhvcNAQELBQADggEBADhfp%2F%2F8hfJzMuTVo4mZlmCvMsEDs2Xfvh4DyqXthbKPr0uMc48qjKkADgEkF%2FfsUoV2yOUcecrDF4dQtgQzNp4qnhgXljISr0PMVxje28fYiCWD5coGJTH9vV1IO1EB3SwUx8FgUemVAdiyM1YOR2aNbM2v%2BYXZ6xxHR4g06PD6wqtPaU4JWdRXxszByOPmGcFYOFLi4oOF3iI03D%2Bm968kvOBvwKtoLVLHawVXLEIbLUiHAwyQq0hIqSi%2BNIr7uu30YJkdFXgRqtltU39pKLy3ayB2f6BVA3F59WensKAKF1eyAKmtz%2F9njD4m5ackvMJvEOiJxnCl0h%2BA7Q0%2FJxM%3D&cert=MIIDdzCCAl%2BgAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN%2BhXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsBUnuId9Mcj8e6uYi1agnnc%2BgRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9%2FlSEy%2FCG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD%2BtqYF%2FLTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f%2FxXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v%2Fyejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1BE3wMBIGA1UdEwEB%2FwQIMAYBAf8CAQMwDgYDVR0PAQH%2FBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF%2BvaKSm2eT929hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE%2FszKN%2BOMY3EU%2Ft3WgxjkzSswF07r51XgdIGn9w%2FxZchMB5hbgF%2FX%2B%2BZRGjD8ACtPhSNzkE1akxehi%2FoCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h%2B3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5%2BNauQrz4wlHrQMz2nZQ%2F1%2FI6eYs9HRCwBXbsdtTLSR9I4LtD%2Bgdwyah617jzV%2FOeBHRnDJELqYzmp",
+ shouldBeRendered: false,
+ },
+ ];
+
+ for (let test of tests) {
+ await checkOCSP(test.url, test.shouldBeRendered);
+ }
+});
diff --git a/toolkit/components/certviewer/tests/browser/browser_checkStandAlonePage.js b/toolkit/components/certviewer/tests/browser/browser_checkStandAlonePage.js
new file mode 100644
index 0000000000..9e90b3678d
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser_checkStandAlonePage.js
@@ -0,0 +1,93 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TYPE_UNKNOWN = 0;
+const TYPE_CA = 1;
+const TYPE_USER = 2;
+const TYPE_EMAIL = 4;
+const TYPE_SERVER = 8;
+
+add_task(async function test_dbItemDisplayed() {
+ await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
+ gBrowser.selectedTab = BrowserTestUtils.addTab(
+ gBrowser,
+ "about:certificate"
+ );
+ });
+
+ let categories = [
+ {
+ type: TYPE_UNKNOWN,
+ tabName: "Unknown",
+ id: "unkonwn",
+ },
+ {
+ type: TYPE_CA,
+ tabName: "Authorities",
+ id: "ca",
+ },
+ {
+ type: TYPE_USER,
+ tabName: "Your Certificates",
+ id: "mine",
+ },
+ {
+ type: TYPE_EMAIL,
+ tabName: "People",
+ id: "people",
+ },
+ {
+ type: TYPE_SERVER,
+ tabName: "Servers",
+ id: "servers",
+ },
+ ];
+
+ let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
+ Ci.nsIX509CertDB
+ );
+ Assert.ok(certdb, "certdb not null");
+ let certcache = certdb.getCerts();
+ Assert.ok(certcache, "certcache not null");
+
+ for (let cert of certcache) {
+ let category = categories.find(({ type }) => type & cert.certType);
+
+ await SpecialPowers.spawn(
+ gBrowser.selectedBrowser,
+ [cert.displayName, category],
+ async function(displayName, category) {
+ let aboutCertificateSection = await ContentTaskUtils.waitForCondition(
+ () => {
+ return content.document.querySelector("about-certificate-section");
+ },
+ "Found aboutCertificateSection."
+ );
+
+ let tab = aboutCertificateSection.shadowRoot.querySelector(
+ `.certificate-tabs #certificate-viewer-tab-${category.id}`
+ );
+ Assert.ok(tab, `${category.tabName} tab should exist.`);
+ tab.click();
+
+ let certificateItems = aboutCertificateSection.shadowRoot.querySelector(
+ `.info-groups #certificate-viewer-tab-${category.id}`
+ );
+
+ let listItems = certificateItems.shadowRoot.querySelectorAll(
+ "list-item"
+ );
+
+ let item = Array.from(listItems).find(
+ i =>
+ i.shadowRoot.querySelector(".item-name").textContent == displayName
+ );
+ Assert.ok(item, `${displayName} should be listed`);
+ }
+ );
+ }
+
+ gBrowser.removeCurrentTab(); // closes about:certificate
+});
diff --git a/toolkit/components/certviewer/tests/browser/browser_checkValiditySection.js b/toolkit/components/certviewer/tests/browser/browser_checkValiditySection.js
new file mode 100644
index 0000000000..56d67f12b5
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser_checkValiditySection.js
@@ -0,0 +1,57 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const github_url =
+ "about:certificate?cert=MIIHQjCCBiqgAwIBAgIQCgYwQn9bvO1pVzllk7ZFHzANBgkqhkiG9w0BAQsFADB1MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTQwMgYDVQQDEytEaWdpQ2VydCBTSEEyIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VydmVyIENBMB4XDTE4MDUwODAwMDAwMFoXDTIwMDYwMzEyMDAwMFowgccxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQITCERlbGF3YXJlMRAwDgYDVQQFEwc1MTU3NTUwMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRMwEQYDVQQDEwpnaXRodWIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxjyq8jyXDDrBTyitcnB90865tWBzpHSbindG%2FXqYQkzFMBlXmqkzC%2BFdTRBYyneZw5Pz%2BXWQvL%2B74JW6LsWNc2EF0xCEqLOJuC9zjPAqbr7uroNLghGxYf13YdqbG5oj%2F4x%2BogEG3dF%2FU5YIwVr658DKyESMV6eoYV9mDVfTuJastkqcwero%2B5ZAKfYVMLUEsMwFtoTDJFmVf6JlkOWwsxp1WcQ%2FMRQK1cyqOoUFUgYylgdh3yeCDPeF22Ax8AlQxbcaI%2BGwfQL1FB7Jy%2Bh%2BKjME9lE%2FUpgV6Qt2R1xNSmvFCBWu%2BNFX6epwFP%2FJRbkMfLz0beYFUvmMgLtwVpEPSwIDAQABo4IDeTCCA3UwHwYDVR0jBBgwFoAUPdNQpdagre7zSmAKZdMh1Pj41g8wHQYDVR0OBBYEFMnCU2FmnV%2BrJfQmzQ84mqhJ6kipMCUGA1UdEQQeMByCCmdpdGh1Yi5jb22CDnd3dy5naXRodWIuY29tMA4GA1UdDwEB%2FwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0fBG4wbDA0oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItZXYtc2VydmVyLWcyLmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItZXYtc2VydmVyLWcyLmNybDBLBgNVHSAERDBCMDcGCWCGSAGG%2FWwCATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAcGBWeBDAEBMIGIBggrBgEFBQcBAQR8MHowJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBSBggrBgEFBQcwAoZGaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkV4dGVuZGVkVmFsaWRhdGlvblNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAAMIIBfgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdgCkuQmQtBhYFIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAWNBYm0KAAAEAwBHMEUCIQDRZp38cTWsWH2GdBpe%2FuPTWnsu%2Fm4BEC2%2BdIcvSykZYgIgCP5gGv6yzaazxBK2NwGdmmyuEFNSg2pARbMJlUFgU5UAdgBWFAaaL9fC7NP14b1Esj7HRna5vJkRXMDvlJhV1onQ3QAAAWNBYm0tAAAEAwBHMEUCIQCi7omUvYLm0b2LobtEeRAYnlIo7n6JxbYdrtYdmPUWJQIgVgw1AZ51vK9ENinBg22FPxb82TvNDO05T17hxXRC2IYAdgC72d%2B8H4pxtZOUI5eqkntHOFeVCqtS6BqQlmQ2jh7RhQAAAWNBYm3fAAAEAwBHMEUCIQChzdTKUU2N%2BXcqcK0OJYrN8EYynloVxho4yPk6Dq3EPgIgdNH5u8rC3UcslQV4B9o0a0w204omDREGKTVuEpxGeOQwDQYJKoZIhvcNAQELBQADggEBAHAPWpanWOW%2Fip2oJ5grAH8mqQfaunuCVE%2Bvac%2B88lkDK%2FLVdFgl2B6kIHZiYClzKtfczG93hWvKbST4NRNHP9LiaQqdNC17e5vNHnXVUGw%2ByxyjMLGqkgepOnZ2Rb14kcTOGp4i5AuJuuaMwXmCo7jUwPwfLe1NUlVBKqg6LK0Hcq4K0sZnxE8HFxiZ92WpV2AVWjRMEc%2F2z2shNoDvxvFUYyY1Oe67xINkmyQKc%2BygSBZzyLnXSFVWmHr3u5dcaaQGGAR42v6Ydr4iL38Hd4dOiBma%2BFXsXBIqWUjbST4VXmdaol7uzFMojA4zkxQDZAvF5XgJlAFadfySna%2Fteik%3D";
+const mozilla_url =
+ "about:certificate?cert=MIIGRjCCBS6gAwIBAgIQDJduPkI49CDWPd%2BG7%2Bu6kDANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5EaWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgxMTA1MDAwMDAwWhcNMTkxMTEzMTIwMDAwWjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxHDAaBgNVBAoTE01vemlsbGEgQ29ycG9yYXRpb24xDzANBgNVBAsTBldlYk9wczEYMBYGA1UEAxMPd3d3Lm1vemlsbGEub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuKruymkkmkqCJh7QjmXlUOBcLFRyw5LG%2FvUUWVrsxC2gsbR8WJq%2BcYoYBpoNVStKrO4U2rBh1GEbccvT6qKOQI%2BpjjDxx9cmRdubGTGp8L0MF1ohVvhIvYLumOEoRDDPU4PvGJjGhek%2FojvedPWe8dhciHkxOC2qPFZvVFMwg1%2Fo%2Fb80147BwZQmzB18mnHsmcyKlpsCN8pxw86uao9Iun8gZQrsllW64rTZlRR56pHdAcuGAoZjYZxwS9Z%2BlvrSjEgrddemWyGGalqyFp1rXlVM1Tf4%2FIYWAQXTgTUN303u3xMjss7QK7eUDsACRxiWPLW9XQDd1c%2ByvaYJKzgJ2wIDAQABo4IC6TCCAuUwHwYDVR0jBBgwFoAUD4BhHIIxYdUvKOeNRji0LOHG2eIwHQYDVR0OBBYEFNpSvSGcN2VT%2FB9TdQ8eXwebo60%2FMCcGA1UdEQQgMB6CD3d3dy5tb3ppbGxhLm9yZ4ILbW96aWxsYS5vcmcwDgYDVR0PAQH%2FBAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBrBgNVHR8EZDBiMC%2BgLaArhilodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc3NjYS1zaGEyLWc2LmNybDAvoC2gK4YpaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nNi5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBAgIwfAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH%2FBAIwADCCAQIGCisGAQQB1nkCBAIEgfMEgfAA7gB1AKS5CZC0GFgUh7sTosxncAo8NZgE%2BRvfuON3zQ7IDdwQAAABZuYWiHwAAAQDAEYwRAIgZnMSH1JdG6NASHWTwD0mlP%2Fzbr0hzP263c02Ym0DU64CIEe4QHJDP47j0b6oTFu6RrZz1NQ9cq8Az1KnMKRuaFAlAHUAh3W%2F51l8%2BIxDmV%2B9827%2FVo1HVjb%2FSrVgwbTq%2F16ggw8AAAFm5haJAgAABAMARjBEAiAxGLXkUaOAkZhXNeNR3pWyahZeKmSaMXadgu18SfK1ZAIgKtwu5eGxK76rgaszLCZ9edBIjuU0DKorzPUuxUXFY0QwDQYJKoZIhvcNAQELBQADggEBAKLJAFO3wuaP5MM%2Fed1lhk5Uc2aDokhcM7XyvdhEKSHbgPhcgMoT9YIVoPa70gNC6KHcwoXu0g8wt7X6Vm1ql%2F68G5q844kFuC6JPl4LVT9mciD%2BVW6bHUSXD9xifL9DqdJ0Ic0SllTlM%2Boq5aAeOxUQGXhXIqj6fSQv9fQN6mXxQIoc%2Fgjxteskq%2FVl8YmY1FIZP9Bh7g27kxZ9GAAGQtjTL03RzKAuSg6yeImYVdQWasc7UPnBXlRAzZ8%2BOJThUbzK16a2CI3Rg4agKSJk%2BuA47h1%2FImmngpFLRb%2FMvRX6H1oWcUuyH6O7PZdl0YpwTpw1THIuqCGl%2FwpPgyQgcTM%3D";
+const youtube_url =
+ "about:certificate?cert=MIIIIDCCBwigAwIBAgIQGk0sGNQUuaOL9Rii2XQ4yjANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZpY2VzMSUwIwYDVQQDExxHb29nbGUgSW50ZXJuZXQgQXV0aG9yaXR5IEczMB4XDTE5MDYxODA4MjE1OFoXDTE5MDkxMDA4MTUwMFowZjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEzARBgNVBAoMCkdvb2dsZSBMTEMxFTATBgNVBAMMDCouZ29vZ2xlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABMRScn8kk6qy3LHVktWZWxm%2FMq4kowlEdxQH40wijThZ%2B%2F5Jrqh6UlWnWuiulNorHH2DEW4OkSKreFoYze7w8O6jggWlMIIFoTATBgNVHSUEDDAKBggrBgEFBQcDATAOBgNVHQ8BAf8EBAMCB4AwggRqBgNVHREEggRhMIIEXYIMKi5nb29nbGUuY29tgg0qLmFuZHJvaWQuY29tghYqLmFwcGVuZ2luZS5nb29nbGUuY29tghIqLmNsb3VkLmdvb2dsZS5jb22CGCouY3Jvd2Rzb3VyY2UuZ29vZ2xlLmNvbYIGKi5nLmNvgg4qLmdjcC5ndnQyLmNvbYIRKi5nY3BjZG4uZ3Z0MS5jb22CCiouZ2dwaHQuY26CFiouZ29vZ2xlLWFuYWx5dGljcy5jb22CCyouZ29vZ2xlLmNhggsqLmdvb2dsZS5jbIIOKi5nb29nbGUuY28uaW6CDiouZ29vZ2xlLmNvLmpwgg4qLmdvb2dsZS5jby51a4IPKi5nb29nbGUuY29tLmFygg8qLmdvb2dsZS5jb20uYXWCDyouZ29vZ2xlLmNvbS5icoIPKi5nb29nbGUuY29tLmNvgg8qLmdvb2dsZS5jb20ubXiCDyouZ29vZ2xlLmNvbS50coIPKi5nb29nbGUuY29tLnZuggsqLmdvb2dsZS5kZYILKi5nb29nbGUuZXOCCyouZ29vZ2xlLmZyggsqLmdvb2dsZS5odYILKi5nb29nbGUuaXSCCyouZ29vZ2xlLm5sggsqLmdvb2dsZS5wbIILKi5nb29nbGUucHSCEiouZ29vZ2xlYWRhcGlzLmNvbYIPKi5nb29nbGVhcGlzLmNughEqLmdvb2dsZWNuYXBwcy5jboIUKi5nb29nbGVjb21tZXJjZS5jb22CESouZ29vZ2xldmlkZW8uY29tggwqLmdzdGF0aWMuY26CDSouZ3N0YXRpYy5jb22CEiouZ3N0YXRpY2NuYXBwcy5jboIKKi5ndnQxLmNvbYIKKi5ndnQyLmNvbYIUKi5tZXRyaWMuZ3N0YXRpYy5jb22CDCoudXJjaGluLmNvbYIQKi51cmwuZ29vZ2xlLmNvbYIWKi55b3V0dWJlLW5vY29va2llLmNvbYINKi55b3V0dWJlLmNvbYIWKi55b3V0dWJlZWR1Y2F0aW9uLmNvbYIRKi55b3V0dWJla2lkcy5jb22CByoueXQuYmWCCyoueXRpbWcuY29tghphbmRyb2lkLmNsaWVudHMuZ29vZ2xlLmNvbYILYW5kcm9pZC5jb22CG2RldmVsb3Blci5hbmRyb2lkLmdvb2dsZS5jboIcZGV2ZWxvcGVycy5hbmRyb2lkLmdvb2dsZS5jboIEZy5jb4IIZ2dwaHQuY26CBmdvby5nbIIUZ29vZ2xlLWFuYWx5dGljcy5jb22CCmdvb2dsZS5jb22CD2dvb2dsZWNuYXBwcy5jboISZ29vZ2xlY29tbWVyY2UuY29tghhzb3VyY2UuYW5kcm9pZC5nb29nbGUuY26CCnVyY2hpbi5jb22CCnd3dy5nb28uZ2yCCHlvdXR1LmJlggt5b3V0dWJlLmNvbYIUeW91dHViZWVkdWNhdGlvbi5jb22CD3lvdXR1YmVraWRzLmNvbYIFeXQuYmUwaAYIKwYBBQUHAQEEXDBaMC0GCCsGAQUFBzAChiFodHRwOi8vcGtpLmdvb2cvZ3NyMi9HVFNHSUFHMy5jcnQwKQYIKwYBBQUHMAGGHWh0dHA6Ly9vY3NwLnBraS5nb29nL0dUU0dJQUczMB0GA1UdDgQWBBT8E5DiGEc7xHswBMF5K5EmFzx6fDAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFHfCuFCaZ3Z2sS3ChtCDoH6mfrpLMCEGA1UdIAQaMBgwDAYKKwYBBAHWeQIFAzAIBgZngQwBAgIwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovL2NybC5wa2kuZ29vZy9HVFNHSUFHMy5jcmwwDQYJKoZIhvcNAQELBQADggEBAGrWCimTdP8%2B6qCqNh1Xza9Wlm%2FGDVb%2BKp0PHUZaNDMThFQQqGn2XVi7ZkhqsxTtMw88Nrl97Bi1OsnNPlabhDwxtRyWkNkLdpFxebRz73CsjyoB3cboH%2FZ8sU9LLwXe%2FIJgMkvT7fznKtKSweWV%2BmAYG%2F3KzaIyLrowYpyOsWaYytPJK7ypuk6yOPxuQcQnelotWpuHUBR3mo3FIW56BPCy20KwqwvWoZe27BNxO%2F11Ym%2FPnric2fWXwgmHdkvVqqssUMFs%2BmG2tS%2FpqnR5yZdQL60xOgDq70mVWYgQT4yUTm7i8qvugvNnuSIjjsbelHgbC8f5%2Fx%2Bo2pEyw%2FDYyKw%3D";
+
+async function checValiditySection(url) {
+ await BrowserTestUtils.withNewTab(url, async function(browser) {
+ await SpecialPowers.spawn(browser, [], async function() {
+ let certificateSection = await ContentTaskUtils.waitForCondition(() => {
+ return content.document.querySelector("certificate-section");
+ }, "Certificate section found");
+
+ let validitySection = certificateSection.shadowRoot.querySelector(
+ "info-group.validity"
+ );
+ Assert.ok(validitySection, "validitySection found");
+
+ let infoItems = validitySection.shadowRoot.querySelectorAll("info-item");
+ Assert.ok(infoItems, "infoItems found");
+ Assert.equal(
+ infoItems.length,
+ 2,
+ "There must be render just one date for Not Before and one for Not After"
+ );
+
+ for (let infoItem of infoItems) {
+ let label = infoItem.shadowRoot
+ .querySelector("label")
+ .getAttribute("data-l10n-id");
+
+ Assert.notEqual(label, "", "Label shouldn't be empty");
+
+ let infoElem = infoItem.shadowRoot.querySelector(".info");
+ let title = infoElem.textContent;
+ Assert.equal(
+ title.includes("GMT"),
+ true,
+ "UTC timezone should be displayed in the label"
+ );
+ }
+ });
+ });
+}
+
+add_task(async function test() {
+ let input = [github_url, mozilla_url, youtube_url];
+ for (let url of input) {
+ await checValiditySection(url);
+ }
+});
diff --git a/toolkit/components/certviewer/tests/browser/browser_clickableLink.js b/toolkit/components/certviewer/tests/browser/browser_clickableLink.js
new file mode 100644
index 0000000000..2c38052e55
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser_clickableLink.js
@@ -0,0 +1,44 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const validCert =
+ "about:certificate?cert=MIIGMDCCBRigAwIBAgIQCa2oS7Nau6nwv1WyRNIJnzANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNzdXJhbmNlIFNlcnZlciBDQTAeFw0xOTA2MDYwMDAwMDBaFw0xOTA5MDQxMjAwMDBaMGExCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTWVubG8gUGFyazEXMBUGA1UEChMORmFjZWJvb2ssIEluYy4xFzAVBgNVBAMMDiouZmFjZWJvb2suY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEALPlfjd8gHkIMDeBOFhRt0e%2B%2F3fdm%2BZdzdM4s1WIHVbYztgmdEy20PUwDCviYKJX4GG%2BT9ivT8kJ%2FvWl1P%2FYqOCA54wggOaMB8GA1UdIwQYMBaAFFFo%2F5CvAgd1PMzZZWRiohK4WXI7MB0GA1UdDgQWBBTsQZVRTuib7KY9w3FfOYsZHvOC9zCBxwYDVR0RBIG%2FMIG8gg4qLmZhY2Vib29rLmNvbYINbWVzc2VuZ2VyLmNvbYILKi5mYmNkbi5uZXSCCCouZmIuY29tghAqLm0uZmFjZWJvb2suY29tggZmYi5jb22CDiouZmFjZWJvb2submV0gg4qLnh4LmZiY2RuLm5ldIIOKi54ei5mYmNkbi5uZXSCDyoubWVzc2VuZ2VyLmNvbYILKi5mYnNieC5jb22CDioueHkuZmJjZG4ubmV0ggxmYWNlYm9vay5jb20wDgYDVR0PAQH%2FBAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzYuY3JsMDSgMqAwhi5odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzYuY3JsMEwGA1UdIARFMEMwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQICMIGDBggrBgEFBQcBAQR3MHUwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBNBggrBgEFBQcwAoZBaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkhpZ2hBc3N1cmFuY2VTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH%2FBAIwADCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB1AKS5CZC0GFgUh7sTosxncAo8NZgE%2BRvfuON3zQ7IDdwQAAABay5CAaUAAAQDAEYwRAIgMwBM6q%2BdBwu2mNtMMjTEwJZZxyoUlHUEYO%2BbfkId%2F9MCIAQ2bxhnxrapYv74fzyoTkt9m%2BELq6%2B43OVpivRVKDKTAHcAdH7agzGtMxCRIZzOJU9CcMK%2F%2FV5CIAjGNzV55hB7zFYAAAFrLkIA%2FAAABAMASDBGAiEA0x1xPWue6RMSE9nbjYBt637CRC86ixrODP%2FEIlI5mCgCIQCHNdqgOlswd0LqaW4QRii2JHN4bnoEj%2FD9j7%2BkqEB7LjANBgkqhkiG9w0BAQsFAAOCAQEAnRdIVNZ850s7IvLgg%2BU9kKxA18kLKVpIF%2FrJHkXTkymvBHKAGOFNfzqF2YxHFhkDMIuoMO2F%2BA1E0Eo8zb1atL6%2FL59broEHTOH6xFmJAlZW0h6mZg8iRJ9Ae0pTN%2FfowaoN9aFVRnVr9ccKhOdqsXYyEZ3Ze39sEwx7Uau9KhzyuJW12Jh3S%2BZJYUdBADeeJNL5ZXSUFIyjgkwSQZPaaWAzSGHZFt3sWhMjdNoBkjRJFlASLDM3m1ZWsKA47vuXvJc%2FDXT35lC1DJmyhYb9qNPR71a1hJ8TS7vUwdDd%2BdEHiJj2wQLV3m7Tn7YvWyJOEyi4n6%2FrPqT44LZmgK7HWw%3D%3D&cert=MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3VyYW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC24C%2FCJAbIbQRf1%2B8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU%2BUDlqUH1VWtMICKq%2FQmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK%2FIHe1NnF9Xt4ZQaJn1itrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j%2F018QsIJzJa9buLnqS9UdAn4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I%2B4G3FhahnSMSTeXXkgisdaScus0Xsh5ENWV%2FUyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcftbZvySC%2FzA%2FWiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH%2FAgEAMA4GA1UdDwEB%2FwQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIGBFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAdBgNVHQ4EFgQUUWj%2FkK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7DaQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwdaOpKj4PWUS%2BNa0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk%2FgNHE%2Br1hspZcX30BJZr01lYPf7TMSVcGDiEo%2Bafgv2MW5gxTs14nhr9hctJqvIni5ly%2FD6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zuxICaEnL6VpPX%2F78whQYwvwt%2FTv9XBZ0k7YXDK%2FumdaisLRbvfXknsuvCnQsH6qqF0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY%2B3sAzm2fTYS5yh%2BRp%2FBIAV0AecPUeybQ%3D&cert=MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm%2B9S75S0tMqbf5YE%2Fyc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG%2B%2BMXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx%2BmM0aBhakaHPQNAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH%2FBAQDAgGGMA8GA1UdEwEB%2FwQFMAMBAf8wHQYDVR0OBBYEFLE%2Bw2kD%2BL9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE%2Bw2kD%2BL9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe%2FEW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9%2BMpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2Yzi9RKR%2F5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2%2FS6cCZdkGCevEsXCS%2B0yx5DaMkHJ8HSXPfqIbloEpw8nL%2Be%2FIBcm2PN7EeqJSdnoDfzAIJ9VNep%2BOkuE6N36B9K";
+
+add_task(async function testClickableLink() {
+ await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
+ gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, validCert);
+ });
+
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function() {
+ let crlEndpoints;
+ await ContentTaskUtils.waitForCondition(() => {
+ crlEndpoints = content.document
+ .querySelector("certificate-section")
+ .shadowRoot.querySelector(".crl-endpoints")
+ .shadowRoot.querySelectorAll(".distribution-point");
+ return crlEndpoints.length;
+ }, "CRL Endpoints should exist.");
+
+ ok(crlEndpoints.length, "CRL Endpoints should exist.");
+
+ for (let i = 0; i < crlEndpoints.length; i++) {
+ let endpoint = crlEndpoints[i];
+ endpoint = endpoint.shadowRoot.querySelector(".info");
+
+ let aTag = endpoint.querySelector("a");
+ Assert.equal(
+ aTag.hasAttribute("disabled"),
+ false,
+ "Link should be clickable."
+ );
+ Assert.equal(
+ aTag.getAttribute("rel"),
+ "noreferrer noopener",
+ "Link should have ref attribute values 'noreferrer noopener'."
+ );
+ }
+ });
+ gBrowser.removeCurrentTab(); // closes about:certificate
+});
diff --git a/toolkit/components/certviewer/tests/browser/browser_downloadLink.js b/toolkit/components/certviewer/tests/browser/browser_downloadLink.js
new file mode 100644
index 0000000000..6a10edb6de
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser_downloadLink.js
@@ -0,0 +1,110 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const validCert =
+ "about:certificate?cert=MIIGMDCCBRigAwIBAgIQCa2oS7Nau6nwv1WyRNIJnzANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNzdXJhbmNlIFNlcnZlciBDQTAeFw0xOTA2MDYwMDAwMDBaFw0xOTA5MDQxMjAwMDBaMGExCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTWVubG8gUGFyazEXMBUGA1UEChMORmFjZWJvb2ssIEluYy4xFzAVBgNVBAMMDiouZmFjZWJvb2suY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEALPlfjd8gHkIMDeBOFhRt0e%2B%2F3fdm%2BZdzdM4s1WIHVbYztgmdEy20PUwDCviYKJX4GG%2BT9ivT8kJ%2FvWl1P%2FYqOCA54wggOaMB8GA1UdIwQYMBaAFFFo%2F5CvAgd1PMzZZWRiohK4WXI7MB0GA1UdDgQWBBTsQZVRTuib7KY9w3FfOYsZHvOC9zCBxwYDVR0RBIG%2FMIG8gg4qLmZhY2Vib29rLmNvbYINbWVzc2VuZ2VyLmNvbYILKi5mYmNkbi5uZXSCCCouZmIuY29tghAqLm0uZmFjZWJvb2suY29tggZmYi5jb22CDiouZmFjZWJvb2submV0gg4qLnh4LmZiY2RuLm5ldIIOKi54ei5mYmNkbi5uZXSCDyoubWVzc2VuZ2VyLmNvbYILKi5mYnNieC5jb22CDioueHkuZmJjZG4ubmV0ggxmYWNlYm9vay5jb20wDgYDVR0PAQH%2FBAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzYuY3JsMDSgMqAwhi5odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzYuY3JsMEwGA1UdIARFMEMwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQICMIGDBggrBgEFBQcBAQR3MHUwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBNBggrBgEFBQcwAoZBaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkhpZ2hBc3N1cmFuY2VTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH%2FBAIwADCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB1AKS5CZC0GFgUh7sTosxncAo8NZgE%2BRvfuON3zQ7IDdwQAAABay5CAaUAAAQDAEYwRAIgMwBM6q%2BdBwu2mNtMMjTEwJZZxyoUlHUEYO%2BbfkId%2F9MCIAQ2bxhnxrapYv74fzyoTkt9m%2BELq6%2B43OVpivRVKDKTAHcAdH7agzGtMxCRIZzOJU9CcMK%2F%2FV5CIAjGNzV55hB7zFYAAAFrLkIA%2FAAABAMASDBGAiEA0x1xPWue6RMSE9nbjYBt637CRC86ixrODP%2FEIlI5mCgCIQCHNdqgOlswd0LqaW4QRii2JHN4bnoEj%2FD9j7%2BkqEB7LjANBgkqhkiG9w0BAQsFAAOCAQEAnRdIVNZ850s7IvLgg%2BU9kKxA18kLKVpIF%2FrJHkXTkymvBHKAGOFNfzqF2YxHFhkDMIuoMO2F%2BA1E0Eo8zb1atL6%2FL59broEHTOH6xFmJAlZW0h6mZg8iRJ9Ae0pTN%2FfowaoN9aFVRnVr9ccKhOdqsXYyEZ3Ze39sEwx7Uau9KhzyuJW12Jh3S%2BZJYUdBADeeJNL5ZXSUFIyjgkwSQZPaaWAzSGHZFt3sWhMjdNoBkjRJFlASLDM3m1ZWsKA47vuXvJc%2FDXT35lC1DJmyhYb9qNPR71a1hJ8TS7vUwdDd%2BdEHiJj2wQLV3m7Tn7YvWyJOEyi4n6%2FrPqT44LZmgK7HWw%3D%3D&cert=MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3VyYW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC24C%2FCJAbIbQRf1%2B8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU%2BUDlqUH1VWtMICKq%2FQmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK%2FIHe1NnF9Xt4ZQaJn1itrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j%2F018QsIJzJa9buLnqS9UdAn4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I%2B4G3FhahnSMSTeXXkgisdaScus0Xsh5ENWV%2FUyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcftbZvySC%2FzA%2FWiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH%2FAgEAMA4GA1UdDwEB%2FwQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIGBFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAdBgNVHQ4EFgQUUWj%2FkK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7DaQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwdaOpKj4PWUS%2BNa0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk%2FgNHE%2Br1hspZcX30BJZr01lYPf7TMSVcGDiEo%2Bafgv2MW5gxTs14nhr9hctJqvIni5ly%2FD6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zuxICaEnL6VpPX%2F78whQYwvwt%2FTv9XBZ0k7YXDK%2FumdaisLRbvfXknsuvCnQsH6qqF0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY%2B3sAzm2fTYS5yh%2BRp%2FBIAV0AecPUeybQ%3D&cert=MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm%2B9S75S0tMqbf5YE%2Fyc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG%2B%2BMXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx%2BmM0aBhakaHPQNAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH%2FBAQDAgGGMA8GA1UdEwEB%2FwQFMAMBAf8wHQYDVR0OBBYEFLE%2Bw2kD%2BL9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE%2Bw2kD%2BL9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe%2FEW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9%2BMpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2Yzi9RKR%2F5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2%2FS6cCZdkGCevEsXCS%2B0yx5DaMkHJ8HSXPfqIbloEpw8nL%2Be%2FIBcm2PN7EeqJSdnoDfzAIJ9VNep%2BOkuE6N36B9K";
+
+add_task(async function test_checkForErrorSection() {
+ await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
+ gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, validCert);
+ });
+
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function() {
+ let infoGroups;
+ let downloadLinkContainers = [];
+
+ await ContentTaskUtils.waitForCondition(() => {
+ infoGroups = content.document
+ .querySelector("certificate-section")
+ .shadowRoot.querySelectorAll(".miscellaneous");
+ for (let i = 0; i < infoGroups.length; i++) {
+ downloadLinkContainers.push(
+ infoGroups[i].shadowRoot
+ .querySelector(".download")
+ .shadowRoot.querySelector(".info")
+ );
+ }
+ return downloadLinkContainers.length;
+ }, "Found download info items.");
+
+ ok(downloadLinkContainers.length, "Download info items should exist.");
+
+ let certTabs = content.document
+ .querySelector("certificate-section")
+ .shadowRoot.querySelectorAll(".certificate-tab");
+
+ await ContentTaskUtils.waitForCondition(
+ () => certTabs.length,
+ "Certificate tabs should exist."
+ );
+
+ let url = new URL(content.document.documentURI);
+ let certs = url.searchParams.getAll("cert");
+ let certChain = [];
+ for (let i = 0; i < certs.length; i++) {
+ certChain.push(
+ `-----BEGIN CERTIFICATE-----\r\n${certs[i]}\r\n-----END CERTIFICATE-----\r\n`
+ );
+ }
+ certChain = certChain.join("").replace(/(\r\n|\n|\r)/gm, "");
+
+ for (let i = 0; i < certTabs.length; i++) {
+ let downloadLink = downloadLinkContainers[i].querySelector(
+ ".download-link"
+ );
+
+ let downloadChainLink = downloadLinkContainers[i].querySelector(
+ ".download-link-chain"
+ );
+
+ let cert = certs[i];
+ cert = `-----BEGIN CERTIFICATE-----\r\n${cert}\r\n-----END CERTIFICATE-----\r\n`;
+ cert = cert.replace(/(\r\n|\n|\r)/gm, "");
+
+ let linkCert = downloadLink.getAttribute("href");
+ linkCert = linkCert.replace("data:,", "");
+ linkCert = decodeURI(linkCert);
+ linkCert = linkCert.replace(/(\r\n|\n|\r)/gm, "");
+
+ let downloadChainCert = downloadChainLink.getAttribute("href");
+ downloadChainCert = downloadChainCert.replace("data:,", "");
+ downloadChainCert = decodeURI(downloadChainCert);
+ downloadChainCert = downloadChainCert.replace(/(\r\n|\n|\r)/gm, "");
+
+ Assert.equal(
+ cert,
+ linkCert,
+ "Download link href should be equal to URL cert."
+ );
+
+ Assert.equal(
+ certChain,
+ downloadChainCert,
+ "Download chain link href should be equal to URL cert."
+ );
+
+ await content.document.l10n.translateElements([
+ downloadChainLink,
+ downloadLink,
+ ]);
+
+ Assert.equal(
+ downloadLinkContainers[i].textContent,
+ "PEM (cert)PEM (chain)",
+ "Download should contain links to PEM cert and PEM chain."
+ );
+
+ if (certTabs[i + 1]) {
+ certTabs[i + 1].click();
+
+ await ContentTaskUtils.waitForCondition(
+ () => certTabs[i + 1].classList.contains("selected"),
+ "Cert tab should be selected"
+ );
+ }
+ }
+ });
+ gBrowser.removeCurrentTab(); // closes about:certificate
+});
diff --git a/toolkit/components/certviewer/tests/browser/browser_handleMultipleCertsURL.js b/toolkit/components/certviewer/tests/browser/browser_handleMultipleCertsURL.js
new file mode 100644
index 0000000000..e500c9e673
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser_handleMultipleCertsURL.js
@@ -0,0 +1,236 @@
+// valids
+const multipleCerts1 =
+ "about:certificate?cert=MIIGRjCCBS6gAwIBAgIQDJduPkI49CDWPd%2BG7%2Bu6kDANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5EaWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgxMTA1MDAwMDAwWhcNMTkxMTEzMTIwMDAwWjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxHDAaBgNVBAoTE01vemlsbGEgQ29ycG9yYXRpb24xDzANBgNVBAsTBldlYk9wczEYMBYGA1UEAxMPd3d3Lm1vemlsbGEub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuKruymkkmkqCJh7QjmXlUOBcLFRyw5LG%2FvUUWVrsxC2gsbR8WJq%2BcYoYBpoNVStKrO4U2rBh1GEbccvT6qKOQI%2BpjjDxx9cmRdubGTGp8L0MF1ohVvhIvYLumOEoRDDPU4PvGJjGhek%2FojvedPWe8dhciHkxOC2qPFZvVFMwg1%2Fo%2Fb80147BwZQmzB18mnHsmcyKlpsCN8pxw86uao9Iun8gZQrsllW64rTZlRR56pHdAcuGAoZjYZxwS9Z%2BlvrSjEgrddemWyGGalqyFp1rXlVM1Tf4%2FIYWAQXTgTUN303u3xMjss7QK7eUDsACRxiWPLW9XQDd1c%2ByvaYJKzgJ2wIDAQABo4IC6TCCAuUwHwYDVR0jBBgwFoAUD4BhHIIxYdUvKOeNRji0LOHG2eIwHQYDVR0OBBYEFNpSvSGcN2VT%2FB9TdQ8eXwebo60%2FMCcGA1UdEQQgMB6CD3d3dy5tb3ppbGxhLm9yZ4ILbW96aWxsYS5vcmcwDgYDVR0PAQH%2FBAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBrBgNVHR8EZDBiMC%2BgLaArhilodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc3NjYS1zaGEyLWc2LmNybDAvoC2gK4YpaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nNi5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBAgIwfAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH%2FBAIwADCCAQIGCisGAQQB1nkCBAIEgfMEgfAA7gB1AKS5CZC0GFgUh7sTosxncAo8NZgE%2BRvfuON3zQ7IDdwQAAABZuYWiHwAAAQDAEYwRAIgZnMSH1JdG6NASHWTwD0mlP%2Fzbr0hzP263c02Ym0DU64CIEe4QHJDP47j0b6oTFu6RrZz1NQ9cq8Az1KnMKRuaFAlAHUAh3W%2F51l8%2BIxDmV%2B9827%2FVo1HVjb%2FSrVgwbTq%2F16ggw8AAAFm5haJAgAABAMARjBEAiAxGLXkUaOAkZhXNeNR3pWyahZeKmSaMXadgu18SfK1ZAIgKtwu5eGxK76rgaszLCZ9edBIjuU0DKorzPUuxUXFY0QwDQYJKoZIhvcNAQELBQADggEBAKLJAFO3wuaP5MM%2Fed1lhk5Uc2aDokhcM7XyvdhEKSHbgPhcgMoT9YIVoPa70gNC6KHcwoXu0g8wt7X6Vm1ql%2F68G5q844kFuC6JPl4LVT9mciD%2BVW6bHUSXD9xifL9DqdJ0Ic0SllTlM%2Boq5aAeOxUQGXhXIqj6fSQv9fQN6mXxQIoc%2Fgjxteskq%2FVl8YmY1FIZP9Bh7g27kxZ9GAAGQtjTL03RzKAuSg6yeImYVdQWasc7UPnBXlRAzZ8%2BOJThUbzK16a2CI3Rg4agKSJk%2BuA47h1%2FImmngpFLRb%2FMvRX6H1oWcUuyH6O7PZdl0YpwTpw1THIuqCGl%2FwpPgyQgcTM%3D&cert=MIIHQjCCBiqgAwIBAgIQCgYwQn9bvO1pVzllk7ZFHzANBgkqhkiG9w0BAQsFADB1MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTQwMgYDVQQDEytEaWdpQ2VydCBTSEEyIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VydmVyIENBMB4XDTE4MDUwODAwMDAwMFoXDTIwMDYwMzEyMDAwMFowgccxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQITCERlbGF3YXJlMRAwDgYDVQQFEwc1MTU3NTUwMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRMwEQYDVQQDEwpnaXRodWIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxjyq8jyXDDrBTyitcnB90865tWBzpHSbindG%2FXqYQkzFMBlXmqkzC%2BFdTRBYyneZw5Pz%2BXWQvL%2B74JW6LsWNc2EF0xCEqLOJuC9zjPAqbr7uroNLghGxYf13YdqbG5oj%2F4x%2BogEG3dF%2FU5YIwVr658DKyESMV6eoYV9mDVfTuJastkqcwero%2B5ZAKfYVMLUEsMwFtoTDJFmVf6JlkOWwsxp1WcQ%2FMRQK1cyqOoUFUgYylgdh3yeCDPeF22Ax8AlQxbcaI%2BGwfQL1FB7Jy%2Bh%2BKjME9lE%2FUpgV6Qt2R1xNSmvFCBWu%2BNFX6epwFP%2FJRbkMfLz0beYFUvmMgLtwVpEPSwIDAQABo4IDeTCCA3UwHwYDVR0jBBgwFoAUPdNQpdagre7zSmAKZdMh1Pj41g8wHQYDVR0OBBYEFMnCU2FmnV%2BrJfQmzQ84mqhJ6kipMCUGA1UdEQQeMByCCmdpdGh1Yi5jb22CDnd3dy5naXRodWIuY29tMA4GA1UdDwEB%2FwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0fBG4wbDA0oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItZXYtc2VydmVyLWcyLmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItZXYtc2VydmVyLWcyLmNybDBLBgNVHSAERDBCMDcGCWCGSAGG%2FWwCATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAcGBWeBDAEBMIGIBggrBgEFBQcBAQR8MHowJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBSBggrBgEFBQcwAoZGaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkV4dGVuZGVkVmFsaWRhdGlvblNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAAMIIBfgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdgCkuQmQtBhYFIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAWNBYm0KAAAEAwBHMEUCIQDRZp38cTWsWH2GdBpe%2FuPTWnsu%2Fm4BEC2%2BdIcvSykZYgIgCP5gGv6yzaazxBK2NwGdmmyuEFNSg2pARbMJlUFgU5UAdgBWFAaaL9fC7NP14b1Esj7HRna5vJkRXMDvlJhV1onQ3QAAAWNBYm0tAAAEAwBHMEUCIQCi7omUvYLm0b2LobtEeRAYnlIo7n6JxbYdrtYdmPUWJQIgVgw1AZ51vK9ENinBg22FPxb82TvNDO05T17hxXRC2IYAdgC72d%2B8H4pxtZOUI5eqkntHOFeVCqtS6BqQlmQ2jh7RhQAAAWNBYm3fAAAEAwBHMEUCIQChzdTKUU2N%2BXcqcK0OJYrN8EYynloVxho4yPk6Dq3EPgIgdNH5u8rC3UcslQV4B9o0a0w204omDREGKTVuEpxGeOQwDQYJKoZIhvcNAQELBQADggEBAHAPWpanWOW%2Fip2oJ5grAH8mqQfaunuCVE%2Bvac%2B88lkDK%2FLVdFgl2B6kIHZiYClzKtfczG93hWvKbST4NRNHP9LiaQqdNC17e5vNHnXVUGw%2ByxyjMLGqkgepOnZ2Rb14kcTOGp4i5AuJuuaMwXmCo7jUwPwfLe1NUlVBKqg6LK0Hcq4K0sZnxE8HFxiZ92WpV2AVWjRMEc%2F2z2shNoDvxvFUYyY1Oe67xINkmyQKc%2BygSBZzyLnXSFVWmHr3u5dcaaQGGAR42v6Ydr4iL38Hd4dOiBma%2BFXsXBIqWUjbST4VXmdaol7uzFMojA4zkxQDZAvF5XgJlAFadfySna%2Fteik%3D";
+const multipleCerts2 =
+ "about:certificate?cert=MIIIIDCCBwigAwIBAgIQGk0sGNQUuaOL9Rii2XQ4yjANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZpY2VzMSUwIwYDVQQDExxHb29nbGUgSW50ZXJuZXQgQXV0aG9yaXR5IEczMB4XDTE5MDYxODA4MjE1OFoXDTE5MDkxMDA4MTUwMFowZjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEzARBgNVBAoMCkdvb2dsZSBMTEMxFTATBgNVBAMMDCouZ29vZ2xlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABMRScn8kk6qy3LHVktWZWxm%2FMq4kowlEdxQH40wijThZ%2B%2F5Jrqh6UlWnWuiulNorHH2DEW4OkSKreFoYze7w8O6jggWlMIIFoTATBgNVHSUEDDAKBggrBgEFBQcDATAOBgNVHQ8BAf8EBAMCB4AwggRqBgNVHREEggRhMIIEXYIMKi5nb29nbGUuY29tgg0qLmFuZHJvaWQuY29tghYqLmFwcGVuZ2luZS5nb29nbGUuY29tghIqLmNsb3VkLmdvb2dsZS5jb22CGCouY3Jvd2Rzb3VyY2UuZ29vZ2xlLmNvbYIGKi5nLmNvgg4qLmdjcC5ndnQyLmNvbYIRKi5nY3BjZG4uZ3Z0MS5jb22CCiouZ2dwaHQuY26CFiouZ29vZ2xlLWFuYWx5dGljcy5jb22CCyouZ29vZ2xlLmNhggsqLmdvb2dsZS5jbIIOKi5nb29nbGUuY28uaW6CDiouZ29vZ2xlLmNvLmpwgg4qLmdvb2dsZS5jby51a4IPKi5nb29nbGUuY29tLmFygg8qLmdvb2dsZS5jb20uYXWCDyouZ29vZ2xlLmNvbS5icoIPKi5nb29nbGUuY29tLmNvgg8qLmdvb2dsZS5jb20ubXiCDyouZ29vZ2xlLmNvbS50coIPKi5nb29nbGUuY29tLnZuggsqLmdvb2dsZS5kZYILKi5nb29nbGUuZXOCCyouZ29vZ2xlLmZyggsqLmdvb2dsZS5odYILKi5nb29nbGUuaXSCCyouZ29vZ2xlLm5sggsqLmdvb2dsZS5wbIILKi5nb29nbGUucHSCEiouZ29vZ2xlYWRhcGlzLmNvbYIPKi5nb29nbGVhcGlzLmNughEqLmdvb2dsZWNuYXBwcy5jboIUKi5nb29nbGVjb21tZXJjZS5jb22CESouZ29vZ2xldmlkZW8uY29tggwqLmdzdGF0aWMuY26CDSouZ3N0YXRpYy5jb22CEiouZ3N0YXRpY2NuYXBwcy5jboIKKi5ndnQxLmNvbYIKKi5ndnQyLmNvbYIUKi5tZXRyaWMuZ3N0YXRpYy5jb22CDCoudXJjaGluLmNvbYIQKi51cmwuZ29vZ2xlLmNvbYIWKi55b3V0dWJlLW5vY29va2llLmNvbYINKi55b3V0dWJlLmNvbYIWKi55b3V0dWJlZWR1Y2F0aW9uLmNvbYIRKi55b3V0dWJla2lkcy5jb22CByoueXQuYmWCCyoueXRpbWcuY29tghphbmRyb2lkLmNsaWVudHMuZ29vZ2xlLmNvbYILYW5kcm9pZC5jb22CG2RldmVsb3Blci5hbmRyb2lkLmdvb2dsZS5jboIcZGV2ZWxvcGVycy5hbmRyb2lkLmdvb2dsZS5jboIEZy5jb4IIZ2dwaHQuY26CBmdvby5nbIIUZ29vZ2xlLWFuYWx5dGljcy5jb22CCmdvb2dsZS5jb22CD2dvb2dsZWNuYXBwcy5jboISZ29vZ2xlY29tbWVyY2UuY29tghhzb3VyY2UuYW5kcm9pZC5nb29nbGUuY26CCnVyY2hpbi5jb22CCnd3dy5nb28uZ2yCCHlvdXR1LmJlggt5b3V0dWJlLmNvbYIUeW91dHViZWVkdWNhdGlvbi5jb22CD3lvdXR1YmVraWRzLmNvbYIFeXQuYmUwaAYIKwYBBQUHAQEEXDBaMC0GCCsGAQUFBzAChiFodHRwOi8vcGtpLmdvb2cvZ3NyMi9HVFNHSUFHMy5jcnQwKQYIKwYBBQUHMAGGHWh0dHA6Ly9vY3NwLnBraS5nb29nL0dUU0dJQUczMB0GA1UdDgQWBBT8E5DiGEc7xHswBMF5K5EmFzx6fDAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFHfCuFCaZ3Z2sS3ChtCDoH6mfrpLMCEGA1UdIAQaMBgwDAYKKwYBBAHWeQIFAzAIBgZngQwBAgIwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovL2NybC5wa2kuZ29vZy9HVFNHSUFHMy5jcmwwDQYJKoZIhvcNAQELBQADggEBAGrWCimTdP8%2B6qCqNh1Xza9Wlm%2FGDVb%2BKp0PHUZaNDMThFQQqGn2XVi7ZkhqsxTtMw88Nrl97Bi1OsnNPlabhDwxtRyWkNkLdpFxebRz73CsjyoB3cboH%2FZ8sU9LLwXe%2FIJgMkvT7fznKtKSweWV%2BmAYG%2F3KzaIyLrowYpyOsWaYytPJK7ypuk6yOPxuQcQnelotWpuHUBR3mo3FIW56BPCy20KwqwvWoZe27BNxO%2F11Ym%2FPnric2fWXwgmHdkvVqqssUMFs%2BmG2tS%2FpqnR5yZdQL60xOgDq70mVWYgQT4yUTm7i8qvugvNnuSIjjsbelHgbC8f5%2Fx%2Bo2pEyw%2FDYyKw%3D&cert=MIIGcTCCBVmgAwIBAgIQCHx760AsIFydVjey10GPXTANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNzdXJhbmNlIFNlcnZlciBDQTAeFw0xOTA1MjQwMDAwMDBaFw0yMDA1MjMxMjAwMDBaMHkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRYwFAYDVQQKEw1Ud2l0dGVyLCBJbmMuMQ0wCwYDVQQLEwRhdGxhMRYwFAYDVQQDDA0qLnR3aXR0ZXIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4IL8Mo0RIfgZmVhwMiaq30EfjJzcB1dalwHZb2K6P6LtmEpLs%2Bnqm1FCdfZgKO3u4CAbd5Oc2EaZB5KjhOcEo6GjhGKcLS430y%2FXhqWo6dDWWYal1Ulu7CCvNLir0Q5aQ2m8EJuafK%2BqwxSBCGXiWeT4HXqabyU34i70bQbgBSjvffaHr27HVrD4hxq0DspKTIpf0fc4%2B%2Fs%2FTTbxEmX7FbVgmu3Y3rTpeNXegL2Lp5nrGp1drWpcM6g8PlrlhcWujdD2Sb0BpIO0dFNCmvOwDspKt8Ih7t0Sw3Q7u0EGEGJLt%2BgY7nrBoRm1G0DSBd0Ih4coHzfgoGBPy11atynvLwIDAQABo4IC%2FDCCAvgwHwYDVR0jBBgwFoAUUWj%2FkK8CB3U8zNllZGKiErhZcjswHQYDVR0OBBYEFNFZBVr1ptzC%2FiUkvSIQ8QAGfB5jMCUGA1UdEQQeMByCDSoudHdpdHRlci5jb22CC3R3aXR0ZXIuY29tMA4GA1UdDwEB%2FwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0fBG4wbDA0oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItaGEtc2VydmVyLWc2LmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItaGEtc2VydmVyLWc2LmNybDBMBgNVHSAERTBDMDcGCWCGSAGG%2FWwBATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeBDAECAjCBgwYIKwYBBQUHAQEEdzB1MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTQYIKwYBBQUHMAKGQWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJIaWdoQXNzdXJhbmNlU2VydmVyQ0EuY3J0MAwGA1UdEwEB%2FwQCMAAwggEFBgorBgEEAdZ5AgQCBIH2BIHzAPEAdgDuS723dc5guuFCaR%2Br4Z5mow9%2BX7By2IMAxHuJeqj9ywAAAWrrCDXmAAAEAwBHMEUCIQCSwzRMoifj1DjYLJuMOH%2BZ6coX83bWIgWgWynLUED87wIgFKdipP9ycAE8S9apXJxKQyp0RoA%2Ftca5%2BWHQE5VlF68AdwCHdb%2FnWXz4jEOZX73zbv9WjUdWNv9KtWDBtOr%2FXqCDDwAAAWrrCDakAAAEAwBIMEYCIQCcmFOfp58BDMFZZS%2FRVl2uiY94RcTozBrcmtkpoWhgkgIhAN%2BX3ODViV4HnN2ZpZ383mFaEHIjKACRdWTRL%2BcYA43lMA0GCSqGSIb3DQEBCwUAA4IBAQB8LQLmUzevGtdw%2FXVL8aFrotloF3zsUPb2Q7CONLzlMGrmfv%2BNKDXN9xqPLLzmX4MddOjfpbVcDX1mJkuvuYNhh5AQrsaxcfEgfMcqPOdELA1mHPfk8H5a8Tvno1nF9wQWqkCQjLedjKReivmDOGfs1%2Fl%2FDnrprc0v4f28cWvN7YkJsdqfEGLbJ6SKsAxNbtNn%2Ffi6LxnemjLbcTrZYps11Ex55PtDNc200ejqpbpzHolgAew4KUzsyElaYSvDwkLMdmfwYSI9wgcPmrPBfZ0N12TAfmJJbE%2FkZc0jIOi92A%2FVgZLKvQrxadnBqPzAR%2F2SrZMT5joWa5sHpwl9fg5Z";
+
+// both invalids
+const errorCerts1 = "about:certificate?cert=aa&cert=bb&cert=abc";
+// one invalid and other valid
+const errorCerts2 =
+ "about:certificate?cert=aa&cert=MIIGRjCCBS6gAwIBAgIQDJduPkI49CDWPd%2BG7%2Bu6kDANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5EaWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgxMTA1MDAwMDAwWhcNMTkxMTEzMTIwMDAwWjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxHDAaBgNVBAoTE01vemlsbGEgQ29ycG9yYXRpb24xDzANBgNVBAsTBldlYk9wczEYMBYGA1UEAxMPd3d3Lm1vemlsbGEub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuKruymkkmkqCJh7QjmXlUOBcLFRyw5LG%2FvUUWVrsxC2gsbR8WJq%2BcYoYBpoNVStKrO4U2rBh1GEbccvT6qKOQI%2BpjjDxx9cmRdubGTGp8L0MF1ohVvhIvYLumOEoRDDPU4PvGJjGhek%2FojvedPWe8dhciHkxOC2qPFZvVFMwg1%2Fo%2Fb80147BwZQmzB18mnHsmcyKlpsCN8pxw86uao9Iun8gZQrsllW64rTZlRR56pHdAcuGAoZjYZxwS9Z%2BlvrSjEgrddemWyGGalqyFp1rXlVM1Tf4%2FIYWAQXTgTUN303u3xMjss7QK7eUDsACRxiWPLW9XQDd1c%2ByvaYJKzgJ2wIDAQABo4IC6TCCAuUwHwYDVR0jBBgwFoAUD4BhHIIxYdUvKOeNRji0LOHG2eIwHQYDVR0OBBYEFNpSvSGcN2VT%2FB9TdQ8eXwebo60%2FMCcGA1UdEQQgMB6CD3d3dy5tb3ppbGxhLm9yZ4ILbW96aWxsYS5vcmcwDgYDVR0PAQH%2FBAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBrBgNVHR8EZDBiMC%2BgLaArhilodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc3NjYS1zaGEyLWc2LmNybDAvoC2gK4YpaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nNi5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBAgIwfAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH%2FBAIwADCCAQIGCisGAQQB1nkCBAIEgfMEgfAA7gB1AKS5CZC0GFgUh7sTosxncAo8NZgE%2BRvfuON3zQ7IDdwQAAABZuYWiHwAAAQDAEYwRAIgZnMSH1JdG6NASHWTwD0mlP%2Fzbr0hzP263c02Ym0DU64CIEe4QHJDP47j0b6oTFu6RrZz1NQ9cq8Az1KnMKRuaFAlAHUAh3W%2F51l8%2BIxDmV%2B9827%2FVo1HVjb%2FSrVgwbTq%2F16ggw8AAAFm5haJAgAABAMARjBEAiAxGLXkUaOAkZhXNeNR3pWyahZeKmSaMXadgu18SfK1ZAIgKtwu5eGxK76rgaszLCZ9edBIjuU0DKorzPUuxUXFY0QwDQYJKoZIhvcNAQELBQADggEBAKLJAFO3wuaP5MM%2Fed1lhk5Uc2aDokhcM7XyvdhEKSHbgPhcgMoT9YIVoPa70gNC6KHcwoXu0g8wt7X6Vm1ql%2F68G5q844kFuC6JPl4LVT9mciD%2BVW6bHUSXD9xifL9DqdJ0Ic0SllTlM%2Boq5aAeOxUQGXhXIqj6fSQv9fQN6mXxQIoc%2Fgjxteskq%2FVl8YmY1FIZP9Bh7g27kxZ9GAAGQtjTL03RzKAuSg6yeImYVdQWasc7UPnBXlRAzZ8%2BOJThUbzK16a2CI3Rg4agKSJk%2BuA47h1%2FImmngpFLRb%2FMvRX6H1oWcUuyH6O7PZdl0YpwTpw1THIuqCGl%2FwpPgyQgcTM%3D";
+
+async function checkSubjectName(inputPage, subjectsNameInfo) {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: inputPage,
+ },
+ async function(browser) {
+ await SpecialPowers.spawn(browser, [subjectsNameInfo], async function(
+ subjectsNameInfoExpected
+ ) {
+ let certificateSection = await ContentTaskUtils.waitForCondition(() => {
+ return content.document.querySelector("certificate-section");
+ }, "Certificate section found");
+
+ async function selectTab(tabName, index) {
+ let tabs = certificateSection.shadowRoot.querySelector(
+ ".certificate-tabs"
+ );
+
+ let tab = tabs.querySelector(`.tab[idnumber="${index}"]`);
+ Assert.ok(tab, `Tab at index ${index} found`);
+ Assert.equal(tab.innerText, tabName, `Tab name should be ${tabName}`);
+
+ tab.click();
+ }
+
+ function checkSelectedTab(sectionItemsExpected, index) {
+ let infoGroup = certificateSection.shadowRoot.querySelector(
+ `#panel${index} info-group`
+ );
+ Assert.ok(infoGroup, "infoGroup found");
+
+ let sectionTitle = infoGroup.shadowRoot.querySelector(
+ ".info-group-title"
+ ).innerText;
+ Assert.equal(
+ sectionTitle,
+ "Subject Name",
+ "Subject Name must be the selected item"
+ );
+
+ let infoItems = infoGroup.shadowRoot.querySelectorAll("info-item");
+ Assert.equal(
+ infoItems.length,
+ sectionItemsExpected.length,
+ "sectionItems must be the same length"
+ );
+ }
+
+ for (let i = 0; i < subjectsNameInfoExpected.length; i++) {
+ await selectTab(subjectsNameInfoExpected[i].tabName, i);
+ checkSelectedTab(subjectsNameInfoExpected[i].sectionItems, i);
+ }
+ });
+ }
+ );
+}
+
+async function checkTabsName(inputPage, tabsNames) {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: inputPage,
+ },
+ async function(browser) {
+ await SpecialPowers.spawn(browser, [tabsNames], async function(
+ expectedTabsNames
+ ) {
+ let certificateSection = await ContentTaskUtils.waitForCondition(() => {
+ return content.document.querySelector("certificate-section");
+ }, "Certificate section found");
+
+ let tabsSection = certificateSection.shadowRoot.querySelector(
+ ".certificate-tabs"
+ );
+ Assert.ok(tabsSection, "Tabs section found");
+
+ let tabs = tabsSection.children;
+ Assert.equal(
+ tabs.length,
+ expectedTabsNames.length,
+ `There must be ${expectedTabsNames.length} tabs`
+ );
+
+ for (let i = 0; i < expectedTabsNames.length; i++) {
+ Assert.equal(
+ tabs[i].innerText,
+ expectedTabsNames[i],
+ "Tab name must be equal to expected tab name"
+ );
+ if (i === 0) {
+ Assert.ok(
+ tabs[i].className.includes("selected"),
+ "First tab must be selected"
+ );
+ } else {
+ Assert.equal(
+ tabs[i].className.includes("selected"),
+ false,
+ "Just the first tab must be selected"
+ );
+ }
+ }
+ });
+ }
+ );
+}
+
+async function checkDOM(inputPage, errorExpected) {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: inputPage,
+ },
+ async function(browser) {
+ await SpecialPowers.spawn(browser, [errorExpected], async function(
+ errorExpected
+ ) {
+ let certificateSection = await ContentTaskUtils.waitForCondition(() => {
+ return content.document.querySelector("certificate-section");
+ }, "Certificate section found");
+
+ let errorSection = certificateSection.shadowRoot.querySelector(
+ "error-section"
+ );
+
+ if (errorExpected) {
+ // should render error page
+ Assert.ok(errorSection, "Error section found");
+ } else {
+ // should render page with certificate info
+ Assert.equal(errorSection, null, "Error section was not found");
+ }
+ });
+ }
+ );
+}
+
+add_task(async function runTests() {
+ let inputs = [
+ {
+ url: multipleCerts1,
+ tabsNames: ["www.mozilla.org", "github.com"],
+ errorPageExpected: false,
+ subjectNameInfo: [
+ {
+ tabName: "www.mozilla.org",
+ sectionTitle: "Subject Name",
+ sectionItems: [
+ { label: "Country", info: "US" },
+ { label: "State / Province", info: "California" },
+ { label: "Locality", info: "Mountain View" },
+ { label: "Organization", info: "Mozilla Corporation" },
+ { label: "Organizational Unit", info: "WebOps" },
+ { label: "Common Name", info: "www.mozilla.org" },
+ ],
+ },
+ {
+ tabName: "github.com",
+ sectionTitle: "Subject Name",
+ sectionItems: [
+ { label: "Business Category", info: "Private Organization" },
+ { label: "Inc. Country", info: "US" },
+ { label: "Inc. State / Province", info: "Delaware" },
+ { label: "Serial Number", info: "5157550" },
+ { label: "Country", info: "US" },
+ { label: "State / Province", info: "California" },
+ { label: "Locality", info: "San Francisco" },
+ { label: "Organization", info: "GitHub, Inc." },
+ { label: "Common Name", info: "github.com" },
+ ],
+ },
+ ],
+ },
+ {
+ url: multipleCerts2,
+ tabsNames: ["*.google.com", "*.twitter.com"],
+ errorPageExpected: false,
+ subjectNameInfo: [
+ {
+ tabName: "*.google.com",
+ sectionTitle: "Subject Name",
+ sectionItems: [
+ { label: "Country", info: "US" },
+ { label: "State / Province", info: "California" },
+ { label: "Locality", info: "Mountain View" },
+ { label: "Organization", info: "Google LLC" },
+ { label: "Common Name", info: "*.google.com" },
+ ],
+ },
+ {
+ tabName: "*.twitter.com",
+ sectionTitle: "Subject Name",
+ sectionItems: [
+ { label: "Country", info: "US" },
+ { label: "State / Province", info: "California" },
+ { label: "Locality", info: "San Francisco" },
+ { label: "Organization", info: "Twitter, Inc." },
+ { label: "Organizational Unit", info: "atla" },
+ { label: "Common Name", info: "*.twitter.com" },
+ ],
+ },
+ ],
+ },
+ {
+ url: errorCerts1,
+ tabsNames: [],
+ errorPageExpected: true,
+ },
+ {
+ url: errorCerts2,
+ tabsNames: [],
+ errorPageExpected: true,
+ },
+ ];
+
+ for (let input of inputs) {
+ await checkDOM(input.url, input.errorPageExpected);
+ if (!input.errorPageExpected) {
+ await checkTabsName(input.url, input.tabsNames);
+ await checkSubjectName(input.url, input.subjectNameInfo);
+ }
+ }
+});
diff --git a/toolkit/components/certviewer/tests/browser/browser_openTabAndSendCertInfo.js b/toolkit/components/certviewer/tests/browser/browser_openTabAndSendCertInfo.js
new file mode 100644
index 0000000000..ff1ce831b0
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser_openTabAndSendCertInfo.js
@@ -0,0 +1,262 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const { ContentTaskUtils } = ChromeUtils.import(
+ "resource://testing-common/ContentTaskUtils.jsm"
+);
+const TEST_CERT_BASE64 =
+ "MIIGRjCCBS6gAwIBAgIQDJduPkI49CDWPd+G7+u6kDANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5EaWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgxMTA1MDAwMDAwWhcNMTkxMTEzMTIwMDAwWjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxHDAaBgNVBAoTE01vemlsbGEgQ29ycG9yYXRpb24xDzANBgNVBAsTBldlYk9wczEYMBYGA1UEAxMPd3d3Lm1vemlsbGEub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuKruymkkmkqCJh7QjmXlUOBcLFRyw5LG/vUUWVrsxC2gsbR8WJq+cYoYBpoNVStKrO4U2rBh1GEbccvT6qKOQI+pjjDxx9cmRdubGTGp8L0MF1ohVvhIvYLumOEoRDDPU4PvGJjGhek/ojvedPWe8dhciHkxOC2qPFZvVFMwg1/o/b80147BwZQmzB18mnHsmcyKlpsCN8pxw86uao9Iun8gZQrsllW64rTZlRR56pHdAcuGAoZjYZxwS9Z+lvrSjEgrddemWyGGalqyFp1rXlVM1Tf4/IYWAQXTgTUN303u3xMjss7QK7eUDsACRxiWPLW9XQDd1c+yvaYJKzgJ2wIDAQABo4IC6TCCAuUwHwYDVR0jBBgwFoAUD4BhHIIxYdUvKOeNRji0LOHG2eIwHQYDVR0OBBYEFNpSvSGcN2VT/B9TdQ8eXwebo60/MCcGA1UdEQQgMB6CD3d3dy5tb3ppbGxhLm9yZ4ILbW96aWxsYS5vcmcwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBrBgNVHR8EZDBiMC+gLaArhilodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc3NjYS1zaGEyLWc2LmNybDAvoC2gK4YpaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nNi5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBAgIwfAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH/BAIwADCCAQIGCisGAQQB1nkCBAIEgfMEgfAA7gB1AKS5CZC0GFgUh7sTosxncAo8NZgE+RvfuON3zQ7IDdwQAAABZuYWiHwAAAQDAEYwRAIgZnMSH1JdG6NASHWTwD0mlP/zbr0hzP263c02Ym0DU64CIEe4QHJDP47j0b6oTFu6RrZz1NQ9cq8Az1KnMKRuaFAlAHUAh3W/51l8+IxDmV+9827/Vo1HVjb/SrVgwbTq/16ggw8AAAFm5haJAgAABAMARjBEAiAxGLXkUaOAkZhXNeNR3pWyahZeKmSaMXadgu18SfK1ZAIgKtwu5eGxK76rgaszLCZ9edBIjuU0DKorzPUuxUXFY0QwDQYJKoZIhvcNAQELBQADggEBAKLJAFO3wuaP5MM/ed1lhk5Uc2aDokhcM7XyvdhEKSHbgPhcgMoT9YIVoPa70gNC6KHcwoXu0g8wt7X6Vm1ql/68G5q844kFuC6JPl4LVT9mciD+VW6bHUSXD9xifL9DqdJ0Ic0SllTlM+oq5aAeOxUQGXhXIqj6fSQv9fQN6mXxQIoc/gjxteskq/Vl8YmY1FIZP9Bh7g27kxZ9GAAGQtjTL03RzKAuSg6yeImYVdQWasc7UPnBXlRAzZ8+OJThUbzK16a2CI3Rg4agKSJk+uA47h1/ImmngpFLRb/MvRX6H1oWcUuyH6O7PZdl0YpwTpw1THIuqCGl/wpPgyQgcTM=";
+
+function checkSpec(spec) {
+ Assert.ok(
+ spec.startsWith("about:certificate"),
+ "about:certificate was opened"
+ );
+
+ let newUrl = new URL(spec);
+ let certEncoded = newUrl.searchParams.get("cert");
+ let certDecoded = decodeURIComponent(certEncoded);
+ Assert.equal(
+ btoa(atob(certDecoded)),
+ certDecoded,
+ "We received an base64 string"
+ );
+}
+
+function checksCertTab(tabsCount) {
+ Assert.equal(gBrowser.tabs.length, tabsCount + 1, "New tab was opened");
+ let spec = gBrowser.tabs[tabsCount].linkedBrowser.documentURI.spec;
+ checkSpec(spec);
+}
+
+async function checkCertChain() {
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function() {
+ let certificateTabs;
+ await ContentTaskUtils.waitForCondition(() => {
+ certificateTabs = content.document
+ .querySelector("certificate-section")
+ .shadowRoot.querySelectorAll(".certificate-tab");
+ return certificateTabs.length;
+ }, "Found certificate tabs.");
+
+ Assert.greaterOrEqual(
+ certificateTabs.length,
+ 1,
+ "Certificate chain tabs shown"
+ );
+ });
+}
+
+// taken from https://searchfox.org/mozilla-central/rev/7ed8e2d3d1d7a1464ba42763a33fd2e60efcaedc/security/manager/ssl/tests/mochitest/browser/browser_downloadCert_ui.js#47
+function openCertDownloadDialog(cert) {
+ let returnVals = Cc["@mozilla.org/hash-property-bag;1"].createInstance(
+ Ci.nsIWritablePropertyBag2
+ );
+ let win = window.openDialog(
+ "chrome://pippki/content/downloadcert.xhtml",
+ "",
+ "",
+ cert,
+ returnVals
+ );
+ return new Promise((resolve, reject) => {
+ win.addEventListener(
+ "load",
+ function() {
+ executeSoon(() => resolve([win]));
+ },
+ { once: true }
+ );
+ });
+}
+
+add_task(async function openFromPopUp() {
+ info("Testing openFromPopUp");
+
+ const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
+ Ci.nsIX509CertDB
+ );
+ let cert = certdb.constructX509FromBase64(TEST_CERT_BASE64);
+
+ let [win] = await openCertDownloadDialog(cert);
+ let viewCertButton = win.document.getElementById("viewC-button");
+ let newWinOpened = BrowserTestUtils.waitForNewWindow();
+ viewCertButton.click();
+
+ let topWin = await newWinOpened;
+ let browser = topWin.gBrowser.selectedBrowser;
+
+ // We're racing against messages sent up from the content process that
+ // loads about:certificate. It may or may not have had the opportunity
+ // to tell the parent that it had loaded the page yet. If not, we wait
+ // for the page to load.
+ //
+ // Note that we can't use the URL parameter for
+ // BrowserTestUtils.waitForNewWindow, since we need to use a function
+ // to choose the right URL.
+ if (!browser.currentURI.spec.startsWith("about:certificate")) {
+ await BrowserTestUtils.browserLoaded(browser, false, spec =>
+ spec.startsWith("about:certificate")
+ );
+ }
+
+ let spec = browser.currentURI.spec;
+ checkSpec(spec);
+
+ await BrowserTestUtils.closeWindow(topWin); // closes about:certificate
+ win.document.getElementById("download_cert").cancelDialog();
+ await BrowserTestUtils.windowClosed(win);
+});
+
+add_task(async function testBadCert() {
+ info("Testing bad cert");
+
+ let tab = await openErrorPage();
+
+ let tabsCount = gBrowser.tabs.length;
+ let loaded = BrowserTestUtils.waitForNewTab(gBrowser, null, true);
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function() {
+ let advancedButton = content.document.getElementById("advancedButton");
+ Assert.ok(advancedButton, "advancedButton found");
+ Assert.equal(
+ advancedButton.hasAttribute("disabled"),
+ false,
+ "advancedButton should be clickable"
+ );
+ advancedButton.click();
+ let viewCertificate = content.document.getElementById("viewCertificate");
+ Assert.ok(viewCertificate, "viewCertificate found");
+ Assert.equal(
+ viewCertificate.hasAttribute("disabled"),
+ false,
+ "viewCertificate should be clickable"
+ );
+
+ viewCertificate.click();
+ });
+ await loaded;
+ checksCertTab(tabsCount);
+
+ gBrowser.removeCurrentTab(); // closes about:certificate
+ gBrowser.removeCurrentTab(); // closes https://expired.example.com/
+});
+
+add_task(async function testBadCertIframe() {
+ info("Testing bad cert in an iframe");
+
+ let tab = await openErrorPage(true);
+
+ let tabsCount = gBrowser.tabs.length;
+ let loaded = BrowserTestUtils.waitForNewTab(gBrowser, null, true);
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function() {
+ let doc = content.document.querySelector("iframe").contentDocument;
+ let advancedButton = doc.getElementById("advancedButton");
+ Assert.ok(advancedButton, "advancedButton found");
+ Assert.equal(
+ advancedButton.hasAttribute("disabled"),
+ false,
+ "advancedButton should be clickable"
+ );
+ advancedButton.click();
+ let viewCertificate = doc.getElementById("viewCertificate");
+ Assert.ok(viewCertificate, "viewCertificate found");
+ Assert.equal(
+ viewCertificate.hasAttribute("disabled"),
+ false,
+ "viewCertificate should be clickable"
+ );
+
+ viewCertificate.click();
+ });
+ await loaded;
+ checksCertTab(tabsCount);
+
+ gBrowser.removeCurrentTab(); // closes about:certificate
+ gBrowser.removeCurrentTab(); // closes https://expired.example.com/
+});
+
+add_task(async function testGoodCert() {
+ info("Testing page info");
+ let url = "https://example.com/";
+
+ let tabsCount = gBrowser.tabs.length;
+
+ info(`Loading ${url}`);
+ await BrowserTestUtils.withNewTab({ gBrowser, url }, async function() {
+ info("Opening pageinfo");
+ let pageInfo = BrowserPageInfo(url, "securityTab", {});
+ await BrowserTestUtils.waitForEvent(pageInfo, "load");
+
+ let securityTab = pageInfo.document.getElementById("securityTab");
+ await TestUtils.waitForCondition(
+ () => BrowserTestUtils.is_visible(securityTab),
+ "Security tab should be visible."
+ );
+ Assert.ok(securityTab, "Security tab is available");
+ let viewCertButton = pageInfo.document.getElementById("security-view-cert");
+ await TestUtils.waitForCondition(
+ () => BrowserTestUtils.is_visible(viewCertButton),
+ "view cert button should be visible."
+ );
+
+ let loaded = BrowserTestUtils.waitForNewTab(gBrowser, null, true);
+ checkAndClickButton(pageInfo.document, "security-view-cert");
+ await loaded;
+
+ pageInfo.close();
+ });
+ checksCertTab(tabsCount);
+
+ gBrowser.removeCurrentTab(); // closes about:certificate
+});
+
+add_task(async function testPreferencesCert() {
+ info("Testing preferences cert");
+ let url = "about:preferences#privacy";
+
+ let tabsCount;
+
+ info(`Loading ${url}`);
+ await BrowserTestUtils.withNewTab({ gBrowser, url }, async function(browser) {
+ tabsCount = gBrowser.tabs.length;
+ checkAndClickButton(browser.contentDocument, "viewCertificatesButton");
+
+ let certDialogLoaded = promiseLoadSubDialog(
+ "chrome://pippki/content/certManager.xhtml"
+ );
+ let dialogWin = await certDialogLoaded;
+ let doc = dialogWin.document;
+ Assert.ok(doc, "doc loaded");
+
+ doc.getElementById("certmanagertabs").selectedTab = doc.getElementById(
+ "mine_tab"
+ );
+ let treeView = doc.getElementById("user-tree").view;
+ let selectedCert;
+ // See https://searchfox.org/mozilla-central/rev/40ef22080910c2e2c27d9e2120642376b1d8b8b2/browser/components/preferences/in-content/tests/browser_cert_export.js#41
+ for (let i = 0; i < treeView.rowCount; i++) {
+ treeView.selection.select(i);
+ dialogWin.getSelectedCerts();
+ let certs = dialogWin.selected_certs;
+ if (certs && certs[0]) {
+ selectedCert = certs[0];
+ break;
+ }
+ }
+ Assert.ok(selectedCert, "A cert should be selected");
+ let viewButton = doc.getElementById("mine_viewButton");
+ Assert.equal(viewButton.disabled, false, "Should enable view button");
+
+ let loaded = BrowserTestUtils.waitForNewTab(gBrowser, null, true);
+ viewButton.click();
+ await loaded;
+
+ checksCertTab(tabsCount);
+ await checkCertChain();
+ });
+ gBrowser.removeCurrentTab(); // closes about:certificate
+});
diff --git a/toolkit/components/certviewer/tests/browser/browser_renderCertToUI.js b/toolkit/components/certviewer/tests/browser/browser_renderCertToUI.js
new file mode 100644
index 0000000000..a8666a652b
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/browser_renderCertToUI.js
@@ -0,0 +1,184 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const url =
+ "about:certificate?cert=MIIHQjCCBiqgAwIBAgIQCgYwQn9bvO1pVzllk7ZFHzANBgkqhkiG9w0BAQsFADB1MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTQwMgYDVQQDEytEaWdpQ2VydCBTSEEyIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VydmVyIENBMB4XDTE4MDUwODAwMDAwMFoXDTIwMDYwMzEyMDAwMFowgccxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQITCERlbGF3YXJlMRAwDgYDVQQFEwc1MTU3NTUwMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRMwEQYDVQQDEwpnaXRodWIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxjyq8jyXDDrBTyitcnB90865tWBzpHSbindG%2FXqYQkzFMBlXmqkzC%2BFdTRBYyneZw5Pz%2BXWQvL%2B74JW6LsWNc2EF0xCEqLOJuC9zjPAqbr7uroNLghGxYf13YdqbG5oj%2F4x%2BogEG3dF%2FU5YIwVr658DKyESMV6eoYV9mDVfTuJastkqcwero%2B5ZAKfYVMLUEsMwFtoTDJFmVf6JlkOWwsxp1WcQ%2FMRQK1cyqOoUFUgYylgdh3yeCDPeF22Ax8AlQxbcaI%2BGwfQL1FB7Jy%2Bh%2BKjME9lE%2FUpgV6Qt2R1xNSmvFCBWu%2BNFX6epwFP%2FJRbkMfLz0beYFUvmMgLtwVpEPSwIDAQABo4IDeTCCA3UwHwYDVR0jBBgwFoAUPdNQpdagre7zSmAKZdMh1Pj41g8wHQYDVR0OBBYEFMnCU2FmnV%2BrJfQmzQ84mqhJ6kipMCUGA1UdEQQeMByCCmdpdGh1Yi5jb22CDnd3dy5naXRodWIuY29tMA4GA1UdDwEB%2FwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0fBG4wbDA0oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItZXYtc2VydmVyLWcyLmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItZXYtc2VydmVyLWcyLmNybDBLBgNVHSAERDBCMDcGCWCGSAGG%2FWwCATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAcGBWeBDAEBMIGIBggrBgEFBQcBAQR8MHowJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBSBggrBgEFBQcwAoZGaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkV4dGVuZGVkVmFsaWRhdGlvblNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAAMIIBfgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdgCkuQmQtBhYFIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAWNBYm0KAAAEAwBHMEUCIQDRZp38cTWsWH2GdBpe%2FuPTWnsu%2Fm4BEC2%2BdIcvSykZYgIgCP5gGv6yzaazxBK2NwGdmmyuEFNSg2pARbMJlUFgU5UAdgBWFAaaL9fC7NP14b1Esj7HRna5vJkRXMDvlJhV1onQ3QAAAWNBYm0tAAAEAwBHMEUCIQCi7omUvYLm0b2LobtEeRAYnlIo7n6JxbYdrtYdmPUWJQIgVgw1AZ51vK9ENinBg22FPxb82TvNDO05T17hxXRC2IYAdgC72d%2B8H4pxtZOUI5eqkntHOFeVCqtS6BqQlmQ2jh7RhQAAAWNBYm3fAAAEAwBHMEUCIQChzdTKUU2N%2BXcqcK0OJYrN8EYynloVxho4yPk6Dq3EPgIgdNH5u8rC3UcslQV4B9o0a0w204omDREGKTVuEpxGeOQwDQYJKoZIhvcNAQELBQADggEBAHAPWpanWOW%2Fip2oJ5grAH8mqQfaunuCVE%2Bvac%2B88lkDK%2FLVdFgl2B6kIHZiYClzKtfczG93hWvKbST4NRNHP9LiaQqdNC17e5vNHnXVUGw%2ByxyjMLGqkgepOnZ2Rb14kcTOGp4i5AuJuuaMwXmCo7jUwPwfLe1NUlVBKqg6LK0Hcq4K0sZnxE8HFxiZ92WpV2AVWjRMEc%2F2z2shNoDvxvFUYyY1Oe67xINkmyQKc%2BygSBZzyLnXSFVWmHr3u5dcaaQGGAR42v6Ydr4iL38Hd4dOiBma%2BFXsXBIqWUjbST4VXmdaol7uzFMojA4zkxQDZAvF5XgJlAFadfySna%2Fteik%3D";
+
+/* import-globals-from ./adjustedCerts.js */
+Services.scriptloader.loadSubScript(
+ "chrome://mochitests/content/browser/toolkit/components/certviewer/tests/browser/adjustedCerts.js",
+ this
+);
+
+add_task(async function test() {
+ Assert.ok(adjustedCerts, "adjustedCerts found");
+
+ let tabName = adjustedCerts[0].tabName;
+ let certItems = adjustedCerts[0].certItems;
+
+ await BrowserTestUtils.withNewTab(url, async function(browser) {
+ await SpecialPowers.spawn(browser, [[certItems, tabName]], async function([
+ adjustedCerts,
+ expectedTabName,
+ ]) {
+ let certificateSection = await ContentTaskUtils.waitForCondition(() => {
+ return content.document.querySelector("certificate-section");
+ }, "Certificate section found");
+
+ let infoGroups = certificateSection.shadowRoot.querySelectorAll(
+ "info-group"
+ );
+ Assert.ok(infoGroups, "infoGroups found");
+ Assert.equal(
+ infoGroups.length,
+ adjustedCerts.length,
+ "infoGroups must have the same length of adjustedCerts"
+ );
+
+ let tabName = certificateSection.shadowRoot.querySelector(
+ ".tab[idnumber='0']"
+ ).textContent;
+ Assert.equal(tabName, expectedTabName, "Tab name should be the same");
+
+ function getElementByAttribute(source, property, target) {
+ for (let elem of source) {
+ if (elem.hasOwnProperty(property) && elem[property] === target) {
+ return elem;
+ }
+ }
+ return null;
+ }
+
+ function checkBooleans(got, expected) {
+ info(
+ "If adjustedCertElments returned true, this value should be Yes, otherwise it should be No"
+ );
+ let gotBool;
+ if (got === "Yes") {
+ gotBool = true;
+ } else if (got === "No") {
+ gotBool = false;
+ } else {
+ gotBool = null;
+ }
+ Assert.equal(gotBool, expected, `Expected ${expected}, got ${gotBool}`);
+ }
+
+ for (let infoGroup of infoGroups) {
+ let sectionId = infoGroup.shadowRoot
+ .querySelector(".info-group-title")
+ .getAttribute("data-l10n-id")
+ .replace("certificate-viewer-", "");
+
+ let adjustedCertsElem = getElementByAttribute(
+ adjustedCerts,
+ "sectionId",
+ sectionId
+ );
+ Assert.ok(adjustedCertsElem, "The element exists in adjustedCerts");
+
+ let infoItems = infoGroup.shadowRoot.querySelectorAll("info-item");
+ Assert.equal(
+ infoItems.length,
+ adjustedCertsElem.sectionItems.length,
+ "sectionItems must be the same length"
+ );
+
+ let i = 0;
+ // Message ID mappings
+ let stringMapping = {
+ signaturealgorithm: "signature-algorithm",
+ };
+ for (let infoItem of infoItems) {
+ let infoItemLabel = infoItem.shadowRoot
+ .querySelector("label")
+ .getAttribute("data-l10n-id");
+ let infoElem = infoItem.shadowRoot.querySelector(".info");
+ let infoItemInfo = infoElem.textContent;
+ let adjustedCertsElemLabel =
+ adjustedCertsElem.sectionItems[i].labelId;
+ let adjustedCertsElemInfo = adjustedCertsElem.sectionItems[i].info;
+
+ if (adjustedCertsElemLabel == null) {
+ adjustedCertsElemLabel = "";
+ }
+ adjustedCertsElemLabel = adjustedCertsElemLabel
+ .replace(/\s+/g, "-")
+ .replace(/\./g, "")
+ .replace(/\//g, "")
+ .replace(/--/g, "-")
+ .toLowerCase();
+ adjustedCertsElemLabel =
+ stringMapping[adjustedCertsElemLabel] || adjustedCertsElemLabel;
+
+ if (adjustedCertsElemInfo == null) {
+ adjustedCertsElemInfo = "";
+ }
+ if (typeof adjustedCertsElemInfo === "boolean") {
+ checkBooleans(infoItemInfo, adjustedCertsElemInfo);
+ continue;
+ }
+
+ if (
+ adjustedCertsElemLabel === "timestamp" ||
+ adjustedCertsElemLabel === "not-after" ||
+ adjustedCertsElemLabel === "not-before"
+ ) {
+ Assert.equal(
+ infoElem.textContent,
+ adjustedCertsElemInfo.utc,
+ "Timestamps must be equal"
+ );
+ i++;
+ continue;
+ }
+ if (adjustedCertsElemLabel === "download") {
+ Assert.equal(infoElem.children.length, 2, "Should have 2 links.");
+ for (let kid of infoElem.children) {
+ Assert.equal(kid.localName, "a", "Should get a cert/chain link.");
+ Assert.ok(
+ kid.download.endsWith("pem"),
+ "Link `download` attribute should point to pem file."
+ );
+ Assert.ok(
+ kid.dataset.l10nId.includes("pem"),
+ "Link should be labeled"
+ );
+ Assert.equal(
+ kid.dataset.l10nId.includes("chain"),
+ kid.download.includes("chain"),
+ "Download label and filename should match"
+ );
+ }
+ // Remaining tests in browser_downloadLink.js
+
+ i++;
+ continue;
+ }
+
+ if (Array.isArray(adjustedCertsElemInfo)) {
+ // there is a case where we have a boolean
+ adjustedCertsElemInfo = adjustedCertsElemInfo
+ .toString()
+ .replace(/,/g, ", ");
+ }
+
+ Assert.ok(
+ infoItemLabel.includes(adjustedCertsElemLabel),
+ "data-l10n-id must contain the original label"
+ );
+
+ Assert.equal(
+ infoItemInfo,
+ adjustedCertsElemInfo,
+ "Info must be equal"
+ );
+
+ i++;
+ }
+ }
+ });
+ });
+});
diff --git a/toolkit/components/certviewer/tests/browser/dummy_page.html b/toolkit/components/certviewer/tests/browser/dummy_page.html
new file mode 100644
index 0000000000..1a87e28408
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/dummy_page.html
@@ -0,0 +1,9 @@
+<html>
+<head>
+<title>Dummy test page</title>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
+</head>
+<body>
+<p>Dummy test page</p>
+</body>
+</html>
diff --git a/toolkit/components/certviewer/tests/browser/head.js b/toolkit/components/certviewer/tests/browser/head.js
new file mode 100644
index 0000000000..f0e515a76b
--- /dev/null
+++ b/toolkit/components/certviewer/tests/browser/head.js
@@ -0,0 +1,125 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+function checkAndClickButton(document, id) {
+ let button = document.getElementById(id);
+ Assert.ok(button, `${id} button found`);
+ Assert.equal(
+ button.hasAttribute("disabled"),
+ false,
+ "button should be clickable"
+ );
+ button.click();
+}
+
+function is_element_visible(aElement, aMsg) {
+ isnot(aElement, null, "Element should not be null, when checking visibility");
+ Assert.ok(!BrowserTestUtils.is_hidden(aElement), aMsg);
+}
+
+// Extracted from https://searchfox.org/mozilla-central/rev/40ef22080910c2e2c27d9e2120642376b1d8b8b2/browser/components/preferences/in-content/tests/head.js#41
+function promiseLoadSubDialog(aURL) {
+ return new Promise((resolve, reject) => {
+ content.gSubDialog._dialogStack.addEventListener(
+ "dialogopen",
+ function dialogopen(aEvent) {
+ if (
+ aEvent.detail.dialog._frame.contentWindow.location == "about:blank"
+ ) {
+ return;
+ }
+ content.gSubDialog._dialogStack.removeEventListener(
+ "dialogopen",
+ dialogopen
+ );
+
+ Assert.equal(
+ aEvent.detail.dialog._frame.contentWindow.location.toString(),
+ aURL,
+ "Check the proper URL is loaded"
+ );
+
+ // Check visibility
+ is_element_visible(aEvent.detail.dialog._overlay, "Overlay is visible");
+
+ // Check that stylesheets were injected
+ let expectedStyleSheetURLs = aEvent.detail.dialog._injectedStyleSheets.slice(
+ 0
+ );
+ for (let styleSheet of aEvent.detail.dialog._frame.contentDocument
+ .styleSheets) {
+ let i = expectedStyleSheetURLs.indexOf(styleSheet.href);
+ if (i >= 0) {
+ info("found " + styleSheet.href);
+ expectedStyleSheetURLs.splice(i, 1);
+ }
+ }
+ Assert.equal(
+ expectedStyleSheetURLs.length,
+ 0,
+ "All expectedStyleSheetURLs should have been found"
+ );
+
+ // Wait for the next event tick to make sure the remaining part of the
+ // testcase runs after the dialog gets ready for input.
+ executeSoon(() => resolve(aEvent.detail.dialog._frame.contentWindow));
+ }
+ );
+ });
+}
+
+function injectErrorPageFrame(tab, src) {
+ return SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [{ frameSrc: src }],
+ async function({ frameSrc }) {
+ let loaded = ContentTaskUtils.waitForEvent(
+ content.wrappedJSObject,
+ "DOMFrameContentLoaded"
+ );
+ let iframe = content.document.createElement("iframe");
+ iframe.src = frameSrc;
+ content.document.body.appendChild(iframe);
+ await loaded;
+ // We will have race conditions when accessing the frame content after setting a src,
+ // so we can't wait for AboutNetErrorLoad. Let's wait for the certerror class to
+ // appear instead (which should happen at the same time as AboutNetErrorLoad).
+ await ContentTaskUtils.waitForCondition(() =>
+ iframe.contentDocument.body.classList.contains("certerror")
+ );
+ }
+ );
+}
+
+async function openErrorPage(useFrame = false) {
+ let src = "https://expired.example.com/";
+ let dummyPage =
+ getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ "https://example.com"
+ ) + "dummy_page.html";
+
+ let tab;
+ if (useFrame) {
+ info("Loading cert error page in an iframe");
+ tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, dummyPage);
+ await injectErrorPageFrame(tab, src);
+ } else {
+ let certErrorLoaded;
+ tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ () => {
+ gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, src);
+ let browser = gBrowser.selectedBrowser;
+ certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
+ },
+ false
+ );
+ info("Loading and waiting for the cert error");
+ await certErrorLoaded;
+ }
+
+ return tab;
+}
diff --git a/toolkit/components/certviewer/tests/chrome/.eslintrc.js b/toolkit/components/certviewer/tests/chrome/.eslintrc.js
new file mode 100644
index 0000000000..f811aa790b
--- /dev/null
+++ b/toolkit/components/certviewer/tests/chrome/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+ parserOptions: {
+ sourceType: "module",
+ },
+};
diff --git a/toolkit/components/certviewer/tests/chrome/CSoutput.js b/toolkit/components/certviewer/tests/chrome/CSoutput.js
new file mode 100644
index 0000000000..c036d847ba
--- /dev/null
+++ b/toolkit/components/certviewer/tests/chrome/CSoutput.js
@@ -0,0 +1,147 @@
+export const certOutputCS = [
+ {
+ ext: {
+ aia: {
+ descriptions: [
+ {
+ location: "http://ocsp.digicert.com",
+ method: "Online Certificate Status Protocol (OCSP)",
+ },
+ {
+ location:
+ "http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt",
+ method: "CA Issuers",
+ },
+ ],
+ critical: false,
+ },
+ aKID: {
+ critical: false,
+ id: "0F:80:61:1C:82:31:61:D5:2F:28:E7:8D:46:38:B4:2C:E1:C6:D9:E2",
+ },
+ basicConstraints: { cA: false, critical: true },
+ crlPoints: {
+ critical: false,
+ points: [
+ "http://crl3.digicert.com/ssca-sha2-g6.crl",
+ "http://crl4.digicert.com/ssca-sha2-g6.crl",
+ ],
+ },
+ cp: {
+ critical: false,
+ policies: [
+ {
+ id: "2.16.840",
+ name: "ANSI Organizational Identifier",
+ qualifiers: [
+ {
+ id: "1.3.6.1.5.5.7.2.1",
+ name: "Practices Statement",
+ value: "https://www.digicert.com/CPS",
+ },
+ ],
+ value: "2.16.840.1.114412.1.1",
+ },
+ {
+ id: "2.23.140.1.2.2",
+ name: "Certificate Type",
+ value: "Organization Validation",
+ },
+ ],
+ },
+ eKeyUsages: {
+ critical: false,
+ purposes: ["Server Authentication", "Client Authentication"],
+ },
+ keyUsages: {
+ critical: true,
+ purposes: ["Digital Signature", "Key Encipherment"],
+ },
+ msCrypto: { exists: false },
+ ocspStaple: { critical: false, required: false },
+ scts: {
+ critical: false,
+ timestamps: [
+ {
+ logId:
+ "A4:B9:09:90:B4:18:58:14:87:BB:13:A2:CC:67:70:0A:3C:35:98:04:F9:1B:DF:B8:E3:77:CD:0E:C8:0D:DC:10",
+ name: "Google “Pilot”",
+ signatureAlgorithm: "SHA-256 ECDSA",
+ timestamp: "11/5/2018, 8:55:28 PM (Brasilia Standard Time)",
+ timestampUTC: "Mon, 05 Nov 2018 22:55:28 GMT",
+ version: 1,
+ },
+ {
+ logId:
+ "87:75:BF:E7:59:7C:F8:8C:43:99:5F:BD:F3:6E:FF:56:8D:47:56:36:FF:4A:B5:60:C1:B4:EA:FF:5E:A0:83:0F",
+ name: "DigiCert Server 2",
+ signatureAlgorithm: "SHA-256 ECDSA",
+ timestamp: "11/5/2018, 8:55:28 PM (Brasilia Standard Time)",
+ timestampUTC: "Mon, 05 Nov 2018 22:55:28 GMT",
+ version: 1,
+ },
+ ],
+ },
+ sKID: {
+ critical: false,
+ id: "DA:52:BD:21:9C:37:65:53:FC:1F:53:75:0F:1E:5F:07:9B:A3:AD:3F",
+ },
+ san: {
+ altNames: [
+ ["DNS Name", "www.mozilla.org"],
+ ["DNS Name", "mozilla.org"],
+ ],
+ critical: false,
+ },
+ },
+ files: {
+ pem:
+ "-----BEGIN%20CERTIFICATE-----%0D%0AMIIGRjCCBS6gAwIBAgIQDJduPkI49CDWPd+G7+u6kDANBgkqhkiG9w0BAQsFADBN%0D%0AMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E%0D%0AaWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgxMTA1MDAwMDAwWhcN%0D%0AMTkxMTEzMTIwMDAwWjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3Ju%0D%0AaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxHDAaBgNVBAoTE01vemlsbGEgQ29y%0D%0AcG9yYXRpb24xDzANBgNVBAsTBldlYk9wczEYMBYGA1UEAxMPd3d3Lm1vemlsbGEu%0D%0Ab3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuKruymkkmkqCJh7Q%0D%0AjmXlUOBcLFRyw5LG/vUUWVrsxC2gsbR8WJq+cYoYBpoNVStKrO4U2rBh1GEbccvT%0D%0A6qKOQI+pjjDxx9cmRdubGTGp8L0MF1ohVvhIvYLumOEoRDDPU4PvGJjGhek/ojve%0D%0AdPWe8dhciHkxOC2qPFZvVFMwg1/o/b80147BwZQmzB18mnHsmcyKlpsCN8pxw86u%0D%0Aao9Iun8gZQrsllW64rTZlRR56pHdAcuGAoZjYZxwS9Z+lvrSjEgrddemWyGGalqy%0D%0AFp1rXlVM1Tf4/IYWAQXTgTUN303u3xMjss7QK7eUDsACRxiWPLW9XQDd1c+yvaYJ%0D%0AKzgJ2wIDAQABo4IC6TCCAuUwHwYDVR0jBBgwFoAUD4BhHIIxYdUvKOeNRji0LOHG%0D%0A2eIwHQYDVR0OBBYEFNpSvSGcN2VT/B9TdQ8eXwebo60/MCcGA1UdEQQgMB6CD3d3%0D%0Ady5tb3ppbGxhLm9yZ4ILbW96aWxsYS5vcmcwDgYDVR0PAQH/BAQDAgWgMB0GA1Ud%0D%0AJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBrBgNVHR8EZDBiMC+gLaArhilodHRw%0D%0AOi8vY3JsMy5kaWdpY2VydC5jb20vc3NjYS1zaGEyLWc2LmNybDAvoC2gK4YpaHR0%0D%0AcDovL2NybDQuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nNi5jcmwwTAYDVR0gBEUw%0D%0AQzA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNl%0D%0AcnQuY29tL0NQUzAIBgZngQwBAgIwfAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzAB%0D%0AhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9j%0D%0AYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5j%0D%0AcnQwDAYDVR0TAQH/BAIwADCCAQIGCisGAQQB1nkCBAIEgfMEgfAA7gB1AKS5CZC0%0D%0AGFgUh7sTosxncAo8NZgE+RvfuON3zQ7IDdwQAAABZuYWiHwAAAQDAEYwRAIgZnMS%0D%0AH1JdG6NASHWTwD0mlP/zbr0hzP263c02Ym0DU64CIEe4QHJDP47j0b6oTFu6RrZz%0D%0A1NQ9cq8Az1KnMKRuaFAlAHUAh3W/51l8+IxDmV+9827/Vo1HVjb/SrVgwbTq/16g%0D%0Agw8AAAFm5haJAgAABAMARjBEAiAxGLXkUaOAkZhXNeNR3pWyahZeKmSaMXadgu18%0D%0ASfK1ZAIgKtwu5eGxK76rgaszLCZ9edBIjuU0DKorzPUuxUXFY0QwDQYJKoZIhvcN%0D%0AAQELBQADggEBAKLJAFO3wuaP5MM/ed1lhk5Uc2aDokhcM7XyvdhEKSHbgPhcgMoT%0D%0A9YIVoPa70gNC6KHcwoXu0g8wt7X6Vm1ql/68G5q844kFuC6JPl4LVT9mciD+VW6b%0D%0AHUSXD9xifL9DqdJ0Ic0SllTlM+oq5aAeOxUQGXhXIqj6fSQv9fQN6mXxQIoc/gjx%0D%0Ateskq/Vl8YmY1FIZP9Bh7g27kxZ9GAAGQtjTL03RzKAuSg6yeImYVdQWasc7UPnB%0D%0AXlRAzZ8+OJThUbzK16a2CI3Rg4agKSJk+uA47h1/ImmngpFLRb/MvRX6H1oWcUuy%0D%0AH6O7PZdl0YpwTpw1THIuqCGl/wpPgyQgcTM=%0D%0A-----END%20CERTIFICATE-----%0D%0A",
+ },
+ fingerprint: {
+ sha1: "0E:95:79:81:17:5C:51:D2:76:05:AC:8E:C4:61:71:61:97:29:ED:61",
+ sha256:
+ "30:23:CB:EC:1B:A8:C2:D9:E7:45:05:D5:4A:E2:0F:73:E1:51:C4:2D:46:59:CE:B4:EE:E6:51:7B:9E:CB:84:7B",
+ },
+ issuer: {
+ cn: "DigiCert SHA2 Secure Server CA",
+ dn: "c=US, o=DigiCert Inc, cn=DigiCert SHA2 Secure Server CA",
+ entries: [
+ ["Country", "US"],
+ ["Organization", "DigiCert Inc"],
+ ["Common Name", "DigiCert SHA2 Secure Server CA"],
+ ],
+ },
+ notBefore: "11/4/2018, 10:00:00 PM (Brasilia Standard Time)",
+ notBeforeUTC: "Mon, 05 Nov 2018 00:00:00 GMT",
+ notAfter: "11/13/2019, 10:00:00 AM (Brasilia Standard Time)",
+ notAfterUTC: "Wed, 13 Nov 2019 12:00:00 GMT",
+ subject: {
+ cn: "www.mozilla.org",
+ dn:
+ "c=US, s=California, l=Mountain View, o=Mozilla Corporation, ou=WebOps, cn=www.mozilla.org",
+ entries: [
+ ["Country", "US"],
+ ["State / Province", "California"],
+ ["Locality", "Mountain View"],
+ ["Organization", "Mozilla Corporation"],
+ ["Organizational Unit", "WebOps"],
+ ["Common Name", "www.mozilla.org"],
+ ],
+ },
+ serialNumber: "0C:97:6E:3E:42:38:F4:20:D6:3D:DF:86:EF:EB:BA:90",
+ signature: {
+ name: "SHA-256 with RSA Encryption",
+ type: "1.2.840.113549.1.1.11",
+ },
+ subjectPublicKeyInfo: {
+ e: 65537,
+ kty: "RSA",
+ n:
+ "B8:AA:EE:CA:69:24:9A:4A:82:26:1E:D0:8E:65:E5:50:E0:5C:2C:54:72:C3:92:C6:FE:F5:14:59:5A:EC:C4:2D:A0:B1:B4:7C:58:9A:BE:71:8A:18:06:9A:0D:55:2B:4A:AC:EE:14:DA:B0:61:D4:61:1B:71:CB:D3:EA:A2:8E:40:8F:A9:8E:30:F1:C7:D7:26:45:DB:9B:19:31:A9:F0:BD:0C:17:5A:21:56:F8:48:BD:82:EE:98:E1:28:44:30:CF:53:83:EF:18:98:C6:85:E9:3F:A2:3B:DE:74:F5:9E:F1:D8:5C:88:79:31:38:2D:AA:3C:56:6F:54:53:30:83:5F:E8:FD:BF:34:D7:8E:C1:C1:94:26:CC:1D:7C:9A:71:EC:99:CC:8A:96:9B:02:37:CA:71:C3:CE:AE:6A:8F:48:BA:7F:20:65:0A:EC:96:55:BA:E2:B4:D9:95:14:79:EA:91:DD:01:CB:86:02:86:63:61:9C:70:4B:D6:7E:96:FA:D2:8C:48:2B:75:D7:A6:5B:21:86:6A:5A:B2:16:9D:6B:5E:55:4C:D5:37:F8:FC:86:16:01:05:D3:81:35:0D:DF:4D:EE:DF:13:23:B2:CE:D0:2B:B7:94:0E:C0:02:47:18:96:3C:B5:BD:5D:00:DD:D5:CF:B2:BD:A6:09:2B:38:09:DB",
+ keysize: 2048,
+ },
+ unsupportedExtensions: [],
+ version: "3",
+ },
+];
diff --git a/toolkit/components/certviewer/tests/chrome/chrome.ini b/toolkit/components/certviewer/tests/chrome/chrome.ini
new file mode 100644
index 0000000000..d71649be72
--- /dev/null
+++ b/toolkit/components/certviewer/tests/chrome/chrome.ini
@@ -0,0 +1,12 @@
+[DEFAULT]
+scheme=https
+[test_adjustCertInformation.html]
+support-files =
+ parseOutput.js
+[test_certDecoder.html]
+[test_certDecoderFields.html]
+support-files =
+ CSoutput.js
+[test_kebabCaseInAdjustCertInformation.html]
+support-files =
+ parseOutput.js
diff --git a/toolkit/components/certviewer/tests/chrome/parseOutput.js b/toolkit/components/certviewer/tests/chrome/parseOutput.js
new file mode 100644
index 0000000000..b581d9d7ff
--- /dev/null
+++ b/toolkit/components/certviewer/tests/chrome/parseOutput.js
@@ -0,0 +1,342 @@
+export const parseOutput = [
+ {
+ ext: {
+ aia: {
+ descriptions: [
+ {
+ location: "http://ocsp.digicert.com",
+ method: "Online Certificate Status Protocol (OCSP)",
+ },
+ {
+ location:
+ "http://cacerts.digicert.com/DigiCertSHA2ExtendedValidationServerCA.crt",
+ method: "CA Issuers",
+ },
+ ],
+ critical: false,
+ },
+ aKID: {
+ critical: false,
+ id: "3D:D3:50:A5:D6:A0:AD:EE:F3:4A:60:0A:65:D3:21:D4:F8:F8:D6:0F",
+ },
+ basicConstraints: { cA: false, critical: true },
+ crlPoints: {
+ critical: false,
+ points: [
+ "http://crl3.digicert.com/sha2-ev-server-g2.crl",
+ "http://crl4.digicert.com/sha2-ev-server-g2.crl",
+ ],
+ },
+ cp: {
+ critical: false,
+ policies: [
+ {
+ id: "2.16.840",
+ name: "ANSI Organizational Identifier",
+ qualifiers: [
+ {
+ id: "1.3.6.1.5.5.7.2.1",
+ name: "Practices Statement",
+ value: "https://www.digicert.com/CPS",
+ },
+ ],
+ value: "2.16.840.1.114412.2.1",
+ },
+ {
+ id: "2.23.140.1.1",
+ name: "Certificate Type",
+ value: "Extended Validation",
+ },
+ ],
+ },
+ eKeyUsages: {
+ critical: false,
+ purposes: ["Server Authentication", "Client Authentication"],
+ },
+ keyUsages: {
+ critical: true,
+ purposes: ["Digital Signature", "Key Encipherment"],
+ },
+ msCrypto: { exists: false },
+ ocspStaple: { critical: false, required: false },
+ scts: {
+ critical: false,
+ timestamps: [
+ {
+ logId:
+ "A4:B9:09:90:B4:18:58:14:87:BB:13:A2:CC:67:70:0A:3C:35:98:04:F9:1B:DF:B8:E3:77:CD:0E:C8:0D:DC:10",
+ name: "Google “Pilot”",
+ signatureAlgorithm: "SHA-256 ECDSA",
+ timestamp: "11/7/2018, 7:50:01 PM (Brasilia Standard Time)",
+ timestampUTC: "Wed, 07 Nov 2018 21:50:01 GMT",
+ version: 1,
+ },
+ {
+ logId:
+ "87:75:BF:E7:59:7C:F8:8C:43:99:5F:BD:F3:6E:FF:56:8D:47:56:36:FF:4A:B5:60:C1:B4:EA:FF:5E:A0:83:0F",
+ name: "DigiCert Server 2",
+ signatureAlgorithm: "SHA-256 ECDSA",
+ timestamp: "11/7/2018, 7:50:01 PM (Brasilia Standard Time)",
+ timestampUTC: "Wed, 07 Nov 2018 21:50:01 GMT",
+ version: 1,
+ },
+ {
+ logId:
+ "EE:4B:BD:B7:75:CE:60:BA:E1:42:69:1F:AB:E1:9E:66:A3:0F:7E:5F:B0:72:D8:83:00:C4:7B:89:7A:A8:FD:CB",
+ name: "Google “Rocketeer”",
+ signatureAlgorithm: "SHA-256 ECDSA",
+ timestamp: "11/7/2018, 7:50:01 PM (Brasilia Standard Time)",
+ timestampUTC: "Wed, 07 Nov 2018 21:50:01 GMT",
+ version: 1,
+ },
+ ],
+ },
+ sKID: {
+ critical: false,
+ id: "6C:B0:43:56:FE:3D:E8:12:EC:D9:12:F5:63:D5:C4:CA:07:AF:B0:76",
+ },
+ san: {
+ altNames: [
+ ["DNS Name", "www.digicert.com"],
+ ["DNS Name", "admin.digicert.com"],
+ ["DNS Name", "digicert.com"],
+ ["DNS Name", "content.digicert.com"],
+ ["DNS Name", "login.digicert.com"],
+ ["DNS Name", "api.digicert.com"],
+ ["DNS Name", "ws.digicert.com"],
+ ["DNS Name", "www.origin.digicert.com"],
+ ],
+ critical: false,
+ },
+ },
+ files: {
+ pem:
+ "-----BEGIN%20CERTIFICATE-----%0D%0AMIIIzDCCB7SgAwIBAgIQDrbqtBjIc9jzwDHc3d8YsDANBgkqhkiG9w0BAQsFADB1%0D%0AMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3%0D%0Ad3cuZGlnaWNlcnQuY29tMTQwMgYDVQQDEytEaWdpQ2VydCBTSEEyIEV4dGVuZGVk%0D%0AIFZhbGlkYXRpb24gU2VydmVyIENBMB4XDTE4MTEwNzAwMDAwMFoXDTIwMTExMzEy%0D%0AMDAwMFowgc8xHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYLKwYB%0D%0ABAGCNzwCAQMTAlVTMRUwEwYLKwYBBAGCNzwCAQITBFV0YWgxFTATBgNVBAUTDDUy%0D%0AOTk1MzctMDE0MjELMAkGA1UEBhMCVVMxDTALBgNVBAgTBFV0YWgxDTALBgNVBAcT%0D%0ABExlaGkxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMQwwCgYDVQQLEwNTUkUxGTAX%0D%0ABgNVBAMTEHd3dy5kaWdpY2VydC5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw%0D%0AggIKAoICAQDOn4XKOTAwt/aYabScEF1QOyVj0OVo1NmlyizWNZWyPg0pi53ggUoE%0D%0A98CeNUkz+6scEYqWNY6l3qKB56pJJIqNQmo9NoWO8k2G/jTIjFFGqNWYIq23i4+H%0D%0AqaXi1/H/aWFgazk1qkyyAOQQA/p56bG9m5Ok/IBM/BZnLqVJLGJOx9ihgG1dI9Dr%0D%0A6vap+8QaPRau3t9sEd2cxe4Ix7gLdaYG3vxsYf3BycKTSKtyrbkX1Qy0dsSxy+GC%0D%0AM2ETxE1gMa7vRomQ/ZoZo8Ib55kFp6lIT6UOOkkdyiJdpWPXIZZlsZR5wkegWDsJ%0D%0AP7Xv7nE0WMkY1+05iNYtrzZRhhlnBw2AoMGNI+tsBXLQKeZfWFmU30bhkzX99pmv%0D%0AIYJ3f1fQGLao44nQEjdknIvpm0HMgvagYCnQVnnhJStzyYz324flWLPSp57OQeNM%0D%0Atr6O5W0HdWyhUZU+D4R6wObYQMZ5biYjRhtAQjMg8EVQEfZzEdr0WGO5JRHLHyot%0D%0A8tErXM9DiF5cCbzfcjeuoik2SHW+vbuPagMiHTM9+3lr0oRO+ZWwcM7fJvn1JfR2%0D%0APDLAaI3QUv7OLhSH32UfQsk+1ICq05m2HwSxiAviDRl5De66MEZDdvu03sUAQTHv%0D%0AWnw0Mr7Jgbjtn0DeUKLYwsRWg+spqoFTJHWGbb9RIb+3lxev7nIqOQIDAQABo4ID%0D%0A+zCCA/cwHwYDVR0jBBgwFoAUPdNQpdagre7zSmAKZdMh1Pj41g8wHQYDVR0OBBYE%0D%0AFGywQ1b+PegS7NkS9WPVxMoHr7B2MIGlBgNVHREEgZ0wgZqCEHd3dy5kaWdpY2Vy%0D%0AdC5jb22CEmFkbWluLmRpZ2ljZXJ0LmNvbYIMZGlnaWNlcnQuY29tghRjb250ZW50%0D%0ALmRpZ2ljZXJ0LmNvbYISbG9naW4uZGlnaWNlcnQuY29tghBhcGkuZGlnaWNlcnQu%0D%0AY29tgg93cy5kaWdpY2VydC5jb22CF3d3dy5vcmlnaW4uZGlnaWNlcnQuY29tMA4G%0D%0AA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYD%0D%0AVR0fBG4wbDA0oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItZXYt%0D%0Ac2VydmVyLWcyLmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3No%0D%0AYTItZXYtc2VydmVyLWcyLmNybDBLBgNVHSAERDBCMDcGCWCGSAGG/WwCATAqMCgG%0D%0ACCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAcGBWeBDAEB%0D%0AMIGIBggrBgEFBQcBAQR8MHowJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2lj%0D%0AZXJ0LmNvbTBSBggrBgEFBQcwAoZGaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29t%0D%0AL0RpZ2lDZXJ0U0hBMkV4dGVuZGVkVmFsaWRhdGlvblNlcnZlckNBLmNydDAMBgNV%0D%0AHRMBAf8EAjAAMIIBfwYKKwYBBAHWeQIEAgSCAW8EggFrAWkAdQCkuQmQtBhYFIe7%0D%0AE6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAWbwJ1QeAAAEAwBGMEQCIAzNFnn0UQyL%0D%0A5ZkwA7BX2JiQkjCk9QZrNHR9S1So7l8LAiAzoHDpWV5Dq5iM5NU86nJwqB1qsjZt%0D%0Aa4fWlvNKs0S+eQB3AId1v+dZfPiMQ5lfvfNu/1aNR1Y2/0q1YMG06v9eoIMPAAAB%0D%0AZvAnVbMAAAQDAEgwRgIhAOr0s3YbgyIs7dytmC1s5ClugVmo+r+W6ZKqRpphsIjT%0D%0AAiEAqgzFns9X9+SKwTSz0h1epijxrnWH+qZ815QgaJVd83UAdwDuS723dc5guuFC%0D%0AaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAWbwJ1RAAAAEAwBIMEYCIQCsFv4KXmNK%0D%0A+POADrfs37hcjApxSuiK14+tN5wFGby6QQIhANa+RvbVx1nYk13IyLCBiCMENLEV%0D%0A9urcBZfprZN+ZsrlMA0GCSqGSIb3DQEBCwUAA4IBAQB+tQhW07rk6eb2L2Ir+Wwq%0D%0Al5ZJaoaZq3zwoG8vPMFTZbcWPYsSVI5KuXELdB1QnmPbHebTJuI/gjfD65vf7C3N%0D%0ABjgLoXui39mwN4UNTBCc2Ls8s8/aVfTZGPCNNwynCEsY9h0HRobI8kiVPvU0kyBJ%0D%0AO3p3msqR7W2lAIWciJWmoPQkEFh7u84/oc7Pz2SSE6tqMW9lZmyBqjSuBufRJn1g%0D%0ACTdp/5DZdQWTNL6L5GSsRoXQnarsVtFVriqOjWf5R4O4z6LQznlbBQCMUR3geUNq%0D%0A0vSblnmgav0+L9HK97wqtONu1CrJ9/Q2JwoxFAs/zps/nh9oJU2ToK9lzl/38gpo%0D%0A-----END%20CERTIFICATE-----%0D%0A",
+ },
+ fingerprint: {
+ sha1: "8E:43:B7:D0:84:FD:B2:6C:08:9E:D3:F1:10:0C:D2:1D:D4:AD:C6:DF",
+ sha256:
+ "37:BF:44:A9:28:03:8A:22:AE:0C:E3:2D:96:3C:36:F5:D2:2D:37:99:D6:B2:63:CB:9C:1D:45:D1:CF:FE:B0:69",
+ },
+ issuer: {
+ cn: "DigiCert SHA2 Extended Validation Server CA",
+ dn:
+ "c=US, o=DigiCert Inc, ou=www.digicert.com, cn=DigiCert SHA2 Extended Validation Server CA",
+ entries: [
+ ["Country", "US"],
+ ["Organization", "DigiCert Inc"],
+ ["Organizational Unit", "www.digicert.com"],
+ ["Common Name", "DigiCert SHA2 Extended Validation Server CA"],
+ ],
+ },
+ notBefore: "11/6/2018, 10:00:00 PM (Brasilia Standard Time)",
+ notBeforeUTC: "Wed, 07 Nov 2018 00:00:00 GMT",
+ notAfter: "11/13/2020, 9:00:00 AM (Brasilia Standard Time)",
+ notAfterUTC: "Fri, 13 Nov 2020 12:00:00 GMT",
+ subject: {
+ cn: "www.digicert.com",
+ dn:
+ "OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.3=US, OID.1.3.6.1.4.1.311.60.2.1.2=Utah, serialNumber=5299537-0142, c=US, s=Utah, l=Lehi, o=DigiCert, Inc., ou=SRE, cn=www.digicert.com",
+ entries: [
+ ["Business Category", "Private Organization"],
+ ["Inc. Country", "US"],
+ ["Inc. State / Province", "Utah"],
+ ["Serial Number", "5299537-0142"],
+ ["Country", "US"],
+ ["State / Province", "Utah"],
+ ["Locality", "Lehi"],
+ ["Organization", "DigiCert, Inc."],
+ ["Organizational Unit", "SRE"],
+ ["Common Name", "www.digicert.com"],
+ ],
+ },
+ serialNumber: "0E:B6:EA:B4:18:C8:73:D8:F3:C0:31:DC:DD:DF:18:B0",
+ signature: {
+ name: "SHA-256 with RSA Encryption",
+ type: "1.2.840.113549.1.1.11",
+ },
+ subjectPublicKeyInfo: {
+ e: 65537,
+ kty: "RSA",
+ n:
+ "CE:9F:85:CA:39:30:30:B7:F6:98:69:B4:9C:10:5D:50:3B:25:63:D0:E5:68:D4:D9:A5:CA:2C:D6:35:95:B2:3E:0D:29:8B:9D:E0:81:4A:04:F7:C0:9E:35:49:33:FB:AB:1C:11:8A:96:35:8E:A5:DE:A2:81:E7:AA:49:24:8A:8D:42:6A:3D:36:85:8E:F2:4D:86:FE:34:C8:8C:51:46:A8:D5:98:22:AD:B7:8B:8F:87:A9:A5:E2:D7:F1:FF:69:61:60:6B:39:35:AA:4C:B2:00:E4:10:03:FA:79:E9:B1:BD:9B:93:A4:FC:80:4C:FC:16:67:2E:A5:49:2C:62:4E:C7:D8:A1:80:6D:5D:23:D0:EB:EA:F6:A9:FB:C4:1A:3D:16:AE:DE:DF:6C:11:DD:9C:C5:EE:08:C7:B8:0B:75:A6:06:DE:FC:6C:61:FD:C1:C9:C2:93:48:AB:72:AD:B9:17:D5:0C:B4:76:C4:B1:CB:E1:82:33:61:13:C4:4D:60:31:AE:EF:46:89:90:FD:9A:19:A3:C2:1B:E7:99:05:A7:A9:48:4F:A5:0E:3A:49:1D:CA:22:5D:A5:63:D7:21:96:65:B1:94:79:C2:47:A0:58:3B:09:3F:B5:EF:EE:71:34:58:C9:18:D7:ED:39:88:D6:2D:AF:36:51:86:19:67:07:0D:80:A0:C1:8D:23:EB:6C:05:72:D0:29:E6:5F:58:59:94:DF:46:E1:93:35:FD:F6:99:AF:21:82:77:7F:57:D0:18:B6:A8:E3:89:D0:12:37:64:9C:8B:E9:9B:41:CC:82:F6:A0:60:29:D0:56:79:E1:25:2B:73:C9:8C:F7:DB:87:E5:58:B3:D2:A7:9E:CE:41:E3:4C:B6:BE:8E:E5:6D:07:75:6C:A1:51:95:3E:0F:84:7A:C0:E6:D8:40:C6:79:6E:26:23:46:1B:40:42:33:20:F0:45:50:11:F6:73:11:DA:F4:58:63:B9:25:11:CB:1F:2A:2D:F2:D1:2B:5C:CF:43:88:5E:5C:09:BC:DF:72:37:AE:A2:29:36:48:75:BE:BD:BB:8F:6A:03:22:1D:33:3D:FB:79:6B:D2:84:4E:F9:95:B0:70:CE:DF:26:F9:F5:25:F4:76:3C:32:C0:68:8D:D0:52:FE:CE:2E:14:87:DF:65:1F:42:C9:3E:D4:80:AA:D3:99:B6:1F:04:B1:88:0B:E2:0D:19:79:0D:EE:BA:30:46:43:76:FB:B4:DE:C5:00:41:31:EF:5A:7C:34:32:BE:C9:81:B8:ED:9F:40:DE:50:A2:D8:C2:C4:56:83:EB:29:AA:81:53:24:75:86:6D:BF:51:21:BF:B7:97:17:AF:EE:72:2A:39",
+ keysize: 4096,
+ },
+ unsupportedExtensions: [],
+ version: "3",
+ },
+ {
+ ext: {
+ aia: {
+ descriptions: [
+ {
+ location: "http://ocsp.digicert.com",
+ method: "Online Certificate Status Protocol (OCSP)",
+ },
+ ],
+ critical: false,
+ },
+ aKID: {
+ critical: false,
+ id: "B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3",
+ },
+ basicConstraints: { cA: true, critical: true },
+ crlPoints: {
+ critical: false,
+ points: ["http://crl4.digicert.com/DigiCertHighAssuranceEVRootCA.crl"],
+ },
+ cp: {
+ critical: false,
+ policies: [
+ {
+ id: "2.5.29.32.0",
+ qualifiers: [
+ {
+ id: "1.3.6.1.5.5.7.2.1",
+ name: "Practices Statement",
+ value: "https://www.digicert.com/CPS",
+ },
+ ],
+ },
+ ],
+ },
+ eKeyUsages: {
+ critical: false,
+ purposes: ["Server Authentication", "Client Authentication"],
+ },
+ keyUsages: {
+ critical: true,
+ purposes: ["Digital Signature", "Certificate Signing", "CRL Signing"],
+ },
+ msCrypto: { exists: false },
+ ocspStaple: { critical: false, required: false },
+ scts: { critical: false, timestamps: [] },
+ sKID: {
+ critical: false,
+ id: "3D:D3:50:A5:D6:A0:AD:EE:F3:4A:60:0A:65:D3:21:D4:F8:F8:D6:0F",
+ },
+ san: { altNames: [], critical: false },
+ },
+ files: {
+ pem:
+ "-----BEGIN%20CERTIFICATE-----%0D%0AMIIEtjCCA56gAwIBAgIQDHmpRLCMEZUgkmFf4msdgzANBgkqhkiG9w0BAQsFADBs%0D%0AMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3%0D%0Ad3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j%0D%0AZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowdTEL%0D%0AMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3%0D%0ALmRpZ2ljZXJ0LmNvbTE0MDIGA1UEAxMrRGlnaUNlcnQgU0hBMiBFeHRlbmRlZCBW%0D%0AYWxpZGF0aW9uIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC%0D%0AggEBANdTpARR+JmmFkhLZyeqk0nQOe0MsLAAh/FnKIaFjI5j2ryxQDji0/XspQUY%0D%0AuD0+xZkXMuwYjPrxDKZkIYXLBxA0sFKIKx9om9KxjxKws9LniB8f7zh3VFNfgHk/%0D%0ALhqqqB5LKw2rt2O5Nbd9FLxZS99RStKh4gzikIKHaq7q12TWmFXo/a8aUGxUvBHy%0D%0A/Urynbt/DvTVvo4WiRJV2MBxNO723C3sxIclho3YIeSwTQyJ3DkmF93215SF2AQh%0D%0AcJ1vb/9cuhnhRctWVyh+HA1BV6q3uCe7seT6Ku8hI3UarS2bhjWMnHe1c63YlC3k%0D%0A8wyd7sFOYn4XwHGeLN7x+RAoGTMCAwEAAaOCAUkwggFFMBIGA1UdEwEB/wQIMAYB%0D%0AAf8CAQAwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF%0D%0ABQcDAjA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRp%0D%0AZ2ljZXJ0LmNvbTBLBgNVHR8ERDBCMECgPqA8hjpodHRwOi8vY3JsNC5kaWdpY2Vy%0D%0AdC5jb20vRGlnaUNlcnRIaWdoQXNzdXJhbmNlRVZSb290Q0EuY3JsMD0GA1UdIAQ2%0D%0AMDQwMgYEVR0gADAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5j%0D%0Ab20vQ1BTMB0GA1UdDgQWBBQ901Cl1qCt7vNKYApl0yHU+PjWDzAfBgNVHSMEGDAW%0D%0AgBSxPsNpA/i/RwHUmCYaCALvY2QrwzANBgkqhkiG9w0BAQsFAAOCAQEAnbbQkIbh%0D%0AhgLtxaDwNBx0wY12zIYKqPBKikLWP8ipTa18CK3mtlC4ohpNiAexKSHc59rGPCHg%0D%0A4xFJcKx6HQGkyhE6V6t9VypAdP3THYUYUN9XR3WhfVUgLkc3UHKMf4Ib0mKPLQNa%0D%0A2sPIoc4sUqIAY+tzunHISScjl2SFnjgOrWNoPLpSgVh5oywM395t6zHyuqB8bPEs%0D%0A1OG9d4Q3A84ytciagRpKkk47RpqF/oOi+Z6Mo8wNXrM9zwR4jxQUezKcxwCmXMS1%0D%0AoVWNWlZopCJwqjyBcdmdqEU79OX2olHdx3ti6G8MdOu42vi/hw15UJGQmxg7kVkn%0D%0A8TUoE6smftX3eg==%0D%0A-----END%20CERTIFICATE-----%0D%0A",
+ },
+ fingerprint: {
+ sha1: "7E:2F:3A:4F:8F:E8:FA:8A:57:30:AE:CA:02:96:96:63:7E:98:6F:3F",
+ sha256:
+ "40:3E:06:2A:26:53:05:91:13:28:5B:AF:80:A0:D4:AE:42:2C:84:8C:9F:78:FA:D0:1F:C9:4B:C5:B8:7F:EF:1A",
+ },
+ issuer: {
+ cn: "DigiCert High Assurance EV Root CA",
+ dn:
+ "c=US, o=DigiCert Inc, ou=www.digicert.com, cn=DigiCert High Assurance EV Root CA",
+ entries: [
+ ["Country", "US"],
+ ["Organization", "DigiCert Inc"],
+ ["Organizational Unit", "www.digicert.com"],
+ ["Common Name", "DigiCert High Assurance EV Root CA"],
+ ],
+ },
+ notBefore: "10/22/2013, 10:00:00 AM (Brasilia Standard Time)",
+ notBeforeUTC: "Tue, 22 Oct 2013 12:00:00 GMT",
+ notAfter: "10/22/2028, 9:00:00 AM (Brasilia Standard Time)",
+ notAfterUTC: "Sun, 22 Oct 2028 12:00:00 GMT",
+ subject: {
+ cn: "DigiCert SHA2 Extended Validation Server CA",
+ dn:
+ "c=US, o=DigiCert Inc, ou=www.digicert.com, cn=DigiCert SHA2 Extended Validation Server CA",
+ entries: [
+ ["Country", "US"],
+ ["Organization", "DigiCert Inc"],
+ ["Organizational Unit", "www.digicert.com"],
+ ["Common Name", "DigiCert SHA2 Extended Validation Server CA"],
+ ],
+ },
+ serialNumber: "0C:79:A9:44:B0:8C:11:95:20:92:61:5F:E2:6B:1D:83",
+ signature: {
+ name: "SHA-256 with RSA Encryption",
+ type: "1.2.840.113549.1.1.11",
+ },
+ subjectPublicKeyInfo: {
+ e: 65537,
+ kty: "RSA",
+ n:
+ "D7:53:A4:04:51:F8:99:A6:16:48:4B:67:27:AA:93:49:D0:39:ED:0C:B0:B0:00:87:F1:67:28:86:85:8C:8E:63:DA:BC:B1:40:38:E2:D3:F5:EC:A5:05:18:B8:3D:3E:C5:99:17:32:EC:18:8C:FA:F1:0C:A6:64:21:85:CB:07:10:34:B0:52:88:2B:1F:68:9B:D2:B1:8F:12:B0:B3:D2:E7:88:1F:1F:EF:38:77:54:53:5F:80:79:3F:2E:1A:AA:A8:1E:4B:2B:0D:AB:B7:63:B9:35:B7:7D:14:BC:59:4B:DF:51:4A:D2:A1:E2:0C:E2:90:82:87:6A:AE:EA:D7:64:D6:98:55:E8:FD:AF:1A:50:6C:54:BC:11:F2:FD:4A:F2:9D:BB:7F:0E:F4:D5:BE:8E:16:89:12:55:D8:C0:71:34:EE:F6:DC:2D:EC:C4:87:25:86:8D:D8:21:E4:B0:4D:0C:89:DC:39:26:17:DD:F6:D7:94:85:D8:04:21:70:9D:6F:6F:FF:5C:BA:19:E1:45:CB:56:57:28:7E:1C:0D:41:57:AA:B7:B8:27:BB:B1:E4:FA:2A:EF:21:23:75:1A:AD:2D:9B:86:35:8C:9C:77:B5:73:AD:D8:94:2D:E4:F3:0C:9D:EE:C1:4E:62:7E:17:C0:71:9E:2C:DE:F1:F9:10:28:19:33",
+ keysize: 2048,
+ },
+ unsupportedExtensions: [],
+ version: "3",
+ },
+ {
+ ext: {
+ aia: { critical: false },
+ aKID: {
+ critical: false,
+ id: "B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3",
+ },
+ basicConstraints: { cA: true, critical: true },
+ cp: { critical: false },
+ keyUsages: {
+ critical: true,
+ purposes: ["Digital Signature", "Certificate Signing", "CRL Signing"],
+ },
+ msCrypto: { exists: false },
+ ocspStaple: { critical: false, required: false },
+ scts: { critical: false, timestamps: [] },
+ sKID: {
+ critical: false,
+ id: "B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3",
+ },
+ san: { altNames: [], critical: false },
+ },
+ files: {
+ pem:
+ "-----BEGIN%20CERTIFICATE-----%0D%0AMIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs%0D%0AMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3%0D%0Ad3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j%0D%0AZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL%0D%0AMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3%0D%0ALmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug%0D%0ARVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm%0D%0A+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW%0D%0APNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM%0D%0AxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB%0D%0AIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3%0D%0AhzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg%0D%0AEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF%0D%0AMAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA%0D%0AFLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec%0D%0AnzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z%0D%0AeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF%0D%0AhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2%0D%0AYzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe%0D%0AvEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep%0D%0A+OkuE6N36B9K%0D%0A-----END%20CERTIFICATE-----%0D%0A",
+ },
+ fingerprint: {
+ sha1: "5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25",
+ sha256:
+ "74:31:E5:F4:C3:C1:CE:46:90:77:4F:0B:61:E0:54:40:88:3B:A9:A0:1E:D0:0B:A6:AB:D7:80:6E:D3:B1:18:CF",
+ },
+ issuer: {
+ cn: "DigiCert High Assurance EV Root CA",
+ dn:
+ "c=US, o=DigiCert Inc, ou=www.digicert.com, cn=DigiCert High Assurance EV Root CA",
+ entries: [
+ ["Country", "US"],
+ ["Organization", "DigiCert Inc"],
+ ["Organizational Unit", "www.digicert.com"],
+ ["Common Name", "DigiCert High Assurance EV Root CA"],
+ ],
+ },
+ notBefore: "11/9/2006, 10:00:00 PM (Brasilia Standard Time)",
+ notBeforeUTC: "Fri, 10 Nov 2006 00:00:00 GMT",
+ notAfter: "11/9/2031, 9:00:00 PM (Brasilia Standard Time)",
+ notAfterUTC: "Mon, 10 Nov 2031 00:00:00 GMT",
+ subject: {
+ cn: "DigiCert High Assurance EV Root CA",
+ dn:
+ "c=US, o=DigiCert Inc, ou=www.digicert.com, cn=DigiCert High Assurance EV Root CA",
+ entries: [
+ ["Country", "US"],
+ ["Organization", "DigiCert Inc"],
+ ["Organizational Unit", "www.digicert.com"],
+ ["Common Name", "DigiCert High Assurance EV Root CA"],
+ ],
+ },
+ serialNumber: "02:AC:5C:26:6A:0B:40:9B:8F:0B:79:F2:AE:46:25:77",
+ signature: {
+ name: "SHA-1 with RSA Encryption",
+ type: "1.2.840.113549.1.1.5",
+ },
+ subjectPublicKeyInfo: {
+ e: 65537,
+ kty: "RSA",
+ n:
+ "C6:CC:E5:73:E6:FB:D4:BB:E5:2D:2D:32:A6:DF:E5:81:3F:C9:CD:25:49:B6:71:2A:C3:D5:94:34:67:A2:0A:1C:B0:5F:69:A6:40:B1:C4:B7:B2:8F:D0:98:A4:A9:41:59:3A:D3:DC:94:D6:3C:DB:74:38:A4:4A:CC:4D:25:82:F7:4A:A5:53:12:38:EE:F3:49:6D:71:91:7E:63:B6:AB:A6:5F:C3:A4:84:F8:4F:62:51:BE:F8:C5:EC:DB:38:92:E3:06:E5:08:91:0C:C4:28:41:55:FB:CB:5A:89:15:7E:71:E8:35:BF:4D:72:09:3D:BE:3A:38:50:5B:77:31:1B:8D:B3:C7:24:45:9A:A7:AC:6D:00:14:5A:04:B7:BA:13:EB:51:0A:98:41:41:22:4E:65:61:87:81:41:50:A6:79:5C:89:DE:19:4A:57:D5:2E:E6:5D:1C:53:2C:7E:98:CD:1A:06:16:A4:68:73:D0:34:04:13:5C:A1:71:D3:5A:7C:55:DB:5E:64:E1:37:87:30:56:04:E5:11:B4:29:80:12:F1:79:39:88:A2:02:11:7C:27:66:B7:88:B7:78:F2:CA:0A:A8:38:AB:0A:64:C2:BF:66:5D:95:84:C1:A1:25:1E:87:5D:1A:50:0B:20:12:CC:41:BB:6E:0B:51:38:B8:4B:CB",
+ keysize: 2048,
+ },
+ unsupportedExtensions: [],
+ version: "3",
+ },
+];
diff --git a/toolkit/components/certviewer/tests/chrome/test_adjustCertInformation.html b/toolkit/components/certviewer/tests/chrome/test_adjustCertInformation.html
new file mode 100644
index 0000000000..13f3df48f5
--- /dev/null
+++ b/toolkit/components/certviewer/tests/chrome/test_adjustCertInformation.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>certviewer adjustCertInformation test</title>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="chrome://global/content/certviewer/pvutils_bundle.js"></script>
+ <script src="chrome://global/content/certviewer/asn1js_bundle.js"></script>
+ <script src="chrome://global/content/certviewer/pkijs_bundle.js"></script>
+
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ </head>
+<body>
+ <script type="module">
+ import { adjustCertInformation } from "chrome://global/content/certviewer/certviewer.js";
+ import { parseOutput } from "./parseOutput.js";
+
+ function hasNullElements(obj) {
+ for (let key of Object.keys(obj)) {
+ if (obj[key] == null) return false;
+ if (typeof(obj[key]) === 'object') {
+ if (hasNullElements(obj[key]) === false) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ async function doTest() {
+ ok(adjustCertInformation, "adjustCertInformation should be available in this context");
+ ok(parseOutput, "parseOutput should be available in this context");
+ is(typeof(parseOutput), 'object', "parseOutput must be an object");
+
+ for (let cert of parseOutput) {
+ let adjustedCerts = adjustCertInformation(cert);
+ let result = hasNullElements(adjustedCerts.certItems);
+ ok(result, "adjustCertInformation function shouldn't return null elements");
+ }
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ doTest();
+
+ </script>
+</body>
+</html>
diff --git a/toolkit/components/certviewer/tests/chrome/test_certDecoder.html b/toolkit/components/certviewer/tests/chrome/test_certDecoder.html
new file mode 100644
index 0000000000..a95faf2366
--- /dev/null
+++ b/toolkit/components/certviewer/tests/chrome/test_certDecoder.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>certviewer parse test</title>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="chrome://global/content/certviewer/pvutils_bundle.js"></script>
+ <script src="chrome://global/content/certviewer/asn1js_bundle.js"></script>
+ <script src="chrome://global/content/certviewer/pkijs_bundle.js"></script>
+
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ </head>
+<body>
+ <script type="module">
+ import { parse } from "chrome://global/content/certviewer/certDecoder.js";
+ import { pemToDER } from "chrome://global/content/certviewer/utils.js";
+
+ // inputPEM is the same input to CS extension (https://github.com/april/certainly-something)
+ const inputPEM = "MIIGRjCCBS6gAwIBAgIQDJduPkI49CDWPd+G7+u6kDANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5EaWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgxMTA1MDAwMDAwWhcNMTkxMTEzMTIwMDAwWjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxHDAaBgNVBAoTE01vemlsbGEgQ29ycG9yYXRpb24xDzANBgNVBAsTBldlYk9wczEYMBYGA1UEAxMPd3d3Lm1vemlsbGEub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuKruymkkmkqCJh7QjmXlUOBcLFRyw5LG/vUUWVrsxC2gsbR8WJq+cYoYBpoNVStKrO4U2rBh1GEbccvT6qKOQI+pjjDxx9cmRdubGTGp8L0MF1ohVvhIvYLumOEoRDDPU4PvGJjGhek/ojvedPWe8dhciHkxOC2qPFZvVFMwg1/o/b80147BwZQmzB18mnHsmcyKlpsCN8pxw86uao9Iun8gZQrsllW64rTZlRR56pHdAcuGAoZjYZxwS9Z+lvrSjEgrddemWyGGalqyFp1rXlVM1Tf4/IYWAQXTgTUN303u3xMjss7QK7eUDsACRxiWPLW9XQDd1c+yvaYJKzgJ2wIDAQABo4IC6TCCAuUwHwYDVR0jBBgwFoAUD4BhHIIxYdUvKOeNRji0LOHG2eIwHQYDVR0OBBYEFNpSvSGcN2VT/B9TdQ8eXwebo60/MCcGA1UdEQQgMB6CD3d3dy5tb3ppbGxhLm9yZ4ILbW96aWxsYS5vcmcwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBrBgNVHR8EZDBiMC+gLaArhilodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc3NjYS1zaGEyLWc2LmNybDAvoC2gK4YpaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nNi5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBAgIwfAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH/BAIwADCCAQIGCisGAQQB1nkCBAIEgfMEgfAA7gB1AKS5CZC0GFgUh7sTosxncAo8NZgE+RvfuON3zQ7IDdwQAAABZuYWiHwAAAQDAEYwRAIgZnMSH1JdG6NASHWTwD0mlP/zbr0hzP263c02Ym0DU64CIEe4QHJDP47j0b6oTFu6RrZz1NQ9cq8Az1KnMKRuaFAlAHUAh3W/51l8+IxDmV+9827/Vo1HVjb/SrVgwbTq/16ggw8AAAFm5haJAgAABAMARjBEAiAxGLXkUaOAkZhXNeNR3pWyahZeKmSaMXadgu18SfK1ZAIgKtwu5eGxK76rgaszLCZ9edBIjuU0DKorzPUuxUXFY0QwDQYJKoZIhvcNAQELBQADggEBAKLJAFO3wuaP5MM/ed1lhk5Uc2aDokhcM7XyvdhEKSHbgPhcgMoT9YIVoPa70gNC6KHcwoXu0g8wt7X6Vm1ql/68G5q844kFuC6JPl4LVT9mciD+VW6bHUSXD9xifL9DqdJ0Ic0SllTlM+oq5aAeOxUQGXhXIqj6fSQv9fQN6mXxQIoc/gjxteskq/Vl8YmY1FIZP9Bh7g27kxZ9GAAGQtjTL03RzKAuSg6yeImYVdQWasc7UPnBXlRAzZ8+OJThUbzK16a2CI3Rg4agKSJk+uA47h1/ImmngpFLRb/MvRX6H1oWcUuyH6O7PZdl0YpwTpw1THIuqCGl/wpPgyQgcTM=";
+ const certOutputCS = "-----BEGIN%20CERTIFICATE-----%0D%0AMIIGRjCCBS6gAwIBAgIQDJduPkI49CDWPd+G7+u6kDANBgkqhkiG9w0BAQsFADBN%0D%0AMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E%0D%0AaWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgxMTA1MDAwMDAwWhcN%0D%0AMTkxMTEzMTIwMDAwWjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3Ju%0D%0AaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxHDAaBgNVBAoTE01vemlsbGEgQ29y%0D%0AcG9yYXRpb24xDzANBgNVBAsTBldlYk9wczEYMBYGA1UEAxMPd3d3Lm1vemlsbGEu%0D%0Ab3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuKruymkkmkqCJh7Q%0D%0AjmXlUOBcLFRyw5LG/vUUWVrsxC2gsbR8WJq+cYoYBpoNVStKrO4U2rBh1GEbccvT%0D%0A6qKOQI+pjjDxx9cmRdubGTGp8L0MF1ohVvhIvYLumOEoRDDPU4PvGJjGhek/ojve%0D%0AdPWe8dhciHkxOC2qPFZvVFMwg1/o/b80147BwZQmzB18mnHsmcyKlpsCN8pxw86u%0D%0Aao9Iun8gZQrsllW64rTZlRR56pHdAcuGAoZjYZxwS9Z+lvrSjEgrddemWyGGalqy%0D%0AFp1rXlVM1Tf4/IYWAQXTgTUN303u3xMjss7QK7eUDsACRxiWPLW9XQDd1c+yvaYJ%0D%0AKzgJ2wIDAQABo4IC6TCCAuUwHwYDVR0jBBgwFoAUD4BhHIIxYdUvKOeNRji0LOHG%0D%0A2eIwHQYDVR0OBBYEFNpSvSGcN2VT/B9TdQ8eXwebo60/MCcGA1UdEQQgMB6CD3d3%0D%0Ady5tb3ppbGxhLm9yZ4ILbW96aWxsYS5vcmcwDgYDVR0PAQH/BAQDAgWgMB0GA1Ud%0D%0AJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBrBgNVHR8EZDBiMC+gLaArhilodHRw%0D%0AOi8vY3JsMy5kaWdpY2VydC5jb20vc3NjYS1zaGEyLWc2LmNybDAvoC2gK4YpaHR0%0D%0AcDovL2NybDQuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nNi5jcmwwTAYDVR0gBEUw%0D%0AQzA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNl%0D%0AcnQuY29tL0NQUzAIBgZngQwBAgIwfAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzAB%0D%0AhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9j%0D%0AYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5j%0D%0AcnQwDAYDVR0TAQH/BAIwADCCAQIGCisGAQQB1nkCBAIEgfMEgfAA7gB1AKS5CZC0%0D%0AGFgUh7sTosxncAo8NZgE+RvfuON3zQ7IDdwQAAABZuYWiHwAAAQDAEYwRAIgZnMS%0D%0AH1JdG6NASHWTwD0mlP/zbr0hzP263c02Ym0DU64CIEe4QHJDP47j0b6oTFu6RrZz%0D%0A1NQ9cq8Az1KnMKRuaFAlAHUAh3W/51l8+IxDmV+9827/Vo1HVjb/SrVgwbTq/16g%0D%0Agw8AAAFm5haJAgAABAMARjBEAiAxGLXkUaOAkZhXNeNR3pWyahZeKmSaMXadgu18%0D%0ASfK1ZAIgKtwu5eGxK76rgaszLCZ9edBIjuU0DKorzPUuxUXFY0QwDQYJKoZIhvcN%0D%0AAQELBQADggEBAKLJAFO3wuaP5MM/ed1lhk5Uc2aDokhcM7XyvdhEKSHbgPhcgMoT%0D%0A9YIVoPa70gNC6KHcwoXu0g8wt7X6Vm1ql/68G5q844kFuC6JPl4LVT9mciD+VW6b%0D%0AHUSXD9xifL9DqdJ0Ic0SllTlM+oq5aAeOxUQGXhXIqj6fSQv9fQN6mXxQIoc/gjx%0D%0Ateskq/Vl8YmY1FIZP9Bh7g27kxZ9GAAGQtjTL03RzKAuSg6yeImYVdQWasc7UPnB%0D%0AXlRAzZ8+OJThUbzK16a2CI3Rg4agKSJk+uA47h1/ImmngpFLRb/MvRX6H1oWcUuy%0D%0AH6O7PZdl0YpwTpw1THIuqCGl/wpPgyQgcTM=%0D%0A-----END%20CERTIFICATE-----%0D%0A";
+
+
+ async function doTest() {
+ ok(parse, "parse should be available in this context");
+ ok(pemToDER, "pemToDER should be available in this context");
+
+ let input = inputPEM.trim()
+ .replace(/\r|\n|\0/g, "")
+ .split()
+ .filter(v => v.startsWith("MII"))[0];
+
+ let certDER = pemToDER(input);
+ let cert = await parse(certDER);
+ ok(cert, "There should be a result");
+ is(cert.files.pem, certOutputCS, "certificates output must be the same");
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ doTest();
+
+ </script>
+</body>
+</html>
diff --git a/toolkit/components/certviewer/tests/chrome/test_certDecoderFields.html b/toolkit/components/certviewer/tests/chrome/test_certDecoderFields.html
new file mode 100644
index 0000000000..a6dc23f235
--- /dev/null
+++ b/toolkit/components/certviewer/tests/chrome/test_certDecoderFields.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>certviewer parse test</title>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="chrome://global/content/certviewer/pvutils_bundle.js"></script>
+ <script src="chrome://global/content/certviewer/asn1js_bundle.js"></script>
+ <script src="chrome://global/content/certviewer/pkijs_bundle.js"></script>
+ <script type="module" src="CSoutput.js"></script>
+
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ </head>
+<body>
+ <script type="module">
+ import { parse } from "chrome://global/content/certviewer/certDecoder.js";
+ import { pemToDER } from "chrome://global/content/certviewer/utils.js";
+ import { certOutputCS } from "./CSoutput.js";
+
+ // inputPEM is the same input to CS extension (https://github.com/april/certainly-something)
+ const inputPEM = "MIIGRjCCBS6gAwIBAgIQDJduPkI49CDWPd+G7+u6kDANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5EaWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgxMTA1MDAwMDAwWhcNMTkxMTEzMTIwMDAwWjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxHDAaBgNVBAoTE01vemlsbGEgQ29ycG9yYXRpb24xDzANBgNVBAsTBldlYk9wczEYMBYGA1UEAxMPd3d3Lm1vemlsbGEub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuKruymkkmkqCJh7QjmXlUOBcLFRyw5LG/vUUWVrsxC2gsbR8WJq+cYoYBpoNVStKrO4U2rBh1GEbccvT6qKOQI+pjjDxx9cmRdubGTGp8L0MF1ohVvhIvYLumOEoRDDPU4PvGJjGhek/ojvedPWe8dhciHkxOC2qPFZvVFMwg1/o/b80147BwZQmzB18mnHsmcyKlpsCN8pxw86uao9Iun8gZQrsllW64rTZlRR56pHdAcuGAoZjYZxwS9Z+lvrSjEgrddemWyGGalqyFp1rXlVM1Tf4/IYWAQXTgTUN303u3xMjss7QK7eUDsACRxiWPLW9XQDd1c+yvaYJKzgJ2wIDAQABo4IC6TCCAuUwHwYDVR0jBBgwFoAUD4BhHIIxYdUvKOeNRji0LOHG2eIwHQYDVR0OBBYEFNpSvSGcN2VT/B9TdQ8eXwebo60/MCcGA1UdEQQgMB6CD3d3dy5tb3ppbGxhLm9yZ4ILbW96aWxsYS5vcmcwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBrBgNVHR8EZDBiMC+gLaArhilodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc3NjYS1zaGEyLWc2LmNybDAvoC2gK4YpaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nNi5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBAgIwfAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH/BAIwADCCAQIGCisGAQQB1nkCBAIEgfMEgfAA7gB1AKS5CZC0GFgUh7sTosxncAo8NZgE+RvfuON3zQ7IDdwQAAABZuYWiHwAAAQDAEYwRAIgZnMSH1JdG6NASHWTwD0mlP/zbr0hzP263c02Ym0DU64CIEe4QHJDP47j0b6oTFu6RrZz1NQ9cq8Az1KnMKRuaFAlAHUAh3W/51l8+IxDmV+9827/Vo1HVjb/SrVgwbTq/16ggw8AAAFm5haJAgAABAMARjBEAiAxGLXkUaOAkZhXNeNR3pWyahZeKmSaMXadgu18SfK1ZAIgKtwu5eGxK76rgaszLCZ9edBIjuU0DKorzPUuxUXFY0QwDQYJKoZIhvcNAQELBQADggEBAKLJAFO3wuaP5MM/ed1lhk5Uc2aDokhcM7XyvdhEKSHbgPhcgMoT9YIVoPa70gNC6KHcwoXu0g8wt7X6Vm1ql/68G5q844kFuC6JPl4LVT9mciD+VW6bHUSXD9xifL9DqdJ0Ic0SllTlM+oq5aAeOxUQGXhXIqj6fSQv9fQN6mXxQIoc/gjxteskq/Vl8YmY1FIZP9Bh7g27kxZ9GAAGQtjTL03RzKAuSg6yeImYVdQWasc7UPnBXlRAzZ8+OJThUbzK16a2CI3Rg4agKSJk+uA47h1/ImmngpFLRb/MvRX6H1oWcUuyH6O7PZdl0YpwTpw1THIuqCGl/wpPgyQgcTM=";
+ const inputPEMerror1 = "MIIGRjCCBS6gAwIBAgIQDJduPkI49CDWPd+G7+u6kDANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5EaWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgxMTA1MDAwMDAwWhcNMTkxMTEzMTIwMDAwWjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxHDAaBgNVBAoTE01vemlsbGEgQ29ycG9yYXRpb24xDzANBgNVBAsTBldlYk9wczEYMBYGA1UEAxMPd3d3Lm1vemlsbGEub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuKruymkkmkqCJh7QjmXlUOBcLFRyw5LG/vUUWVrsxC2gsbR8WJq+cYoYBpoNVStKrO4U2rBh1GEbccvT6qKOQI+pjjDxx9cmRdubGTGp8L0MF1ohVvhIvYLumOEoRDDPU4PvGJjGhek/ojvedPWe8dhciHkxOC2qPFZvVFMwg1/o/b80147BwZQmzB18mnHsmcyKlpsCN8pxw86uao9Iun8gZQrsllW64rTZlRR56pHdAcuGAoZjYZxwS9Z+lvrSjEgrddemWyGGalqyFp1rXlVM1Tf4/IYWAQXTgTUN303u3xMjss7QK7eUDsACRxiWPLW9XQDd1c+yvaYJKzgJ2wIDAQABo4IC6TCCAuUwHwYDVR0jBBgwFoAUD4BhHIIxYdUvKOeNRji0LOHG2eIwHQYDVR0OBBYEFNpSvSGcN2VT/B9TdQ8eXwebo60/MCcGA1UdEQQgMB6CD3d3dy5tb3ppbGxhLm9yZ4ILbW96aWxsYS5vcmcwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBrBgNVHR8EZDBiMC+gLaArhilodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc3NjYS1zaGEyLWc2LmNybDAvoC2gK4YpaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nNi5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBAgIwfAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH/BAIwADCCAQIGCisGAQQB1nkCBAIEgfMEgfAA7gB1AKS5CZC0GFgUh7sTosxncAo8NZgE+RvfuON3zQ7IDdwQAAABZuYWiHwAAAQDAEYwRAIgZnMSH1JdG6NASHWTwD0mlP/zbr0hzP263c02Ym0DU64CIEe4QHJDP47j0b6oTFu6RrZz1NQ9cq8Az1KnMKRuaFAlAHUAh3W/51l8+IxDmV+9827/Vo1HVjb/SrVgwbTq/16ggw8AAAFm5haJAgAABAMARjBEAiAxGLXkUaOAkZhXNeNR3pWyahZeKmSaMXadgu18SfK1ZAIgKtwu5eGxK76rgaszLCZ9edBIjuU0DKorzPUuxUXFY0QwDQYJKoZIhvcNAQELBQADggEBAKLJAFO3wuaP5MM/ed1lhk5Uc2aDokhcM7XyvdhEKSHbgPhcgMoT9YIVoPa70gNC6KHcwoXu0g8wt7X6Vm1ql/68G5q844kFuC6JPl4LVT9mciD+VW6bHUSXD9xifL9D";
+ const inputPEMerror2 = "VUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5EaWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgxMTA1MDAwMDAwWhcNMTkxMTEzMTIwMDAwWjCBgzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxHDAaBgNVBAoTE01vemlsbGEgQ29ycG9yYXRpb24xDzANBgNVBAsTBldlYk9wczEYMBYGA1UEAxMPd3d3Lm1vemlsbGEub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuKruymkkmkqCJh7QjmXlUOBcLFRyw5LG/vUUWVrsxC2gsbR8WJq+cYoYBpoNVStKrO4U2rBh1GEbccvT6qKOQI+pjjDxx9cmRdubGTGp8L0MF1ohVvhIvYLumOEoRDDPU4PvGJjGhek/ojvedPWe8dhciHkxOC2qPFZvVFMwg1/o/b80147BwZQmzB18mnHsmcyKlpsCN8pxw86uao9Iun8gZQrsllW64rTZlRR56pHdAcuGAoZjYZxwS9Z+lvrSjEgrddemWyGGalqyFp1rXlVM1Tf4/IYWAQXTgTUN303u3xMjss7QK7eUDsACRxiWPLW9XQDd1c+yvaYJKzgJ2wIDAQABo4IC6TCCAuUwHwYDVR0jBBgwFoAUD4BhHIIxYdUvKOeNRji0LOHG2eIwHQYDVR0OBBYEFNpSvSGcN2VT/B9TdQ8eXwebo60/MCcGA1UdEQQgMB6CD3d3dy5tb3ppbGxhLm9yZ4ILbW96aWxsYS5vcmcwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBrBgNVHR8EZDBiMC+gLaArhilodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc3NjYS1zaGEyLWc2LmNybDAvoC2gK4YpaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nNi5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBAgIwfAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH/BAIwADCCAQIGCisGAQQB1nkCBAIEgfMEgfAA7gB1AKS5CZC0GFgUh7sTosxncAo8NZgE+RvfuON3zQ7IDdwQAAABZuYWiHwAAAQDAEYwRAIgZnMSH1JdG6NASHWTwD0mlP/zbr0hzP263c02Ym0DU64CIEe4QHJDP47j0b6oTFu6RrZz1NQ9cq8Az1KnMKRuaFAlAHUAh3W/51l8+IxDmV+9827/Vo1HVjb/SrVgwbTq/16ggw8AAAFm5haJAgAABAMARjBEAiAxGLXkUaOAkZhXNeNR3pWyahZeKmSaMXadgu18SfK1ZAIgKtwu5eGxK76rgaszLCZ9edBIjuU0DKorzPUuxUXFY0QwDQYJKoZIhvcNAQELBQADggEBAKLJAFO3wuaP5MM/ed1lhk5Uc2aDokhcM7XyvdhEKSHbgPhcgMoT9YIVoPa70gNC6KHcwoXu0g8wt7X6Vm1ql/68G5q844kFuC6JPl4LVT9mciD+VW6bHUSXD9xifL9DqdJ0Ic0SllTlM+oq5aAeOxUQGXhXIqj6fSQv9fQN6mXxQIoc/gjxteskq/Vl8YmY1FIZP9Bh7g27kxZ9GAAGQtjTL03RzKAuSg6yeImYVdQWasc7UPnBXlRAzZ8+OJThUbzK16a2CI3Rg4agKSJk+uA47h1/ImmngpFLRb/MvRX6H1oWcUuyH6O7PZdl0YpwTpw1THIuqCGl/wpPgyQgcTM=";
+
+ async function run(input, expected) {
+ let certDER;
+ try {
+ certDER = pemToDER(input);
+ } catch (err) {
+ is("error", expected, "OK, error found when executing pemToDER function");
+ return;
+ }
+ ok(certDER, "pemToDER returned a non null value");
+
+ let cert;
+ try {
+ cert = await parse(certDER);
+ } catch (err) {
+ is("error", expected, "OK, error found when executing parse function");
+ return;
+ }
+ ok(cert, "Parse function returned an Object");
+
+ // "Because the representation of JS Date objects will vary depending on the timezone,
+ // we don't consider them in the test. Instead we test their corresponding UTC values (e.g notAfterUTC)."
+ cert.notAfter = "";
+ expected.notAfter = "";
+
+ cert.notBefore = "";
+ expected.notBefore = "";
+
+ cert.ext.scts.timestamps = cert.ext.scts.timestamps.map(elem => elem.timestamp = "");
+ expected.ext.scts.timestamps = expected.ext.scts.timestamps.map(elem => elem.timestamp = "");
+
+ is(JSON.stringify(cert), JSON.stringify(expected), "All the fields in CS must be equal to our output");
+ }
+
+ async function doTest() {
+ ok(parse, "parse should be available in this context");
+ ok(pemToDER, "pemToDER should be available in this context");
+ ok(certOutputCS, "certOutputCS should be available in this context");
+ is(typeof(certOutputCS), 'object', "certOutputCS must be an object");
+
+ let inputs = [
+ inputPEM,
+ inputPEMerror1,
+ inputPEMerror2
+ ];
+
+ let expected = [
+ certOutputCS[0],
+ "error",
+ "error"
+ ];
+
+ for (let i = 0; i < inputs.length; i++) {
+ await run(inputs[i], expected[i]);
+ }
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ doTest();
+
+ </script>
+</body>
+</html>
diff --git a/toolkit/components/certviewer/tests/chrome/test_kebabCaseInAdjustCertInformation.html b/toolkit/components/certviewer/tests/chrome/test_kebabCaseInAdjustCertInformation.html
new file mode 100644
index 0000000000..663cc2baae
--- /dev/null
+++ b/toolkit/components/certviewer/tests/chrome/test_kebabCaseInAdjustCertInformation.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>certviewer adjustCertInformation test</title>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="chrome://global/content/certviewer/pvutils_bundle.js"></script>
+ <script src="chrome://global/content/certviewer/asn1js_bundle.js"></script>
+ <script src="chrome://global/content/certviewer/pkijs_bundle.js"></script>
+
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ </head>
+<body>
+ <script type="module">
+ import { adjustCertInformation } from "chrome://global/content/certviewer/certviewer.js";
+ import { parseOutput } from "./parseOutput.js";
+
+ function isKebabCase(str) {
+ if (str === "") return true;
+ return /^([a-z][a-z0-9]*)(-[a-z0-9]+)*$/.test(str);
+ }
+
+ function validateIsKebabCase() {
+ let tests = [
+ {
+ input: "",
+ expected: true
+ },
+ {
+ input: "A",
+ expected: false
+ },
+ {
+ input: "Ab",
+ expected: false
+ },
+ {
+ input: "Ab-ad",
+ expected: false
+ },
+ {
+ input: "ad-Az",
+ expected: false
+ },
+ {
+ input: "ad- z",
+ expected: false
+ },
+ {
+ input: "ad-z ",
+ expected: false
+ },
+ {
+ input: "ad z",
+ expected: false
+ },
+ {
+ input: "ad--fz",
+ expected: false
+ },
+ {
+ input: "-a-b-c",
+ expected: false
+ },
+ {
+ input: "ad-fz",
+ expected: true
+ },
+ {
+ input: "ad",
+ expected: true
+ },
+ {
+ input: "a-b-c",
+ expected: true
+ },
+ ];
+
+ for (let test of tests) {
+ let result = isKebabCase(test.input);
+ is(result, test.expected, `${test.input} should${test.expected === false ? "n't" : ""} be a kebab-case string`);
+ }
+ }
+
+ async function doTest() {
+ ok(adjustCertInformation, "adjustCertInformation should be available in this context");
+ ok(parseOutput, "parseOutput should be available in this context");
+ is(typeof(parseOutput), 'object', "parseOutput must be an object");
+
+ validateIsKebabCase();
+
+ for (let cert of parseOutput) {
+ let adjustedCerts = adjustCertInformation(cert);
+ adjustedCerts.certItems.forEach(item => {
+ ok(isKebabCase(item.sectionId), `${item.sectionId} should be a valid kebab-case string`);
+ item.sectionItems.forEach(element => {
+ ok(isKebabCase(element.label), `${element.label} should be a valid kebab-case string`);
+ });
+ });
+ }
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ doTest();
+
+ </script>
+</body>
+</html>