import { __commonJS } from "../../../_virtual/rolldown_runtime.mjs";
import { require_forge } from "./forge.mjs";
import { require_util } from "./util.mjs";
import { require_aes } from "./aes.mjs";
import { require_oids } from "./oids.mjs";
import { require_asn1 } from "./asn1.mjs";
import { require_md } from "./md.mjs";
import { require_pem } from "./pem.mjs";
import { require_des } from "./des.mjs";
import { require_rsa } from "./rsa.mjs";
import { require_mgf } from "./mgf.mjs";
import { require_pss } from "./pss.mjs";

//#region ../../node_modules/node-forge/lib/x509.js
var require_x509 = /* @__PURE__ */ __commonJS({ "../../node_modules/node-forge/lib/x509.js": ((exports, module) => {
	/**
	* Javascript implementation of X.509 and related components (such as
	* Certification Signing Requests) of a Public Key Infrastructure.
	*
	* @author Dave Longley
	*
	* Copyright (c) 2010-2014 Digital Bazaar, Inc.
	*
	* The ASN.1 representation of an X.509v3 certificate is as follows
	* (see RFC 2459):
	*
	* Certificate ::= SEQUENCE {
	*   tbsCertificate       TBSCertificate,
	*   signatureAlgorithm   AlgorithmIdentifier,
	*   signatureValue       BIT STRING
	* }
	*
	* 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 shall be v2 or v3
	*   subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
	*                        -- If present, version shall be v2 or v3
	*   extensions      [3]  EXPLICIT Extensions OPTIONAL
	*                        -- If present, version shall be v3
	* }
	*
	* Version ::= INTEGER  { v1(0), v2(1), v3(2) }
	*
	* CertificateSerialNumber ::= INTEGER
	*
	* Name ::= CHOICE {
	*   // only one possible choice for now
	*   RDNSequence
	* }
	*
	* RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
	*
	* RelativeDistinguishedName ::= SET OF AttributeTypeAndValue
	*
	* AttributeTypeAndValue ::= SEQUENCE {
	*   type     AttributeType,
	*   value    AttributeValue
	* }
	* AttributeType ::= OBJECT IDENTIFIER
	* AttributeValue ::= ANY DEFINED BY AttributeType
	*
	* Validity ::= SEQUENCE {
	*   notBefore      Time,
	*   notAfter       Time
	* }
	*
	* Time ::= CHOICE {
	*   utcTime        UTCTime,
	*   generalTime    GeneralizedTime
	* }
	*
	* UniqueIdentifier ::= BIT STRING
	*
	* SubjectPublicKeyInfo ::= SEQUENCE {
	*   algorithm            AlgorithmIdentifier,
	*   subjectPublicKey     BIT STRING
	* }
	*
	* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
	*
	* Extension ::= SEQUENCE {
	*   extnID      OBJECT IDENTIFIER,
	*   critical    BOOLEAN DEFAULT FALSE,
	*   extnValue   OCTET STRING
	* }
	*
	* The only key algorithm currently supported for PKI is RSA.
	*
	* RSASSA-PSS signatures are described in RFC 3447 and RFC 4055.
	*
	* PKCS#10 v1.7 describes certificate signing requests:
	*
	* CertificationRequestInfo:
	*
	* CertificationRequestInfo ::= SEQUENCE {
	*   version       INTEGER { v1(0) } (v1,...),
	*   subject       Name,
	*   subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
	*   attributes    [0] Attributes{{ CRIAttributes }}
	* }
	*
	* Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
	*
	* CRIAttributes  ATTRIBUTE  ::= {
	*   ... -- add any locally defined attributes here -- }
	*
	* Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
	*   type   ATTRIBUTE.&id({IOSet}),
	*   values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type})
	* }
	*
	* CertificationRequest ::= SEQUENCE {
	*   certificationRequestInfo CertificationRequestInfo,
	*   signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }},
	*   signature          BIT STRING
	* }
	*/
	var forge = require_forge();
	require_aes();
	require_asn1();
	require_des();
	require_md();
	require_mgf();
	require_oids();
	require_pem();
	require_pss();
	require_rsa();
	require_util();
	var asn1 = forge.asn1;
	var pki = module.exports = forge.pki = forge.pki || {};
	var oids = pki.oids;
	var _shortNames = {};
	_shortNames["CN"] = oids["commonName"];
	_shortNames["commonName"] = "CN";
	_shortNames["C"] = oids["countryName"];
	_shortNames["countryName"] = "C";
	_shortNames["L"] = oids["localityName"];
	_shortNames["localityName"] = "L";
	_shortNames["ST"] = oids["stateOrProvinceName"];
	_shortNames["stateOrProvinceName"] = "ST";
	_shortNames["O"] = oids["organizationName"];
	_shortNames["organizationName"] = "O";
	_shortNames["OU"] = oids["organizationalUnitName"];
	_shortNames["organizationalUnitName"] = "OU";
	_shortNames["E"] = oids["emailAddress"];
	_shortNames["emailAddress"] = "E";
	var publicKeyValidator = forge.pki.rsa.publicKeyValidator;
	var x509CertificateValidator = {
		name: "Certificate",
		tagClass: asn1.Class.UNIVERSAL,
		type: asn1.Type.SEQUENCE,
		constructed: true,
		value: [
			{
				name: "Certificate.TBSCertificate",
				tagClass: asn1.Class.UNIVERSAL,
				type: asn1.Type.SEQUENCE,
				constructed: true,
				captureAsn1: "tbsCertificate",
				value: [
					{
						name: "Certificate.TBSCertificate.version",
						tagClass: asn1.Class.CONTEXT_SPECIFIC,
						type: 0,
						constructed: true,
						optional: true,
						value: [{
							name: "Certificate.TBSCertificate.version.integer",
							tagClass: asn1.Class.UNIVERSAL,
							type: asn1.Type.INTEGER,
							constructed: false,
							capture: "certVersion"
						}]
					},
					{
						name: "Certificate.TBSCertificate.serialNumber",
						tagClass: asn1.Class.UNIVERSAL,
						type: asn1.Type.INTEGER,
						constructed: false,
						capture: "certSerialNumber"
					},
					{
						name: "Certificate.TBSCertificate.signature",
						tagClass: asn1.Class.UNIVERSAL,
						type: asn1.Type.SEQUENCE,
						constructed: true,
						value: [{
							name: "Certificate.TBSCertificate.signature.algorithm",
							tagClass: asn1.Class.UNIVERSAL,
							type: asn1.Type.OID,
							constructed: false,
							capture: "certinfoSignatureOid"
						}, {
							name: "Certificate.TBSCertificate.signature.parameters",
							tagClass: asn1.Class.UNIVERSAL,
							optional: true,
							captureAsn1: "certinfoSignatureParams"
						}]
					},
					{
						name: "Certificate.TBSCertificate.issuer",
						tagClass: asn1.Class.UNIVERSAL,
						type: asn1.Type.SEQUENCE,
						constructed: true,
						captureAsn1: "certIssuer"
					},
					{
						name: "Certificate.TBSCertificate.validity",
						tagClass: asn1.Class.UNIVERSAL,
						type: asn1.Type.SEQUENCE,
						constructed: true,
						value: [
							{
								name: "Certificate.TBSCertificate.validity.notBefore (utc)",
								tagClass: asn1.Class.UNIVERSAL,
								type: asn1.Type.UTCTIME,
								constructed: false,
								optional: true,
								capture: "certValidity1UTCTime"
							},
							{
								name: "Certificate.TBSCertificate.validity.notBefore (generalized)",
								tagClass: asn1.Class.UNIVERSAL,
								type: asn1.Type.GENERALIZEDTIME,
								constructed: false,
								optional: true,
								capture: "certValidity2GeneralizedTime"
							},
							{
								name: "Certificate.TBSCertificate.validity.notAfter (utc)",
								tagClass: asn1.Class.UNIVERSAL,
								type: asn1.Type.UTCTIME,
								constructed: false,
								optional: true,
								capture: "certValidity3UTCTime"
							},
							{
								name: "Certificate.TBSCertificate.validity.notAfter (generalized)",
								tagClass: asn1.Class.UNIVERSAL,
								type: asn1.Type.GENERALIZEDTIME,
								constructed: false,
								optional: true,
								capture: "certValidity4GeneralizedTime"
							}
						]
					},
					{
						name: "Certificate.TBSCertificate.subject",
						tagClass: asn1.Class.UNIVERSAL,
						type: asn1.Type.SEQUENCE,
						constructed: true,
						captureAsn1: "certSubject"
					},
					publicKeyValidator,
					{
						name: "Certificate.TBSCertificate.issuerUniqueID",
						tagClass: asn1.Class.CONTEXT_SPECIFIC,
						type: 1,
						constructed: true,
						optional: true,
						value: [{
							name: "Certificate.TBSCertificate.issuerUniqueID.id",
							tagClass: asn1.Class.UNIVERSAL,
							type: asn1.Type.BITSTRING,
							constructed: false,
							captureBitStringValue: "certIssuerUniqueId"
						}]
					},
					{
						name: "Certificate.TBSCertificate.subjectUniqueID",
						tagClass: asn1.Class.CONTEXT_SPECIFIC,
						type: 2,
						constructed: true,
						optional: true,
						value: [{
							name: "Certificate.TBSCertificate.subjectUniqueID.id",
							tagClass: asn1.Class.UNIVERSAL,
							type: asn1.Type.BITSTRING,
							constructed: false,
							captureBitStringValue: "certSubjectUniqueId"
						}]
					},
					{
						name: "Certificate.TBSCertificate.extensions",
						tagClass: asn1.Class.CONTEXT_SPECIFIC,
						type: 3,
						constructed: true,
						captureAsn1: "certExtensions",
						optional: true
					}
				]
			},
			{
				name: "Certificate.signatureAlgorithm",
				tagClass: asn1.Class.UNIVERSAL,
				type: asn1.Type.SEQUENCE,
				constructed: true,
				value: [{
					name: "Certificate.signatureAlgorithm.algorithm",
					tagClass: asn1.Class.UNIVERSAL,
					type: asn1.Type.OID,
					constructed: false,
					capture: "certSignatureOid"
				}, {
					name: "Certificate.TBSCertificate.signature.parameters",
					tagClass: asn1.Class.UNIVERSAL,
					optional: true,
					captureAsn1: "certSignatureParams"
				}]
			},
			{
				name: "Certificate.signatureValue",
				tagClass: asn1.Class.UNIVERSAL,
				type: asn1.Type.BITSTRING,
				constructed: false,
				captureBitStringValue: "certSignature"
			}
		]
	};
	var rsassaPssParameterValidator = {
		name: "rsapss",
		tagClass: asn1.Class.UNIVERSAL,
		type: asn1.Type.SEQUENCE,
		constructed: true,
		value: [
			{
				name: "rsapss.hashAlgorithm",
				tagClass: asn1.Class.CONTEXT_SPECIFIC,
				type: 0,
				constructed: true,
				value: [{
					name: "rsapss.hashAlgorithm.AlgorithmIdentifier",
					tagClass: asn1.Class.UNIVERSAL,
					type: asn1.Class.SEQUENCE,
					constructed: true,
					optional: true,
					value: [{
						name: "rsapss.hashAlgorithm.AlgorithmIdentifier.algorithm",
						tagClass: asn1.Class.UNIVERSAL,
						type: asn1.Type.OID,
						constructed: false,
						capture: "hashOid"
					}]
				}]
			},
			{
				name: "rsapss.maskGenAlgorithm",
				tagClass: asn1.Class.CONTEXT_SPECIFIC,
				type: 1,
				constructed: true,
				value: [{
					name: "rsapss.maskGenAlgorithm.AlgorithmIdentifier",
					tagClass: asn1.Class.UNIVERSAL,
					type: asn1.Class.SEQUENCE,
					constructed: true,
					optional: true,
					value: [{
						name: "rsapss.maskGenAlgorithm.AlgorithmIdentifier.algorithm",
						tagClass: asn1.Class.UNIVERSAL,
						type: asn1.Type.OID,
						constructed: false,
						capture: "maskGenOid"
					}, {
						name: "rsapss.maskGenAlgorithm.AlgorithmIdentifier.params",
						tagClass: asn1.Class.UNIVERSAL,
						type: asn1.Type.SEQUENCE,
						constructed: true,
						value: [{
							name: "rsapss.maskGenAlgorithm.AlgorithmIdentifier.params.algorithm",
							tagClass: asn1.Class.UNIVERSAL,
							type: asn1.Type.OID,
							constructed: false,
							capture: "maskGenHashOid"
						}]
					}]
				}]
			},
			{
				name: "rsapss.saltLength",
				tagClass: asn1.Class.CONTEXT_SPECIFIC,
				type: 2,
				optional: true,
				value: [{
					name: "rsapss.saltLength.saltLength",
					tagClass: asn1.Class.UNIVERSAL,
					type: asn1.Class.INTEGER,
					constructed: false,
					capture: "saltLength"
				}]
			},
			{
				name: "rsapss.trailerField",
				tagClass: asn1.Class.CONTEXT_SPECIFIC,
				type: 3,
				optional: true,
				value: [{
					name: "rsapss.trailer.trailer",
					tagClass: asn1.Class.UNIVERSAL,
					type: asn1.Class.INTEGER,
					constructed: false,
					capture: "trailer"
				}]
			}
		]
	};
	var certificationRequestInfoValidator = {
		name: "CertificationRequestInfo",
		tagClass: asn1.Class.UNIVERSAL,
		type: asn1.Type.SEQUENCE,
		constructed: true,
		captureAsn1: "certificationRequestInfo",
		value: [
			{
				name: "CertificationRequestInfo.integer",
				tagClass: asn1.Class.UNIVERSAL,
				type: asn1.Type.INTEGER,
				constructed: false,
				capture: "certificationRequestInfoVersion"
			},
			{
				name: "CertificationRequestInfo.subject",
				tagClass: asn1.Class.UNIVERSAL,
				type: asn1.Type.SEQUENCE,
				constructed: true,
				captureAsn1: "certificationRequestInfoSubject"
			},
			publicKeyValidator,
			{
				name: "CertificationRequestInfo.attributes",
				tagClass: asn1.Class.CONTEXT_SPECIFIC,
				type: 0,
				constructed: true,
				optional: true,
				capture: "certificationRequestInfoAttributes",
				value: [{
					name: "CertificationRequestInfo.attributes",
					tagClass: asn1.Class.UNIVERSAL,
					type: asn1.Type.SEQUENCE,
					constructed: true,
					value: [{
						name: "CertificationRequestInfo.attributes.type",
						tagClass: asn1.Class.UNIVERSAL,
						type: asn1.Type.OID,
						constructed: false
					}, {
						name: "CertificationRequestInfo.attributes.value",
						tagClass: asn1.Class.UNIVERSAL,
						type: asn1.Type.SET,
						constructed: true
					}]
				}]
			}
		]
	};
	var certificationRequestValidator = {
		name: "CertificationRequest",
		tagClass: asn1.Class.UNIVERSAL,
		type: asn1.Type.SEQUENCE,
		constructed: true,
		captureAsn1: "csr",
		value: [
			certificationRequestInfoValidator,
			{
				name: "CertificationRequest.signatureAlgorithm",
				tagClass: asn1.Class.UNIVERSAL,
				type: asn1.Type.SEQUENCE,
				constructed: true,
				value: [{
					name: "CertificationRequest.signatureAlgorithm.algorithm",
					tagClass: asn1.Class.UNIVERSAL,
					type: asn1.Type.OID,
					constructed: false,
					capture: "csrSignatureOid"
				}, {
					name: "CertificationRequest.signatureAlgorithm.parameters",
					tagClass: asn1.Class.UNIVERSAL,
					optional: true,
					captureAsn1: "csrSignatureParams"
				}]
			},
			{
				name: "CertificationRequest.signature",
				tagClass: asn1.Class.UNIVERSAL,
				type: asn1.Type.BITSTRING,
				constructed: false,
				captureBitStringValue: "csrSignature"
			}
		]
	};
	/**
	* Converts an RDNSequence of ASN.1 DER-encoded RelativeDistinguishedName
	* sets into an array with objects that have type and value properties.
	*
	* @param rdn the RDNSequence to convert.
	* @param md a message digest to append type and value to if provided.
	*/
	pki.RDNAttributesAsArray = function(rdn, md) {
		var rval = [];
		var set, attr, obj;
		for (var si = 0; si < rdn.value.length; ++si) {
			set = rdn.value[si];
			for (var i = 0; i < set.value.length; ++i) {
				obj = {};
				attr = set.value[i];
				obj.type = asn1.derToOid(attr.value[0].value);
				obj.value = attr.value[1].value;
				obj.valueTagClass = attr.value[1].type;
				if (obj.type in oids) {
					obj.name = oids[obj.type];
					if (obj.name in _shortNames) obj.shortName = _shortNames[obj.name];
				}
				if (md) {
					md.update(obj.type);
					md.update(obj.value);
				}
				rval.push(obj);
			}
		}
		return rval;
	};
	/**
	* Converts ASN.1 CRIAttributes into an array with objects that have type and
	* value properties.
	*
	* @param attributes the CRIAttributes to convert.
	*/
	pki.CRIAttributesAsArray = function(attributes) {
		var rval = [];
		for (var si = 0; si < attributes.length; ++si) {
			var seq = attributes[si];
			var type = asn1.derToOid(seq.value[0].value);
			var values = seq.value[1].value;
			for (var vi = 0; vi < values.length; ++vi) {
				var obj = {};
				obj.type = type;
				obj.value = values[vi].value;
				obj.valueTagClass = values[vi].type;
				if (obj.type in oids) {
					obj.name = oids[obj.type];
					if (obj.name in _shortNames) obj.shortName = _shortNames[obj.name];
				}
				if (obj.type === oids.extensionRequest) {
					obj.extensions = [];
					for (var ei = 0; ei < obj.value.length; ++ei) obj.extensions.push(pki.certificateExtensionFromAsn1(obj.value[ei]));
				}
				rval.push(obj);
			}
		}
		return rval;
	};
	/**
	* Gets an issuer or subject attribute from its name, type, or short name.
	*
	* @param obj the issuer or subject object.
	* @param options a short name string or an object with:
	*          shortName the short name for the attribute.
	*          name the name for the attribute.
	*          type the type for the attribute.
	*
	* @return the attribute.
	*/
	function _getAttribute(obj, options) {
		if (typeof options === "string") options = { shortName: options };
		var rval = null;
		var attr;
		for (var i = 0; rval === null && i < obj.attributes.length; ++i) {
			attr = obj.attributes[i];
			if (options.type && options.type === attr.type) rval = attr;
			else if (options.name && options.name === attr.name) rval = attr;
			else if (options.shortName && options.shortName === attr.shortName) rval = attr;
		}
		return rval;
	}
	/**
	* Converts signature parameters from ASN.1 structure.
	*
	* Currently only RSASSA-PSS supported.  The PKCS#1 v1.5 signature scheme had
	* no parameters.
	*
	* RSASSA-PSS-params  ::=  SEQUENCE  {
	*   hashAlgorithm      [0] HashAlgorithm DEFAULT
	*                             sha1Identifier,
	*   maskGenAlgorithm   [1] MaskGenAlgorithm DEFAULT
	*                             mgf1SHA1Identifier,
	*   saltLength         [2] INTEGER DEFAULT 20,
	*   trailerField       [3] INTEGER DEFAULT 1
	* }
	*
	* HashAlgorithm  ::=  AlgorithmIdentifier
	*
	* MaskGenAlgorithm  ::=  AlgorithmIdentifier
	*
	* AlgorithmIdentifer ::= SEQUENCE {
	*   algorithm OBJECT IDENTIFIER,
	*   parameters ANY DEFINED BY algorithm OPTIONAL
	* }
	*
	* @param oid The OID specifying the signature algorithm
	* @param obj The ASN.1 structure holding the parameters
	* @param fillDefaults Whether to use return default values where omitted
	* @return signature parameter object
	*/
	var _readSignatureParameters = function(oid, obj, fillDefaults) {
		var params = {};
		if (oid !== oids["RSASSA-PSS"]) return params;
		if (fillDefaults) params = {
			hash: { algorithmOid: oids["sha1"] },
			mgf: {
				algorithmOid: oids["mgf1"],
				hash: { algorithmOid: oids["sha1"] }
			},
			saltLength: 20
		};
		var capture = {};
		var errors = [];
		if (!asn1.validate(obj, rsassaPssParameterValidator, capture, errors)) {
			var error = /* @__PURE__ */ new Error("Cannot read RSASSA-PSS parameter block.");
			error.errors = errors;
			throw error;
		}
		if (capture.hashOid !== void 0) {
			params.hash = params.hash || {};
			params.hash.algorithmOid = asn1.derToOid(capture.hashOid);
		}
		if (capture.maskGenOid !== void 0) {
			params.mgf = params.mgf || {};
			params.mgf.algorithmOid = asn1.derToOid(capture.maskGenOid);
			params.mgf.hash = params.mgf.hash || {};
			params.mgf.hash.algorithmOid = asn1.derToOid(capture.maskGenHashOid);
		}
		if (capture.saltLength !== void 0) params.saltLength = capture.saltLength.charCodeAt(0);
		return params;
	};
	/**
	* Create signature digest for OID.
	*
	* @param options
	*   signatureOid: the OID specifying the signature algorithm.
	*   type: a human readable type for error messages
	* @return a created md instance. throws if unknown oid.
	*/
	var _createSignatureDigest = function(options) {
		switch (oids[options.signatureOid]) {
			case "sha1WithRSAEncryption":
			case "sha1WithRSASignature": return forge.md.sha1.create();
			case "md5WithRSAEncryption": return forge.md.md5.create();
			case "sha256WithRSAEncryption": return forge.md.sha256.create();
			case "sha384WithRSAEncryption": return forge.md.sha384.create();
			case "sha512WithRSAEncryption": return forge.md.sha512.create();
			case "RSASSA-PSS": return forge.md.sha256.create();
			default:
				var error = /* @__PURE__ */ new Error("Could not compute " + options.type + " digest. Unknown signature OID.");
				error.signatureOid = options.signatureOid;
				throw error;
		}
	};
	/**
	* Verify signature on certificate or CSR.
	*
	* @param options:
	*   certificate the certificate or CSR to verify.
	*   md the signature digest.
	*   signature the signature
	* @return a created md instance. throws if unknown oid.
	*/
	var _verifySignature = function(options) {
		var cert = options.certificate;
		var scheme;
		switch (cert.signatureOid) {
			case oids.sha1WithRSAEncryption:
			case oids.sha1WithRSASignature: break;
			case oids["RSASSA-PSS"]:
				var hash = oids[cert.signatureParameters.mgf.hash.algorithmOid], mgf;
				if (hash === void 0 || forge.md[hash] === void 0) {
					var error = /* @__PURE__ */ new Error("Unsupported MGF hash function.");
					error.oid = cert.signatureParameters.mgf.hash.algorithmOid;
					error.name = hash;
					throw error;
				}
				mgf = oids[cert.signatureParameters.mgf.algorithmOid];
				if (mgf === void 0 || forge.mgf[mgf] === void 0) {
					var error = /* @__PURE__ */ new Error("Unsupported MGF function.");
					error.oid = cert.signatureParameters.mgf.algorithmOid;
					error.name = mgf;
					throw error;
				}
				mgf = forge.mgf[mgf].create(forge.md[hash].create());
				hash = oids[cert.signatureParameters.hash.algorithmOid];
				if (hash === void 0 || forge.md[hash] === void 0) {
					var error = /* @__PURE__ */ new Error("Unsupported RSASSA-PSS hash function.");
					error.oid = cert.signatureParameters.hash.algorithmOid;
					error.name = hash;
					throw error;
				}
				scheme = forge.pss.create(forge.md[hash].create(), mgf, cert.signatureParameters.saltLength);
				break;
		}
		return cert.publicKey.verify(options.md.digest().getBytes(), options.signature, scheme);
	};
	/**
	* Converts an X.509 certificate from PEM format.
	*
	* Note: If the certificate is to be verified then compute hash should
	* be set to true. This will scan the TBSCertificate part of the ASN.1
	* object while it is converted so it doesn't need to be converted back
	* to ASN.1-DER-encoding later.
	*
	* @param pem the PEM-formatted certificate.
	* @param computeHash true to compute the hash for verification.
	* @param strict true to be strict when checking ASN.1 value lengths, false to
	*          allow truncated values (default: true).
	*
	* @return the certificate.
	*/
	pki.certificateFromPem = function(pem, computeHash, strict) {
		var msg = forge.pem.decode(pem)[0];
		if (msg.type !== "CERTIFICATE" && msg.type !== "X509 CERTIFICATE" && msg.type !== "TRUSTED CERTIFICATE") {
			var error = /* @__PURE__ */ new Error("Could not convert certificate from PEM; PEM header type is not \"CERTIFICATE\", \"X509 CERTIFICATE\", or \"TRUSTED CERTIFICATE\".");
			error.headerType = msg.type;
			throw error;
		}
		if (msg.procType && msg.procType.type === "ENCRYPTED") throw new Error("Could not convert certificate from PEM; PEM is encrypted.");
		var obj = asn1.fromDer(msg.body, strict);
		return pki.certificateFromAsn1(obj, computeHash);
	};
	/**
	* Converts an X.509 certificate to PEM format.
	*
	* @param cert the certificate.
	* @param maxline the maximum characters per line, defaults to 64.
	*
	* @return the PEM-formatted certificate.
	*/
	pki.certificateToPem = function(cert, maxline) {
		var msg = {
			type: "CERTIFICATE",
			body: asn1.toDer(pki.certificateToAsn1(cert)).getBytes()
		};
		return forge.pem.encode(msg, { maxline });
	};
	/**
	* Converts an RSA public key from PEM format.
	*
	* @param pem the PEM-formatted public key.
	*
	* @return the public key.
	*/
	pki.publicKeyFromPem = function(pem) {
		var msg = forge.pem.decode(pem)[0];
		if (msg.type !== "PUBLIC KEY" && msg.type !== "RSA PUBLIC KEY") {
			var error = /* @__PURE__ */ new Error("Could not convert public key from PEM; PEM header type is not \"PUBLIC KEY\" or \"RSA PUBLIC KEY\".");
			error.headerType = msg.type;
			throw error;
		}
		if (msg.procType && msg.procType.type === "ENCRYPTED") throw new Error("Could not convert public key from PEM; PEM is encrypted.");
		var obj = asn1.fromDer(msg.body);
		return pki.publicKeyFromAsn1(obj);
	};
	/**
	* Converts an RSA public key to PEM format (using a SubjectPublicKeyInfo).
	*
	* @param key the public key.
	* @param maxline the maximum characters per line, defaults to 64.
	*
	* @return the PEM-formatted public key.
	*/
	pki.publicKeyToPem = function(key, maxline) {
		var msg = {
			type: "PUBLIC KEY",
			body: asn1.toDer(pki.publicKeyToAsn1(key)).getBytes()
		};
		return forge.pem.encode(msg, { maxline });
	};
	/**
	* Converts an RSA public key to PEM format (using an RSAPublicKey).
	*
	* @param key the public key.
	* @param maxline the maximum characters per line, defaults to 64.
	*
	* @return the PEM-formatted public key.
	*/
	pki.publicKeyToRSAPublicKeyPem = function(key, maxline) {
		var msg = {
			type: "RSA PUBLIC KEY",
			body: asn1.toDer(pki.publicKeyToRSAPublicKey(key)).getBytes()
		};
		return forge.pem.encode(msg, { maxline });
	};
	/**
	* Gets a fingerprint for the given public key.
	*
	* @param options the options to use.
	*          [md] the message digest object to use (defaults to forge.md.sha1).
	*          [type] the type of fingerprint, such as 'RSAPublicKey',
	*            'SubjectPublicKeyInfo' (defaults to 'RSAPublicKey').
	*          [encoding] an alternative output encoding, such as 'hex'
	*            (defaults to none, outputs a byte buffer).
	*          [delimiter] the delimiter to use between bytes for 'hex' encoded
	*            output, eg: ':' (defaults to none).
	*
	* @return the fingerprint as a byte buffer or other encoding based on options.
	*/
	pki.getPublicKeyFingerprint = function(key, options) {
		options = options || {};
		var md = options.md || forge.md.sha1.create();
		var type = options.type || "RSAPublicKey";
		var bytes;
		switch (type) {
			case "RSAPublicKey":
				bytes = asn1.toDer(pki.publicKeyToRSAPublicKey(key)).getBytes();
				break;
			case "SubjectPublicKeyInfo":
				bytes = asn1.toDer(pki.publicKeyToAsn1(key)).getBytes();
				break;
			default: throw new Error("Unknown fingerprint type \"" + options.type + "\".");
		}
		md.start();
		md.update(bytes);
		var digest = md.digest();
		if (options.encoding === "hex") {
			var hex = digest.toHex();
			if (options.delimiter) return hex.match(/.{2}/g).join(options.delimiter);
			return hex;
		} else if (options.encoding === "binary") return digest.getBytes();
		else if (options.encoding) throw new Error("Unknown encoding \"" + options.encoding + "\".");
		return digest;
	};
	/**
	* Converts a PKCS#10 certification request (CSR) from PEM format.
	*
	* Note: If the certification request is to be verified then compute hash
	* should be set to true. This will scan the CertificationRequestInfo part of
	* the ASN.1 object while it is converted so it doesn't need to be converted
	* back to ASN.1-DER-encoding later.
	*
	* @param pem the PEM-formatted certificate.
	* @param computeHash true to compute the hash for verification.
	* @param strict true to be strict when checking ASN.1 value lengths, false to
	*          allow truncated values (default: true).
	*
	* @return the certification request (CSR).
	*/
	pki.certificationRequestFromPem = function(pem, computeHash, strict) {
		var msg = forge.pem.decode(pem)[0];
		if (msg.type !== "CERTIFICATE REQUEST") {
			var error = /* @__PURE__ */ new Error("Could not convert certification request from PEM; PEM header type is not \"CERTIFICATE REQUEST\".");
			error.headerType = msg.type;
			throw error;
		}
		if (msg.procType && msg.procType.type === "ENCRYPTED") throw new Error("Could not convert certification request from PEM; PEM is encrypted.");
		var obj = asn1.fromDer(msg.body, strict);
		return pki.certificationRequestFromAsn1(obj, computeHash);
	};
	/**
	* Converts a PKCS#10 certification request (CSR) to PEM format.
	*
	* @param csr the certification request.
	* @param maxline the maximum characters per line, defaults to 64.
	*
	* @return the PEM-formatted certification request.
	*/
	pki.certificationRequestToPem = function(csr, maxline) {
		var msg = {
			type: "CERTIFICATE REQUEST",
			body: asn1.toDer(pki.certificationRequestToAsn1(csr)).getBytes()
		};
		return forge.pem.encode(msg, { maxline });
	};
	/**
	* Creates an empty X.509v3 RSA certificate.
	*
	* @return the certificate.
	*/
	pki.createCertificate = function() {
		var cert = {};
		cert.version = 2;
		cert.serialNumber = "00";
		cert.signatureOid = null;
		cert.signature = null;
		cert.siginfo = {};
		cert.siginfo.algorithmOid = null;
		cert.validity = {};
		cert.validity.notBefore = /* @__PURE__ */ new Date();
		cert.validity.notAfter = /* @__PURE__ */ new Date();
		cert.issuer = {};
		cert.issuer.getField = function(sn) {
			return _getAttribute(cert.issuer, sn);
		};
		cert.issuer.addField = function(attr) {
			_fillMissingFields([attr]);
			cert.issuer.attributes.push(attr);
		};
		cert.issuer.attributes = [];
		cert.issuer.hash = null;
		cert.subject = {};
		cert.subject.getField = function(sn) {
			return _getAttribute(cert.subject, sn);
		};
		cert.subject.addField = function(attr) {
			_fillMissingFields([attr]);
			cert.subject.attributes.push(attr);
		};
		cert.subject.attributes = [];
		cert.subject.hash = null;
		cert.extensions = [];
		cert.publicKey = null;
		cert.md = null;
		/**
		* Sets the subject of this certificate.
		*
		* @param attrs the array of subject attributes to use.
		* @param uniqueId an optional a unique ID to use.
		*/
		cert.setSubject = function(attrs, uniqueId) {
			_fillMissingFields(attrs);
			cert.subject.attributes = attrs;
			delete cert.subject.uniqueId;
			if (uniqueId) cert.subject.uniqueId = uniqueId;
			cert.subject.hash = null;
		};
		/**
		* Sets the issuer of this certificate.
		*
		* @param attrs the array of issuer attributes to use.
		* @param uniqueId an optional a unique ID to use.
		*/
		cert.setIssuer = function(attrs, uniqueId) {
			_fillMissingFields(attrs);
			cert.issuer.attributes = attrs;
			delete cert.issuer.uniqueId;
			if (uniqueId) cert.issuer.uniqueId = uniqueId;
			cert.issuer.hash = null;
		};
		/**
		* Sets the extensions of this certificate.
		*
		* @param exts the array of extensions to use.
		*/
		cert.setExtensions = function(exts) {
			for (var i = 0; i < exts.length; ++i) _fillMissingExtensionFields(exts[i], { cert });
			cert.extensions = exts;
		};
		/**
		* Gets an extension by its name or id.
		*
		* @param options the name to use or an object with:
		*          name the name to use.
		*          id the id to use.
		*
		* @return the extension or null if not found.
		*/
		cert.getExtension = function(options) {
			if (typeof options === "string") options = { name: options };
			var rval = null;
			var ext;
			for (var i = 0; rval === null && i < cert.extensions.length; ++i) {
				ext = cert.extensions[i];
				if (options.id && ext.id === options.id) rval = ext;
				else if (options.name && ext.name === options.name) rval = ext;
			}
			return rval;
		};
		/**
		* Signs this certificate using the given private key.
		*
		* @param key the private key to sign with.
		* @param md the message digest object to use (defaults to forge.md.sha1).
		*/
		cert.sign = function(key, md) {
			cert.md = md || forge.md.sha1.create();
			var algorithmOid = oids[cert.md.algorithm + "WithRSAEncryption"];
			if (!algorithmOid) {
				var error = /* @__PURE__ */ new Error("Could not compute certificate digest. Unknown message digest algorithm OID.");
				error.algorithm = cert.md.algorithm;
				throw error;
			}
			cert.signatureOid = cert.siginfo.algorithmOid = algorithmOid;
			cert.tbsCertificate = pki.getTBSCertificate(cert);
			var bytes = asn1.toDer(cert.tbsCertificate);
			cert.md.update(bytes.getBytes());
			cert.signature = key.sign(cert.md);
		};
		/**
		* Attempts verify the signature on the passed certificate using this
		* certificate's public key.
		*
		* @param child the certificate to verify.
		*
		* @return true if verified, false if not.
		*/
		cert.verify = function(child) {
			var rval = false;
			if (!cert.issued(child)) {
				var issuer = child.issuer;
				var subject = cert.subject;
				var error = /* @__PURE__ */ new Error("The parent certificate did not issue the given child certificate; the child certificate's issuer does not match the parent's subject.");
				error.expectedIssuer = subject.attributes;
				error.actualIssuer = issuer.attributes;
				throw error;
			}
			var md = child.md;
			if (md === null) {
				md = _createSignatureDigest({
					signatureOid: child.signatureOid,
					type: "certificate"
				});
				var tbsCertificate = child.tbsCertificate || pki.getTBSCertificate(child);
				var bytes = asn1.toDer(tbsCertificate);
				md.update(bytes.getBytes());
			}
			if (md !== null) rval = _verifySignature({
				certificate: cert,
				md,
				signature: child.signature
			});
			return rval;
		};
		/**
		* Returns true if this certificate's issuer matches the passed
		* certificate's subject. Note that no signature check is performed.
		*
		* @param parent the certificate to check.
		*
		* @return true if this certificate's issuer matches the passed certificate's
		*         subject.
		*/
		cert.isIssuer = function(parent) {
			var rval = false;
			var i = cert.issuer;
			var s = parent.subject;
			if (i.hash && s.hash) rval = i.hash === s.hash;
			else if (i.attributes.length === s.attributes.length) {
				rval = true;
				var iattr, sattr;
				for (var n = 0; rval && n < i.attributes.length; ++n) {
					iattr = i.attributes[n];
					sattr = s.attributes[n];
					if (iattr.type !== sattr.type || iattr.value !== sattr.value) rval = false;
				}
			}
			return rval;
		};
		/**
		* Returns true if this certificate's subject matches the issuer of the
		* given certificate). Note that not signature check is performed.
		*
		* @param child the certificate to check.
		*
		* @return true if this certificate's subject matches the passed
		*         certificate's issuer.
		*/
		cert.issued = function(child) {
			return child.isIssuer(cert);
		};
		/**
		* Generates the subjectKeyIdentifier for this certificate as byte buffer.
		*
		* @return the subjectKeyIdentifier for this certificate as byte buffer.
		*/
		cert.generateSubjectKeyIdentifier = function() {
			return pki.getPublicKeyFingerprint(cert.publicKey, { type: "RSAPublicKey" });
		};
		/**
		* Verifies the subjectKeyIdentifier extension value for this certificate
		* against its public key. If no extension is found, false will be
		* returned.
		*
		* @return true if verified, false if not.
		*/
		cert.verifySubjectKeyIdentifier = function() {
			var oid = oids["subjectKeyIdentifier"];
			for (var i = 0; i < cert.extensions.length; ++i) {
				var ext = cert.extensions[i];
				if (ext.id === oid) {
					var ski = cert.generateSubjectKeyIdentifier().getBytes();
					return forge.util.hexToBytes(ext.subjectKeyIdentifier) === ski;
				}
			}
			return false;
		};
		return cert;
	};
	/**
	* Converts an X.509v3 RSA certificate from an ASN.1 object.
	*
	* Note: If the certificate is to be verified then compute hash should
	* be set to true. There is currently no implementation for converting
	* a certificate back to ASN.1 so the TBSCertificate part of the ASN.1
	* object needs to be scanned before the cert object is created.
	*
	* @param obj the asn1 representation of an X.509v3 RSA certificate.
	* @param computeHash true to compute the hash for verification.
	*
	* @return the certificate.
	*/
	pki.certificateFromAsn1 = function(obj, computeHash) {
		var capture = {};
		var errors = [];
		if (!asn1.validate(obj, x509CertificateValidator, capture, errors)) {
			var error = /* @__PURE__ */ new Error("Cannot read X.509 certificate. ASN.1 object is not an X509v3 Certificate.");
			error.errors = errors;
			throw error;
		}
		if (asn1.derToOid(capture.publicKeyOid) !== pki.oids.rsaEncryption) throw new Error("Cannot read public key. OID is not RSA.");
		var cert = pki.createCertificate();
		cert.version = capture.certVersion ? capture.certVersion.charCodeAt(0) : 0;
		cert.serialNumber = forge.util.createBuffer(capture.certSerialNumber).toHex();
		cert.signatureOid = forge.asn1.derToOid(capture.certSignatureOid);
		cert.signatureParameters = _readSignatureParameters(cert.signatureOid, capture.certSignatureParams, true);
		cert.siginfo.algorithmOid = forge.asn1.derToOid(capture.certinfoSignatureOid);
		cert.siginfo.parameters = _readSignatureParameters(cert.siginfo.algorithmOid, capture.certinfoSignatureParams, false);
		cert.signature = capture.certSignature;
		var validity = [];
		if (capture.certValidity1UTCTime !== void 0) validity.push(asn1.utcTimeToDate(capture.certValidity1UTCTime));
		if (capture.certValidity2GeneralizedTime !== void 0) validity.push(asn1.generalizedTimeToDate(capture.certValidity2GeneralizedTime));
		if (capture.certValidity3UTCTime !== void 0) validity.push(asn1.utcTimeToDate(capture.certValidity3UTCTime));
		if (capture.certValidity4GeneralizedTime !== void 0) validity.push(asn1.generalizedTimeToDate(capture.certValidity4GeneralizedTime));
		if (validity.length > 2) throw new Error("Cannot read notBefore/notAfter validity times; more than two times were provided in the certificate.");
		if (validity.length < 2) throw new Error("Cannot read notBefore/notAfter validity times; they were not provided as either UTCTime or GeneralizedTime.");
		cert.validity.notBefore = validity[0];
		cert.validity.notAfter = validity[1];
		cert.tbsCertificate = capture.tbsCertificate;
		if (computeHash) {
			cert.md = _createSignatureDigest({
				signatureOid: cert.signatureOid,
				type: "certificate"
			});
			var bytes = asn1.toDer(cert.tbsCertificate);
			cert.md.update(bytes.getBytes());
		}
		var imd = forge.md.sha1.create();
		var ibytes = asn1.toDer(capture.certIssuer);
		imd.update(ibytes.getBytes());
		cert.issuer.getField = function(sn) {
			return _getAttribute(cert.issuer, sn);
		};
		cert.issuer.addField = function(attr) {
			_fillMissingFields([attr]);
			cert.issuer.attributes.push(attr);
		};
		cert.issuer.attributes = pki.RDNAttributesAsArray(capture.certIssuer);
		if (capture.certIssuerUniqueId) cert.issuer.uniqueId = capture.certIssuerUniqueId;
		cert.issuer.hash = imd.digest().toHex();
		var smd = forge.md.sha1.create();
		var sbytes = asn1.toDer(capture.certSubject);
		smd.update(sbytes.getBytes());
		cert.subject.getField = function(sn) {
			return _getAttribute(cert.subject, sn);
		};
		cert.subject.addField = function(attr) {
			_fillMissingFields([attr]);
			cert.subject.attributes.push(attr);
		};
		cert.subject.attributes = pki.RDNAttributesAsArray(capture.certSubject);
		if (capture.certSubjectUniqueId) cert.subject.uniqueId = capture.certSubjectUniqueId;
		cert.subject.hash = smd.digest().toHex();
		if (capture.certExtensions) cert.extensions = pki.certificateExtensionsFromAsn1(capture.certExtensions);
		else cert.extensions = [];
		cert.publicKey = pki.publicKeyFromAsn1(capture.subjectPublicKeyInfo);
		return cert;
	};
	/**
	* Converts an ASN.1 extensions object (with extension sequences as its
	* values) into an array of extension objects with types and values.
	*
	* Supported extensions:
	*
	* id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
	* KeyUsage ::= BIT STRING {
	*   digitalSignature        (0),
	*   nonRepudiation          (1),
	*   keyEncipherment         (2),
	*   dataEncipherment        (3),
	*   keyAgreement            (4),
	*   keyCertSign             (5),
	*   cRLSign                 (6),
	*   encipherOnly            (7),
	*   decipherOnly            (8)
	* }
	*
	* id-ce-basicConstraints OBJECT IDENTIFIER ::=  { id-ce 19 }
	* BasicConstraints ::= SEQUENCE {
	*   cA                      BOOLEAN DEFAULT FALSE,
	*   pathLenConstraint       INTEGER (0..MAX) OPTIONAL
	* }
	*
	* subjectAltName EXTENSION ::= {
	*   SYNTAX GeneralNames
	*   IDENTIFIED BY id-ce-subjectAltName
	* }
	*
	* GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
	*
	* GeneralName ::= CHOICE {
	*   otherName      [0] INSTANCE OF OTHER-NAME,
	*   rfc822Name     [1] IA5String,
	*   dNSName        [2] IA5String,
	*   x400Address    [3] ORAddress,
	*   directoryName  [4] Name,
	*   ediPartyName   [5] EDIPartyName,
	*   uniformResourceIdentifier [6] IA5String,
	*   IPAddress      [7] OCTET STRING,
	*   registeredID   [8] OBJECT IDENTIFIER
	* }
	*
	* OTHER-NAME ::= TYPE-IDENTIFIER
	*
	* EDIPartyName ::= SEQUENCE {
	*   nameAssigner [0] DirectoryString {ub-name} OPTIONAL,
	*   partyName    [1] DirectoryString {ub-name}
	* }
	*
	* @param exts the extensions ASN.1 with extension sequences to parse.
	*
	* @return the array.
	*/
	pki.certificateExtensionsFromAsn1 = function(exts) {
		var rval = [];
		for (var i = 0; i < exts.value.length; ++i) {
			var extseq = exts.value[i];
			for (var ei = 0; ei < extseq.value.length; ++ei) rval.push(pki.certificateExtensionFromAsn1(extseq.value[ei]));
		}
		return rval;
	};
	/**
	* Parses a single certificate extension from ASN.1.
	*
	* @param ext the extension in ASN.1 format.
	*
	* @return the parsed extension as an object.
	*/
	pki.certificateExtensionFromAsn1 = function(ext) {
		var e = {};
		e.id = asn1.derToOid(ext.value[0].value);
		e.critical = false;
		if (ext.value[1].type === asn1.Type.BOOLEAN) {
			e.critical = ext.value[1].value.charCodeAt(0) !== 0;
			e.value = ext.value[2].value;
		} else e.value = ext.value[1].value;
		if (e.id in oids) {
			e.name = oids[e.id];
			if (e.name === "keyUsage") {
				var ev = asn1.fromDer(e.value);
				var b2 = 0;
				var b3 = 0;
				if (ev.value.length > 1) {
					b2 = ev.value.charCodeAt(1);
					b3 = ev.value.length > 2 ? ev.value.charCodeAt(2) : 0;
				}
				e.digitalSignature = (b2 & 128) === 128;
				e.nonRepudiation = (b2 & 64) === 64;
				e.keyEncipherment = (b2 & 32) === 32;
				e.dataEncipherment = (b2 & 16) === 16;
				e.keyAgreement = (b2 & 8) === 8;
				e.keyCertSign = (b2 & 4) === 4;
				e.cRLSign = (b2 & 2) === 2;
				e.encipherOnly = (b2 & 1) === 1;
				e.decipherOnly = (b3 & 128) === 128;
			} else if (e.name === "basicConstraints") {
				var ev = asn1.fromDer(e.value);
				if (ev.value.length > 0 && ev.value[0].type === asn1.Type.BOOLEAN) e.cA = ev.value[0].value.charCodeAt(0) !== 0;
				else e.cA = false;
				var value = null;
				if (ev.value.length > 0 && ev.value[0].type === asn1.Type.INTEGER) value = ev.value[0].value;
				else if (ev.value.length > 1) value = ev.value[1].value;
				if (value !== null) e.pathLenConstraint = asn1.derToInteger(value);
			} else if (e.name === "extKeyUsage") {
				var ev = asn1.fromDer(e.value);
				for (var vi = 0; vi < ev.value.length; ++vi) {
					var oid = asn1.derToOid(ev.value[vi].value);
					if (oid in oids) e[oids[oid]] = true;
					else e[oid] = true;
				}
			} else if (e.name === "nsCertType") {
				var ev = asn1.fromDer(e.value);
				var b2 = 0;
				if (ev.value.length > 1) b2 = ev.value.charCodeAt(1);
				e.client = (b2 & 128) === 128;
				e.server = (b2 & 64) === 64;
				e.email = (b2 & 32) === 32;
				e.objsign = (b2 & 16) === 16;
				e.reserved = (b2 & 8) === 8;
				e.sslCA = (b2 & 4) === 4;
				e.emailCA = (b2 & 2) === 2;
				e.objCA = (b2 & 1) === 1;
			} else if (e.name === "subjectAltName" || e.name === "issuerAltName") {
				e.altNames = [];
				var gn;
				var ev = asn1.fromDer(e.value);
				for (var n = 0; n < ev.value.length; ++n) {
					gn = ev.value[n];
					var altName = {
						type: gn.type,
						value: gn.value
					};
					e.altNames.push(altName);
					switch (gn.type) {
						case 1:
						case 2:
						case 6: break;
						case 7:
							altName.ip = forge.util.bytesToIP(gn.value);
							break;
						case 8:
							altName.oid = asn1.derToOid(gn.value);
							break;
						default:
					}
				}
			} else if (e.name === "subjectKeyIdentifier") {
				var ev = asn1.fromDer(e.value);
				e.subjectKeyIdentifier = forge.util.bytesToHex(ev.value);
			}
		}
		return e;
	};
	/**
	* Converts a PKCS#10 certification request (CSR) from an ASN.1 object.
	*
	* Note: If the certification request is to be verified then compute hash
	* should be set to true. There is currently no implementation for converting
	* a certificate back to ASN.1 so the CertificationRequestInfo part of the
	* ASN.1 object needs to be scanned before the csr object is created.
	*
	* @param obj the asn1 representation of a PKCS#10 certification request (CSR).
	* @param computeHash true to compute the hash for verification.
	*
	* @return the certification request (CSR).
	*/
	pki.certificationRequestFromAsn1 = function(obj, computeHash) {
		var capture = {};
		var errors = [];
		if (!asn1.validate(obj, certificationRequestValidator, capture, errors)) {
			var error = /* @__PURE__ */ new Error("Cannot read PKCS#10 certificate request. ASN.1 object is not a PKCS#10 CertificationRequest.");
			error.errors = errors;
			throw error;
		}
		if (asn1.derToOid(capture.publicKeyOid) !== pki.oids.rsaEncryption) throw new Error("Cannot read public key. OID is not RSA.");
		var csr = pki.createCertificationRequest();
		csr.version = capture.csrVersion ? capture.csrVersion.charCodeAt(0) : 0;
		csr.signatureOid = forge.asn1.derToOid(capture.csrSignatureOid);
		csr.signatureParameters = _readSignatureParameters(csr.signatureOid, capture.csrSignatureParams, true);
		csr.siginfo.algorithmOid = forge.asn1.derToOid(capture.csrSignatureOid);
		csr.siginfo.parameters = _readSignatureParameters(csr.siginfo.algorithmOid, capture.csrSignatureParams, false);
		csr.signature = capture.csrSignature;
		csr.certificationRequestInfo = capture.certificationRequestInfo;
		if (computeHash) {
			csr.md = _createSignatureDigest({
				signatureOid: csr.signatureOid,
				type: "certification request"
			});
			var bytes = asn1.toDer(csr.certificationRequestInfo);
			csr.md.update(bytes.getBytes());
		}
		var smd = forge.md.sha1.create();
		csr.subject.getField = function(sn) {
			return _getAttribute(csr.subject, sn);
		};
		csr.subject.addField = function(attr) {
			_fillMissingFields([attr]);
			csr.subject.attributes.push(attr);
		};
		csr.subject.attributes = pki.RDNAttributesAsArray(capture.certificationRequestInfoSubject, smd);
		csr.subject.hash = smd.digest().toHex();
		csr.publicKey = pki.publicKeyFromAsn1(capture.subjectPublicKeyInfo);
		csr.getAttribute = function(sn) {
			return _getAttribute(csr, sn);
		};
		csr.addAttribute = function(attr) {
			_fillMissingFields([attr]);
			csr.attributes.push(attr);
		};
		csr.attributes = pki.CRIAttributesAsArray(capture.certificationRequestInfoAttributes || []);
		return csr;
	};
	/**
	* Creates an empty certification request (a CSR or certificate signing
	* request). Once created, its public key and attributes can be set and then
	* it can be signed.
	*
	* @return the empty certification request.
	*/
	pki.createCertificationRequest = function() {
		var csr = {};
		csr.version = 0;
		csr.signatureOid = null;
		csr.signature = null;
		csr.siginfo = {};
		csr.siginfo.algorithmOid = null;
		csr.subject = {};
		csr.subject.getField = function(sn) {
			return _getAttribute(csr.subject, sn);
		};
		csr.subject.addField = function(attr) {
			_fillMissingFields([attr]);
			csr.subject.attributes.push(attr);
		};
		csr.subject.attributes = [];
		csr.subject.hash = null;
		csr.publicKey = null;
		csr.attributes = [];
		csr.getAttribute = function(sn) {
			return _getAttribute(csr, sn);
		};
		csr.addAttribute = function(attr) {
			_fillMissingFields([attr]);
			csr.attributes.push(attr);
		};
		csr.md = null;
		/**
		* Sets the subject of this certification request.
		*
		* @param attrs the array of subject attributes to use.
		*/
		csr.setSubject = function(attrs) {
			_fillMissingFields(attrs);
			csr.subject.attributes = attrs;
			csr.subject.hash = null;
		};
		/**
		* Sets the attributes of this certification request.
		*
		* @param attrs the array of attributes to use.
		*/
		csr.setAttributes = function(attrs) {
			_fillMissingFields(attrs);
			csr.attributes = attrs;
		};
		/**
		* Signs this certification request using the given private key.
		*
		* @param key the private key to sign with.
		* @param md the message digest object to use (defaults to forge.md.sha1).
		*/
		csr.sign = function(key, md) {
			csr.md = md || forge.md.sha1.create();
			var algorithmOid = oids[csr.md.algorithm + "WithRSAEncryption"];
			if (!algorithmOid) {
				var error = /* @__PURE__ */ new Error("Could not compute certification request digest. Unknown message digest algorithm OID.");
				error.algorithm = csr.md.algorithm;
				throw error;
			}
			csr.signatureOid = csr.siginfo.algorithmOid = algorithmOid;
			csr.certificationRequestInfo = pki.getCertificationRequestInfo(csr);
			var bytes = asn1.toDer(csr.certificationRequestInfo);
			csr.md.update(bytes.getBytes());
			csr.signature = key.sign(csr.md);
		};
		/**
		* Attempts verify the signature on the passed certification request using
		* its public key.
		*
		* A CSR that has been exported to a file in PEM format can be verified using
		* OpenSSL using this command:
		*
		* openssl req -in <the-csr-pem-file> -verify -noout -text
		*
		* @return true if verified, false if not.
		*/
		csr.verify = function() {
			var rval = false;
			var md = csr.md;
			if (md === null) {
				md = _createSignatureDigest({
					signatureOid: csr.signatureOid,
					type: "certification request"
				});
				var cri = csr.certificationRequestInfo || pki.getCertificationRequestInfo(csr);
				var bytes = asn1.toDer(cri);
				md.update(bytes.getBytes());
			}
			if (md !== null) rval = _verifySignature({
				certificate: csr,
				md,
				signature: csr.signature
			});
			return rval;
		};
		return csr;
	};
	/**
	* Converts an X.509 subject or issuer to an ASN.1 RDNSequence.
	*
	* @param obj the subject or issuer (distinguished name).
	*
	* @return the ASN.1 RDNSequence.
	*/
	function _dnToAsn1(obj) {
		var rval = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
		var attr, set;
		var attrs = obj.attributes;
		for (var i = 0; i < attrs.length; ++i) {
			attr = attrs[i];
			var value = attr.value;
			var valueTagClass = asn1.Type.PRINTABLESTRING;
			if ("valueTagClass" in attr) {
				valueTagClass = attr.valueTagClass;
				if (valueTagClass === asn1.Type.UTF8) value = forge.util.encodeUtf8(value);
			}
			set = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, [asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, asn1.oidToDer(attr.type).getBytes()), asn1.create(asn1.Class.UNIVERSAL, valueTagClass, false, value)])]);
			rval.value.push(set);
		}
		return rval;
	}
	/**
	* Fills in missing fields in attributes.
	*
	* @param attrs the attributes to fill missing fields in.
	*/
	function _fillMissingFields(attrs) {
		var attr;
		for (var i = 0; i < attrs.length; ++i) {
			attr = attrs[i];
			if (typeof attr.name === "undefined") {
				if (attr.type && attr.type in pki.oids) attr.name = pki.oids[attr.type];
				else if (attr.shortName && attr.shortName in _shortNames) attr.name = pki.oids[_shortNames[attr.shortName]];
			}
			if (typeof attr.type === "undefined") if (attr.name && attr.name in pki.oids) attr.type = pki.oids[attr.name];
			else {
				var error = /* @__PURE__ */ new Error("Attribute type not specified.");
				error.attribute = attr;
				throw error;
			}
			if (typeof attr.shortName === "undefined") {
				if (attr.name && attr.name in _shortNames) attr.shortName = _shortNames[attr.name];
			}
			if (attr.type === oids.extensionRequest) {
				attr.valueConstructed = true;
				attr.valueTagClass = asn1.Type.SEQUENCE;
				if (!attr.value && attr.extensions) {
					attr.value = [];
					for (var ei = 0; ei < attr.extensions.length; ++ei) attr.value.push(pki.certificateExtensionToAsn1(_fillMissingExtensionFields(attr.extensions[ei])));
				}
			}
			if (typeof attr.value === "undefined") {
				var error = /* @__PURE__ */ new Error("Attribute value not specified.");
				error.attribute = attr;
				throw error;
			}
		}
	}
	/**
	* Fills in missing fields in certificate extensions.
	*
	* @param e the extension.
	* @param [options] the options to use.
	*          [cert] the certificate the extensions are for.
	*
	* @return the extension.
	*/
	function _fillMissingExtensionFields(e, options) {
		options = options || {};
		if (typeof e.name === "undefined") {
			if (e.id && e.id in pki.oids) e.name = pki.oids[e.id];
		}
		if (typeof e.id === "undefined") if (e.name && e.name in pki.oids) e.id = pki.oids[e.name];
		else {
			var error = /* @__PURE__ */ new Error("Extension ID not specified.");
			error.extension = e;
			throw error;
		}
		if (typeof e.value !== "undefined") return e;
		if (e.name === "keyUsage") {
			var unused = 0;
			var b2 = 0;
			var b3 = 0;
			if (e.digitalSignature) {
				b2 |= 128;
				unused = 7;
			}
			if (e.nonRepudiation) {
				b2 |= 64;
				unused = 6;
			}
			if (e.keyEncipherment) {
				b2 |= 32;
				unused = 5;
			}
			if (e.dataEncipherment) {
				b2 |= 16;
				unused = 4;
			}
			if (e.keyAgreement) {
				b2 |= 8;
				unused = 3;
			}
			if (e.keyCertSign) {
				b2 |= 4;
				unused = 2;
			}
			if (e.cRLSign) {
				b2 |= 2;
				unused = 1;
			}
			if (e.encipherOnly) {
				b2 |= 1;
				unused = 0;
			}
			if (e.decipherOnly) {
				b3 |= 128;
				unused = 7;
			}
			var value = String.fromCharCode(unused);
			if (b3 !== 0) value += String.fromCharCode(b2) + String.fromCharCode(b3);
			else if (b2 !== 0) value += String.fromCharCode(b2);
			e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, value);
		} else if (e.name === "basicConstraints") {
			e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
			if (e.cA) e.value.value.push(asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BOOLEAN, false, String.fromCharCode(255)));
			if ("pathLenConstraint" in e) e.value.value.push(asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, asn1.integerToDer(e.pathLenConstraint).getBytes()));
		} else if (e.name === "extKeyUsage") {
			e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
			var seq = e.value.value;
			for (var key in e) {
				if (e[key] !== true) continue;
				if (key in oids) seq.push(asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, asn1.oidToDer(oids[key]).getBytes()));
				else if (key.indexOf(".") !== -1) seq.push(asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, asn1.oidToDer(key).getBytes()));
			}
		} else if (e.name === "nsCertType") {
			var unused = 0;
			var b2 = 0;
			if (e.client) {
				b2 |= 128;
				unused = 7;
			}
			if (e.server) {
				b2 |= 64;
				unused = 6;
			}
			if (e.email) {
				b2 |= 32;
				unused = 5;
			}
			if (e.objsign) {
				b2 |= 16;
				unused = 4;
			}
			if (e.reserved) {
				b2 |= 8;
				unused = 3;
			}
			if (e.sslCA) {
				b2 |= 4;
				unused = 2;
			}
			if (e.emailCA) {
				b2 |= 2;
				unused = 1;
			}
			if (e.objCA) {
				b2 |= 1;
				unused = 0;
			}
			var value = String.fromCharCode(unused);
			if (b2 !== 0) value += String.fromCharCode(b2);
			e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, value);
		} else if (e.name === "subjectAltName" || e.name === "issuerAltName") {
			e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
			var altName;
			for (var n = 0; n < e.altNames.length; ++n) {
				altName = e.altNames[n];
				var value = altName.value;
				if (altName.type === 7 && altName.ip) {
					value = forge.util.bytesFromIP(altName.ip);
					if (value === null) {
						var error = /* @__PURE__ */ new Error("Extension \"ip\" value is not a valid IPv4 or IPv6 address.");
						error.extension = e;
						throw error;
					}
				} else if (altName.type === 8) if (altName.oid) value = asn1.oidToDer(asn1.oidToDer(altName.oid));
				else value = asn1.oidToDer(value);
				e.value.value.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, altName.type, false, value));
			}
		} else if (e.name === "nsComment" && options.cert) {
			if (!/^[\x00-\x7F]*$/.test(e.comment) || e.comment.length < 1 || e.comment.length > 128) throw new Error("Invalid \"nsComment\" content.");
			e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.IA5STRING, false, e.comment);
		} else if (e.name === "subjectKeyIdentifier" && options.cert) {
			var ski = options.cert.generateSubjectKeyIdentifier();
			e.subjectKeyIdentifier = ski.toHex();
			e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, ski.getBytes());
		} else if (e.name === "authorityKeyIdentifier" && options.cert) {
			e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
			var seq = e.value.value;
			if (e.keyIdentifier) {
				var keyIdentifier = e.keyIdentifier === true ? options.cert.generateSubjectKeyIdentifier().getBytes() : e.keyIdentifier;
				seq.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, false, keyIdentifier));
			}
			if (e.authorityCertIssuer) {
				var authorityCertIssuer = [asn1.create(asn1.Class.CONTEXT_SPECIFIC, 4, true, [_dnToAsn1(e.authorityCertIssuer === true ? options.cert.issuer : e.authorityCertIssuer)])];
				seq.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, authorityCertIssuer));
			}
			if (e.serialNumber) {
				var serialNumber = forge.util.hexToBytes(e.serialNumber === true ? options.cert.serialNumber : e.serialNumber);
				seq.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 2, false, serialNumber));
			}
		} else if (e.name === "cRLDistributionPoints") {
			e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
			var seq = e.value.value;
			var subSeq = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
			var fullNameGeneralNames = asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, []);
			var altName;
			for (var n = 0; n < e.altNames.length; ++n) {
				altName = e.altNames[n];
				var value = altName.value;
				if (altName.type === 7 && altName.ip) {
					value = forge.util.bytesFromIP(altName.ip);
					if (value === null) {
						var error = /* @__PURE__ */ new Error("Extension \"ip\" value is not a valid IPv4 or IPv6 address.");
						error.extension = e;
						throw error;
					}
				} else if (altName.type === 8) if (altName.oid) value = asn1.oidToDer(asn1.oidToDer(altName.oid));
				else value = asn1.oidToDer(value);
				fullNameGeneralNames.value.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, altName.type, false, value));
			}
			subSeq.value.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [fullNameGeneralNames]));
			seq.push(subSeq);
		}
		if (typeof e.value === "undefined") {
			var error = /* @__PURE__ */ new Error("Extension value not specified.");
			error.extension = e;
			throw error;
		}
		return e;
	}
	/**
	* Convert signature parameters object to ASN.1
	*
	* @param {String} oid Signature algorithm OID
	* @param params The signature parametrs object
	* @return ASN.1 object representing signature parameters
	*/
	function _signatureParametersToAsn1(oid, params) {
		switch (oid) {
			case oids["RSASSA-PSS"]:
				var parts = [];
				if (params.hash.algorithmOid !== void 0) parts.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, asn1.oidToDer(params.hash.algorithmOid).getBytes()), asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, "")])]));
				if (params.mgf.algorithmOid !== void 0) parts.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, [asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, asn1.oidToDer(params.mgf.algorithmOid).getBytes()), asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, asn1.oidToDer(params.mgf.hash.algorithmOid).getBytes()), asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, "")])])]));
				if (params.saltLength !== void 0) parts.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 2, true, [asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, asn1.integerToDer(params.saltLength).getBytes())]));
				return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, parts);
			default: return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, "");
		}
	}
	/**
	* Converts a certification request's attributes to an ASN.1 set of
	* CRIAttributes.
	*
	* @param csr certification request.
	*
	* @return the ASN.1 set of CRIAttributes.
	*/
	function _CRIAttributesToAsn1(csr) {
		var rval = asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, []);
		if (csr.attributes.length === 0) return rval;
		var attrs = csr.attributes;
		for (var i = 0; i < attrs.length; ++i) {
			var attr = attrs[i];
			var value = attr.value;
			var valueTagClass = asn1.Type.UTF8;
			if ("valueTagClass" in attr) valueTagClass = attr.valueTagClass;
			if (valueTagClass === asn1.Type.UTF8) value = forge.util.encodeUtf8(value);
			var valueConstructed = false;
			if ("valueConstructed" in attr) valueConstructed = attr.valueConstructed;
			var seq = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, asn1.oidToDer(attr.type).getBytes()), asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, [asn1.create(asn1.Class.UNIVERSAL, valueTagClass, valueConstructed, value)])]);
			rval.value.push(seq);
		}
		return rval;
	}
	var jan_1_1950 = /* @__PURE__ */ new Date("1950-01-01T00:00:00Z");
	var jan_1_2050 = /* @__PURE__ */ new Date("2050-01-01T00:00:00Z");
	/**
	* Converts a Date object to ASN.1
	* Handles the different format before and after 1st January 2050
	*
	* @param date date object.
	*
	* @return the ASN.1 object representing the date.
	*/
	function _dateToAsn1(date) {
		if (date >= jan_1_1950 && date < jan_1_2050) return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.UTCTIME, false, asn1.dateToUtcTime(date));
		else return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.GENERALIZEDTIME, false, asn1.dateToGeneralizedTime(date));
	}
	/**
	* Gets the ASN.1 TBSCertificate part of an X.509v3 certificate.
	*
	* @param cert the certificate.
	*
	* @return the asn1 TBSCertificate.
	*/
	pki.getTBSCertificate = function(cert) {
		var notBefore = _dateToAsn1(cert.validity.notBefore);
		var notAfter = _dateToAsn1(cert.validity.notAfter);
		var tbs = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
			asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, asn1.integerToDer(cert.version).getBytes())]),
			asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, forge.util.hexToBytes(cert.serialNumber)),
			asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, asn1.oidToDer(cert.siginfo.algorithmOid).getBytes()), _signatureParametersToAsn1(cert.siginfo.algorithmOid, cert.siginfo.parameters)]),
			_dnToAsn1(cert.issuer),
			asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [notBefore, notAfter]),
			_dnToAsn1(cert.subject),
			pki.publicKeyToAsn1(cert.publicKey)
		]);
		if (cert.issuer.uniqueId) tbs.value.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, [asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, String.fromCharCode(0) + cert.issuer.uniqueId)]));
		if (cert.subject.uniqueId) tbs.value.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 2, true, [asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, String.fromCharCode(0) + cert.subject.uniqueId)]));
		if (cert.extensions.length > 0) tbs.value.push(pki.certificateExtensionsToAsn1(cert.extensions));
		return tbs;
	};
	/**
	* Gets the ASN.1 CertificationRequestInfo part of a
	* PKCS#10 CertificationRequest.
	*
	* @param csr the certification request.
	*
	* @return the asn1 CertificationRequestInfo.
	*/
	pki.getCertificationRequestInfo = function(csr) {
		return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
			asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, asn1.integerToDer(csr.version).getBytes()),
			_dnToAsn1(csr.subject),
			pki.publicKeyToAsn1(csr.publicKey),
			_CRIAttributesToAsn1(csr)
		]);
	};
	/**
	* Converts a DistinguishedName (subject or issuer) to an ASN.1 object.
	*
	* @param dn the DistinguishedName.
	*
	* @return the asn1 representation of a DistinguishedName.
	*/
	pki.distinguishedNameToAsn1 = function(dn) {
		return _dnToAsn1(dn);
	};
	/**
	* Converts an X.509v3 RSA certificate to an ASN.1 object.
	*
	* @param cert the certificate.
	*
	* @return the asn1 representation of an X.509v3 RSA certificate.
	*/
	pki.certificateToAsn1 = function(cert) {
		var tbsCertificate = cert.tbsCertificate || pki.getTBSCertificate(cert);
		return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
			tbsCertificate,
			asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, asn1.oidToDer(cert.signatureOid).getBytes()), _signatureParametersToAsn1(cert.signatureOid, cert.signatureParameters)]),
			asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, String.fromCharCode(0) + cert.signature)
		]);
	};
	/**
	* Converts X.509v3 certificate extensions to ASN.1.
	*
	* @param exts the extensions to convert.
	*
	* @return the extensions in ASN.1 format.
	*/
	pki.certificateExtensionsToAsn1 = function(exts) {
		var rval = asn1.create(asn1.Class.CONTEXT_SPECIFIC, 3, true, []);
		var seq = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
		rval.value.push(seq);
		for (var i = 0; i < exts.length; ++i) seq.value.push(pki.certificateExtensionToAsn1(exts[i]));
		return rval;
	};
	/**
	* Converts a single certificate extension to ASN.1.
	*
	* @param ext the extension to convert.
	*
	* @return the extension in ASN.1 format.
	*/
	pki.certificateExtensionToAsn1 = function(ext) {
		var extseq = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
		extseq.value.push(asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, asn1.oidToDer(ext.id).getBytes()));
		if (ext.critical) extseq.value.push(asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BOOLEAN, false, String.fromCharCode(255)));
		var value = ext.value;
		if (typeof ext.value !== "string") value = asn1.toDer(value).getBytes();
		extseq.value.push(asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, value));
		return extseq;
	};
	/**
	* Converts a PKCS#10 certification request to an ASN.1 object.
	*
	* @param csr the certification request.
	*
	* @return the asn1 representation of a certification request.
	*/
	pki.certificationRequestToAsn1 = function(csr) {
		var cri = csr.certificationRequestInfo || pki.getCertificationRequestInfo(csr);
		return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
			cri,
			asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, asn1.oidToDer(csr.signatureOid).getBytes()), _signatureParametersToAsn1(csr.signatureOid, csr.signatureParameters)]),
			asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, String.fromCharCode(0) + csr.signature)
		]);
	};
	/**
	* Creates a CA store.
	*
	* @param certs an optional array of certificate objects or PEM-formatted
	*          certificate strings to add to the CA store.
	*
	* @return the CA store.
	*/
	pki.createCaStore = function(certs) {
		var caStore = { certs: {} };
		/**
		* Gets the certificate that issued the passed certificate or its
		* 'parent'.
		*
		* @param cert the certificate to get the parent for.
		*
		* @return the parent certificate or null if none was found.
		*/
		caStore.getIssuer = function(cert$1) {
			return getBySubject(cert$1.issuer);
		};
		/**
		* Adds a trusted certificate to the store.
		*
		* @param cert the certificate to add as a trusted certificate (either a
		*          pki.certificate object or a PEM-formatted certificate).
		*/
		caStore.addCertificate = function(cert$1) {
			if (typeof cert$1 === "string") cert$1 = forge.pki.certificateFromPem(cert$1);
			ensureSubjectHasHash(cert$1.subject);
			if (!caStore.hasCertificate(cert$1)) if (cert$1.subject.hash in caStore.certs) {
				var tmp = caStore.certs[cert$1.subject.hash];
				if (!forge.util.isArray(tmp)) tmp = [tmp];
				tmp.push(cert$1);
				caStore.certs[cert$1.subject.hash] = tmp;
			} else caStore.certs[cert$1.subject.hash] = cert$1;
		};
		/**
		* Checks to see if the given certificate is in the store.
		*
		* @param cert the certificate to check (either a pki.certificate or a
		*          PEM-formatted certificate).
		*
		* @return true if the certificate is in the store, false if not.
		*/
		caStore.hasCertificate = function(cert$1) {
			if (typeof cert$1 === "string") cert$1 = forge.pki.certificateFromPem(cert$1);
			var match = getBySubject(cert$1.subject);
			if (!match) return false;
			if (!forge.util.isArray(match)) match = [match];
			var der1 = asn1.toDer(pki.certificateToAsn1(cert$1)).getBytes();
			for (var i$1 = 0; i$1 < match.length; ++i$1) if (der1 === asn1.toDer(pki.certificateToAsn1(match[i$1])).getBytes()) return true;
			return false;
		};
		/**
		* Lists all of the certificates kept in the store.
		*
		* @return an array of all of the pki.certificate objects in the store.
		*/
		caStore.listAllCertificates = function() {
			var certList = [];
			for (var hash in caStore.certs) if (caStore.certs.hasOwnProperty(hash)) {
				var value = caStore.certs[hash];
				if (!forge.util.isArray(value)) certList.push(value);
				else for (var i$1 = 0; i$1 < value.length; ++i$1) certList.push(value[i$1]);
			}
			return certList;
		};
		/**
		* Removes a certificate from the store.
		*
		* @param cert the certificate to remove (either a pki.certificate or a
		*          PEM-formatted certificate).
		*
		* @return the certificate that was removed or null if the certificate
		*           wasn't in store.
		*/
		caStore.removeCertificate = function(cert$1) {
			var result;
			if (typeof cert$1 === "string") cert$1 = forge.pki.certificateFromPem(cert$1);
			ensureSubjectHasHash(cert$1.subject);
			if (!caStore.hasCertificate(cert$1)) return null;
			var match = getBySubject(cert$1.subject);
			if (!forge.util.isArray(match)) {
				result = caStore.certs[cert$1.subject.hash];
				delete caStore.certs[cert$1.subject.hash];
				return result;
			}
			var der1 = asn1.toDer(pki.certificateToAsn1(cert$1)).getBytes();
			for (var i$1 = 0; i$1 < match.length; ++i$1) if (der1 === asn1.toDer(pki.certificateToAsn1(match[i$1])).getBytes()) {
				result = match[i$1];
				match.splice(i$1, 1);
			}
			if (match.length === 0) delete caStore.certs[cert$1.subject.hash];
			return result;
		};
		function getBySubject(subject) {
			ensureSubjectHasHash(subject);
			return caStore.certs[subject.hash] || null;
		}
		function ensureSubjectHasHash(subject) {
			if (!subject.hash) {
				var md = forge.md.sha1.create();
				subject.attributes = pki.RDNAttributesAsArray(_dnToAsn1(subject), md);
				subject.hash = md.digest().toHex();
			}
		}
		if (certs) for (var i = 0; i < certs.length; ++i) {
			var cert = certs[i];
			caStore.addCertificate(cert);
		}
		return caStore;
	};
	/**
	* Certificate verification errors, based on TLS.
	*/
	pki.certificateError = {
		bad_certificate: "forge.pki.BadCertificate",
		unsupported_certificate: "forge.pki.UnsupportedCertificate",
		certificate_revoked: "forge.pki.CertificateRevoked",
		certificate_expired: "forge.pki.CertificateExpired",
		certificate_unknown: "forge.pki.CertificateUnknown",
		unknown_ca: "forge.pki.UnknownCertificateAuthority"
	};
	/**
	* Verifies a certificate chain against the given Certificate Authority store
	* with an optional custom verify callback.
	*
	* @param caStore a certificate store to verify against.
	* @param chain the certificate chain to verify, with the root or highest
	*          authority at the end (an array of certificates).
	* @param options a callback to be called for every certificate in the chain or
	*                  an object with:
	*                  verify a callback to be called for every certificate in the
	*                    chain
	*                  validityCheckDate the date against which the certificate
	*                    validity period should be checked. Pass null to not check
	*                    the validity period. By default, the current date is used.
	*
	* The verify callback has the following signature:
	*
	* verified - Set to true if certificate was verified, otherwise the
	*   pki.certificateError for why the certificate failed.
	* depth - The current index in the chain, where 0 is the end point's cert.
	* certs - The certificate chain, *NOTE* an empty chain indicates an anonymous
	*   end point.
	*
	* The function returns true on success and on failure either the appropriate
	* pki.certificateError or an object with 'error' set to the appropriate
	* pki.certificateError and 'message' set to a custom error message.
	*
	* @return true if successful, error thrown if not.
	*/
	pki.verifyCertificateChain = function(caStore, chain, options) {
		if (typeof options === "function") options = { verify: options };
		options = options || {};
		chain = chain.slice(0);
		var certs = chain.slice(0);
		var validityCheckDate = options.validityCheckDate;
		if (typeof validityCheckDate === "undefined") validityCheckDate = /* @__PURE__ */ new Date();
		var first = true;
		var error = null;
		var depth = 0;
		do {
			var cert = chain.shift();
			var parent = null;
			var selfSigned = false;
			if (validityCheckDate) {
				if (validityCheckDate < cert.validity.notBefore || validityCheckDate > cert.validity.notAfter) error = {
					message: "Certificate is not valid yet or has expired.",
					error: pki.certificateError.certificate_expired,
					notBefore: cert.validity.notBefore,
					notAfter: cert.validity.notAfter,
					now: validityCheckDate
				};
			}
			if (error === null) {
				parent = chain[0] || caStore.getIssuer(cert);
				if (parent === null) {
					if (cert.isIssuer(cert)) {
						selfSigned = true;
						parent = cert;
					}
				}
				if (parent) {
					var parents = parent;
					if (!forge.util.isArray(parents)) parents = [parents];
					var verified = false;
					while (!verified && parents.length > 0) {
						parent = parents.shift();
						try {
							verified = parent.verify(cert);
						} catch (ex) {}
					}
					if (!verified) error = {
						message: "Certificate signature is invalid.",
						error: pki.certificateError.bad_certificate
					};
				}
				if (error === null && (!parent || selfSigned) && !caStore.hasCertificate(cert)) error = {
					message: "Certificate is not trusted.",
					error: pki.certificateError.unknown_ca
				};
			}
			if (error === null && parent && !cert.isIssuer(parent)) error = {
				message: "Certificate issuer is invalid.",
				error: pki.certificateError.bad_certificate
			};
			if (error === null) {
				var se = {
					keyUsage: true,
					basicConstraints: true
				};
				for (var i = 0; error === null && i < cert.extensions.length; ++i) {
					var ext = cert.extensions[i];
					if (ext.critical && !(ext.name in se)) error = {
						message: "Certificate has an unsupported critical extension.",
						error: pki.certificateError.unsupported_certificate
					};
				}
			}
			if (error === null && (!first || chain.length === 0 && (!parent || selfSigned))) {
				var bcExt = cert.getExtension("basicConstraints");
				var keyUsageExt = cert.getExtension("keyUsage");
				if (keyUsageExt !== null) {
					if (!keyUsageExt.keyCertSign || bcExt === null) error = {
						message: "Certificate keyUsage or basicConstraints conflict or indicate that the certificate is not a CA. If the certificate is the only one in the chain or isn't the first then the certificate must be a valid CA.",
						error: pki.certificateError.bad_certificate
					};
				}
				if (error === null && bcExt !== null && !bcExt.cA) error = {
					message: "Certificate basicConstraints indicates the certificate is not a CA.",
					error: pki.certificateError.bad_certificate
				};
				if (error === null && keyUsageExt !== null && "pathLenConstraint" in bcExt) {
					if (depth - 1 > bcExt.pathLenConstraint) error = {
						message: "Certificate basicConstraints pathLenConstraint violated.",
						error: pki.certificateError.bad_certificate
					};
				}
			}
			var vfd = error === null ? true : error.error;
			var ret = options.verify ? options.verify(vfd, depth, certs) : vfd;
			if (ret === true) error = null;
			else {
				if (vfd === true) error = {
					message: "The application rejected the certificate.",
					error: pki.certificateError.bad_certificate
				};
				if (ret || ret === 0) {
					if (typeof ret === "object" && !forge.util.isArray(ret)) {
						if (ret.message) error.message = ret.message;
						if (ret.error) error.error = ret.error;
					} else if (typeof ret === "string") error.error = ret;
				}
				throw error;
			}
			first = false;
			++depth;
		} while (chain.length > 0);
		return true;
	};
}) });

//#endregion
export default require_x509();

export { require_x509 };
//# sourceMappingURL=x509.mjs.map