From ae03e344898876c5583d72061fede178517774fc Mon Sep 17 00:00:00 2001 From: Robin Sandhu Date: Sun, 9 Jun 2024 00:07:16 +0100 Subject: [PATCH 01/11] Add support for ECDSA and DSA keys to Parse CSR operation --- src/core/operations/ParseCSR.mjs | 295 +++++---- tests/operations/tests/ParseCSR.mjs | 897 ++++++++++++++++++++++++++-- 2 files changed, 1026 insertions(+), 166 deletions(-) diff --git a/src/core/operations/ParseCSR.mjs b/src/core/operations/ParseCSR.mjs index 6ab44cb20..63d66c6ea 100644 --- a/src/core/operations/ParseCSR.mjs +++ b/src/core/operations/ParseCSR.mjs @@ -4,8 +4,9 @@ * @license Apache-2.0 */ +import r from "jsrsasign"; import Operation from "../Operation.mjs"; -import forge from "node-forge"; +import { formatDnObj } from "../lib/PublicKey.mjs"; import Utils from "../Utils.mjs"; /** @@ -30,16 +31,6 @@ class ParseCSR extends Operation { "name": "Input format", "type": "option", "value": ["PEM"] - }, - { - "name": "Key type", - "type": "option", - "value": ["RSA"] - }, - { - "name": "Strict ASN.1 value lengths", - "type": "boolean", - "value": true } ]; this.checks = [ @@ -61,73 +52,71 @@ class ParseCSR extends Operation { return "No input"; } - const csr = forge.pki.certificationRequestFromPem(input, args[1]); - - // RSA algorithm is the only one supported for CSR in node-forge as of 1.3.1 - return `Version: ${1 + csr.version} (0x${Utils.hex(csr.version)}) -Subject${formatSubject(csr.subject)} -Subject Alternative Names${formatSubjectAlternativeNames(csr)} -Public Key - Algorithm: RSA - Length: ${csr.publicKey.n.bitLength()} bits - Modulus: ${formatMultiLine(chop(csr.publicKey.n.toString(16).replace(/(..)/g, "$&:")))} - Exponent: ${csr.publicKey.e} (0x${Utils.hex(csr.publicKey.e)}) -Signature - Algorithm: ${forge.pki.oids[csr.signatureOid]} - Signature: ${formatMultiLine(Utils.strToByteArray(csr.signature).map(b => Utils.hex(b)).join(":"))} -Extensions${formatExtensions(csr)}`; + // Parse the CSR into JSON parameters + const csrParam = new r.KJUR.asn1.csr.CSRUtil.getParam(input); + + return `Subject\n${formatDnObj(csrParam.subject, 2)} +Public Key${formatSubjectPublicKey(csrParam.sbjpubkey)} +Signature${formatSignature(csrParam.sigalg, csrParam.sighex)} +Requested Extensions${formatRequestedExtensions(csrParam)}`; } } /** - * Format Subject of the request as a multi-line string - * @param {*} subject CSR Subject - * @returns Multi-line string describing Subject + * Format signature of a CSR + * @param {*} sigAlg string + * @param {*} sigHex string + * @returns Multi-line string describing CSR Signature */ -function formatSubject(subject) { - let out = "\n"; - - for (const attribute of subject.attributes) { - out += ` ${attribute.shortName} = ${attribute.value}\n`; +function formatSignature(sigAlg, sigHex) { + let out = `\n`; + + out += ` Algorithm: ${sigAlg}\n`; + + if (new RegExp("withdsa", "i").test(sigAlg)) { + const d = new r.KJUR.crypto.DSA(); + const sigParam = d.parseASN1Signature(sigHex); + out += ` Signature: + R: ${formatHexOntoMultiLine(sigParam[0].toString(16))} + S: ${formatHexOntoMultiLine(sigParam[1].toString(16))}\n`; + } else if (new RegExp("withrsa", "i").test(sigAlg)) { + out += ` Signature: ${formatHexOntoMultiLine(sigHex, false)}\n`; + } else { + out += ` Signature: ${formatHexOntoMultiLine(sigHex)}\n`; } return chop(out); } - /** - * Format Subject Alternative Names from the name `subjectAltName` extension - * @param {*} extension CSR object - * @returns Multi-line string describing Subject Alternative Names + * Format Subject Public Key from PEM encoded public key string + * @param {*} publicKeyPEM string + * @returns Multi-line string describing Subject Public Key Info */ -function formatSubjectAlternativeNames(csr) { +function formatSubjectPublicKey(publicKeyPEM) { let out = "\n"; - for (const attribute of csr.attributes) { - for (const extension of attribute.extensions) { - if (extension.name === "subjectAltName") { - const names = []; - for (const altName of extension.altNames) { - switch (altName.type) { - case 1: - names.push(`EMAIL: ${altName.value}`); - break; - case 2: - names.push(`DNS: ${altName.value}`); - break; - case 6: - names.push(`URI: ${altName.value}`); - break; - case 7: - names.push(`IP: ${altName.ip}`); - break; - default: - names.push(`(unable to format type ${altName.type} name)\n`); - } - } - out += indent(2, names); - } - } + const publicKey = r.KEYUTIL.getKey(publicKeyPEM); + if (publicKey instanceof r.RSAKey) { + out += ` Algorithm: RSA + Length: ${publicKey.n.bitLength()} bits + Modulus: ${formatHexOntoMultiLine(publicKey.n.toString(16))} + Exponent: ${publicKey.e} (0x${Utils.hex(publicKey.e)})\n`; + } else if (publicKey instanceof r.KJUR.crypto.ECDSA) { + out += ` Algorithm: ECDSA + Length: ${publicKey.ecparams.keylen} bits + Pub: ${formatHexOntoMultiLine(publicKey.pubKeyHex)} + ASN1 OID: ${r.KJUR.crypto.ECDSA.getName(publicKey.getShortNISTPCurveName())} + NIST CURVE: ${publicKey.getShortNISTPCurveName()}\n`; + } else if (publicKey instanceof r.KJUR.crypto.DSA) { + out += ` Algorithm: DSA + Length: ${publicKey.p.toString(16).length * 4} bits + Pub: ${formatHexOntoMultiLine(publicKey.y.toString(16))} + P: ${formatHexOntoMultiLine(publicKey.p.toString(16))} + Q: ${formatHexOntoMultiLine(publicKey.q.toString(16))} + G: ${formatHexOntoMultiLine(publicKey.g.toString(16))}\n`; + } else { + out += `unsupported public key algorithm\n`; } return chop(out); @@ -135,45 +124,79 @@ function formatSubjectAlternativeNames(csr) { /** * Format known extensions of a CSR - * @param {*} csr CSR object - * @returns Multi-line string describing attributes + * @param {*} csrParam object + * @returns Multi-line string describing CSR Requested Extensions */ -function formatExtensions(csr) { - let out = "\n"; +function formatRequestedExtensions(csrParam) { + const formattedExtensions = new Array(4).fill(""); - for (const attribute of csr.attributes) { - for (const extension of attribute.extensions) { - // formatted separately - if (extension.name === "subjectAltName") { - continue; - } - out += ` ${extension.name}${(extension.critical ? " CRITICAL" : "")}:\n`; + if (Object.hasOwn(csrParam, "extreq")) { + for (const extension of csrParam.extreq) { let parts = []; - switch (extension.name) { + switch (extension.extname) { case "basicConstraints" : parts = describeBasicConstraints(extension); + formattedExtensions[0] = ` Basic Constraints:${formatExtensionCriticalTag(extension)}\n${indent(4, parts)}`; break; case "keyUsage" : parts = describeKeyUsage(extension); + formattedExtensions[1] = ` Key Usage:${formatExtensionCriticalTag(extension)}\n${indent(4, parts)}`; break; case "extKeyUsage" : parts = describeExtendedKeyUsage(extension); + formattedExtensions[2] = ` Extended Key Usage:${formatExtensionCriticalTag(extension)}\n${indent(4, parts)}`; + break; + case "subjectAltName" : + parts = describeSubjectAlternativeName(extension); + formattedExtensions[3] = ` Subject Alternative Name:${formatExtensionCriticalTag(extension)}\n${indent(4, parts)}`; break; default : - parts = ["(unable to format extension)"]; + parts = ["(unsuported extension)"]; + formattedExtensions.push(` ${extension.extname}:${formatExtensionCriticalTag(extension)}\n${indent(4, parts)}`); } - out += indent(4, parts); } } + let out = "\n"; + + formattedExtensions.forEach((formattedExtension) => { + if (formattedExtension !== undefined && formattedExtension !== null && formattedExtension.length !== 0) { + out += formattedExtension; + } + }); + return chop(out); } +/** + * Format extension critical tag + * @param {*} extension Object + * @returns String describing whether the extension is critical or not + */ +function formatExtensionCriticalTag(extension) { + return Object.hasOwn(extension, "critical") && extension.critical ? " critical" : ""; +} + +/** + * Format hex input on multiple lines + * @param {*} hex string + * @returns Multi-line string describing the Hex input + */ +function formatHexOntoMultiLine(hex, prependZero=true) { + let colonSeparatedHex = chop(hex.replace(/(..)/g, "$&:")); + + // prepend 00 if most significant bit it 1 + if ((parseInt(colonSeparatedHex.substring(0, 2), 16) & 128) && prependZero) { + colonSeparatedHex = "00:" + colonSeparatedHex; + } + + return formatMultiLine(colonSeparatedHex); +} /** - * Format hex string onto multiple lines + * Format string onto multiple lines * @param {*} longStr - * @returns Hex string as a multi-line hex string + * @returns String as a multi-line string */ function formatMultiLine(longStr) { const lines = []; @@ -194,8 +217,8 @@ function formatMultiLine(longStr) { function describeBasicConstraints(extension) { const constraints = []; - constraints.push(`CA = ${extension.cA}`); - if (extension.pathLenConstraint !== undefined) constraints.push(`PathLenConstraint = ${extension.pathLenConstraint}`); + constraints.push(`CA = ${Object.hasOwn(extension, "cA") && extension.cA ? "true" : "false"}`); + if (Object.hasOwn(extension, "pathLen")) constraints.push(`PathLenConstraint = ${extension.pathLen}`); return constraints; } @@ -209,15 +232,27 @@ function describeBasicConstraints(extension) { function describeKeyUsage(extension) { const usage = []; - if (extension.digitalSignature) usage.push("Digital signature"); - if (extension.nonRepudiation) usage.push("Non-repudiation"); - if (extension.keyEncipherment) usage.push("Key encipherment"); - if (extension.dataEncipherment) usage.push("Data encipherment"); - if (extension.keyAgreement) usage.push("Key agreement"); - if (extension.keyCertSign) usage.push("Key certificate signing"); - if (extension.cRLSign) usage.push("CRL signing"); - if (extension.encipherOnly) usage.push("Encipher only"); - if (extension.decipherOnly) usage.push("Decipher only"); + const kuIdentifierToName = new Map([ + ["digitalSignature", "Digital Signature"], + ["nonRepudiation", "Non-repudiation"], + ["keyEncipherment", "Key encipherment"], + ["dataEncipherment", "Data encipherment"], + ["keyAgreement", "Key agreement"], + ["keyCertSign", "Key certificate signing"], + ["cRLSign", "CRL signing"], + ["encipherOnly", "Encipher Only"], + ["decipherOnly", "Decipher Only"], + ]); + + if (Object.hasOwn(extension, "names")) { + extension.names.forEach((ku) => { + if (kuIdentifierToName.has(ku)) { + usage.push(kuIdentifierToName.get(ku)); + } else { + usage.push(`unknown key usage (${ku})`); + } + }); + } if (usage.length === 0) usage.push("(none)"); @@ -233,23 +268,79 @@ function describeKeyUsage(extension) { function describeExtendedKeyUsage(extension) { const usage = []; - if (extension.serverAuth) usage.push("TLS Web Server Authentication"); - if (extension.clientAuth) usage.push("TLS Web Client Authentication"); - if (extension.codeSigning) usage.push("Code signing"); - if (extension.emailProtection) usage.push("E-mail Protection (S/MIME)"); - if (extension.timeStamping) usage.push("Trusted Timestamping"); - if (extension.msCodeInd) usage.push("Microsoft Individual Code Signing"); - if (extension.msCodeCom) usage.push("Microsoft Commercial Code Signing"); - if (extension.msCTLSign) usage.push("Microsoft Trust List Signing"); - if (extension.msSGC) usage.push("Microsoft Server Gated Crypto"); - if (extension.msEFS) usage.push("Microsoft Encrypted File System"); - if (extension.nsSGC) usage.push("Netscape Server Gated Crypto"); + const ekuIdentifierToName = new Map([ + ["serverAuth", "TLS Web Server Authentication"], + ["clientAuth", "TLS Web Client Authentication"], + ["codeSigning", "Code signing"], + ["emailProtection", "E-mail Protection (S/MIME)"], + ["timeStamping", "Trusted Timestamping"], + ["1.3.6.1.4.1.311.2.1.21", "Microsoft Individual Code Signing"], // msCodeInd + ["1.3.6.1.4.1.311.2.1.22", "Microsoft Commercial Code Signing"], // msCodeCom + ["1.3.6.1.4.1.311.10.3.1", "Microsoft Trust List Signing"], // msCTLSign + ["1.3.6.1.4.1.311.10.3.3", "Microsoft Server Gated Crypto"], // msSGC + ["1.3.6.1.4.1.311.10.3.4", "Microsoft Encrypted File System"], // msEFS + ["1.3.6.1.4.1.311.20.2.2", "Microsoft Smartcard Login"], // msSmartcardLogin + ["2.16.840.1.113730.4.1", "Netscape Server Gated Crypto"], // nsSGC + ]); + + if (Object.hasOwn(extension, "array")) { + extension.array.forEach((eku) => { + if (ekuIdentifierToName.has(eku)) { + usage.push(ekuIdentifierToName.get(eku)); + } else { + usage.push(`unknown extended key usage (${eku})`); + } + }); + } if (usage.length === 0) usage.push("(none)"); return usage; } +/** + * Format Subject Alternative Names from the name `subjectAltName` extension + * @see RFC 5280 4.2.1.6. Subject Alternative Name https://www.ietf.org/rfc/rfc5280.txt + * @param {*} extension object + * @returns Array of strings describing Subject Alternative Name extension + */ +function describeSubjectAlternativeName(extension) { + const names = []; + + if (Object.hasOwn(extension, "extname") && extension.extname === "subjectAltName") { + if (Object.hasOwn(extension, "array")) { + for (const altName of extension.array) { + Object.keys(altName).forEach((key) => { + switch (key) { + case "rfc822": + names.push(`EMAIL: ${altName[key]}`); + break; + case "dns": + names.push(`DNS: ${altName[key]}`); + break; + case "uri": + names.push(`URI: ${altName[key]}`); + break; + case "ip": + names.push(`IP: ${altName[key]}`); + break; + case "dn": + names.push(`DIR: ${altName[key].str}`); + break; + case "other" : + names.push(`Other: ${altName[key].oid}::${altName[key].value.utf8str.str}`); + break; + default: + names.push(`(unable to format type '${key}' name)\n`); + } + }); + } + } + } + + return names; +} + /** * Join an array of strings and add leading spaces to each line. * @param {*} n How many leading spaces diff --git a/tests/operations/tests/ParseCSR.mjs b/tests/operations/tests/ParseCSR.mjs index 1ba7e73f5..b8c510e9f 100644 --- a/tests/operations/tests/ParseCSR.mjs +++ b/tests/operations/tests/ParseCSR.mjs @@ -29,31 +29,28 @@ NFgFNIvSXhbqMYoHAAApMHJOxiWpBFdYKp3tESnlgh2lUh7lQtmOjD4a1dzfU8PU oViyp+UJGasN2WRd+4VtaPw64w== -----END CERTIFICATE REQUEST-----`; -const OUT_EXAMPLE_COM_RSA_1024 = `Version: 1 (0x00) -Subject - C = CH +const OUT_EXAMPLE_COM_RSA_1024 = `Subject + C = CH ST = Zurich - L = Zurich - O = Example RE + L = Zurich + O = Example RE OU = IT Department CN = example.com -Subject Alternative Names - DNS: example.com - DNS: www.example.com Public Key Algorithm: RSA Length: 1024 bits - Modulus: ae:b4:eb:2c:8e:85:93:38:d7:f0:56:5f:72:5b:76:a3: - 1d:43:cf:b2:91:c2:de:5f:e9:f7:d9:89:ce:ed:c0:b0: - 0a:27:86:a8:fc:7d:c0:3e:3c:28:15:55:17:1a:38:8d: - 8f:f5:c5:d9:19:48:77:85:31:07:56:fa:0a:05:a3:ba: - 30:5b:f5:6e:75:ad:37:6f:7d:62:f2:00:7b:2b:2d:ca: - 6d:a5:5c:fe:57:d6:3c:5f:d9:04:14:24:46:18:3c:86: - e7:e5:fe:36:ee:82:3b:34:e9:50:f0:e3:e1:b2:08:5f: - fb:8f:93:77:c3:60:31:2a:2c:29:55:cb:cf:d5:4b:8f + Modulus: 00:ae:b4:eb:2c:8e:85:93:38:d7:f0:56:5f:72:5b:76: + a3:1d:43:cf:b2:91:c2:de:5f:e9:f7:d9:89:ce:ed:c0: + b0:0a:27:86:a8:fc:7d:c0:3e:3c:28:15:55:17:1a:38: + 8d:8f:f5:c5:d9:19:48:77:85:31:07:56:fa:0a:05:a3: + ba:30:5b:f5:6e:75:ad:37:6f:7d:62:f2:00:7b:2b:2d: + ca:6d:a5:5c:fe:57:d6:3c:5f:d9:04:14:24:46:18:3c: + 86:e7:e5:fe:36:ee:82:3b:34:e9:50:f0:e3:e1:b2:08: + 5f:fb:8f:93:77:c3:60:31:2a:2c:29:55:cb:cf:d5:4b: + 8f Exponent: 65537 (0x10001) Signature - Algorithm: sha256WithRSAEncryption + Algorithm: SHA256withRSA Signature: 74:99:49:4f:82:de:a9:b7:f9:23:0f:4a:73:39:43:64: e5:ef:67:04:54:18:40:6b:86:20:71:98:6c:f5:f7:9a: 2e:16:77:db:d4:09:d3:e2:c6:d3:d2:4e:e9:c7:5a:cd: @@ -62,14 +59,17 @@ Signature 25:a9:04:57:58:2a:9d:ed:11:29:e5:82:1d:a5:52:1e: e5:42:d9:8e:8c:3e:1a:d5:dc:df:53:c3:d4:a1:58:b2: a7:e5:09:19:ab:0d:d9:64:5d:fb:85:6d:68:fc:3a:e3 -Extensions - basicConstraints CRITICAL: +Requested Extensions + Basic Constraints: critical CA = false - keyUsage CRITICAL: - Digital signature + Key Usage: critical + Digital Signature Key encipherment - extKeyUsage: - TLS Web Server Authentication`; + Extended Key Usage: + TLS Web Server Authentication + Subject Alternative Name: + DNS: example.com + DNS: www.example.com`; // openssl req -newkey rsa:2048 -keyout test-rsa-2048.key -out test-rsa-2048.csr \ // -subj "/C=CH/ST=Zurich/L=Zurich/O=Example RE/OU=IT Department/CN=example.com" \ @@ -97,39 +97,36 @@ m9cpVxuxGLtONBnohzohnFECytSXWEXPIj8L9SpYK97G02nJYYCAcb5BF11Alfux sNxtsr6zgPaLRrvOBT11WxJVKerbhfezAJ3naem1eM3VLxCGWwMwxg== -----END CERTIFICATE REQUEST-----`; -const OUT_EXAMPLE_COM_RSA_2048 = `Version: 1 (0x00) -Subject - C = CH +const OUT_EXAMPLE_COM_RSA_2048 = `Subject + C = CH ST = Zurich - L = Zurich - O = Example RE + L = Zurich + O = Example RE OU = IT Department CN = example.com -Subject Alternative Names - DNS: example.com - DNS: www.example.com Public Key Algorithm: RSA Length: 2048 bits - Modulus: a3:e8:80:b9:96:3e:e2:bf:20:67:5c:b7:6b:ff:dc:c1: - 4a:55:a5:5e:2a:9d:87:97:96:ad:ff:30:c5:2c:20:1e: - e7:56:f0:87:b0:6a:35:52:44:72:2e:00:a7:09:57:03: - 55:95:99:03:c1:14:12:65:63:04:19:56:3c:f9:50:03: - 76:0a:63:47:c6:e7:79:9d:5d:37:62:66:76:fc:89:a5: - 47:3a:4a:71:93:0f:a9:4f:a5:88:90:82:d3:82:fe:5c: - 86:ce:77:1f:95:cf:9d:9d:17:ef:82:73:e1:6e:48:5a: - bc:d3:7c:96:fa:a7:9f:2b:c2:6c:24:d3:bd:2a:e3:f1: - 44:b6:0a:48:00:03:6b:d3:08:26:2b:2b:bb:53:f3:70: - 10:0e:72:29:8e:98:d9:c5:5a:ea:3e:2c:ab:1d:e2:55: - 37:d0:e1:31:0d:d2:87:c2:dc:ad:eb:63:23:d5:cd:e8: - 94:ed:49:8e:f9:23:b5:65:a3:c0:72:3e:d0:48:13:8e: - f9:1e:5e:57:14:61:9b:ef:2e:5c:ac:74:a1:11:31:1a: - 33:bc:c4:c6:aa:aa:07:58:28:16:97:e4:6a:f5:9e:8f: - 4e:03:6c:44:ee:02:2a:e8:35:67:09:a1:f3:2e:9a:71: - 9e:ec:61:bf:dd:6a:bf:07:39:ea:89:9d:cd:29:0a:ff + Modulus: 00:a3:e8:80:b9:96:3e:e2:bf:20:67:5c:b7:6b:ff:dc: + c1:4a:55:a5:5e:2a:9d:87:97:96:ad:ff:30:c5:2c:20: + 1e:e7:56:f0:87:b0:6a:35:52:44:72:2e:00:a7:09:57: + 03:55:95:99:03:c1:14:12:65:63:04:19:56:3c:f9:50: + 03:76:0a:63:47:c6:e7:79:9d:5d:37:62:66:76:fc:89: + a5:47:3a:4a:71:93:0f:a9:4f:a5:88:90:82:d3:82:fe: + 5c:86:ce:77:1f:95:cf:9d:9d:17:ef:82:73:e1:6e:48: + 5a:bc:d3:7c:96:fa:a7:9f:2b:c2:6c:24:d3:bd:2a:e3: + f1:44:b6:0a:48:00:03:6b:d3:08:26:2b:2b:bb:53:f3: + 70:10:0e:72:29:8e:98:d9:c5:5a:ea:3e:2c:ab:1d:e2: + 55:37:d0:e1:31:0d:d2:87:c2:dc:ad:eb:63:23:d5:cd: + e8:94:ed:49:8e:f9:23:b5:65:a3:c0:72:3e:d0:48:13: + 8e:f9:1e:5e:57:14:61:9b:ef:2e:5c:ac:74:a1:11:31: + 1a:33:bc:c4:c6:aa:aa:07:58:28:16:97:e4:6a:f5:9e: + 8f:4e:03:6c:44:ee:02:2a:e8:35:67:09:a1:f3:2e:9a: + 71:9e:ec:61:bf:dd:6a:bf:07:39:ea:89:9d:cd:29:0a: + ff Exponent: 65537 (0x10001) Signature - Algorithm: sha256WithRSAEncryption + Algorithm: SHA256withRSA Signature: 1b:47:23:7d:10:58:d6:90:73:bb:e8:df:ef:23:10:ac: ae:66:42:b8:7b:d9:a8:ab:56:e5:c7:9a:87:21:9b:25: 31:ca:dd:06:ee:8b:e7:36:12:84:af:e5:fd:b2:74:a1: @@ -146,14 +143,17 @@ Signature be:41:17:5d:40:95:fb:b1:b0:dc:6d:b2:be:b3:80:f6: 8b:46:bb:ce:05:3d:75:5b:12:55:29:ea:db:85:f7:b3: 00:9d:e7:69:e9:b5:78:cd:d5:2f:10:86:5b:03:30:c6 -Extensions - basicConstraints CRITICAL: +Requested Extensions + Basic Constraints: critical CA = false - keyUsage CRITICAL: - Digital signature + Key Usage: critical + Digital Signature Key encipherment - extKeyUsage: - TLS Web Server Authentication`; + Extended Key Usage: + TLS Web Server Authentication + Subject Alternative Name: + DNS: example.com + DNS: www.example.com`; // openssl genpkey -genparam -algorithm ec -pkeyopt ec_paramgen_curve:P-256 -out test-ec-param.pem // openssl req -newkey ec:test-ec-param.pem -keyout test-ec.key -out test-ec.csr \ @@ -162,7 +162,7 @@ Extensions // -addext "basicConstraints = critical,CA:FALSE" \ // -addext "keyUsage = critical,digitalSignature,keyEncipherment" \ // -addext "extendedKeyUsage = serverAuth" -const IN_EXAMPLE_COM_EC = `-----BEGIN CERTIFICATE REQUEST----- +const IN_EXAMPLE_COM_EC_P256 = `-----BEGIN CERTIFICATE REQUEST----- MIIBmzCCAUECAQAwcjELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBlp1cmljaDEPMA0G A1UEBwwGWnVyaWNoMRMwEQYDVQQKDApFeGFtcGxlIFJFMRYwFAYDVQQLDA1JVCBE ZXBhcnRtZW50MRQwEgYDVQQDDAtleGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqG @@ -174,7 +174,690 @@ zj0EAwIDSAAwRQIgQkum/qaLzE3QZ3WD00uLpalUn113FObd7rM5Mr3HQwQCIQCr 7OjzYI9v7qIJp/E9N16XfJN87G2ZVIZ4FuPXVjokCQ== -----END CERTIFICATE REQUEST-----`; -const OUT_EXAMPLE_COM_EC = `Parse CSR - Cannot read public key. OID is not RSA.`; +const OUT_EXAMPLE_COM_EC_P256 = `Subject + C = CH + ST = Zurich + L = Zurich + O = Example RE + OU = IT Department + CN = example.com +Public Key + Algorithm: ECDSA + Length: 256 bits + Pub: 04:09:a9:61:73:61:f8:bf:44:d1:0d:ec:2e:1a:ce:f8: + c1:75:5e:02:82:7e:a2:67:b6:b3:b2:22:4a:c6:c2:88: + 90:7e:d1:db:25:64:c0:e9:db:b1:42:15:3f:dd:df:41: + f9:23:7f:89:b7:8a:63:ec:5e:88:d0:6b:b3:67:93:61: + 9e + ASN1 OID: secp256r1 + NIST CURVE: P-256 +Signature + Algorithm: SHA256withECDSA + Signature: 30:45:02:20:42:4b:a6:fe:a6:8b:cc:4d:d0:67:75:83: + d3:4b:8b:a5:a9:54:9f:5d:77:14:e6:dd:ee:b3:39:32: + bd:c7:43:04:02:21:00:ab:ec:e8:f3:60:8f:6f:ee:a2: + 09:a7:f1:3d:37:5e:97:7c:93:7c:ec:6d:99:54:86:78: + 16:e3:d7:56:3a:24:09 +Requested Extensions + Basic Constraints: critical + CA = false + Key Usage: critical + Digital Signature + Key encipherment + Extended Key Usage: + TLS Web Server Authentication + Subject Alternative Name: + DNS: example.com + DNS: www.example.com`; + +// openssl ecparam -name secp384r1 -genkey -noout -out test-ec-key.pem +// openssl req -new -key test-ec-key.pem -out test-ec.csr +// -subj "/C=CH/ST=Zurich/L=Zurich/O=Example RE/OU=IT Department/CN=example.com" +// -addext "subjectAltName = DNS:example.com,DNS:www.example.com" +// -addext "basicConstraints = critical,CA:FALSE" +// -addext "keyUsage = critical,digitalSignature,keyEncipherment" +// -addext "extendedKeyUsage = serverAuth" +const IN_EXAMPLE_COM_EC_P384 = `-----BEGIN CERTIFICATE REQUEST----- +MIIB2TCCAV4CAQAwcjELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBlp1cmljaDEPMA0G +A1UEBwwGWnVyaWNoMRMwEQYDVQQKDApFeGFtcGxlIFJFMRYwFAYDVQQLDA1JVCBE +ZXBhcnRtZW50MRQwEgYDVQQDDAtleGFtcGxlLmNvbTB2MBAGByqGSM49AgEGBSuB +BAAiA2IABE3rpRO164NtXx2kYMP1zlN7YgHEincO4YgwoyAYyJm3LwcbR+XyKg6A +/i+DUaGWa2FQ+f8w8VmEUFAgLozVxwnntPOCSODrXAQwJFPLCqs7m3o8OuzU3t07 +POGhPtj7f6BtMGsGCSqGSIb3DQEJDjFeMFwwJwYDVR0RBCAwHoILZXhhbXBsZS5j +b22CD3d3dy5leGFtcGxlLmNvbTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF +oDATBgNVHSUEDDAKBggrBgEFBQcDATAKBggqhkjOPQQDAgNpADBmAjEAlq7RaEXU +aNHEC+qfuIitonWHOatm+qiiaNSh80QjLw5P1rszg9yQQigHd8cD7I4DAjEAzmo1 +DLpcESwZCBrh3sPflDA38TZjoedRNeWcVxdn1QmwDWMeprD/zgPAey8GOmyj +-----END CERTIFICATE REQUEST-----`; + +const OUT_EXAMPLE_COM_EC_P384 = `Subject + C = CH + ST = Zurich + L = Zurich + O = Example RE + OU = IT Department + CN = example.com +Public Key + Algorithm: ECDSA + Length: 384 bits + Pub: 04:4d:eb:a5:13:b5:eb:83:6d:5f:1d:a4:60:c3:f5:ce: + 53:7b:62:01:c4:8a:77:0e:e1:88:30:a3:20:18:c8:99: + b7:2f:07:1b:47:e5:f2:2a:0e:80:fe:2f:83:51:a1:96: + 6b:61:50:f9:ff:30:f1:59:84:50:50:20:2e:8c:d5:c7: + 09:e7:b4:f3:82:48:e0:eb:5c:04:30:24:53:cb:0a:ab: + 3b:9b:7a:3c:3a:ec:d4:de:dd:3b:3c:e1:a1:3e:d8:fb: + 7f + ASN1 OID: secp384r1 + NIST CURVE: P-384 +Signature + Algorithm: SHA256withECDSA + Signature: 30:66:02:31:00:96:ae:d1:68:45:d4:68:d1:c4:0b:ea: + 9f:b8:88:ad:a2:75:87:39:ab:66:fa:a8:a2:68:d4:a1: + f3:44:23:2f:0e:4f:d6:bb:33:83:dc:90:42:28:07:77: + c7:03:ec:8e:03:02:31:00:ce:6a:35:0c:ba:5c:11:2c: + 19:08:1a:e1:de:c3:df:94:30:37:f1:36:63:a1:e7:51: + 35:e5:9c:57:17:67:d5:09:b0:0d:63:1e:a6:b0:ff:ce: + 03:c0:7b:2f:06:3a:6c:a3 +Requested Extensions + Basic Constraints: critical + CA = false + Key Usage: critical + Digital Signature + Key encipherment + Extended Key Usage: + TLS Web Server Authentication + Subject Alternative Name: + DNS: example.com + DNS: www.example.com`; + +// openssl ecparam -name secp521r1 -genkey -noout -out test-ec-key.pem +// openssl req -new -key test-ec-key.pem -out test-ec.csr +// -subj "/C=CH/ST=Zurich/L=Zurich/O=Example RE/OU=IT Department/CN=example.com" +// -addext "subjectAltName = DNS:example.com,DNS:www.example.com" +// -addext "basicConstraints = critical,CA:FALSE" +// -addext "keyUsage = critical,digitalSignature,keyEncipherment" +// -addext "extendedKeyUsage = serverAuth" +const IN_EXAMPLE_COM_EC_P521 = `-----BEGIN CERTIFICATE REQUEST----- +MIICIjCCAYQCAQAwcjELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBlp1cmljaDEPMA0G +A1UEBwwGWnVyaWNoMRMwEQYDVQQKDApFeGFtcGxlIFJFMRYwFAYDVQQLDA1JVCBE +ZXBhcnRtZW50MRQwEgYDVQQDDAtleGFtcGxlLmNvbTCBmzAQBgcqhkjOPQIBBgUr +gQQAIwOBhgAEAKf5BRB57svfglRz5dM0bnJAnieMFjNjOFca5/pJ2bOpORkp9Uol +x//mHY5WOMYYC/xvM5lJRcmUnL791zQ6rf6pAD/CrEpDF2svae6e5nA/fN2XsB98 +xjmkTpYZVC5nFT83Ceo9J0kHbvliYlAMsEOO60qGghyWV7myiDgORfE+POU3oG0w +awYJKoZIhvcNAQkOMV4wXDAnBgNVHREEIDAeggtleGFtcGxlLmNvbYIPd3d3LmV4 +YW1wbGUuY29tMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQM +MAoGCCsGAQUFBwMBMAoGCCqGSM49BAMCA4GLADCBhwJBDeIpSuvIT+kiE0ZnJwPS +DVik93CLqjFm5Ieq02d81GwusSgAA82WlZZVZRsTEjkZXtk96zMBnh5/uxk+wN+j ++PoCQgEDmXREwi0BPkHj6QlktE+7SLELVkrd75D9mfw/SV6ZJiLiLIT9yeoA0Zon +uhcl2rK/DLQutuJF6JIBe5s7lieKfQ== +-----END CERTIFICATE REQUEST-----`; + +const OUT_EXAMPLE_COM_EC_P521 = `Subject + C = CH + ST = Zurich + L = Zurich + O = Example RE + OU = IT Department + CN = example.com +Public Key + Algorithm: ECDSA + Length: 521 bits + Pub: 04:00:a7:f9:05:10:79:ee:cb:df:82:54:73:e5:d3:34: + 6e:72:40:9e:27:8c:16:33:63:38:57:1a:e7:fa:49:d9: + b3:a9:39:19:29:f5:4a:25:c7:ff:e6:1d:8e:56:38:c6: + 18:0b:fc:6f:33:99:49:45:c9:94:9c:be:fd:d7:34:3a: + ad:fe:a9:00:3f:c2:ac:4a:43:17:6b:2f:69:ee:9e:e6: + 70:3f:7c:dd:97:b0:1f:7c:c6:39:a4:4e:96:19:54:2e: + 67:15:3f:37:09:ea:3d:27:49:07:6e:f9:62:62:50:0c: + b0:43:8e:eb:4a:86:82:1c:96:57:b9:b2:88:38:0e:45: + f1:3e:3c:e5:37 + ASN1 OID: secp521r1 + NIST CURVE: P-521 +Signature + Algorithm: SHA256withECDSA + Signature: 30:81:87:02:41:0d:e2:29:4a:eb:c8:4f:e9:22:13:46: + 67:27:03:d2:0d:58:a4:f7:70:8b:aa:31:66:e4:87:aa: + d3:67:7c:d4:6c:2e:b1:28:00:03:cd:96:95:96:55:65: + 1b:13:12:39:19:5e:d9:3d:eb:33:01:9e:1e:7f:bb:19: + 3e:c0:df:a3:f8:fa:02:42:01:03:99:74:44:c2:2d:01: + 3e:41:e3:e9:09:64:b4:4f:bb:48:b1:0b:56:4a:dd:ef: + 90:fd:99:fc:3f:49:5e:99:26:22:e2:2c:84:fd:c9:ea: + 00:d1:9a:27:ba:17:25:da:b2:bf:0c:b4:2e:b6:e2:45: + e8:92:01:7b:9b:3b:96:27:8a:7d +Requested Extensions + Basic Constraints: critical + CA = false + Key Usage: critical + Digital Signature + Key encipherment + Extended Key Usage: + TLS Web Server Authentication + Subject Alternative Name: + DNS: example.com + DNS: www.example.com`; + +// openssl dsaparam -out dsaparam.pem 1024 +// openssl gendsa -out dsakey.pem dsaparam.pem +// openssl req -new -key dsakey.pem -out test-dsa.csr \ +// -subj "/C=CH/ST=Zurich/L=Zurich/O=Example RE/OU=IT Department/CN=example.com" \ +// -addext "subjectAltName = DNS:example.com,DNS:www.example.com" \ +// -addext "basicConstraints = critical,CA:FALSE" \ +// -addext "keyUsage = critical,digitalSignature,keyEncipherment" \ +// -addext "extendedKeyUsage = serverAuth" +const IN_EXAMPLE_COM_DSA_1024 = `-----BEGIN CERTIFICATE REQUEST----- +MIIC/jCCAqoCAQAwcjELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBlp1cmljaDEPMA0G +A1UEBwwGWnVyaWNoMRMwEQYDVQQKDApFeGFtcGxlIFJFMRYwFAYDVQQLDA1JVCBE +ZXBhcnRtZW50MRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCAcAwggE0BgcqhkjOOAQB +MIIBJwKBgQD8vvCmdM8wttdbq3kWigTEnnug4+2SLMl2RNXrlCQjmuZc7tGMyP1u +gsSc9Pxd/tMrPKRawFP5SvUOkZ4cIrujdJVTb/hlfnGH4cWACe8EupwRzoqwZB1x +awiHFzL9G6Go0HOy7bSbRdxBIYu46fnxNsDFf7lMlcBOKdq4Y12kvwIdAN4/vtK9 +KxhQfcrrzHsPXW+/xW0CMfr+NQir8PkCgYEAiNdM7IRZhXPaGRtGDpepSoRAf4uQ +LWY9q+vFUx4fVRSSgwKBKLjW+BvzE2eJq0pXv7O09QHOghtcwzY3UrdN952sjUkJ +LItt+5FxB7/JqCBPRrrVsyGEjR3+WbeI3wl6OvQFxm/OTNTTkemFdAfpT/YDSw+n +1xLODTfegT/oyOoDgYUAAoGBAMz15lRPVAj8cje3ShbuACHPVE85d0Tk0Dw9qUcQ +NCNS6A3STSbUiLGKeiRMGg2v/HM9ivV8tq1rywmgBAwtidcQ6P5yqYSZs6z3x9xZ +OzeQ5jXftBQ1GXeU8zi1fC99inFGNixbPFVIz4/KiV0+So44n9ki2ylhbz0YQtpU +wMF+oG0wawYJKoZIhvcNAQkOMV4wXDAnBgNVHREEIDAeggtleGFtcGxlLmNvbYIP +d3d3LmV4YW1wbGUuY29tMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgWgMBMG +A1UdJQQMMAoGCCsGAQUFBwMBMAsGCWCGSAFlAwQDAgNBADA+Ah0AkTogUUyKE5v9 +ezKrOKpP07i2E9Zz0n/yjIvw4wIdAMB5yVMOEgI877vOFQ7zzf7oDR9eJMYlf4QV +2sQ= +-----END CERTIFICATE REQUEST-----`; + +const OUT_EXAMPLE_COM_DSA_1024 = `Subject + C = CH + ST = Zurich + L = Zurich + O = Example RE + OU = IT Department + CN = example.com +Public Key + Algorithm: DSA + Length: 1024 bits + Pub: 00:cc:f5:e6:54:4f:54:08:fc:72:37:b7:4a:16:ee:00: + 21:cf:54:4f:39:77:44:e4:d0:3c:3d:a9:47:10:34:23: + 52:e8:0d:d2:4d:26:d4:88:b1:8a:7a:24:4c:1a:0d:af: + fc:73:3d:8a:f5:7c:b6:ad:6b:cb:09:a0:04:0c:2d:89: + d7:10:e8:fe:72:a9:84:99:b3:ac:f7:c7:dc:59:3b:37: + 90:e6:35:df:b4:14:35:19:77:94:f3:38:b5:7c:2f:7d: + 8a:71:46:36:2c:5b:3c:55:48:cf:8f:ca:89:5d:3e:4a: + 8e:38:9f:d9:22:db:29:61:6f:3d:18:42:da:54:c0:c1: + 7e + P: 00:fc:be:f0:a6:74:cf:30:b6:d7:5b:ab:79:16:8a:04: + c4:9e:7b:a0:e3:ed:92:2c:c9:76:44:d5:eb:94:24:23: + 9a:e6:5c:ee:d1:8c:c8:fd:6e:82:c4:9c:f4:fc:5d:fe: + d3:2b:3c:a4:5a:c0:53:f9:4a:f5:0e:91:9e:1c:22:bb: + a3:74:95:53:6f:f8:65:7e:71:87:e1:c5:80:09:ef:04: + ba:9c:11:ce:8a:b0:64:1d:71:6b:08:87:17:32:fd:1b: + a1:a8:d0:73:b2:ed:b4:9b:45:dc:41:21:8b:b8:e9:f9: + f1:36:c0:c5:7f:b9:4c:95:c0:4e:29:da:b8:63:5d:a4: + bf + Q: 00:de:3f:be:d2:bd:2b:18:50:7d:ca:eb:cc:7b:0f:5d: + 6f:bf:c5:6d:02:31:fa:fe:35:08:ab:f0:f9 + G: 00:88:d7:4c:ec:84:59:85:73:da:19:1b:46:0e:97:a9: + 4a:84:40:7f:8b:90:2d:66:3d:ab:eb:c5:53:1e:1f:55: + 14:92:83:02:81:28:b8:d6:f8:1b:f3:13:67:89:ab:4a: + 57:bf:b3:b4:f5:01:ce:82:1b:5c:c3:36:37:52:b7:4d: + f7:9d:ac:8d:49:09:2c:8b:6d:fb:91:71:07:bf:c9:a8: + 20:4f:46:ba:d5:b3:21:84:8d:1d:fe:59:b7:88:df:09: + 7a:3a:f4:05:c6:6f:ce:4c:d4:d3:91:e9:85:74:07:e9: + 4f:f6:03:4b:0f:a7:d7:12:ce:0d:37:de:81:3f:e8:c8: + ea +Signature + Algorithm: SHA256withDSA + Signature: + R: 00:91:3a:20:51:4c:8a:13:9b:fd:7b:32:ab:38:aa:4f: + d3:b8:b6:13:d6:73:d2:7f:f2:8c:8b:f0:e3 + S: 00:c0:79:c9:53:0e:12:02:3c:ef:bb:ce:15:0e:f3:cd: + fe:e8:0d:1f:5e:24:c6:25:7f:84:15:da:c4 +Requested Extensions + Basic Constraints: critical + CA = false + Key Usage: critical + Digital Signature + Key encipherment + Extended Key Usage: + TLS Web Server Authentication + Subject Alternative Name: + DNS: example.com + DNS: www.example.com`; + +// openssl dsaparam -out dsaparam.pem 2048 +// openssl gendsa -out dsakey.pem dsaparam.pem +// openssl req -new -key dsakey.pem -out test-dsa.csr \ +// -subj "/C=CH/ST=Zurich/L=Zurich/O=Example RE/OU=IT Department/CN=example.com" \ +// -addext "subjectAltName = DNS:example.com,DNS:www.example.com" \ +// -addext "basicConstraints = critical,CA:FALSE" \ +// -addext "keyUsage = critical,digitalSignature,keyEncipherment" \ +// -addext "extendedKeyUsage = serverAuth" +const IN_EXAMPLE_COM_DSA_2048 = `-----BEGIN CERTIFICATE REQUEST----- +MIIEfzCCBCwCAQAwcjELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBlp1cmljaDEPMA0G +A1UEBwwGWnVyaWNoMRMwEQYDVQQKDApFeGFtcGxlIFJFMRYwFAYDVQQLDA1JVCBE +ZXBhcnRtZW50MRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCA0IwggI1BgcqhkjOOAQB +MIICKAKCAQEAsvoKmCHcR2y8qQ/kpBHOvlaGifq//F/0zhWSpfjvwqI3g2EjqXL7 +rCYyu9wxoogODo6Dnenxfw1xp3ZIJNCtfrSJyt0AudjOedtVWMSnTndoQVQtYSI0 +mmrBAqFL26i1bmEMxsd6pz2nU3p8yGY/wpYiWwyy+/TZv8a2t58owpw9Qkm4cX4E +Po3ih/XbN6eooOx9ZaErcS9mg3UvwQDm0VYD3ZjSeqwP7YWGyhq7gPJsEiMrft12 +1SjyNz8rkhXzqZFRujjmfTT5dpCC/Z4d7/ZE30tbqHaNDM+YwBrb/aL7PnoWs847 +VpjCVxmVmgIPoMHlTbg29RsIUoFlFScaUQIdAMGwwpzilrReaEqcoX7PY5u4vtV0 +5zuiVIqkdBMCggEAQZhk5qdAYoMvZhPi5TOgysTzQE1FeAEtgypxZI65TpwO/JOr +AX9vYZ/qCYX/ncj455qiPZenl59lo/iQPzhJUubuCevPWJ3dsKRbAyL/5NCwifnf +YBMJGj0UFGL4ekVV0emLL9H5eqYz64w0eV2Sp40O8yCu0qr7QTi3zpqzJZ43E+26 +Z9bgR6c1lmgKW2QN72PHwMlTlq0O6mN+eikEWoGr09JWpXMThZemAO2mHLAiq6ju +0+zduzWZyjZPZA1B4XUlTgCtzHveYpUzZ1NhZyM8jcGFOmmZWAFNwt03bq9/Ma0q +3jB0Dyz7IDGm8D6Y770wJRP3jf7iCVYt8jB49gOCAQUAAoIBACnVv+1ROrUiHAwn +xXGlsZdTEYZfWbE8Cter15JNNqh/Z1cdIp9m1t/rVF69nSWQvrvLeFo5p5mGxK8r +IKHTZTaAn6uO6PcNJc6iB7fS15L4uiB7p73MdjE+3PcYMbhttDlexdm6QxsmCP1F +3LYW3Uh879AURWZwPH3z4NZL2u1AFSyS1vQhtiCmztq94QwhjoDf9anFR8q05dAC +juPlKYEIhMsoq+r/l/kOM1UghhXX6BmeF8R9hhW1p4Rv+gyAgbYjowJFtZnwE5p0 +OYLJzSQWjFMYEzHAoH8J4+D5okt4IXEd0BDxLBkm1WonIxYL/NL95p3qXpgUXqRX +M9spEzWgbTBrBgkqhkiG9w0BCQ4xXjBcMCcGA1UdEQQgMB6CC2V4YW1wbGUuY29t +gg93d3cuZXhhbXBsZS5jb20wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBaAw +EwYDVR0lBAwwCgYIKwYBBQUHAwEwCwYJYIZIAWUDBAMCA0AAMD0CHQCyrstoqfvs +MCfsZUeycKrKQmAJAHxuoGPCKl7yAhwhNH9RNxBm5roO2U901BeF2p0pT410ghH8 +oA+F +-----END CERTIFICATE REQUEST-----`; + +const OUT_EXAMPLE_COM_DSA_2048 = `Subject + C = CH + ST = Zurich + L = Zurich + O = Example RE + OU = IT Department + CN = example.com +Public Key + Algorithm: DSA + Length: 2048 bits + Pub: 29:d5:bf:ed:51:3a:b5:22:1c:0c:27:c5:71:a5:b1:97: + 53:11:86:5f:59:b1:3c:0a:d7:ab:d7:92:4d:36:a8:7f: + 67:57:1d:22:9f:66:d6:df:eb:54:5e:bd:9d:25:90:be: + bb:cb:78:5a:39:a7:99:86:c4:af:2b:20:a1:d3:65:36: + 80:9f:ab:8e:e8:f7:0d:25:ce:a2:07:b7:d2:d7:92:f8: + ba:20:7b:a7:bd:cc:76:31:3e:dc:f7:18:31:b8:6d:b4: + 39:5e:c5:d9:ba:43:1b:26:08:fd:45:dc:b6:16:dd:48: + 7c:ef:d0:14:45:66:70:3c:7d:f3:e0:d6:4b:da:ed:40: + 15:2c:92:d6:f4:21:b6:20:a6:ce:da:bd:e1:0c:21:8e: + 80:df:f5:a9:c5:47:ca:b4:e5:d0:02:8e:e3:e5:29:81: + 08:84:cb:28:ab:ea:ff:97:f9:0e:33:55:20:86:15:d7: + e8:19:9e:17:c4:7d:86:15:b5:a7:84:6f:fa:0c:80:81: + b6:23:a3:02:45:b5:99:f0:13:9a:74:39:82:c9:cd:24: + 16:8c:53:18:13:31:c0:a0:7f:09:e3:e0:f9:a2:4b:78: + 21:71:1d:d0:10:f1:2c:19:26:d5:6a:27:23:16:0b:fc: + d2:fd:e6:9d:ea:5e:98:14:5e:a4:57:33:db:29:13:35 + P: 00:b2:fa:0a:98:21:dc:47:6c:bc:a9:0f:e4:a4:11:ce: + be:56:86:89:fa:bf:fc:5f:f4:ce:15:92:a5:f8:ef:c2: + a2:37:83:61:23:a9:72:fb:ac:26:32:bb:dc:31:a2:88: + 0e:0e:8e:83:9d:e9:f1:7f:0d:71:a7:76:48:24:d0:ad: + 7e:b4:89:ca:dd:00:b9:d8:ce:79:db:55:58:c4:a7:4e: + 77:68:41:54:2d:61:22:34:9a:6a:c1:02:a1:4b:db:a8: + b5:6e:61:0c:c6:c7:7a:a7:3d:a7:53:7a:7c:c8:66:3f: + c2:96:22:5b:0c:b2:fb:f4:d9:bf:c6:b6:b7:9f:28:c2: + 9c:3d:42:49:b8:71:7e:04:3e:8d:e2:87:f5:db:37:a7: + a8:a0:ec:7d:65:a1:2b:71:2f:66:83:75:2f:c1:00:e6: + d1:56:03:dd:98:d2:7a:ac:0f:ed:85:86:ca:1a:bb:80: + f2:6c:12:23:2b:7e:dd:76:d5:28:f2:37:3f:2b:92:15: + f3:a9:91:51:ba:38:e6:7d:34:f9:76:90:82:fd:9e:1d: + ef:f6:44:df:4b:5b:a8:76:8d:0c:cf:98:c0:1a:db:fd: + a2:fb:3e:7a:16:b3:ce:3b:56:98:c2:57:19:95:9a:02: + 0f:a0:c1:e5:4d:b8:36:f5:1b:08:52:81:65:15:27:1a: + 51 + Q: 00:c1:b0:c2:9c:e2:96:b4:5e:68:4a:9c:a1:7e:cf:63: + 9b:b8:be:d5:74:e7:3b:a2:54:8a:a4:74:13 + G: 41:98:64:e6:a7:40:62:83:2f:66:13:e2:e5:33:a0:ca: + c4:f3:40:4d:45:78:01:2d:83:2a:71:64:8e:b9:4e:9c: + 0e:fc:93:ab:01:7f:6f:61:9f:ea:09:85:ff:9d:c8:f8: + e7:9a:a2:3d:97:a7:97:9f:65:a3:f8:90:3f:38:49:52: + e6:ee:09:eb:cf:58:9d:dd:b0:a4:5b:03:22:ff:e4:d0: + b0:89:f9:df:60:13:09:1a:3d:14:14:62:f8:7a:45:55: + d1:e9:8b:2f:d1:f9:7a:a6:33:eb:8c:34:79:5d:92:a7: + 8d:0e:f3:20:ae:d2:aa:fb:41:38:b7:ce:9a:b3:25:9e: + 37:13:ed:ba:67:d6:e0:47:a7:35:96:68:0a:5b:64:0d: + ef:63:c7:c0:c9:53:96:ad:0e:ea:63:7e:7a:29:04:5a: + 81:ab:d3:d2:56:a5:73:13:85:97:a6:00:ed:a6:1c:b0: + 22:ab:a8:ee:d3:ec:dd:bb:35:99:ca:36:4f:64:0d:41: + e1:75:25:4e:00:ad:cc:7b:de:62:95:33:67:53:61:67: + 23:3c:8d:c1:85:3a:69:99:58:01:4d:c2:dd:37:6e:af: + 7f:31:ad:2a:de:30:74:0f:2c:fb:20:31:a6:f0:3e:98: + ef:bd:30:25:13:f7:8d:fe:e2:09:56:2d:f2:30:78:f6 +Signature + Algorithm: SHA256withDSA + Signature: + R: 00:b2:ae:cb:68:a9:fb:ec:30:27:ec:65:47:b2:70:aa: + ca:42:60:09:00:7c:6e:a0:63:c2:2a:5e:f2 + S: 21:34:7f:51:37:10:66:e6:ba:0e:d9:4f:74:d4:17:85: + da:9d:29:4f:8d:74:82:11:fc:a0:0f:85 +Requested Extensions + Basic Constraints: critical + CA = false + Key Usage: critical + Digital Signature + Key encipherment + Extended Key Usage: + TLS Web Server Authentication + Subject Alternative Name: + DNS: example.com + DNS: www.example.com`; + +// openssl req -newkey rsa:4096 -keyout test-rsa-4096.key -out test-rsa-4096.csr +// -subj "/C=CH/ST=Zurich/L=Zurich/O=Example RE/OU=IT Department/CN=example.com" +// -addext "subjectAltName = DNS:example.com,DNS:www.example.com,IP:127.0.0.1, \ +// email:user@example.com,URI:http://example.com/api,otherName:1.2.3.4;UTF8:some value" +// -addext "basicConstraints = critical,CA:FALSE" +// -addext "keyUsage = critical,digitalSignature,keyEncipherment" +// -addext "extendedKeyUsage = serverAuth" +const IN_EXAMPLE_COM_SAN = `-----BEGIN CERTIFICATE REQUEST----- +MIIFbTCCA1UCAQAwcjELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBlp1cmljaDEPMA0G +A1UEBwwGWnVyaWNoMRMwEQYDVQQKDApFeGFtcGxlIFJFMRYwFAYDVQQLDA1JVCBE +ZXBhcnRtZW50MRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBAJf8uQDFcQfj6qCuPa4hNyDWr3Lwzfc3qQZdOgNJ/kym +GxxRHUXJyBtgkmAqDoSGmg1hUWgt9eZwd/Cf4Wd3qr+Q0ppg6dwZeWgYSunseoKl +f0E5FvUfECNyDwCSbltN9TCsom2ePNOOJJHWo4Y3E3jGXz0n1Vwa6ePR0j62Rcey +4lHLscQ3GoNvMLcXbY1HIhnbaI25MmFPB8p4PvpPsAYgbWHbw0jIR9dSxEK0HAU3 +2VkRkm8XaF4BOEfugqT3Bc7zAvwdFZRTTTZIICYW5T3zvtxBidJ8OSej16LV6ZeE +/4VcTzXYTzIUXbNaev3XN1r5ZodkbZvxxk/EZmfes2OtedPulW4TW27HSl6XBos/ +8VQohelUXiyCLPrtbnjeHKSz47+ZAm23jMAFYWkTVdWvAa+G74UstuRRXfLAKCNv +7VeA3l8IgEkfj48u+EenV6cJ3ZJJ5/qvZo7OUjhAtYJmNtlRYE4r3uWRmaNXYwrD +7vJuMiZafaVC+74/UHLGGm7sHVJdo4KBO/LUbHJ/SKZIYMc14kJLOf6TPZXSGm9N +TxbOV9Vzcjzivq1HxaYirLAM+nyVApVwwpVq/uiEFz579yrwySvBuwnewfdfZ6EZ +iNAKiBwQ8diFMnFfd/28hJ8TrIlq+5bkVo1ODuhyRIw9YB19IrmytaVvkR8624Ld +AgMBAAGggbUwgbIGCSqGSIb3DQEJDjGBpDCBoTBsBgNVHREEZTBjggtleGFtcGxl +LmNvbYIPd3d3LmV4YW1wbGUuY29thwR/AAABgRB1c2VyQGV4YW1wbGUuY29thhZo +dHRwOi8vZXhhbXBsZS5jb20vYXBpoBMGAyoDBKAMDApzb21lIHZhbHVlMAwGA1Ud +EwEB/wQCMAAwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0G +CSqGSIb3DQEBCwUAA4ICAQAtOuh6MEralwgChJHBaGJavBxpCQ0p5K77RlAPIk5Q +Mv5086DxiZEFBKCRiZRtkOvo0aCHUn3awDrlEOgECiAYQqMIBUWeNwImtmpDopuI +ZMmVmzc2ojf9nUlPrPV+B6P2jTxTIQYpDQocbOgxDkcdZVSvLyMEFnHIMNQV7GS2 +gBmUnPp+4z2d8X9XaRspkuEt2nbA1NoXekWaG46jG56VoBycepOiNkwL4AsqunLa +T0urcHq34g+HRQWwOA+q/72qP4oaj2ZO0fFJQl2ZsGRT/IuM1g2YsnVSpBOGY/J6 +Qi2hDr6EEqphg501ny+FZE1BouQ/lSykafYyauwNq1puu/VyuF8grFmL0SoxWWfP +h6viblGM/Vu69Bhl4gkWKtufWpOVpCA4vHzes8IVMFg7vhpwm33Xjo0lCPcIUin6 +0CqHZQCsWtj2yIAF66WHB0I1DHL5FNCWRPnQCo54qRZIYqtSP20QRr6GWC2d+ZgX +wDxRpmzr8T8owBYWw3j+RK9CtZoWO4O586UR4J1Bn5PQfoR78Z/4mzv2sxVi9Fdf +sJzlG6/nhmMaCqneIn97gkguvSgpOuKSeo/fjbpnthufgilrpDQoGrhZaXic0GVZ +6JmbOh3tLMVf4ooyyaLfOCfV2FN12rDa3pdWhQ4MVN4gg9U3Cq0x7yRQKiSBlBnw +oA== +-----END CERTIFICATE REQUEST-----`; + +const OUT_EXAMPLE_COM_SAN = `Subject + C = CH + ST = Zurich + L = Zurich + O = Example RE + OU = IT Department + CN = example.com +Public Key + Algorithm: RSA + Length: 4096 bits + Modulus: 00:97:fc:b9:00:c5:71:07:e3:ea:a0:ae:3d:ae:21:37: + 20:d6:af:72:f0:cd:f7:37:a9:06:5d:3a:03:49:fe:4c: + a6:1b:1c:51:1d:45:c9:c8:1b:60:92:60:2a:0e:84:86: + 9a:0d:61:51:68:2d:f5:e6:70:77:f0:9f:e1:67:77:aa: + bf:90:d2:9a:60:e9:dc:19:79:68:18:4a:e9:ec:7a:82: + a5:7f:41:39:16:f5:1f:10:23:72:0f:00:92:6e:5b:4d: + f5:30:ac:a2:6d:9e:3c:d3:8e:24:91:d6:a3:86:37:13: + 78:c6:5f:3d:27:d5:5c:1a:e9:e3:d1:d2:3e:b6:45:c7: + b2:e2:51:cb:b1:c4:37:1a:83:6f:30:b7:17:6d:8d:47: + 22:19:db:68:8d:b9:32:61:4f:07:ca:78:3e:fa:4f:b0: + 06:20:6d:61:db:c3:48:c8:47:d7:52:c4:42:b4:1c:05: + 37:d9:59:11:92:6f:17:68:5e:01:38:47:ee:82:a4:f7: + 05:ce:f3:02:fc:1d:15:94:53:4d:36:48:20:26:16:e5: + 3d:f3:be:dc:41:89:d2:7c:39:27:a3:d7:a2:d5:e9:97: + 84:ff:85:5c:4f:35:d8:4f:32:14:5d:b3:5a:7a:fd:d7: + 37:5a:f9:66:87:64:6d:9b:f1:c6:4f:c4:66:67:de:b3: + 63:ad:79:d3:ee:95:6e:13:5b:6e:c7:4a:5e:97:06:8b: + 3f:f1:54:28:85:e9:54:5e:2c:82:2c:fa:ed:6e:78:de: + 1c:a4:b3:e3:bf:99:02:6d:b7:8c:c0:05:61:69:13:55: + d5:af:01:af:86:ef:85:2c:b6:e4:51:5d:f2:c0:28:23: + 6f:ed:57:80:de:5f:08:80:49:1f:8f:8f:2e:f8:47:a7: + 57:a7:09:dd:92:49:e7:fa:af:66:8e:ce:52:38:40:b5: + 82:66:36:d9:51:60:4e:2b:de:e5:91:99:a3:57:63:0a: + c3:ee:f2:6e:32:26:5a:7d:a5:42:fb:be:3f:50:72:c6: + 1a:6e:ec:1d:52:5d:a3:82:81:3b:f2:d4:6c:72:7f:48: + a6:48:60:c7:35:e2:42:4b:39:fe:93:3d:95:d2:1a:6f: + 4d:4f:16:ce:57:d5:73:72:3c:e2:be:ad:47:c5:a6:22: + ac:b0:0c:fa:7c:95:02:95:70:c2:95:6a:fe:e8:84:17: + 3e:7b:f7:2a:f0:c9:2b:c1:bb:09:de:c1:f7:5f:67:a1: + 19:88:d0:0a:88:1c:10:f1:d8:85:32:71:5f:77:fd:bc: + 84:9f:13:ac:89:6a:fb:96:e4:56:8d:4e:0e:e8:72:44: + 8c:3d:60:1d:7d:22:b9:b2:b5:a5:6f:91:1f:3a:db:82: + dd + Exponent: 65537 (0x10001) +Signature + Algorithm: SHA256withRSA + Signature: 2d:3a:e8:7a:30:4a:da:97:08:02:84:91:c1:68:62:5a: + bc:1c:69:09:0d:29:e4:ae:fb:46:50:0f:22:4e:50:32: + fe:74:f3:a0:f1:89:91:05:04:a0:91:89:94:6d:90:eb: + e8:d1:a0:87:52:7d:da:c0:3a:e5:10:e8:04:0a:20:18: + 42:a3:08:05:45:9e:37:02:26:b6:6a:43:a2:9b:88:64: + c9:95:9b:37:36:a2:37:fd:9d:49:4f:ac:f5:7e:07:a3: + f6:8d:3c:53:21:06:29:0d:0a:1c:6c:e8:31:0e:47:1d: + 65:54:af:2f:23:04:16:71:c8:30:d4:15:ec:64:b6:80: + 19:94:9c:fa:7e:e3:3d:9d:f1:7f:57:69:1b:29:92:e1: + 2d:da:76:c0:d4:da:17:7a:45:9a:1b:8e:a3:1b:9e:95: + a0:1c:9c:7a:93:a2:36:4c:0b:e0:0b:2a:ba:72:da:4f: + 4b:ab:70:7a:b7:e2:0f:87:45:05:b0:38:0f:aa:ff:bd: + aa:3f:8a:1a:8f:66:4e:d1:f1:49:42:5d:99:b0:64:53: + fc:8b:8c:d6:0d:98:b2:75:52:a4:13:86:63:f2:7a:42: + 2d:a1:0e:be:84:12:aa:61:83:9d:35:9f:2f:85:64:4d: + 41:a2:e4:3f:95:2c:a4:69:f6:32:6a:ec:0d:ab:5a:6e: + bb:f5:72:b8:5f:20:ac:59:8b:d1:2a:31:59:67:cf:87: + ab:e2:6e:51:8c:fd:5b:ba:f4:18:65:e2:09:16:2a:db: + 9f:5a:93:95:a4:20:38:bc:7c:de:b3:c2:15:30:58:3b: + be:1a:70:9b:7d:d7:8e:8d:25:08:f7:08:52:29:fa:d0: + 2a:87:65:00:ac:5a:d8:f6:c8:80:05:eb:a5:87:07:42: + 35:0c:72:f9:14:d0:96:44:f9:d0:0a:8e:78:a9:16:48: + 62:ab:52:3f:6d:10:46:be:86:58:2d:9d:f9:98:17:c0: + 3c:51:a6:6c:eb:f1:3f:28:c0:16:16:c3:78:fe:44:af: + 42:b5:9a:16:3b:83:b9:f3:a5:11:e0:9d:41:9f:93:d0: + 7e:84:7b:f1:9f:f8:9b:3b:f6:b3:15:62:f4:57:5f:b0: + 9c:e5:1b:af:e7:86:63:1a:0a:a9:de:22:7f:7b:82:48: + 2e:bd:28:29:3a:e2:92:7a:8f:df:8d:ba:67:b6:1b:9f: + 82:29:6b:a4:34:28:1a:b8:59:69:78:9c:d0:65:59:e8: + 99:9b:3a:1d:ed:2c:c5:5f:e2:8a:32:c9:a2:df:38:27: + d5:d8:53:75:da:b0:da:de:97:56:85:0e:0c:54:de:20: + 83:d5:37:0a:ad:31:ef:24:50:2a:24:81:94:19:f0:a0 +Requested Extensions + Basic Constraints: critical + CA = false + Key Usage: critical + Digital Signature + Key encipherment + Extended Key Usage: + TLS Web Server Authentication + Subject Alternative Name: + DNS: example.com + DNS: www.example.com + IP: 127.0.0.1 + EMAIL: user@example.com + URI: http://example.com/api + Other: 1.2.3.4::some value`; + +// openssl req -newkey rsa:2048 -keyout test-rsa-2048.key -out test-rsa-2048.csr \ +// -subj "/C=CH/ST=Zurich/L=Zurich/O=Example RE/OU=IT Department/CN=example.com" \ +// -addext "subjectAltName = DNS:example.com,DNS:www.example.com" \ +// -addext "basicConstraints = critical,CA:FALSE" \ +// -addext "keyUsage = critical,digitalSignature,keyEncipherment," \ +// -addext "extendedKeyUsage = serverAuth" +const IN_EXAMPLE_COM_KEY_USAGE = `-----BEGIN CERTIFICATE REQUEST----- +MIIDJDCCAgwCAQAwcjELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBlp1cmljaDEPMA0G +A1UEBwwGWnVyaWNoMRMwEQYDVQQKDApFeGFtcGxlIFJFMRYwFAYDVQQLDA1JVCBE +ZXBhcnRtZW50MRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAKHQWxqtdJQ1l7ApTgwgsyrN/kRDrog/DsUlZQg3YodY +4RRAgPr+AeQ1BhuWDVxaXein0XmXOESHgK9Z7X/hLgRy2ifK+n20Ij3+k6VSh6Lt +lpjUPwK7PWBtZ969DukBIvq64XrJTNWIJPvXXQxkL4dk5NcDY4TjXWt0GgDVR+GH +OU1JwfzviGVRdOmY8+Ckfxc+3QytTdP6KBQaiUk5sBEniovDpKfImtql72JsCRbA +9Wue7X4EbXi2zvoAlJ5NXF3Ps1q2XsVJeIx/mMDcgRW7s5AVM9NQW0O1JLoA7dY+ +vSrKZj+ssuKCIWM7u9Big2I0miEl5AXrDlwZPBhM9FMCAwEAAaBtMGsGCSqGSIb3 +DQEJDjFeMFwwJwYDVR0RBCAwHoILZXhhbXBsZS5jb22CD3d3dy5leGFtcGxlLmNv +bTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIB/jATBgNVHSUEDDAKBggrBgEF +BQcDATANBgkqhkiG9w0BAQsFAAOCAQEAPOr6jfq/mXilqXA11CTza69Ydd4fvp6q +UG47PefzQqSmYtpUytwZRLGQ1IFRlYeXwbazVLkRmLNwpbB8C5fh9FPp55JCpM/O +tgCW2uqLkCtkQMUCaSdRX/Y+9ypYhdBkSNv1Q+3QXi2jmi5QMqwerAwNmeXmH6AZ +swMgAhuoLS9OrIqHjFoHGoXsgXMkbLr6m6hgyFt8ZbbwK4WpVcgCZfhtBiLilCJN +Xr9GUXL3FqUb7sIaYKAaghr2haqKhFsIH57XVK3DZYhOkLd9uC8TLdl2e+t9Hcy9 +ymLwiIGMUfuBQMP8nVu3jGXAQ5N4VV+IZfF8UaBFW8tG+Ms2TeW68Q== +-----END CERTIFICATE REQUEST-----`; + +const OUT_EXAMPLE_COM_KEY_USAGE = `Subject + C = CH + ST = Zurich + L = Zurich + O = Example RE + OU = IT Department + CN = example.com +Public Key + Algorithm: RSA + Length: 2048 bits + Modulus: 00:a1:d0:5b:1a:ad:74:94:35:97:b0:29:4e:0c:20:b3: + 2a:cd:fe:44:43:ae:88:3f:0e:c5:25:65:08:37:62:87: + 58:e1:14:40:80:fa:fe:01:e4:35:06:1b:96:0d:5c:5a: + 5d:e8:a7:d1:79:97:38:44:87:80:af:59:ed:7f:e1:2e: + 04:72:da:27:ca:fa:7d:b4:22:3d:fe:93:a5:52:87:a2: + ed:96:98:d4:3f:02:bb:3d:60:6d:67:de:bd:0e:e9:01: + 22:fa:ba:e1:7a:c9:4c:d5:88:24:fb:d7:5d:0c:64:2f: + 87:64:e4:d7:03:63:84:e3:5d:6b:74:1a:00:d5:47:e1: + 87:39:4d:49:c1:fc:ef:88:65:51:74:e9:98:f3:e0:a4: + 7f:17:3e:dd:0c:ad:4d:d3:fa:28:14:1a:89:49:39:b0: + 11:27:8a:8b:c3:a4:a7:c8:9a:da:a5:ef:62:6c:09:16: + c0:f5:6b:9e:ed:7e:04:6d:78:b6:ce:fa:00:94:9e:4d: + 5c:5d:cf:b3:5a:b6:5e:c5:49:78:8c:7f:98:c0:dc:81: + 15:bb:b3:90:15:33:d3:50:5b:43:b5:24:ba:00:ed:d6: + 3e:bd:2a:ca:66:3f:ac:b2:e2:82:21:63:3b:bb:d0:62: + 83:62:34:9a:21:25:e4:05:eb:0e:5c:19:3c:18:4c:f4: + 53 + Exponent: 65537 (0x10001) +Signature + Algorithm: SHA256withRSA + Signature: 3c:ea:fa:8d:fa:bf:99:78:a5:a9:70:35:d4:24:f3:6b: + af:58:75:de:1f:be:9e:aa:50:6e:3b:3d:e7:f3:42:a4: + a6:62:da:54:ca:dc:19:44:b1:90:d4:81:51:95:87:97: + c1:b6:b3:54:b9:11:98:b3:70:a5:b0:7c:0b:97:e1:f4: + 53:e9:e7:92:42:a4:cf:ce:b6:00:96:da:ea:8b:90:2b: + 64:40:c5:02:69:27:51:5f:f6:3e:f7:2a:58:85:d0:64: + 48:db:f5:43:ed:d0:5e:2d:a3:9a:2e:50:32:ac:1e:ac: + 0c:0d:99:e5:e6:1f:a0:19:b3:03:20:02:1b:a8:2d:2f: + 4e:ac:8a:87:8c:5a:07:1a:85:ec:81:73:24:6c:ba:fa: + 9b:a8:60:c8:5b:7c:65:b6:f0:2b:85:a9:55:c8:02:65: + f8:6d:06:22:e2:94:22:4d:5e:bf:46:51:72:f7:16:a5: + 1b:ee:c2:1a:60:a0:1a:82:1a:f6:85:aa:8a:84:5b:08: + 1f:9e:d7:54:ad:c3:65:88:4e:90:b7:7d:b8:2f:13:2d: + d9:76:7b:eb:7d:1d:cc:bd:ca:62:f0:88:81:8c:51:fb: + 81:40:c3:fc:9d:5b:b7:8c:65:c0:43:93:78:55:5f:88: + 65:f1:7c:51:a0:45:5b:cb:46:f8:cb:36:4d:e5:ba:f1 +Requested Extensions + Basic Constraints: critical + CA = false + Key Usage: critical + Digital Signature + Non-repudiation + Key encipherment + Data encipherment + Key agreement + Key certificate signing + CRL signing + Extended Key Usage: + TLS Web Server Authentication + Subject Alternative Name: + DNS: example.com + DNS: www.example.com`; + +// openssl req -newkey rsa:2048 -keyout test-rsa-2048.key -out test-rsa-2048.csr \ +// -subj "/C=CH/ST=Zurich/L=Zurich/O=Example RE/OU=IT Department/CN=example.com" \ +// -addext "subjectAltName = DNS:example.com,DNS:www.example.com" \ +// -addext "basicConstraints = critical,CA:FALSE" \ +// -addext "keyUsage = critical,digitalSignature,keyEncipherment" \ +// -addext "extendedKeyUsage = serverAuth" +const IN_EXAMPLE_COM_EXTENDED_KEY_USAGE = `-----BEGIN CERTIFICATE REQUEST----- +MIIDpzCCAo8CAQAwcjELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBlp1cmljaDEPMA0G +A1UEBwwGWnVyaWNoMRMwEQYDVQQKDApFeGFtcGxlIFJFMRYwFAYDVQQLDA1JVCBE +ZXBhcnRtZW50MRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAMjQ/Bz+CzA/WaS+Nyp3ijWzYlKY7GmA/a2FuzNSPQlr +WuGyZJcfb0CpLIpRF8qcDllAe+hFQnVGnk3svQIhfEOD7qwzBRMHVhe59jkv2kER +s+u88KBCNfIAS6m5d45y4xH338aXq4lZexiEASWHS7SsWAR3kL3c9p14U9EHOaym +ZWPO/SCfCJyhxszDLM2eG5S2rviuu9nY+rk0Oo7z8x8PZF9Wl1NamLl1tWPqsznS +3bfjdJYeUlm7XvTzC6EMAT6K/5ker0chl7Hg0mcEO9w4c2cSTAHvZ2b2sRYbxNQZ +49byQsRAXW8TNnOaK9Phmvwy/irEXU9PEl3u7KvSnNcCAwEAAaCB7zCB7AYJKoZI +hvcNAQkOMYHeMIHbMCcGA1UdEQQgMB6CC2V4YW1wbGUuY29tgg93d3cuZXhhbXBs +ZS5jb20wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBaAwgZEGA1UdJQSBiTCB +hgYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDAwYIKwYBBQUHAwQGCCsGAQUF +BwMIBgorBgEEAYI3AgEVBgorBgEEAYI3AgEWBgorBgEEAYI3CgMBBgorBgEEAYI3 +CgMDBgorBgEEAYI3CgMEBgorBgEEAYI3FAICBgorBgEEAYI3CgMDMA0GCSqGSIb3 +DQEBCwUAA4IBAQCcYWj1eIxj/FUEhhm2lZr06Pq4GEtIVsMWw5IrUn2FIFb/yY8x +GHuB5v7XNA/8zhRWvIAXGaa8Bnajk4mR0rkxy1MXpd2YevdrF/XFa2Totv4E4/I6 +pvrFefYTSGpmCu5zQTuoanM7JjE81vvbTLFdaHMdLOekpuK5v5kbuNdtDpEiAkd0 +vmV4BQ0BV3b3zhIRQqBB60pSBHYvMhHNn/80RhVUQxaPTS7/AMHRZGRc1lD9/bjA +pMBis9CL4AbXtTcztU5qy4VpB1/Ej3AbAjuJIbpbPH6XtxIEtqdM4Seqi44w9oX4 +rxQagXmvJPp+E4253EkeHwhfHh4SnJEtsibQ +-----END CERTIFICATE REQUEST-----`; + +const OUT_EXAMPLE_COM_EXTENDED_KEY_USAGE = `Subject + C = CH + ST = Zurich + L = Zurich + O = Example RE + OU = IT Department + CN = example.com +Public Key + Algorithm: RSA + Length: 2048 bits + Modulus: 00:c8:d0:fc:1c:fe:0b:30:3f:59:a4:be:37:2a:77:8a: + 35:b3:62:52:98:ec:69:80:fd:ad:85:bb:33:52:3d:09: + 6b:5a:e1:b2:64:97:1f:6f:40:a9:2c:8a:51:17:ca:9c: + 0e:59:40:7b:e8:45:42:75:46:9e:4d:ec:bd:02:21:7c: + 43:83:ee:ac:33:05:13:07:56:17:b9:f6:39:2f:da:41: + 11:b3:eb:bc:f0:a0:42:35:f2:00:4b:a9:b9:77:8e:72: + e3:11:f7:df:c6:97:ab:89:59:7b:18:84:01:25:87:4b: + b4:ac:58:04:77:90:bd:dc:f6:9d:78:53:d1:07:39:ac: + a6:65:63:ce:fd:20:9f:08:9c:a1:c6:cc:c3:2c:cd:9e: + 1b:94:b6:ae:f8:ae:bb:d9:d8:fa:b9:34:3a:8e:f3:f3: + 1f:0f:64:5f:56:97:53:5a:98:b9:75:b5:63:ea:b3:39: + d2:dd:b7:e3:74:96:1e:52:59:bb:5e:f4:f3:0b:a1:0c: + 01:3e:8a:ff:99:1e:af:47:21:97:b1:e0:d2:67:04:3b: + dc:38:73:67:12:4c:01:ef:67:66:f6:b1:16:1b:c4:d4: + 19:e3:d6:f2:42:c4:40:5d:6f:13:36:73:9a:2b:d3:e1: + 9a:fc:32:fe:2a:c4:5d:4f:4f:12:5d:ee:ec:ab:d2:9c: + d7 + Exponent: 65537 (0x10001) +Signature + Algorithm: SHA256withRSA + Signature: 9c:61:68:f5:78:8c:63:fc:55:04:86:19:b6:95:9a:f4: + e8:fa:b8:18:4b:48:56:c3:16:c3:92:2b:52:7d:85:20: + 56:ff:c9:8f:31:18:7b:81:e6:fe:d7:34:0f:fc:ce:14: + 56:bc:80:17:19:a6:bc:06:76:a3:93:89:91:d2:b9:31: + cb:53:17:a5:dd:98:7a:f7:6b:17:f5:c5:6b:64:e8:b6: + fe:04:e3:f2:3a:a6:fa:c5:79:f6:13:48:6a:66:0a:ee: + 73:41:3b:a8:6a:73:3b:26:31:3c:d6:fb:db:4c:b1:5d: + 68:73:1d:2c:e7:a4:a6:e2:b9:bf:99:1b:b8:d7:6d:0e: + 91:22:02:47:74:be:65:78:05:0d:01:57:76:f7:ce:12: + 11:42:a0:41:eb:4a:52:04:76:2f:32:11:cd:9f:ff:34: + 46:15:54:43:16:8f:4d:2e:ff:00:c1:d1:64:64:5c:d6: + 50:fd:fd:b8:c0:a4:c0:62:b3:d0:8b:e0:06:d7:b5:37: + 33:b5:4e:6a:cb:85:69:07:5f:c4:8f:70:1b:02:3b:89: + 21:ba:5b:3c:7e:97:b7:12:04:b6:a7:4c:e1:27:aa:8b: + 8e:30:f6:85:f8:af:14:1a:81:79:af:24:fa:7e:13:8d: + b9:dc:49:1e:1f:08:5f:1e:1e:12:9c:91:2d:b2:26:d0 +Requested Extensions + Basic Constraints: critical + CA = false + Key Usage: critical + Digital Signature + Key encipherment + Extended Key Usage: + TLS Web Server Authentication + TLS Web Client Authentication + Code signing + E-mail Protection (S/MIME) + Trusted Timestamping + Microsoft Individual Code Signing + Microsoft Commercial Code Signing + Microsoft Trust List Signing + Microsoft Server Gated Crypto + Microsoft Encrypted File System + Microsoft Smartcard Login + Microsoft Server Gated Crypto + Subject Alternative Name: + DNS: example.com + DNS: www.example.com`; TestRegister.addTests([ { @@ -184,7 +867,7 @@ TestRegister.addTests([ recipeConfig: [ { "op": "Parse CSR", - "args": ["PEM", true] + "args": ["PEM"] } ] }, @@ -195,21 +878,107 @@ TestRegister.addTests([ recipeConfig: [ { "op": "Parse CSR", - "args": ["PEM", true] + "args": ["PEM"] } ] }, - // RSA algorithm is the only one supported for CSR in node-forge as of 1.3.1 { name: "Parse CSR: Example Certificate Signing Request (CSR) with EC 256", - input: IN_EXAMPLE_COM_EC, - expectedError: true, - expectedOutput: OUT_EXAMPLE_COM_EC, + input: IN_EXAMPLE_COM_EC_P256, + expectedOutput: OUT_EXAMPLE_COM_EC_P256, + recipeConfig: [ + { + "op": "Parse CSR", + "args": ["PEM"] + } + ] + }, + { + name: "Parse CSR: Example Certificate Signing Request (CSR) with EC 384", + input: IN_EXAMPLE_COM_EC_P384, + expectedOutput: OUT_EXAMPLE_COM_EC_P384, + recipeConfig: [ + { + "op": "Parse CSR", + "args": ["PEM"] + } + ] + }, + { + name: "Parse CSR: Example Certificate Signing Request (CSR) with EC 521", + input: IN_EXAMPLE_COM_EC_P521, + expectedOutput: OUT_EXAMPLE_COM_EC_P521, + recipeConfig: [ + { + "op": "Parse CSR", + "args": ["PEM"] + } + ] + }, + { + name: "Parse CSR: Example Certificate Signing Request (CSR) with DSA 1024", + input: IN_EXAMPLE_COM_DSA_1024, + expectedOutput: OUT_EXAMPLE_COM_DSA_1024, + recipeConfig: [ + { + "op": "Parse CSR", + "args": ["PEM"] + } + ] + }, + { + name: "Parse CSR: Example Certificate Signing Request (CSR) with DSA 2048", + input: IN_EXAMPLE_COM_DSA_2048, + expectedOutput: OUT_EXAMPLE_COM_DSA_2048, + recipeConfig: [ + { + "op": "Parse CSR", + "args": ["PEM"] + } + ] + }, + { + name: "Parse CSR: Example Certificate Signing Request (CSR) with DSA 2048", + input: IN_EXAMPLE_COM_DSA_2048, + expectedOutput: OUT_EXAMPLE_COM_DSA_2048, recipeConfig: [ { "op": "Parse CSR", - "args": ["PEM", true] + "args": ["PEM"] } ] - } + }, + { + name: "Parse CSR: Example Certificate Signing Request (CSR) with various SAN types", + input: IN_EXAMPLE_COM_SAN, + expectedOutput: OUT_EXAMPLE_COM_SAN, + recipeConfig: [ + { + "op": "Parse CSR", + "args": ["PEM"] + } + ] + }, + { + name: "Parse CSR: Example Certificate Signing Request (CSR) with various Key Usages", + input: IN_EXAMPLE_COM_KEY_USAGE, + expectedOutput: OUT_EXAMPLE_COM_KEY_USAGE, + recipeConfig: [ + { + "op": "Parse CSR", + "args": ["PEM"] + } + ] + }, + { + name: "Parse CSR: Example Certificate Signing Request (CSR) with various Extended Key Usages", + input: IN_EXAMPLE_COM_EXTENDED_KEY_USAGE, + expectedOutput: OUT_EXAMPLE_COM_EXTENDED_KEY_USAGE, + recipeConfig: [ + { + "op": "Parse CSR", + "args": ["PEM"] + } + ] + }, ]); From e80d3d59bc19c30a46b225399733044f556b886b Mon Sep 17 00:00:00 2001 From: Robin Sandhu Date: Wed, 12 Jun 2024 18:52:55 +0100 Subject: [PATCH 02/11] Refactor code --- src/core/operations/ParseCSR.mjs | 123 +++++++++++++++++++------------ 1 file changed, 75 insertions(+), 48 deletions(-) diff --git a/src/core/operations/ParseCSR.mjs b/src/core/operations/ParseCSR.mjs index 63d66c6ea..3950d4d87 100644 --- a/src/core/operations/ParseCSR.mjs +++ b/src/core/operations/ParseCSR.mjs @@ -77,12 +77,12 @@ function formatSignature(sigAlg, sigHex) { const d = new r.KJUR.crypto.DSA(); const sigParam = d.parseASN1Signature(sigHex); out += ` Signature: - R: ${formatHexOntoMultiLine(sigParam[0].toString(16))} - S: ${formatHexOntoMultiLine(sigParam[1].toString(16))}\n`; + R: ${formatHexOntoMultiLine(absBigIntToHex(sigParam[0]))} + S: ${formatHexOntoMultiLine(absBigIntToHex(sigParam[1]))}\n`; } else if (new RegExp("withrsa", "i").test(sigAlg)) { - out += ` Signature: ${formatHexOntoMultiLine(sigHex, false)}\n`; - } else { out += ` Signature: ${formatHexOntoMultiLine(sigHex)}\n`; + } else { + out += ` Signature: ${formatHexOntoMultiLine(ensureHexIsPositiveInTwosComplement(sigHex))}\n`; } return chop(out); @@ -100,7 +100,7 @@ function formatSubjectPublicKey(publicKeyPEM) { if (publicKey instanceof r.RSAKey) { out += ` Algorithm: RSA Length: ${publicKey.n.bitLength()} bits - Modulus: ${formatHexOntoMultiLine(publicKey.n.toString(16))} + Modulus: ${formatHexOntoMultiLine(absBigIntToHex(publicKey.n))} Exponent: ${publicKey.e} (0x${Utils.hex(publicKey.e)})\n`; } else if (publicKey instanceof r.KJUR.crypto.ECDSA) { out += ` Algorithm: ECDSA @@ -111,10 +111,10 @@ function formatSubjectPublicKey(publicKeyPEM) { } else if (publicKey instanceof r.KJUR.crypto.DSA) { out += ` Algorithm: DSA Length: ${publicKey.p.toString(16).length * 4} bits - Pub: ${formatHexOntoMultiLine(publicKey.y.toString(16))} - P: ${formatHexOntoMultiLine(publicKey.p.toString(16))} - Q: ${formatHexOntoMultiLine(publicKey.q.toString(16))} - G: ${formatHexOntoMultiLine(publicKey.g.toString(16))}\n`; + Pub: ${formatHexOntoMultiLine(absBigIntToHex(publicKey.y))} + P: ${formatHexOntoMultiLine(absBigIntToHex(publicKey.p))} + Q: ${formatHexOntoMultiLine(absBigIntToHex(publicKey.q))} + G: ${formatHexOntoMultiLine(absBigIntToHex(publicKey.g))}\n`; } else { out += `unsupported public key algorithm\n`; } @@ -178,19 +178,46 @@ function formatExtensionCriticalTag(extension) { } /** - * Format hex input on multiple lines - * @param {*} hex string + * Format string input as a comma separated hex string on multiple lines + * @param {*} hex String * @returns Multi-line string describing the Hex input */ -function formatHexOntoMultiLine(hex, prependZero=true) { - let colonSeparatedHex = chop(hex.replace(/(..)/g, "$&:")); +function formatHexOntoMultiLine(hex) { + if (hex.length % 2 !== 0) { + hex = "0" + hex + } + + return formatMultiLine(chop(hex.replace(/(..)/g, "$&:"))); +} + +/** + * Convert BigInt to abs value in Hex + * @param {*} int BigInt + * @returns String representing absolute value in Hex + */ +function absBigIntToHex(int) { + int = int < 0n ? -int : int; + let hInt = int.toString(16); + + return ensureHexIsPositiveInTwosComplement(hInt); +} + +/** + * Ensure Hex String remains positive in 2's complement + * @param {*} hex String + * @returns Hex String ensuring value remains positive in 2's complement + */ +function ensureHexIsPositiveInTwosComplement(hex) { + if (hex.length % 2 !== 0) { + return "0" + hex; + } - // prepend 00 if most significant bit it 1 - if ((parseInt(colonSeparatedHex.substring(0, 2), 16) & 128) && prependZero) { - colonSeparatedHex = "00:" + colonSeparatedHex; + // prepend 00 if most significant bit is 1 (sign bit) + if (hex.length >=2 && (parseInt(hex.substring(0, 2), 16) & 128)) { + hex = "00" + hex; } - return formatMultiLine(colonSeparatedHex); + return hex } /** @@ -232,22 +259,22 @@ function describeBasicConstraints(extension) { function describeKeyUsage(extension) { const usage = []; - const kuIdentifierToName = new Map([ - ["digitalSignature", "Digital Signature"], - ["nonRepudiation", "Non-repudiation"], - ["keyEncipherment", "Key encipherment"], - ["dataEncipherment", "Data encipherment"], - ["keyAgreement", "Key agreement"], - ["keyCertSign", "Key certificate signing"], - ["cRLSign", "CRL signing"], - ["encipherOnly", "Encipher Only"], - ["decipherOnly", "Decipher Only"], - ]); + const kuIdentifierToName = { + digitalSignature: "Digital Signature", + nonRepudiation: "Non-repudiation", + keyEncipherment: "Key encipherment", + dataEncipherment: "Data encipherment", + keyAgreement: "Key agreement", + keyCertSign: "Key certificate signing", + cRLSign: "CRL signing", + encipherOnly: "Encipher Only", + decipherOnly: "Decipher Only", + }; if (Object.hasOwn(extension, "names")) { extension.names.forEach((ku) => { - if (kuIdentifierToName.has(ku)) { - usage.push(kuIdentifierToName.get(ku)); + if (Object.hasOwn(kuIdentifierToName, ku)) { + usage.push(kuIdentifierToName[ku]); } else { usage.push(`unknown key usage (${ku})`); } @@ -268,27 +295,27 @@ function describeKeyUsage(extension) { function describeExtendedKeyUsage(extension) { const usage = []; - const ekuIdentifierToName = new Map([ - ["serverAuth", "TLS Web Server Authentication"], - ["clientAuth", "TLS Web Client Authentication"], - ["codeSigning", "Code signing"], - ["emailProtection", "E-mail Protection (S/MIME)"], - ["timeStamping", "Trusted Timestamping"], - ["1.3.6.1.4.1.311.2.1.21", "Microsoft Individual Code Signing"], // msCodeInd - ["1.3.6.1.4.1.311.2.1.22", "Microsoft Commercial Code Signing"], // msCodeCom - ["1.3.6.1.4.1.311.10.3.1", "Microsoft Trust List Signing"], // msCTLSign - ["1.3.6.1.4.1.311.10.3.3", "Microsoft Server Gated Crypto"], // msSGC - ["1.3.6.1.4.1.311.10.3.4", "Microsoft Encrypted File System"], // msEFS - ["1.3.6.1.4.1.311.20.2.2", "Microsoft Smartcard Login"], // msSmartcardLogin - ["2.16.840.1.113730.4.1", "Netscape Server Gated Crypto"], // nsSGC - ]); + const ekuIdentifierToName = { + "serverAuth": "TLS Web Server Authentication", + "clientAuth": "TLS Web Client Authentication", + "codeSigning": "Code signing", + "emailProtection": "E-mail Protection (S/MIME)", + "timeStamping": "Trusted Timestamping", + "1.3.6.1.4.1.311.2.1.21": "Microsoft Individual Code Signing", // msCodeInd + "1.3.6.1.4.1.311.2.1.22": "Microsoft Commercial Code Signing", // msCodeCom + "1.3.6.1.4.1.311.10.3.1": "Microsoft Trust List Signing", // msCTLSign + "1.3.6.1.4.1.311.10.3.3": "Microsoft Server Gated Crypto", // msSGC + "1.3.6.1.4.1.311.10.3.4": "Microsoft Encrypted File System", // msEFS + "1.3.6.1.4.1.311.20.2.2": "Microsoft Smartcard Login", // msSmartcardLogin + "2.16.840.1.113730.4.1": "Netscape Server Gated Crypto", // nsSGC + }; if (Object.hasOwn(extension, "array")) { extension.array.forEach((eku) => { - if (ekuIdentifierToName.has(eku)) { - usage.push(ekuIdentifierToName.get(eku)); + if (Object.hasOwn(ekuIdentifierToName, eku)) { + usage.push(ekuIdentifierToName[eku]); } else { - usage.push(`unknown extended key usage (${eku})`); + usage.push(eku); } }); } @@ -331,7 +358,7 @@ function describeSubjectAlternativeName(extension) { names.push(`Other: ${altName[key].oid}::${altName[key].value.utf8str.str}`); break; default: - names.push(`(unable to format type '${key}' name)\n`); + names.push(`(unable to format SAN '${key}':${altName[key]})\n`); } }); } From fe9f4fa7a93680b0a7db6db71a564be8b399addc Mon Sep 17 00:00:00 2001 From: Robin Sandhu Date: Wed, 12 Jun 2024 19:00:14 +0100 Subject: [PATCH 03/11] Fix linting errors --- src/core/operations/ParseCSR.mjs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/core/operations/ParseCSR.mjs b/src/core/operations/ParseCSR.mjs index 3950d4d87..d3b3c364a 100644 --- a/src/core/operations/ParseCSR.mjs +++ b/src/core/operations/ParseCSR.mjs @@ -184,7 +184,7 @@ function formatExtensionCriticalTag(extension) { */ function formatHexOntoMultiLine(hex) { if (hex.length % 2 !== 0) { - hex = "0" + hex + hex = "0" + hex; } return formatMultiLine(chop(hex.replace(/(..)/g, "$&:"))); @@ -197,9 +197,8 @@ function formatHexOntoMultiLine(hex) { */ function absBigIntToHex(int) { int = int < 0n ? -int : int; - let hInt = int.toString(16); - return ensureHexIsPositiveInTwosComplement(hInt); + return ensureHexIsPositiveInTwosComplement(int.toString(16)); } /** @@ -217,7 +216,7 @@ function ensureHexIsPositiveInTwosComplement(hex) { hex = "00" + hex; } - return hex + return hex; } /** From 534ab23d9b3befeca5edd7aaed9ba38eba09bf3c Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Fri, 14 Jun 2024 00:38:25 +0900 Subject: [PATCH 04/11] chore: update SIGABA.mjs intial -> initial --- src/core/operations/SIGABA.mjs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/core/operations/SIGABA.mjs b/src/core/operations/SIGABA.mjs index 274f09f65..e3a9b82ef 100644 --- a/src/core/operations/SIGABA.mjs +++ b/src/core/operations/SIGABA.mjs @@ -40,7 +40,7 @@ class Sigaba extends Operation { value: false }, { - name: "1st cipher rotor intial value", + name: "1st cipher rotor initial value", type: "option", value: LETTERS }, @@ -56,7 +56,7 @@ class Sigaba extends Operation { value: false }, { - name: "2nd cipher rotor intial value", + name: "2nd cipher rotor initial value", type: "option", value: LETTERS }, @@ -72,7 +72,7 @@ class Sigaba extends Operation { value: false }, { - name: "3rd cipher rotor intial value", + name: "3rd cipher rotor initial value", type: "option", value: LETTERS }, @@ -88,7 +88,7 @@ class Sigaba extends Operation { value: false }, { - name: "4th cipher rotor intial value", + name: "4th cipher rotor initial value", type: "option", value: LETTERS }, @@ -104,7 +104,7 @@ class Sigaba extends Operation { value: false }, { - name: "5th cipher rotor intial value", + name: "5th cipher rotor initial value", type: "option", value: LETTERS }, @@ -120,7 +120,7 @@ class Sigaba extends Operation { value: false }, { - name: "1st control rotor intial value", + name: "1st control rotor initial value", type: "option", value: LETTERS }, @@ -136,7 +136,7 @@ class Sigaba extends Operation { value: false }, { - name: "2nd control rotor intial value", + name: "2nd control rotor initial value", type: "option", value: LETTERS }, @@ -152,7 +152,7 @@ class Sigaba extends Operation { value: false }, { - name: "3rd control rotor intial value", + name: "3rd control rotor initial value", type: "option", value: LETTERS }, @@ -168,7 +168,7 @@ class Sigaba extends Operation { value: false }, { - name: "4th control rotor intial value", + name: "4th control rotor initial value", type: "option", value: LETTERS }, @@ -184,7 +184,7 @@ class Sigaba extends Operation { value: false }, { - name: "5th control rotor intial value", + name: "5th control rotor initial value", type: "option", value: LETTERS }, @@ -195,7 +195,7 @@ class Sigaba extends Operation { defaultIndex: 0 }, { - name: "1st index rotor intial value", + name: "1st index rotor initial value", type: "option", value: NUMBERS }, @@ -206,7 +206,7 @@ class Sigaba extends Operation { defaultIndex: 0 }, { - name: "2nd index rotor intial value", + name: "2nd index rotor initial value", type: "option", value: NUMBERS }, @@ -217,7 +217,7 @@ class Sigaba extends Operation { defaultIndex: 0 }, { - name: "3rd index rotor intial value", + name: "3rd index rotor initial value", type: "option", value: NUMBERS }, @@ -228,7 +228,7 @@ class Sigaba extends Operation { defaultIndex: 0 }, { - name: "4th index rotor intial value", + name: "4th index rotor initial value", type: "option", value: NUMBERS }, @@ -239,7 +239,7 @@ class Sigaba extends Operation { defaultIndex: 0 }, { - name: "5th index rotor intial value", + name: "5th index rotor initial value", type: "option", value: NUMBERS }, From 40fda00db41b14cada5c84979fd28a5419c8fdfb Mon Sep 17 00:00:00 2001 From: a3957273 <89583054+a3957273@users.noreply.github.com> Date: Fri, 21 Jun 2024 08:09:53 +0000 Subject: [PATCH 05/11] Bump to 10.19.0 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9fbb1540..d3a8feb70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ All major and minor version changes will be documented in this file. Details of ## Details +### [10.19.0] - 2024-06-21 +- Add support for ECDSA and DSA in 'Parse CSR' [@robinsandhu] | [#1828] +- Fix typos in SIGABA.mjs [@eltociear] | [#1834] + ### [10.18.0] - 2024-04-24 - Added 'XXTEA Encrypt' and 'XXTEA Decrypt' operations [@n1474335] | [0a353ee] @@ -436,6 +440,7 @@ All major and minor version changes will be documented in this file. Details of ## [4.0.0] - 2016-11-28 - Initial open source commit [@n1474335] | [b1d73a72](https://github.com/gchq/CyberChef/commit/b1d73a725dc7ab9fb7eb789296efd2b7e4b08306) +[10.19.0]: https://github.com/gchq/CyberChef/releases/tag/v10.19.0 [10.18.0]: https://github.com/gchq/CyberChef/releases/tag/v10.18.0 [10.17.0]: https://github.com/gchq/CyberChef/releases/tag/v10.17.0 [10.16.0]: https://github.com/gchq/CyberChef/releases/tag/v10.16.0 @@ -623,6 +628,8 @@ All major and minor version changes will be documented in this file. Details of [@TheZ3ro]: https://github.com/TheZ3ro [@EvieHarv]: https://github.com/EvieHarv [@cplussharp]: https://github.com/cplussharp +[@robinsandhu]: https://github.com/robinsandhu +[@eltociear]: https://github.com/eltociear [8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7 diff --git a/package-lock.json b/package-lock.json index 029423591..a006a8536 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cyberchef", - "version": "10.18.8", + "version": "10.19.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cyberchef", - "version": "10.18.8", + "version": "10.19.0", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index 1e4d06652..710a42e0b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cyberchef", - "version": "10.18.8", + "version": "10.19.0", "description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.", "author": "n1474335 ", "homepage": "https://gchq.github.io/CyberChef", From ab37c1e562dbee0495ed32876ecbb8225282af25 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Fri, 21 Jun 2024 14:12:28 +0100 Subject: [PATCH 06/11] Fixed Optical Character Recognition and added tests --- .../OpticalCharacterRecognition.mjs | 21 +++++++----- tests/browser/02_ops.js | 32 +++++++++++------- tests/browser/browserUtils.js | 5 +-- tests/samples/files/testocr.png | Bin 0 -> 23359 bytes 4 files changed, 34 insertions(+), 24 deletions(-) create mode 100644 tests/samples/files/testocr.png diff --git a/src/core/operations/OpticalCharacterRecognition.mjs b/src/core/operations/OpticalCharacterRecognition.mjs index 6262df7b4..dfcff9654 100644 --- a/src/core/operations/OpticalCharacterRecognition.mjs +++ b/src/core/operations/OpticalCharacterRecognition.mjs @@ -12,9 +12,10 @@ import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; import { isWorkerEnvironment } from "../Utils.mjs"; -import process from "process"; import { createWorker } from "tesseract.js"; +const OEM_MODES = ["Tesseract only", "LSTM only", "Tesseract/LSTM Combined"]; + /** * Optical Character Recognition operation */ @@ -37,6 +38,12 @@ class OpticalCharacterRecognition extends Operation { name: "Show confidence", type: "boolean", value: true + }, + { + name: "OCR Engine Mode", + type: "option", + value: OEM_MODES, + defaultIndex: 1 } ]; } @@ -47,7 +54,7 @@ class OpticalCharacterRecognition extends Operation { * @returns {string} */ async run(input, args) { - const [showConfidence] = args; + const [showConfidence, oemChoice] = args; if (!isWorkerEnvironment()) throw new OperationError("This operation only works in a browser"); @@ -56,12 +63,13 @@ class OpticalCharacterRecognition extends Operation { throw new OperationError("Unsupported file type (supported: jpg,png,pbm,bmp) or no file provided"); } - const assetDir = isWorkerEnvironment() ? `${self.docURL}/assets/` : `${process.cwd()}/src/core/vendor/`; + const assetDir = `${self.docURL}/assets/`; + const oem = OEM_MODES.indexOf(oemChoice); try { self.sendStatusMessage("Spinning up Tesseract worker..."); const image = `data:${type};base64,${toBase64(input)}`; - const worker = createWorker({ + const worker = await createWorker("eng", oem, { workerPath: `${assetDir}tesseract/worker.min.js`, langPath: `${assetDir}tesseract/lang-data`, corePath: `${assetDir}tesseract/tesseract-core.wasm.js`, @@ -71,11 +79,6 @@ class OpticalCharacterRecognition extends Operation { } } }); - await worker.load(); - self.sendStatusMessage(`Loading English language pack...`); - await worker.loadLanguage("eng"); - self.sendStatusMessage("Intialising Tesseract API..."); - await worker.initialize("eng"); self.sendStatusMessage("Finding text..."); const result = await worker.recognize(image); diff --git a/tests/browser/02_ops.js b/tests/browser/02_ops.js index 37f75f584..70cfd3ba1 100644 --- a/tests/browser/02_ops.js +++ b/tests/browser/02_ops.js @@ -236,7 +236,7 @@ module.exports = { // testOp(browser, "OR", "test input", "test_output"); // testOp(browser, "Object Identifier to Hex", "test input", "test_output"); testOpHtml(browser, "Offset checker", "test input\n\nbest input", ".hl5", "est input"); - // testOp(browser, "Optical Character Recognition", "test input", "test_output"); + testOpFile(browser, "Optical Character Recognition", "files/testocr.png", false, /This is a lot of 12 point text to test the/, [], 10000); // testOp(browser, "PEM to Hex", "test input", "test_output"); // testOp(browser, "PGP Decrypt", "test input", "test_output"); // testOp(browser, "PGP Decrypt and Verify", "test input", "test_output"); @@ -408,7 +408,7 @@ module.exports = { * @param {Browser} browser - Nightwatch client * @param {string|Array} opName - name of operation to be tested, array for multiple ops * @param {string} input - input text for test - * @param {Array|Array>} args - arguments, nested if multiple ops + * @param {Array|Array>} [args=[]] - arguments, nested if multiple ops */ function bakeOp(browser, opName, input, args=[]) { browser.perform(function() { @@ -425,8 +425,8 @@ function bakeOp(browser, opName, input, args=[]) { * @param {Browser} browser - Nightwatch client * @param {string|Array} opName - name of operation to be tested, array for multiple ops * @param {string} input - input text - * @param {string} output - expected output - * @param {Array|Array>} args - arguments, nested if multiple ops + * @param {string|RegExp} output - expected output + * @param {Array|Array>} [args=[]] - arguments, nested if multiple ops */ function testOp(browser, opName, input, output, args=[]) { bakeOp(browser, opName, input, args); @@ -440,8 +440,8 @@ function testOp(browser, opName, input, output, args=[]) { * @param {string|Array} opName - name of operation to be tested array for multiple ops * @param {string} input - input text * @param {string} cssSelector - CSS selector for HTML output - * @param {string} output - expected output - * @param {Array|Array>} args - arguments, nested if multiple ops + * @param {string|RegExp} output - expected output + * @param {Array|Array>} [args=[]] - arguments, nested if multiple ops */ function testOpHtml(browser, opName, input, cssSelector, output, args=[]) { bakeOp(browser, opName, input, args); @@ -459,9 +459,9 @@ function testOpHtml(browser, opName, input, cssSelector, output, args=[]) { * @param {Browser} browser - Nightwatch client * @param {string|Array} opName - name of operation to be tested array for multiple ops * @param {string} filename - filename of image file from samples directory - * @param {Array|Array>} args - arguments, nested if multiple ops + * @param {Array|Array>} [args=[]] - arguments, nested if multiple ops */ -function testOpImage(browser, opName, filename, args) { +function testOpImage(browser, opName, filename, args=[]) { browser.perform(function() { console.log(`Current test: ${opName}`); }); @@ -481,11 +481,12 @@ function testOpImage(browser, opName, filename, args) { * @param {Browser} browser - Nightwatch client * @param {string|Array} opName - name of operation to be tested array for multiple ops * @param {string} filename - filename of file from samples directory - * @param {string} cssSelector - CSS selector for HTML output - * @param {string} output - expected output - * @param {Array|Array>} args - arguments, nested if multiple ops + * @param {string|boolean} cssSelector - CSS selector for HTML output or false for normal text output + * @param {string|RegExp} output - expected output + * @param {Array|Array>} [args=[]] - arguments, nested if multiple ops + * @param {number} [waitWindow=1000] - The number of milliseconds to wait for the output to be correct */ -function testOpFile(browser, opName, filename, cssSelector, output, args) { +function testOpFile(browser, opName, filename, cssSelector, output, args=[], waitWindow=1000) { browser.perform(function() { console.log(`Current test: ${opName}`); }); @@ -494,9 +495,14 @@ function testOpFile(browser, opName, filename, cssSelector, output, args) { browser.pause(100).waitForElementVisible("#stale-indicator", 5000); utils.bake(browser); - if (typeof output === "string") { + if (!cssSelector) { + // Text output + utils.expectOutput(browser, output, true, waitWindow); + } else if (typeof output === "string") { + // HTML output - string match browser.expect.element("#output-html " + cssSelector).text.that.equals(output); } else if (output instanceof RegExp) { + // HTML output - RegEx match browser.expect.element("#output-html " + cssSelector).text.that.matches(output); } } diff --git a/tests/browser/browserUtils.js b/tests/browser/browserUtils.js index dc0774af9..7711c004b 100644 --- a/tests/browser/browserUtils.js +++ b/tests/browser/browserUtils.js @@ -180,15 +180,16 @@ function loadRecipe(browser, opName, input, args) { * @param {Browser} browser - Nightwatch client * @param {string|RegExp} expected - The expected output value * @param {boolean} [waitNotNull=false] - Wait for the output to not be empty before testing the value + * @param {number} [waitWindow=1000] - The number of milliseconds to wait for the output to be correct */ -function expectOutput(browser, expected, waitNotNull=false) { +function expectOutput(browser, expected, waitNotNull=false, waitWindow=1000) { if (waitNotNull && expected !== "") { browser.waitUntil(async function() { const output = await this.execute(function() { return window.app.manager.output.outputEditorView.state.doc.toString(); }); return output.length; - }, 1000); + }, waitWindow); } browser.execute(expected => { diff --git a/tests/samples/files/testocr.png b/tests/samples/files/testocr.png new file mode 100644 index 0000000000000000000000000000000000000000..ce8d0e78b5d4cdb46258b479fb7def468e0040b6 GIT binary patch literal 23359 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 literal 0 HcmV?d00001 From 965570d2504c17ee1f96211a1dc10ed40cd2b332 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Fri, 21 Jun 2024 14:12:36 +0100 Subject: [PATCH 07/11] 10.18.9 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 029423591..51acbda77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cyberchef", - "version": "10.18.8", + "version": "10.18.9", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cyberchef", - "version": "10.18.8", + "version": "10.18.9", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index 1e4d06652..56f2bee35 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cyberchef", - "version": "10.18.8", + "version": "10.18.9", "description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.", "author": "n1474335 ", "homepage": "https://gchq.github.io/CyberChef", From 7a5225c961a5e0d192b03152117cd10a761f73d6 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Wed, 14 Aug 2024 15:21:57 +0100 Subject: [PATCH 08/11] Fixed JA4 version fallback value --- src/core/lib/JA4.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/lib/JA4.mjs b/src/core/lib/JA4.mjs index 5e606f46b..f600f4d89 100644 --- a/src/core/lib/JA4.mjs +++ b/src/core/lib/JA4.mjs @@ -44,7 +44,7 @@ export function toJA4(bytes) { the TLS version is the value of the Protocol Version. Handshake version (located at the top of the packet) should be ignored. */ - let version = tlsr.version.value; + let version = tlsr.handshake.value.helloVersion.value; for (const ext of tlsr.handshake.value.extensions.value) { if (ext.type.value === "supported_versions") { version = parseHighestSupportedVersion(ext.value.data); @@ -189,7 +189,7 @@ export function toJA4S(bytes) { the TLS version is the value of the Protocol Version. Handshake version (located at the top of the packet) should be ignored. */ - let version = tlsr.version.value; + let version = tlsr.handshake.value.helloVersion.value; for (const ext of tlsr.handshake.value.extensions.value) { if (ext.type.value === "supported_versions") { version = parseHighestSupportedVersion(ext.value.data); From 5f88ae44ec77228d9bed8f11e8cc8e7dcfb36914 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Wed, 14 Aug 2024 15:22:06 +0100 Subject: [PATCH 09/11] 10.19.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index a006a8536..3d098c7c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cyberchef", - "version": "10.19.0", + "version": "10.19.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cyberchef", - "version": "10.19.0", + "version": "10.19.1", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index 710a42e0b..e458bd9b3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cyberchef", - "version": "10.19.0", + "version": "10.19.1", "description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.", "author": "n1474335 ", "homepage": "https://gchq.github.io/CyberChef", From 0e82e4b7c6c77cadb8be61cb145e081d6ecfdc88 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Wed, 14 Aug 2024 15:35:12 +0100 Subject: [PATCH 10/11] Updated chromedriver --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3d098c7c5..aa018e1ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -115,7 +115,7 @@ "babel-plugin-dynamic-import-node": "^2.3.3", "babel-plugin-transform-builtin-extend": "1.1.2", "base64-loader": "^1.0.0", - "chromedriver": "^125.0.3", + "chromedriver": "^127.0.2", "cli-progress": "^3.12.0", "colors": "^1.4.0", "copy-webpack-plugin": "^12.0.2", @@ -5093,9 +5093,9 @@ } }, "node_modules/chromedriver": { - "version": "125.0.3", - "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-125.0.3.tgz", - "integrity": "sha512-Qzuk5Wian2o3EVGjtbz6V/jv+pT/AV9246HbG6kUljZXXjsKZLZxqJC+kHR3qEh/wdv4EJD0YwAOWV72v9hogw==", + "version": "127.0.2", + "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-127.0.2.tgz", + "integrity": "sha512-mYfJ/8FqzsdFOs2rPiAI4y0suFnv78cRnzZK0MHdSfSIDeRPbqZz0rNX4lrXt14hXc9vqXa+a8cMxlrhWtXKSQ==", "dev": true, "hasInstallScript": true, "dependencies": { diff --git a/package.json b/package.json index e458bd9b3..bde3df48a 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "babel-plugin-dynamic-import-node": "^2.3.3", "babel-plugin-transform-builtin-extend": "1.1.2", "base64-loader": "^1.0.0", - "chromedriver": "^125.0.3", + "chromedriver": "^127.0.2", "cli-progress": "^3.12.0", "colors": "^1.4.0", "copy-webpack-plugin": "^12.0.2", From d635cca2106aae2a59caf0e5d7e3633ee1ea3155 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Wed, 14 Aug 2024 15:35:17 +0100 Subject: [PATCH 11/11] 10.19.2 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index aa018e1ca..3904f8408 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cyberchef", - "version": "10.19.1", + "version": "10.19.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cyberchef", - "version": "10.19.1", + "version": "10.19.2", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index bde3df48a..cc3517d35 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cyberchef", - "version": "10.19.1", + "version": "10.19.2", "description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.", "author": "n1474335 ", "homepage": "https://gchq.github.io/CyberChef",