node-opcua-crypto
Version:
Crypto tools for Node-OPCUA
1 lines • 495 kB
Source Map (JSON)
{"version":3,"sources":["../../../node_modules/tsup/assets/esm_shims.js","../source/asn1.ts","../source/oid_map.ts","../source/crypto_utils.ts","../source/buffer_utils.ts","../source/crypto_explore_certificate.ts","../source/directory_name.ts","../source/explore_private_key.ts","../source/public_private_match.ts","../source/common.ts","../source/crypto_utils2.ts","../source/derived_keys.ts","../source/explore_certificate.ts","../source/explore_asn1.ts","../source/explore_certificate_revocation_list.ts","../source/explore_certificate_signing_request.ts","../source/make_private_key_from_pem.ts","../source/make_private_key_thumbprint.ts","../source/subject.ts","../source/verify_certificate_signature.ts","../source/x509/_crypto.ts","../source/x509/create_key_pair.ts","../source/x509/coerce_private_key.ts","../source/x509/_get_attributes.ts","../source/x509/_build_public_key.ts","../source/x509/create_certificate_signing_request.ts","../../../node_modules/asn1js/build/index.es.js","../../../node_modules/pvtsutils/build/index.es.js","../../../node_modules/pvutils/build/utils.es.js","../../../node_modules/@peculiar/asn1-schema/build/es2015/enums.js","../../../node_modules/@peculiar/asn1-schema/build/es2015/converters.js","../../../node_modules/@peculiar/asn1-schema/build/es2015/helper.js","../../../node_modules/@peculiar/asn1-schema/build/es2015/schema.js","../../../node_modules/@peculiar/asn1-schema/build/es2015/storage.js","../../../node_modules/@peculiar/asn1-schema/build/es2015/errors/schema_validation.js","../../../node_modules/@peculiar/asn1-schema/build/es2015/parser.js","../../../node_modules/@peculiar/asn1-schema/build/es2015/serializer.js","../../../node_modules/@peculiar/asn1-schema/build/es2015/convert.js","../source/x509/create_self_signed_certificate.ts","../source/index_web.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport { fileURLToPath } from 'url'\nimport path from 'path'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import assert from \"assert\";\nimport { oid_map } from \"./oid_map.js\";\nimport { DirectoryName } from \"./directory_name.js\";\n// https://github.com/lapo-luchini/asn1js/blob/master/asn1.js\nexport enum TagType {\n BOOLEAN = 0x01,\n INTEGER = 0x02,\n BIT_STRING = 0x03,\n OCTET_STRING = 0x04,\n NULL = 0x05,\n OBJECT_IDENTIFIER = 0x06,\n UTF8String = 0x0c,\n NumericString = 0x12,\n PrintableString = 0x13,\n TeletexString = 0x14,\n IA5String = 0x16,\n UTCTime = 0x17,\n GeneralizedTime = 0x18,\n GraphicString = 0x19,\n VisibleString = 0x1a,\n GeneralString = 0x1b,\n UniversalString = 0x1c,\n BMPString = 0x1e,\n\n SEQUENCE = 0x30,\n\n SET = 0x31,\n\n CONTEXT_SPECIFIC0 = 0xa0,\n CONTEXT_SPECIFIC1 = 0xa1,\n CONTEXT_SPECIFIC2 = 0xa2,\n CONTEXT_SPECIFIC3 = 0xa3,\n A4 = 0xa4,\n}\n\nexport interface BlockInfo {\n tag: TagType | number;\n position: number;\n length: number;\n start: number;\n}\n\nexport function readTag(buf: Buffer, pos: number): BlockInfo {\n const start = pos;\n // istanbul ignore next\n if (buf.length <= pos) {\n throw new Error(\"Invalid position : buf.length=\" + buf.length + \" pos =\" + pos);\n }\n const tag = buf.readUInt8(pos);\n pos += 1;\n\n let length = buf.readUInt8(pos);\n pos += 1;\n\n // tslint:disable:no-bitwise\n if (length > 127) {\n const nbBytes = length & 0x7f;\n length = 0;\n for (let i = 0; i < nbBytes; i++) {\n length = length * 256 + buf.readUInt8(pos);\n pos += 1;\n }\n }\n return { start, tag, position: pos, length };\n}\n\nexport function readStruct(buf: Buffer, blockInfo: BlockInfo): BlockInfo[] {\n const length = blockInfo.length;\n let cursor = blockInfo.position;\n const end = blockInfo.position + length;\n const blocks: BlockInfo[] = [];\n while (cursor < end) {\n const inner = readTag(buf, cursor);\n cursor = inner.position + inner.length;\n blocks.push(inner);\n }\n return blocks;\n}\n\nexport function parseBitString(buffer: Buffer, start: number, end: number, maxLength: number): string {\n const unusedBit = buffer.readUInt8(start),\n lenBit = ((end - start - 1) << 3) - unusedBit,\n intro = \"(\" + lenBit + \" bit)\\n\";\n\n let s = \"\",\n skip = unusedBit;\n\n for (let i = end - 1; i > start; --i) {\n const b = buffer.readUInt8(i);\n\n for (let j = skip; j < 8; ++j) {\n // noinspection JSBitwiseOperatorUsage\n s += (b >> j) & 1 ? \"1\" : \"0\";\n }\n skip = 0;\n assert(s.length <= maxLength);\n }\n return intro + s;\n}\n\nexport interface BitString {\n lengthInBits: number;\n lengthInBytes: number;\n data: Buffer;\n debug?: any;\n}\n\nexport function readBitString(buffer: Buffer, block: BlockInfo): BitString {\n assert(block.tag === TagType.BIT_STRING);\n const data = getBlock(buffer, block);\n // number of skipped bits\n const ignore_bits = data.readUInt8(0);\n\n return {\n lengthInBits: data.length * 8 - ignore_bits,\n lengthInBytes: data.length - 1,\n data: data.subarray(1),\n debug: parseBitString(buffer, block.position, block.length + block.position, 4 * 16 * 1024),\n };\n}\n\nexport function formatBuffer2DigitHexWithColum(buffer: Buffer): string {\n const value: string[] = [];\n for (let i = 0; i < buffer.length; i++) {\n value.push((\"00\" + buffer.readUInt8(i).toString(16)).substr(-2, 2));\n }\n // remove leading 00\n return value\n .join(\":\")\n .toUpperCase()\n .replace(/^(00:)*/, \"\");\n}\n\nexport function readOctetString(buffer: Buffer, block: BlockInfo): Buffer {\n assert(block.tag === TagType.OCTET_STRING);\n const tag = readTag(buffer, block.position);\n assert(tag.tag === TagType.OCTET_STRING);\n\n const nbBytes = tag.length;\n const pos = tag.position;\n const b = buffer.subarray(pos, pos + nbBytes);\n return b;\n}\n\nexport function getBlock(buffer: Buffer, block: BlockInfo): Buffer {\n const start = block.position;\n const end = block.position + block.length;\n return buffer.subarray(start, end);\n}\n\nexport interface AlgorithmIdentifier {\n identifier: string;\n}\n\nexport function readIntegerAsByteString(buffer: Buffer, block: BlockInfo): Buffer {\n return getBlock(buffer, block);\n}\n\nexport function readListOfInteger(buffer: Buffer): Buffer[] {\n const block = readTag(buffer, 0);\n const inner_blocks = readStruct(buffer, block);\n return inner_blocks.map((innerBlock: BlockInfo) => {\n return readIntegerAsByteString(buffer, innerBlock);\n });\n}\n\nfunction parseOID(buffer: Buffer, start: number, end: number): string {\n // ASN.1 JavaScript decoder\n // Copyright (c) 2008-2014 Lapo Luchini <lapo@lapo.it>\n let s = \"\",\n n = 0,\n bits = 0;\n for (let i = start; i < end; ++i) {\n const v = buffer.readUInt8(i);\n\n // tslint:disable-next-line: no-bitwise\n n = n * 128 + (v & 0x7f);\n bits += 7;\n\n // noinspection JSBitwiseOperatorUsage\n // tslint:disable-next-line: no-bitwise\n if (!(v & 0x80)) {\n // finished\n if (s === \"\") {\n const m = n < 80 ? (n < 40 ? 0 : 1) : 2;\n s = m + \".\" + (n - m * 40);\n } else {\n s += \".\" + n.toString();\n }\n n = 0;\n bits = 0;\n }\n }\n assert(bits === 0); // if (bits > 0) { s += \".incomplete\"; }\n return s;\n}\n\nexport function readObjectIdentifier(buffer: Buffer, block: BlockInfo): { oid: string; name: string } {\n assert(block.tag === TagType.OBJECT_IDENTIFIER);\n const b = buffer.subarray(block.position, block.position + block.length);\n const oid = parseOID(b, 0, block.length);\n return {\n oid,\n name: oid_map[oid] ? oid_map[oid].d : oid,\n };\n}\n\nexport function readAlgorithmIdentifier(buffer: Buffer, block: BlockInfo): AlgorithmIdentifier {\n const inner_blocks = readStruct(buffer, block);\n return {\n identifier: readObjectIdentifier(buffer, inner_blocks[0]).name,\n };\n}\n\nexport function readECCAlgorithmIdentifier(buffer: Buffer, block: BlockInfo): AlgorithmIdentifier {\n const inner_blocks = readStruct(buffer, block);\n return {\n identifier: readObjectIdentifier(buffer, inner_blocks[1]).name, // difference with RSA as algorithm is second element of nested block\n };\n}\n\nexport type SignatureValue = string;\n\nexport function readSignatureValueBin(buffer: Buffer, block: BlockInfo): Buffer {\n return readBitString(buffer, block).data;\n}\n\nexport function readSignatureValue(buffer: Buffer, block: BlockInfo): SignatureValue {\n return readSignatureValueBin(buffer, block).toString(\"hex\");\n}\n\nexport function readLongIntegerValue(buffer: Buffer, block: BlockInfo): Buffer {\n assert(block.tag === TagType.INTEGER, \"expecting a INTEGER tag\");\n const pos = block.position;\n const nbBytes = block.length;\n const buf = buffer.subarray(pos, pos + nbBytes);\n return buf;\n}\n\nexport function readIntegerValue(buffer: Buffer, block: BlockInfo): number {\n assert(block.tag === TagType.INTEGER, \"expecting a INTEGER tag\");\n let pos = block.position;\n const nbBytes = block.length;\n assert(nbBytes < 4);\n let value = 0;\n for (let i = 0; i < nbBytes; i++) {\n value = value * 256 + buffer.readUInt8(pos);\n pos += 1;\n }\n return value;\n}\n\nexport function readBooleanValue(buffer: Buffer, block: BlockInfo): boolean {\n assert(block.tag === TagType.BOOLEAN, \"expecting a BOOLEAN tag. got \" + TagType[block.tag]);\n const pos = block.position;\n const nbBytes = block.length;\n assert(nbBytes < 4);\n const value = buffer.readUInt8(pos) ? true : false;\n return value as boolean;\n}\n\nexport function readVersionValue(buffer: Buffer, block: BlockInfo): number {\n block = readTag(buffer, block.position);\n return readIntegerValue(buffer, block);\n}\n\n/*\n 4.1.2.5.2 GeneralizedTime\n\n The generalized time type, GeneralizedTime, is a standard ASN.1 type\n for variable precision representation of time. Optionally, the\n GeneralizedTime field can include a representation of the time\n differential between local and Greenwich Mean Time.\n\n For the purposes of this profile, GeneralizedTime values MUST be\n expressed Greenwich Mean Time (Zulu) and MUST include seconds (i.e.,\n times are YYYYMMDDHHMMSSZ), even where the number of seconds is zero.\n GeneralizedTime values MUST NOT include fractional seconds.\n\n */\nfunction convertGeneralizedTime(str: string): Date {\n const year = parseInt(str.substr(0, 4), 10);\n const month = parseInt(str.substr(4, 2), 10) - 1;\n const day = parseInt(str.substr(6, 2), 10);\n const hours = parseInt(str.substr(8, 2), 10);\n const mins = parseInt(str.substr(10, 2), 10);\n const secs = parseInt(str.substr(12, 2), 10);\n\n return new Date(Date.UTC(year, month, day, hours, mins, secs));\n}\n\nfunction _readBMPString(buffer: Buffer, block: BlockInfo): string {\n const strBuff = getBlock(buffer, block);\n let str = \"\";\n for (let i = 0; i < strBuff.length; i += 2) {\n const word = strBuff.readUInt16BE(i);\n str += String.fromCharCode(word);\n }\n return str;\n}\n\n/*\n http://tools.ietf.org/html/rfc5280\n\n 4.1.2.5. Validity\n [...]\n As conforming to this profile MUST always encode certificate\n validity dates through the year 2049 as UTCTime; certificate validity\n dates in 2050 or later MUST be encoded as GeneralizedTime.\n Conforming applications MUST be able to process validity dates that\n are encoded in either UTCTime or GeneralizedTime.\n [...]\n\n 4.1.2.5.1 UTCTime\n\n The universal time type, UTCTime, is a standard ASN.1 type intended\n for representation of dates and time. UTCTime specifies the year\n through the two low order digits and time is specified to the\n precision of one minute or one second. UTCTime includes either Z\n (for Zulu, or Greenwich Mean Time) or a time differential.\n\n For the purposes of this profile, UTCTime values MUST be expressed\n Greenwich Mean Time (Zulu) and MUST include seconds (i.e., times are\n YYMMDDHHMMSSZ), even where the number of seconds is zero. Conforming\n systems MUST interpret the year field (YY) as follows:\n\n Where YY is greater than or equal to 50, the year SHALL be\n interpreted as 19YY; and\n\n Where YY is less than 50, the year SHALL be interpreted as 20YY.\n */\nfunction convertUTCTime(str: string): Date {\n let year = parseInt(str.substr(0, 2), 10);\n const month = parseInt(str.substr(2, 2), 10) - 1;\n const day = parseInt(str.substr(4, 2), 10);\n const hours = parseInt(str.substr(6, 2), 10);\n const mins = parseInt(str.substr(8, 2), 10);\n const secs = parseInt(str.substr(10, 2), 10);\n\n year += year >= 50 ? 1900 : 2000;\n return new Date(Date.UTC(year, month, day, hours, mins, secs));\n}\n\nexport function readValue(buffer: Buffer, block: BlockInfo): any {\n switch (block.tag) {\n case TagType.BOOLEAN:\n return readBooleanValue(buffer, block);\n case TagType.BMPString:\n return _readBMPString(buffer, block);\n case TagType.PrintableString:\n case TagType.TeletexString:\n case TagType.UTF8String:\n case TagType.NumericString:\n case TagType.IA5String:\n return getBlock(buffer, block).toString(\"ascii\");\n case TagType.UTCTime:\n return convertUTCTime(getBlock(buffer, block).toString(\"ascii\"));\n case TagType.GeneralizedTime:\n return convertGeneralizedTime(getBlock(buffer, block).toString(\"ascii\"));\n default:\n throw new Error(\"Invalid tag 0x\" + block.tag.toString(16) + \"\");\n //xx return \" ??? <\" + block.tag + \">\";\n }\n}\n\nexport function compactDirectoryName(d: DirectoryName): string {\n return JSON.stringify(d);\n}\n\nexport function findBlockAtIndex(blocks: BlockInfo[], index: number): BlockInfo | null {\n const tmp = blocks.filter((b: BlockInfo) => b.tag === 0xa0 + index || b.tag === 0x80 + index);\n if (tmp.length === 0) {\n return null;\n }\n return tmp[0];\n}\n\nexport function readTime(buffer: Buffer, block: BlockInfo): any {\n return readValue(buffer, block);\n}\n","// https://github.com/lapo-luchini/asn1js/blob/master/oids.js\nexport const oid_map: { [key: string]: { d: string; c: string; w?: boolean } } = {\n \"0.9.2342.19200300.100.1.1\": { d: \"userID\", c: \"Some oddball X.500 attribute collection\" },\n \"0.9.2342.19200300.100.1.3\": { d: \"rfc822Mailbox\", c: \"Some oddball X.500 attribute collection\" },\n \"0.9.2342.19200300.100.1.25\": { d: \"domainComponent\", c: \"Men are from Mars, this OID is from Pluto\" },\n\n \"1.2.840.10045.2\": { d: \"publicKeyType\", c: \"ANSI X9.62\" },\n \"1.2.840.10045.2.1\": { d: \"ecPublicKey\", c: \"ANSI X9.62 public key type\" },\n \"1.2.840.10045.3.0.1\": { d: \"c2pnb163v1\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.0.2\": { d: \"c2pnb163v2\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.0.3\": { d: \"c2pnb163v3\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.0.5\": { d: \"c2tnb191v1\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.0.6\": { d: \"c2tnb191v2\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.0.7\": { d: \"c2tnb191v3\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.0.10\": { d: \"c2pnb208w1\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.0.11\": { d: \"c2tnb239v1\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.0.12\": { d: \"c2tnb239v2\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.0.13\": { d: \"c2tnb239v3\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.0.16\": { d: \"c2pnb272w1\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.0.18\": { d: \"c2tnb359v1\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.0.19\": { d: \"c2pnb368w1\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.0.20\": { d: \"c2tnb431r1\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.1.1\": { d: \"prime192v1\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.1.2\": { d: \"prime192v2\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.1.3\": { d: \"prime192v3\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.1.4\": { d: \"prime239v1\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.1.5\": { d: \"prime239v2\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.1.6\": { d: \"prime239v3\", c: \"ANSI X9.62 named elliptic curve\" },\n \"1.2.840.10045.3.1.7\": { d: \"prime256v1\", c: \"ANSI X9.62 named elliptic curve\" },\n\n \"1.2.840.113549.1.1\": { d: \"pkcs-1\", c: \"\", w: false },\n \"1.2.840.113549.1.1.1\": { d: \"rsaEncryption\", c: \"PKCS #1\", w: false },\n \"1.2.840.113549.1.1.2\": { d: \"md2WithRSAEncryption\", c: \"PKCS #1\", w: false },\n \"1.2.840.113549.1.1.3\": { d: \"md4WithRSAEncryption\", c: \"PKCS #1\", w: false },\n \"1.2.840.113549.1.1.4\": { d: \"md5WithRSAEncryption\", c: \"PKCS #1\", w: false },\n \"1.2.840.113549.1.1.5\": { d: \"sha1WithRSAEncryption\", c: \"PKCS #1\", w: false },\n \"1.2.840.113549.1.1.7\": { d: \"rsaOAEP\", c: \"PKCS #1\", w: false },\n \"1.2.840.113549.1.1.8\": { d: \"pkcs1-MGF\", c: \"PKCS #1\", w: false },\n \"1.2.840.113549.1.1.9\": { d: \"rsaOAEP-pSpecified\", c: \"PKCS #1\", w: false },\n \"1.2.840.113549.1.1.10\": { d: \"rsaPSS\", c: \"PKCS #1\", w: false },\n \"1.2.840.113549.1.1.11\": { d: \"sha256WithRSAEncryption\", c: \"PKCS #1\", w: false },\n \"1.2.840.113549.1.1.12\": { d: \"sha384WithRSAEncryption\", c: \"PKCS #1\", w: false },\n \"1.2.840.113549.1.1.13\": { d: \"sha512WithRSAEncryption\", c: \"PKCS #1\", w: false },\n \"1.2.840.113549.1.1.14\": { d: \"sha224WithRSAEncryption\", c: \"PKCS #1\", w: false },\n\n \"1.2.840.113549.1.9.1\": {\n d: \"emailAddress\",\n c: \"PKCS #9. Deprecated, use an altName extension instead\",\n w: false,\n },\n \"1.2.840.113549.1.9.2\": { d: \"unstructuredName\", c: \"PKCS #9\", w: false },\n \"1.2.840.113549.1.9.3\": { d: \"contentType\", c: \"PKCS #9\", w: false },\n \"1.2.840.113549.1.9.4\": { d: \"messageDigest\", c: \"PKCS #9\", w: false },\n \"1.2.840.113549.1.9.5\": { d: \"signingTime\", c: \"PKCS #9\", w: false },\n \"1.2.840.113549.1.9.6\": { d: \"countersignature\", c: \"PKCS #9\", w: false },\n \"1.2.840.113549.1.9.7\": { d: \"challengePassword\", c: \"PKCS #9\", w: false },\n \"1.2.840.113549.1.9.8\": { d: \"unstructuredAddress\", c: \"PKCS #9\", w: false },\n \"1.2.840.113549.1.9.9\": { d: \"extendedCertificateAttributes\", c: \"PKCS #9\", w: false },\n \"1.2.840.113549.1.9.10\": { d: \"issuerAndSerialNumber\", c: \"PKCS #9 experimental\", w: true },\n \"1.2.840.113549.1.9.11\": { d: \"passwordCheck\", c: \"PKCS #9 experimental\", w: true },\n \"1.2.840.113549.1.9.12\": { d: \"publicKey\", c: \"PKCS #9 experimental\", w: true },\n \"1.2.840.113549.1.9.13\": { d: \"signingDescription\", c: \"PKCS #9\", w: false },\n \"1.2.840.113549.1.9.14\": { d: \"extensionRequest\", c: \"PKCS #9 via CRMF\", w: false },\n\n \"1.3.6.1.4.1.311.2.1.21\": { d: \"1.3.6.1.4.1.311.2.1.21\", c: \"SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID\" },\n \"1.3.6.1.4.1.311.2.1.22\": { d: \"1.3.6.1.4.1.311.2.1.22\", c: \"SPC_COMMERCIAL_SP_KEY_PURPOSE_OBJID\" },\n \"1.3.6.1.4.1.311.10.3.1\": { d: \"1.3.6.1.4.1.311.10.3.1\", c: \"Signer of CTLs -- szOID_KP_CTL_USAGE_SIGNING\" },\n \"1.3.6.1.4.1.311.10.3.4\": { d: \"1.3.6.1.4.1.311.10.3.4\", c: \"szOID_EFS_RECOVERY (Encryption File System)\" },\n\n \"1.3.6.1.4.1.311.20.2.3\": { d: \"1.3.6.1.4.1.311.20.2.3\", c: \"id-on-personalData\" },\n\n \"1.3.6.1.5.5.7.3.17\": { d: \"1.3.6.1.5.5.7.3.17\", c: \"Internet Key Exchange (IKE)\" },\n\n \"1.3.6.1.5.5.7.3.1\": { d: \"serverAuth\", c: \"PKIX key purpose\" },\n \"1.3.6.1.5.5.7.3.2\": { d: \"clientAuth\", c: \"PKIX key purpose\" },\n \"1.3.6.1.5.5.7.3.3\": { d: \"codeSigning\", c: \"PKIX key purpose\" },\n \"1.3.6.1.5.5.7.3.4\": { d: \"emailProtection\", c: \"PKIX key purpose\" },\n \"1.3.6.1.5.5.7.3.5\": { d: \"ipsecEndSystem\", c: \"PKIX key purpose\" },\n \"1.3.6.1.5.5.7.3.6\": { d: \"ipsecTunnel\", c: \"PKIX key purpose\" },\n \"1.3.6.1.5.5.7.3.7\": { d: \"ipsecUser\", c: \"PKIX key purpose\" },\n \"1.3.6.1.5.5.7.3.8\": { d: \"timeStamping\", c: \"PKIX key purpose\" },\n \"1.3.6.1.5.5.7.3.9\": { d: \"ocspSigning\", c: \"PKIX key purpose\" },\n \"1.3.6.1.5.5.7.3.10\": { d: \"dvcs\", c: \"PKIX key purpose\" },\n \"1.3.6.1.5.5.7.3.11\": { d: \"sbgpCertAAServerAuth\", c: \"PKIX key purpose\" },\n \"1.3.6.1.5.5.7.3.13\": { d: \"eapOverPPP\", c: \"PKIX key purpose\" },\n \"1.3.6.1.5.5.7.3.14\": { d: \"eapOverLAN\", c: \"PKIX key purpose\" },\n\n \"1.3.36.3.3.2.8.1.1.1\": { d: \"brainpoolP160r1\", c: \"ECC Brainpool Standard Curves and Curve Generation\" },\n \"1.3.36.3.3.2.8.1.1.2\": { d: \"brainpoolP160t1\", c: \"ECC Brainpool Standard Curves and Curve Generation\" },\n \"1.3.36.3.3.2.8.1.1.3\": { d: \"brainpoolP192r1\", c: \"ECC Brainpool Standard Curves and Curve Generation\" },\n \"1.3.36.3.3.2.8.1.1.4\": { d: \"brainpoolP192t1\", c: \"ECC Brainpool Standard Curves and Curve Generation\" },\n \"1.3.36.3.3.2.8.1.1.5\": { d: \"brainpoolP224r1\", c: \"ECC Brainpool Standard Curves and Curve Generation\" },\n \"1.3.36.3.3.2.8.1.1.6\": { d: \"brainpoolP224t1\", c: \"ECC Brainpool Standard Curves and Curve Generation\" },\n \"1.3.36.3.3.2.8.1.1.7\": { d: \"brainpoolP256r1\", c: \"ECC Brainpool Standard Curves and Curve Generation\" },\n \"1.3.36.3.3.2.8.1.1.8\": { d: \"brainpoolP256t1\", c: \"ECC Brainpool Standard Curves and Curve Generation\" },\n \"1.3.36.3.3.2.8.1.1.9\": { d: \"brainpoolP320r1\", c: \"ECC Brainpool Standard Curves and Curve Generation\" },\n \"1.3.36.3.3.2.8.1.1.10\": { d: \"brainpoolP320t1\", c: \"ECC Brainpool Standard Curves and Curve Generation\" },\n \"1.3.36.3.3.2.8.1.1.11\": { d: \"brainpoolP384r1\", c: \"ECC Brainpool Standard Curves and Curve Generation\" },\n \"1.3.36.3.3.2.8.1.1.12\": { d: \"brainpoolP384t1\", c: \"ECC Brainpool Standard Curves and Curve Generation\" },\n \"1.3.36.3.3.2.8.1.1.13\": { d: \"brainpoolP512r1\", c: \"ECC Brainpool Standard Curves and Curve Generation\" },\n \"1.3.36.3.3.2.8.1.1.14\": { d: \"brainpoolP512t1\", c: \"ECC Brainpool Standard Curves and Curve Generation\" },\n\n \"2.5.4.0\": { d: \"objectClass\", c: \"X.520 DN component\", w: false },\n \"2.5.4.1\": { d: \"aliasedEntryName\", c: \"X.520 DN component\", w: false },\n \"2.5.4.2\": { d: \"knowledgeInformation\", c: \"X.520 DN component\", w: false },\n \"2.5.4.3\": { d: \"commonName\", c: \"X.520 DN component\", w: false },\n \"2.5.4.4\": { d: \"surname\", c: \"X.520 DN component\", w: false },\n \"2.5.4.5\": { d: \"serialNumber\", c: \"X.520 DN component\", w: false },\n \"2.5.4.6\": { d: \"countryName\", c: \"X.520 DN component\", w: false },\n \"2.5.4.7\": { d: \"localityName\", c: \"X.520 DN component\", w: false },\n \"2.5.4.7.1\": { d: \"collectiveLocalityName\", c: \"X.520 DN component\", w: false },\n \"2.5.4.8\": { d: \"stateOrProvinceName\", c: \"X.520 DN component\", w: false },\n \"2.5.4.8.1\": { d: \"collectiveStateOrProvinceName\", c: \"X.520 DN component\", w: false },\n \"2.5.4.9\": { d: \"streetAddress\", c: \"X.520 DN component\", w: false },\n \"2.5.4.9.1\": { d: \"collectiveStreetAddress\", c: \"X.520 DN component\", w: false },\n \"2.5.4.10\": { d: \"organizationName\", c: \"X.520 DN component\", w: false },\n \"2.5.4.10.1\": { d: \"collectiveOrganizationName\", c: \"X.520 DN component\", w: false },\n \"2.5.4.11\": { d: \"organizationalUnitName\", c: \"X.520 DN component\", w: false },\n \"2.5.4.11.1\": { d: \"collectiveOrganizationalUnitName\", c: \"X.520 DN component\", w: false },\n \"2.5.4.12\": { d: \"title\", c: \"X.520 DN component\", w: false },\n \"2.5.4.13\": { d: \"description\", c: \"X.520 DN component\", w: false },\n \"2.5.4.14\": { d: \"searchGuide\", c: \"X.520 DN component\", w: false },\n \"2.5.4.15\": { d: \"businessCategory\", c: \"X.520 DN component\", w: false },\n \"2.5.4.16\": { d: \"postalAddress\", c: \"X.520 DN component\", w: false },\n \"2.5.4.16.1\": { d: \"collectivePostalAddress\", c: \"X.520 DN component\", w: false },\n \"2.5.4.17\": { d: \"postalCode\", c: \"X.520 DN component\", w: false },\n \"2.5.4.17.1\": { d: \"collectivePostalCode\", c: \"X.520 DN component\", w: false },\n \"2.5.4.18\": { d: \"postOfficeBox\", c: \"X.520 DN component\", w: false },\n \"2.5.4.18.1\": { d: \"collectivePostOfficeBox\", c: \"X.520 DN component\", w: false },\n \"2.5.4.19\": { d: \"physicalDeliveryOfficeName\", c: \"X.520 DN component\", w: false },\n \"2.5.4.19.1\": { d: \"collectivePhysicalDeliveryOfficeName\", c: \"X.520 DN component\", w: false },\n \"2.5.4.20\": { d: \"telephoneNumber\", c: \"X.520 DN component\", w: false },\n \"2.5.4.20.1\": { d: \"collectiveTelephoneNumber\", c: \"X.520 DN component\", w: false },\n \"2.5.4.21\": { d: \"telexNumber\", c: \"X.520 DN component\", w: false },\n \"2.5.4.21.1\": { d: \"collectiveTelexNumber\", c: \"X.520 DN component\", w: false },\n \"2.5.4.22\": { d: \"teletexTerminalIdentifier\", c: \"X.520 DN component\", w: false },\n \"2.5.4.22.1\": { d: \"collectiveTeletexTerminalIdentifier\", c: \"X.520 DN component\", w: false },\n \"2.5.4.23\": { d: \"facsimileTelephoneNumber\", c: \"X.520 DN component\", w: false },\n \"2.5.4.23.1\": { d: \"collectiveFacsimileTelephoneNumber\", c: \"X.520 DN component\", w: false },\n \"2.5.4.24\": { d: \"x121Address\", c: \"X.520 DN component\", w: false },\n \"2.5.4.25\": { d: \"internationalISDNNumber\", c: \"X.520 DN component\", w: false },\n \"2.5.4.25.1\": { d: \"collectiveInternationalISDNNumber\", c: \"X.520 DN component\", w: false },\n \"2.5.4.26\": { d: \"registeredAddress\", c: \"X.520 DN component\", w: false },\n \"2.5.4.27\": { d: \"destinationIndicator\", c: \"X.520 DN component\", w: false },\n \"2.5.4.28\": { d: \"preferredDeliveryMehtod\", c: \"X.520 DN component\", w: false },\n \"2.5.4.29\": { d: \"presentationAddress\", c: \"X.520 DN component\", w: false },\n \"2.5.4.30\": { d: \"supportedApplicationContext\", c: \"X.520 DN component\", w: false },\n \"2.5.4.31\": { d: \"member\", c: \"X.520 DN component\", w: false },\n \"2.5.4.32\": { d: \"owner\", c: \"X.520 DN component\", w: false },\n \"2.5.4.33\": { d: \"roleOccupant\", c: \"X.520 DN component\", w: false },\n \"2.5.4.34\": { d: \"seeAlso\", c: \"X.520 DN component\", w: false },\n \"2.5.4.35\": { d: \"userPassword\", c: \"X.520 DN component\", w: false },\n \"2.5.4.36\": { d: \"userCertificate\", c: \"X.520 DN component\", w: false },\n \"2.5.4.37\": { d: \"caCertificate\", c: \"X.520 DN component\", w: false },\n \"2.5.4.38\": { d: \"authorityRevocationList\", c: \"X.520 DN component\", w: false },\n \"2.5.4.39\": { d: \"certificateRevocationList\", c: \"X.520 DN component\", w: false },\n \"2.5.4.40\": { d: \"crossCertificatePair\", c: \"X.520 DN component\", w: false },\n \"2.5.4.41\": { d: \"name\", c: \"X.520 DN component\", w: false },\n \"2.5.4.42\": { d: \"givenName\", c: \"X.520 DN component\", w: false },\n \"2.5.4.43\": { d: \"initials\", c: \"X.520 DN component\", w: false },\n \"2.5.4.44\": { d: \"generationQualifier\", c: \"X.520 DN component\", w: false },\n \"2.5.4.45\": { d: \"uniqueIdentifier\", c: \"X.520 DN component\", w: false },\n \"2.5.4.46\": { d: \"dnQualifier\", c: \"X.520 DN component\", w: false },\n \"2.5.4.47\": { d: \"enhancedSearchGuide\", c: \"X.520 DN component\", w: false },\n \"2.5.4.48\": { d: \"protocolInformation\", c: \"X.520 DN component\", w: false },\n \"2.5.4.49\": { d: \"distinguishedName\", c: \"X.520 DN component\", w: false },\n \"2.5.4.50\": { d: \"uniqueMember\", c: \"X.520 DN component\", w: false },\n \"2.5.4.51\": { d: \"houseIdentifier\", c: \"X.520 DN component\", w: false },\n \"2.5.4.52\": { d: \"supportedAlgorithms\", c: \"X.520 DN component\", w: false },\n \"2.5.4.53\": { d: \"deltaRevocationList\", c: \"X.520 DN component\", w: false },\n \"2.5.4.54\": { d: \"dmdName\", c: \"X.520 DN component\", w: false },\n \"2.5.4.55\": { d: \"clearance\", c: \"X.520 DN component\", w: false },\n \"2.5.4.56\": { d: \"defaultDirQop\", c: \"X.520 DN component\", w: false },\n \"2.5.4.57\": { d: \"attributeIntegrityInfo\", c: \"X.520 DN component\", w: false },\n \"2.5.4.58\": { d: \"attributeCertificate\", c: \"X.520 DN component\", w: false },\n \"2.5.4.59\": { d: \"attributeCertificateRevocationList\", c: \"X.520 DN component\", w: false },\n \"2.5.4.60\": { d: \"confKeyInfo\", c: \"X.520 DN component\", w: false },\n \"2.5.4.61\": { d: \"aACertificate\", c: \"X.520 DN component\", w: false },\n \"2.5.4.62\": { d: \"attributeDescriptorCertificate\", c: \"X.520 DN component\", w: false },\n \"2.5.4.63\": { d: \"attributeAuthorityRevocationList\", c: \"X.520 DN component\", w: false },\n \"2.5.4.64\": { d: \"familyInformation\", c: \"X.520 DN component\", w: false },\n \"2.5.4.65\": { d: \"pseudonym\", c: \"X.520 DN component\", w: false },\n \"2.5.4.66\": { d: \"communicationsService\", c: \"X.520 DN component\", w: false },\n \"2.5.4.67\": { d: \"communicationsNetwork\", c: \"X.520 DN component\", w: false },\n \"2.5.4.68\": { d: \"certificationPracticeStmt\", c: \"X.520 DN component\", w: false },\n \"2.5.4.69\": { d: \"certificatePolicy\", c: \"X.520 DN component\", w: false },\n \"2.5.4.70\": { d: \"pkiPath\", c: \"X.520 DN component\", w: false },\n \"2.5.4.71\": { d: \"privPolicy\", c: \"X.520 DN component\", w: false },\n \"2.5.4.72\": { d: \"role\", c: \"X.520 DN component\", w: false },\n \"2.5.4.73\": { d: \"delegationPath\", c: \"X.520 DN component\", w: false },\n \"2.5.4.74\": { d: \"protPrivPolicy\", c: \"X.520 DN component\", w: false },\n \"2.5.4.75\": { d: \"xMLPrivilegeInfo\", c: \"X.520 DN component\", w: false },\n \"2.5.4.76\": { d: \"xmlPrivPolicy\", c: \"X.520 DN component\", w: false },\n \"2.5.4.82\": { d: \"permission\", c: \"X.520 DN component\", w: false },\n \"2.5.6.0\": { d: \"top\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.1\": { d: \"alias\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.2\": { d: \"country\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.3\": { d: \"locality\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.4\": { d: \"organization\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.5\": { d: \"organizationalUnit\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.6\": { d: \"person\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.7\": { d: \"organizationalPerson\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.8\": { d: \"organizationalRole\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.9\": { d: \"groupOfNames\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.10\": { d: \"residentialPerson\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.11\": { d: \"applicationProcess\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.12\": { d: \"applicationEntity\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.13\": { d: \"dSA\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.14\": { d: \"device\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.15\": { d: \"strongAuthenticationUser\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.16\": { d: \"certificateAuthority\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.17\": { d: \"groupOfUniqueNames\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.21\": { d: \"pkiUser\", c: \"X.520 objectClass\", w: false },\n \"2.5.6.22\": { d: \"pkiCA\", c: \"X.520 objectClass\", w: false },\n\n \"2.5.29.1\": { d: \"authorityKeyIdentifier\", c: \"X.509 extension. Deprecated, use 2 5 29 35 instead\", w: true },\n \"2.5.29.2\": { d: \"keyAttributes\", c: \"X.509 extension. Obsolete, use keyUsage/extKeyUsage instead\", w: true },\n \"2.5.29.3\": { d: \"certificatePolicies\", c: \"X.509 extension. Deprecated, use 2 5 29 32 instead\", w: true },\n \"2.5.29.4\": {\n d: \"keyUsageRestriction\",\n c: \"X.509 extension. Obsolete, use keyUsage/extKeyUsage instead\",\n w: true,\n },\n \"2.5.29.5\": { d: \"policyMapping\", c: \"X.509 extension. Deprecated, use 2 5 29 33 instead\", w: true },\n \"2.5.29.6\": { d: \"subtreesConstraint\", c: \"X.509 extension. Obsolete, use nameConstraints instead\", w: true },\n \"2.5.29.7\": { d: \"subjectAltName\", c: \"X.509 extension. Deprecated, use 2 5 29 17 instead\", w: true },\n \"2.5.29.8\": { d: \"issuerAltName\", c: \"X.509 extension. Deprecated, use 2 5 29 18 instead\", w: true },\n \"2.5.29.9\": { d: \"subjectDirectoryAttributes\", c: \"X.509 extension\", w: false },\n \"2.5.29.10\": { d: \"basicConstraints\", c: \"X.509 extension. Deprecated, use 2 5 29 19 instead\", w: true },\n \"2.5.29.11\": { d: \"nameConstraints\", c: \"X.509 extension. Deprecated, use 2 5 29 30 instead\", w: true },\n \"2.5.29.12\": { d: \"policyConstraints\", c: \"X.509 extension. Deprecated, use 2 5 29 36 instead\", w: true },\n \"2.5.29.13\": { d: \"basicConstraints\", c: \"X.509 extension. Deprecated, use 2 5 29 19 instead\", w: true },\n \"2.5.29.14\": { d: \"subjectKeyIdentifier\", c: \"X.509 extension\", w: false },\n \"2.5.29.15\": { d: \"keyUsage\", c: \"X.509 extension\", w: false },\n \"2.5.29.16\": { d: \"privateKeyUsagePeriod\", c: \"X.509 extension\", w: false },\n \"2.5.29.17\": { d: \"subjectAltName\", c: \"X.509 extension\", w: false },\n \"2.5.29.18\": { d: \"issuerAltName\", c: \"X.509 extension\", w: false },\n \"2.5.29.19\": { d: \"basicConstraints\", c: \"X.509 extension\", w: false },\n \"2.5.29.20\": { d: \"cRLNumber\", c: \"X.509 extension\", w: false },\n \"2.5.29.21\": { d: \"cRLReason\", c: \"X.509 extension\", w: false },\n \"2.5.29.22\": { d: \"expirationDate\", c: \"X.509 extension. Deprecated, alternative OID uncertain\", w: true },\n \"2.5.29.23\": { d: \"instructionCode\", c: \"X.509 extension\", w: false },\n \"2.5.29.24\": { d: \"invalidityDate\", c: \"X.509 extension\", w: false },\n \"2.5.29.25\": { d: \"cRLDistributionPoints\", c: \"X.509 extension. Deprecated, use 2 5 29 31 instead\", w: true },\n \"2.5.29.26\": {\n d: \"issuingDistributionPoint\",\n c: \"X.509 extension. Deprecated, use 2 5 29 28 instead\",\n w: true,\n },\n \"2.5.29.27\": { d: \"deltaCRLIndicator\", c: \"X.509 extension\", w: false },\n \"2.5.29.28\": { d: \"issuingDistributionPoint\", c: \"X.509 extension\", w: false },\n \"2.5.29.29\": { d: \"certificateIssuer\", c: \"X.509 extension\", w: false },\n \"2.5.29.30\": { d: \"nameConstraints\", c: \"X.509 extension\", w: false },\n \"2.5.29.31\": { d: \"cRLDistributionPoints\", c: \"X.509 extension\", w: false },\n \"2.5.29.32\": { d: \"certificatePolicies\", c: \"X.509 extension\", w: false },\n \"2.5.29.32.0\": { d: \"anyPolicy\", c: \"X.509 certificate policy\", w: false },\n \"2.5.29.33\": { d: \"policyMappings\", c: \"X.509 extension\", w: false },\n \"2.5.29.34\": { d: \"policyConstraints\", c: \"X.509 extension. Deprecated, use 2 5 29 36 instead\", w: true },\n \"2.5.29.35\": { d: \"authorityKeyIdentifier\", c: \"X.509 extension\", w: false },\n \"2.5.29.36\": { d: \"policyConstraints\", c: \"X.509 extension\", w: false },\n \"2.5.29.37\": { d: \"extKeyUsage\", c: \"X.509 extension\", w: false },\n \"2.5.29.37.0\": { d: \"anyExtendedKeyUsage\", c: \"X.509 extended key usage\", w: false },\n \"2.5.29.38\": { d: \"authorityAttributeIdentifier\", c: \"X.509 extension\", w: false },\n \"2.5.29.39\": { d: \"roleSpecCertIdentifier\", c: \"X.509 extension\", w: false },\n \"2.5.29.40\": { d: \"cRLStreamIdentifier\", c: \"X.509 extension\", w: false },\n \"2.5.29.41\": { d: \"basicAttConstraints\", c: \"X.509 extension\", w: false },\n \"2.5.29.42\": { d: \"delegatedNameConstraints\", c: \"X.509 extension\", w: false },\n \"2.5.29.43\": { d: \"timeSpecification\", c: \"X.509 extension\", w: false },\n \"2.5.29.44\": { d: \"cRLScope\", c: \"X.509 extension\", w: false },\n \"2.5.29.45\": { d: \"statusReferrals\", c: \"X.509 extension\", w: false },\n \"2.5.29.46\": { d: \"freshestCRL\", c: \"X.509 extension\", w: false },\n \"2.5.29.47\": { d: \"orderedList\", c: \"X.509 extension\", w: false },\n \"2.5.29.48\": { d: \"attributeDescriptor\", c: \"X.509 extension\", w: false },\n \"2.5.29.49\": { d: \"userNotice\", c: \"X.509 extension\", w: false },\n \"2.5.29.50\": { d: \"sOAIdentifier\", c: \"X.509 extension\", w: false },\n \"2.5.29.51\": { d: \"baseUpdateTime\", c: \"X.509 extension\", w: false },\n \"2.5.29.52\": { d: \"acceptableCertPolicies\", c: \"X.509 extension\", w: false },\n \"2.5.29.53\": { d: \"deltaInfo\", c: \"X.509 extension\", w: false },\n \"2.5.29.54\": { d: \"inhibitAnyPolicy\", c: \"X.509 extension\", w: false },\n \"2.5.29.55\": { d: \"targetInformation\", c: \"X.509 extension\", w: false },\n \"2.5.29.56\": { d: \"noRevAvail\", c: \"X.509 extension\", w: false },\n \"2.5.29.57\": { d: \"acceptablePrivilegePolicies\", c: \"X.509 extension\", w: false },\n \"2.5.29.58\": { d: \"toBeRevoked\", c: \"X.509 extension\", w: false },\n \"2.5.29.59\": { d: \"revokedGroups\", c: \"X.509 extension\", w: false },\n \"2.5.29.60\": { d: \"expiredCertsOnCRL\", c: \"X.509 extension\", w: false },\n \"2.5.29.61\": { d: \"indirectIssuer\", c: \"X.509 extension\", w: false },\n \"2.5.29.62\": { d: \"noAssertion\", c: \"X.509 extension\", w: false },\n \"2.5.29.63\": { d: \"aAissuingDistributionPoint\", c: \"X.509 extension\", w: false },\n \"2.5.29.64\": { d: \"issuedOnBehalfOf\", c: \"X.509 extension\", w: false },\n \"2.5.29.65\": { d: \"singleUse\", c: \"X.509 extension\", w: false },\n \"2.5.29.66\": { d: \"groupAC\", c: \"X.509 extension\", w: false },\n \"2.5.29.67\": { d: \"allowedAttAss\", c: \"X.509 extension\", w: false },\n \"2.5.29.68\": { d: \"attributeMappings\", c: \"X.509 extension\", w: false },\n \"2.5.29.69\": { d: \"holderNameConstraints\", c: \"X.509 extension\", w: false },\n\n // Netscape certificate type\n // An X.509 v3 certificate extension used to identify whether\n // the certificate subject is an SSL client, …\n \"2.16.840.1.113730.1\": { d: \"certExtension\", c: \"Netscape\" },\n \"2.16.840.1.113730.1.1\": { d: \"netscapeCertType\", c: \"Netscape certificate extension\" },\n \"2.16.840.1.113730.1.2\": { d: \"netscapeBaseUrl\", c: \"Netscape certificate extension\" },\n \"2.16.840.1.113730.1.3\": { d: \"netscapeRevocationUrl\", c: \"Netscape certificate extension\" },\n \"2.16.840.1.113730.1.4\": { d: \"netscapeCaRevocationUrl\", c: \"Netscape certificate extension\" },\n \"2.16.840.1.113730.1.7\": { d: \"netscapeCertRenewalUrl\", c: \"Netscape certificate extension\" },\n \"2.16.840.1.113730.1.8\": { d: \"netscapeCaPolicyUrl\", c: \"Netscape certificate extension\" },\n \"2.16.840.1.113730.1.9\": { d: \"HomePageUrl\", c: \"Netscape certificate extension\" },\n \"2.16.840.1.113730.1.10\": { d: \"EntityLogo\", c: \"Netscape certificate extension\" },\n \"2.16.840.1.113730.1.11\": { d: \"UserPicture\", c: \"Netscape certificate extension\" },\n \"2.16.840.1.113730.1.12\": { d: \"netscapeSslServerName\", c: \"Netscape certificate extension\" },\n \"2.16.840.1.113730.1.13\": { d: \"netscapeComment\", c: \"Netscape certificate extension\" },\n\n done: { d: \"\", c: \"\" },\n};\n","// ---------------------------------------------------------------------------------------------------------------------\n// node-opcua-crypto\n// ---------------------------------------------------------------------------------------------------------------------\n// Copyright (c) 2014-2022 - Etienne Rossignon - etienne.rossignon (at) gadz.org\n// Copyright (c) 2022-2024 - Sterfive.com\n// ---------------------------------------------------------------------------------------------------------------------\n//\n// This project is licensed under the terms of the MIT license.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n// ---------------------------------------------------------------------------------------------------------------------\n\n// tslint:disabled:no-var-requires\n/**\n * @module node_opcua_crypto\n */\nimport constants from \"constants\";\nimport assert from \"assert\";\nimport {\n createHash,\n createSign,\n createVerify,\n publicEncrypt as publicEncrypt1,\n privateDecrypt as privateDecrypt1,\n KeyLike,\n KeyObject,\n} from \"crypto\";\n\nimport pkg_hexy from \"hexy\";\nconst { hexy } = pkg_hexy;\n\nimport { createFastUninitializedBuffer } from \"./buffer_utils.js\";\nimport { Certificate, CertificatePEM, DER, PEM, PublicKeyPEM, Signature, PrivateKey } from \"./common.js\";\nimport { combine_der } from \"./crypto_explore_certificate.js\";\nimport jsrsasign from \"jsrsasign\";\n\nconst PEM_REGEX = /^(-----BEGIN (.*)-----\\r?\\n([/+=a-zA-Z0-9\\r\\n]*)\\r?\\n-----END \\2-----\\r?\\n?)/gm;\n\nconst PEM_TYPE_REGEX = /^(-----BEGIN (.*)-----)/m;\n// Copyright 2012 The Obvious Corporation.\n// identifyPemType\n\n/*=\n * Extract and identify the PEM file type represented in the given\n * buffer. Returns the extracted type string or undefined if the\n * buffer doesn't seem to be any sort of PEM format file.\n */\nexport function identifyPemType(rawKey: Buffer | string): undefined | string {\n if (Buffer.isBuffer(rawKey)) {\n rawKey = rawKey.toString(\"utf8\");\n }\n const match = PEM_TYPE_REGEX.exec(rawKey as string);\n return !match ? undefined : match[2];\n}\n\nexport function removeTrailingLF(str: string): string {\n const tmp = str.replace(/(\\r|\\n)+$/m, \"\").replace(/\\r\\n/gm, \"\\n\");\n return tmp;\n}\n\nexport function toPem(raw_key: Buffer | string, pem: string): string {\n assert(raw_key, \"expecting a key\");\n assert(typeof pem === \"string\");\n let pemType = identifyPemType(raw_key);\n if (pemType) {\n return Buffer.isBuffer(raw_key)\n ? removeTrailingLF((raw_key as Buffer).toString(\"utf8\"))\n : removeTrailingLF(raw_key as string);\n } else {\n pemType = pem;\n assert([\"CERTIFICATE REQUEST\", \"CERTIFICATE\", \"RSA PRIVATE KEY\", \"PUBLIC KEY\", \"X509 CRL\"].indexOf(pemType) >= 0);\n let b = (raw_key as Buffer).toString(\"base64\");\n let str = \"-----BEGIN \" + pemType + \"-----\\n\";\n while (b.length) {\n str += b.substring(0, 64) + \"\\n\";\n b = b.substring(64);\n }\n str += \"-----END \" + pemType + \"-----\";\n // no leading \\n\n return str;\n }\n}\n\nexport function convertPEMtoDER(raw_key: PEM): DER {\n let match: any;\n let pemType;\n let base64str;\n\n const parts: DER[] = [];\n\n PEM_REGEX.lastIndex = 0;\n // tslint:disable-next-line:no-conditional-assignment\n while ((match = PEM_REGEX.exec(raw_key)) !== null) {\n pemType = match[2];\n // pemType shall be \"RSA PRIVATE KEY\" , \"PUBLIC KEY\", \"CERTIFICATE\", \"X509 CRL\"\n base64str = match[3];\n base64str = base64str.replace(/\\r?\\n/g, \"\");\n parts.push(Buffer.from(base64str, \"base64\"));\n }\n return combine_der(parts);\n}\n\n// istanbul ignore next\nexport function hexDump(buffer: Buffer, width?: number): string {\n if (!buffer) {\n return \"<>\";\n }\n width = width || 32;\n if (buffer.length > 1024) {\n return hexy(buffer.subarray(0, 1024), { width, format: \"twos\" }) + \"\\n .... ( \" + buffer.length + \")\";\n } else {\n return hexy(buffer, { width, format: \"twos\" });\n }\n}\n\ninterface MakeMessageChunkSignatureOptions {\n signatureLength: number;\n algorithm: string;\n privateKey: PrivateKey;\n}\n\nexport function makeMessageChunkSignature(chunk: Buffer, options: MakeMessageChunkSignatureOptions): Buffer {\n // signature length = 128 bytes\n const signer = createSign(options.algorithm);\n signer.update(chunk);\n const signature = signer.sign(options.privateKey.hidden as KeyObject);\n assert(!options.signatureLength || signature.length === options.signatureLength);\n return signature;\n}\n\nexport interface VerifyMessageChunkSignatureOptions {\n signatureLength?: number;\n algorithm: string;\n publicKey: PublicKeyPEM;\n}\n\n/**\n * @method verifyMessageChunkSignature\n *\n * const signer = {\n * signatureLength : 128,\n * algorithm : \"RSA-SHA256\",\n * publicKey: \"qsdqsdqsd\"\n * };\n * @param blockToVerify\n * @param signature\n * @param options\n * @param options.signatureLength\n * @param options.algorithm for example \"RSA-SHA256\"\n * @param options.publicKey\n * @return true if the signature is valid\n */\nexport function verifyMessageChunkSignature(\n blockToVerify: Buffer,\n signature: Signature,\n options: VerifyMessageChunkSignatureOptions\n): boolean {\n // Note those assets are failing in web browse\n // assert(blockToVerify instanceof Buffer || blockToVerify instanceof Uint8Array);\n // assert(signature instanceof Buffer || blockToVerify instanceof Uint8Array);\n // assert(typeof options.publicKey === \"string\");\n // assert(identifyPemType(options.publicKey));\n\n const verify = createVerify(options.algorithm);\n verify.update(blockToVerify);\n return verify.verify(options.publicKey, signature);\n}\n\nexport function makeSHA1Thumbprint(buffer: Buffer): Signature {\n return createHash(\"sha1\").update(buffer).digest();\n}\n\n// Basically when you =encrypt something using an RSA key (whether public or private), the encrypted value must\n// be smaller than the key (due to the maths used to do the actual encryption). So if you have a 1024-bit key,\n// in theory you could encrypt any 1023-bit value (or a 1024-bit value smaller than the key) with that key.\n// However, the PKCS#1 standard, which OpenSSL uses, specifies a padding scheme (so you can encrypt smaller\n// quantities without losing security), and that padding scheme takes a minimum of 11 bytes (it will be longer\n// if the value you're encrypting is smaller). So the highest number of bits you can encrypt with a 1024-bit\n// key is 936 bits because of this (unless you disable the padding by adding the OPENSSL_NO_PADDING flag,\n// in which case you can go up to 1023-1024 bits). With a 2048-bit key it's 1960 bits instead.\n\nexport const RSA_PKCS1_OAEP_PADDING: number = constants.RSA_PKCS1_OAEP_PADDING;\nexport const RSA_PKCS1_PADDING: number = constants.RSA_PKCS1_PADDING;\n\nexport enum PaddingAlgorithm {\n RSA_PKCS1_OAEP_PADDING = 4,\n RSA_PKCS1_PADDING = 1,\n}\n\nassert(PaddingAlgorithm.RSA_PKCS1_OAEP_PADDING === constants.RSA_PKCS1_OAEP_PADDING);\nassert(PaddingAlgorithm.RSA_PKCS1_PADDING === constants.RSA_PKCS1_PADDING);\n\n// publicEncrypt and privateDecrypt only work with\n// small buffer that depends of the key size.\nexport function publicEncrypt_native(buffer: Buffer, publicKey: KeyLike, algorithm?: PaddingAlgorithm): Buffer {\n if (algorithm === undefined) {\n algorithm = PaddingAlgorithm.RSA_PKCS1_OAEP_PADDING;\n }\n return publicEncrypt1(\n {\n key: publicKey,\n padding: algorithm,\n },\n buffer\n );\n}\n\nexport function privateDecrypt_native(buffer: Buffer, privateKey: PrivateKey, algorithm?: PaddingAlgorithm): Buffer {\n if (algorithm === undefined) {\n algorithm = PaddingAlgorithm.RSA_PKCS1_OAEP_PADDING;\n }\n\n try {\n return privateDecrypt1(\n {\n key: privateKey.hidden as KeyObject,\n padding: