add Certificate Signing Request (CSR) parse action
This commit is contained in:
parent
8a17abae45
commit
c5e5ed2b4d
@ -179,7 +179,8 @@
|
||||
"RSA Verify",
|
||||
"RSA Encrypt",
|
||||
"RSA Decrypt",
|
||||
"Parse SSH Host Key"
|
||||
"Parse SSH Host Key",
|
||||
"Parse CSR"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
268
src/core/operations/ParseCSR.mjs
Normal file
268
src/core/operations/ParseCSR.mjs
Normal file
@ -0,0 +1,268 @@
|
||||
/**
|
||||
* @author jkataja
|
||||
* @copyright Crown Copyright 2023
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import forge from "node-forge";
|
||||
import Utils from "../Utils.mjs";
|
||||
|
||||
/**
|
||||
* Parse CSR operation
|
||||
*/
|
||||
class ParseCSR extends Operation {
|
||||
|
||||
/**
|
||||
* ParseCSR constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Parse CSR";
|
||||
this.module = "PublicKey";
|
||||
this.description = "Parse Certificate Signing Request (CSR) for an X.509 certificate";
|
||||
this.infoURL = "https://en.wikipedia.org/wiki/Certificate_signing_request";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Input format",
|
||||
"type": "option",
|
||||
"value": ["PEM"]
|
||||
},
|
||||
{
|
||||
"name": "Strict ASN.1 value lengths",
|
||||
"type": "boolean",
|
||||
"value": true
|
||||
}
|
||||
];
|
||||
this.checks = [
|
||||
{
|
||||
"pattern": "^-+BEGIN CERTIFICATE REQUEST-+\\r?\\n[\\da-z+/\\n\\r]+-+END CERTIFICATE REQUEST-+\\r?\\n?$",
|
||||
"flags": "i",
|
||||
"args": ["PEM"]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string} Human-readable description of a Certificate Signing Request (CSR).
|
||||
*/
|
||||
run(input, args) {
|
||||
if (!input.length) {
|
||||
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)}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format Subject of the request as a multi-line string
|
||||
* @param {*} subject CSR Subject
|
||||
* @returns Multi-line string describing Subject
|
||||
*/
|
||||
function formatSubject(subject) {
|
||||
let out = "\n";
|
||||
|
||||
for (const attribute of subject.attributes) {
|
||||
out += ` ${attribute.shortName} = ${attribute.value}\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
|
||||
*/
|
||||
function formatSubjectAlternativeNames(csr) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return chop(out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format known extensions of a CSR
|
||||
* @param {*} csr CSR object
|
||||
* @returns Multi-line string describing attributes
|
||||
*/
|
||||
function formatExtensions(csr) {
|
||||
let out = "\n";
|
||||
|
||||
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`;
|
||||
let parts = [];
|
||||
switch (extension.name) {
|
||||
case "basicConstraints" :
|
||||
parts = describeBasicConstraints(extension);
|
||||
break;
|
||||
case "keyUsage" :
|
||||
parts = describeKeyUsage(extension);
|
||||
break;
|
||||
case "extKeyUsage" :
|
||||
parts = describeExtendedKeyUsage(extension);
|
||||
break;
|
||||
default :
|
||||
parts = ["(unable to format extension)"];
|
||||
}
|
||||
out += indent(4, parts);
|
||||
}
|
||||
}
|
||||
|
||||
return chop(out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Format hex string onto multiple lines
|
||||
* @param {*} longStr
|
||||
* @returns Hex string as a multi-line hex string
|
||||
*/
|
||||
function formatMultiLine(longStr) {
|
||||
const lines = [];
|
||||
|
||||
for (let remain = longStr ; remain !== "" ; remain = remain.substring(48)) {
|
||||
lines.push(remain.substring(0, 48));
|
||||
}
|
||||
|
||||
return lines.join("\n ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe Basic Constraints
|
||||
* @see RFC 5280 4.2.1.9. Basic Constraints https://www.ietf.org/rfc/rfc5280.txt
|
||||
* @param {*} extension CSR extension with the name `basicConstraints`
|
||||
* @returns Array of strings describing Basic Constraints
|
||||
*/
|
||||
function describeBasicConstraints(extension) {
|
||||
const constraints = [];
|
||||
|
||||
constraints.push(`CA = ${extension.cA}`);
|
||||
if (extension.pathLenConstraint !== undefined) constraints.push(`PathLenConstraint = ${extension.pathLenConstraint}`);
|
||||
|
||||
return constraints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe Key Usage extension permitted use cases
|
||||
* @see RFC 5280 4.2.1.3. Key Usage https://www.ietf.org/rfc/rfc5280.txt
|
||||
* @param {*} extension CSR extension with the name `keyUsage`
|
||||
* @returns Array of strings describing Key Usage extension permitted use cases
|
||||
*/
|
||||
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");
|
||||
|
||||
if (usage.length === 0) usage.push("(none)");
|
||||
|
||||
return usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe Extended Key Usage extension permitted use cases
|
||||
* @see RFC 5280 4.2.1.12. Extended Key Usage https://www.ietf.org/rfc/rfc5280.txt
|
||||
* @param {*} extension CSR extension with the name `extendedKeyUsage`
|
||||
* @returns Array of strings describing Extended Key Usage extension permitted use cases
|
||||
*/
|
||||
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");
|
||||
|
||||
if (usage.length === 0) usage.push("(none)");
|
||||
|
||||
return usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an array of strings and add leading spaces to each line.
|
||||
* @param {*} n How many leading spaces
|
||||
* @param {*} parts Array of strings
|
||||
* @returns Joined and indented string.
|
||||
*/
|
||||
function indent(n, parts) {
|
||||
const fluff = " ".repeat(n);
|
||||
return fluff + parts.join("\n" + fluff) + "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove last character from a string.
|
||||
* @param {*} s String
|
||||
* @returns Chopped string.
|
||||
*/
|
||||
function chop(s) {
|
||||
return s.substring(0, s.length - 1);
|
||||
}
|
||||
|
||||
export default ParseCSR;
|
@ -147,6 +147,7 @@ import "./tests/Typex.mjs";
|
||||
import "./tests/UnescapeString.mjs";
|
||||
import "./tests/Unicode.mjs";
|
||||
import "./tests/YARA.mjs";
|
||||
import "./tests/ParseCSR.mjs";
|
||||
|
||||
const testStatus = {
|
||||
allTestsPassing: true,
|
||||
|
215
tests/operations/tests/ParseCSR.mjs
Normal file
215
tests/operations/tests/ParseCSR.mjs
Normal file
@ -0,0 +1,215 @@
|
||||
/**
|
||||
* Parse CSR tests.
|
||||
*
|
||||
* @author jkataja
|
||||
* @copyright Crown Copyright 2023
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
// openssl req -newkey rsa:1024 -keyout test-rsa-1024.key -out test-rsa-1024.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_RSA_1024 = `-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICHzCCAYgCAQAwcjELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBlp1cmljaDEPMA0G
|
||||
A1UEBwwGWnVyaWNoMRMwEQYDVQQKDApFeGFtcGxlIFJFMRYwFAYDVQQLDA1JVCBE
|
||||
ZXBhcnRtZW50MRQwEgYDVQQDDAtleGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEF
|
||||
AAOBjQAwgYkCgYEArrTrLI6FkzjX8FZfclt2ox1Dz7KRwt5f6ffZic7twLAKJ4ao
|
||||
/H3APjwoFVUXGjiNj/XF2RlId4UxB1b6CgWjujBb9W51rTdvfWLyAHsrLcptpVz+
|
||||
V9Y8X9kEFCRGGDyG5+X+Nu6COzTpUPDj4bIIX/uPk3fDYDEqLClVy8/VS48CAwEA
|
||||
AaBtMGsGCSqGSIb3DQEJDjFeMFwwJwYDVR0RBCAwHoILZXhhbXBsZS5jb22CD3d3
|
||||
dy5leGFtcGxlLmNvbTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFoDATBgNV
|
||||
HSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOBgQB0mUlPgt6pt/kjD0pz
|
||||
OUNk5e9nBFQYQGuGIHGYbPX3mi4Wd9vUCdPixtPSTunHWs2cxX2nM8+MdcNTY+7Q
|
||||
NFgFNIvSXhbqMYoHAAApMHJOxiWpBFdYKp3tESnlgh2lUh7lQtmOjD4a1dzfU8PU
|
||||
oViyp+UJGasN2WRd+4VtaPw64w==
|
||||
-----END CERTIFICATE REQUEST-----`;
|
||||
|
||||
const OUT_EXAMPLE_COM_RSA_1024 = `Version: 1 (0x00)
|
||||
Subject
|
||||
C = CH
|
||||
ST = Zurich
|
||||
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
|
||||
Exponent: 65537 (0x10001)
|
||||
Signature
|
||||
Algorithm: sha256WithRSAEncryption
|
||||
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:
|
||||
9c:c5:7d:a7:33:cf:8c:75:c3:53:63:ee:d0:34:58:05:
|
||||
34:8b:d2:5e:16:ea:31:8a:07:00:00:29:30:72:4e:c6:
|
||||
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:
|
||||
CA = false
|
||||
keyUsage CRITICAL:
|
||||
Digital signature
|
||||
Key encipherment
|
||||
extKeyUsage:
|
||||
TLS Web Server Authentication`;
|
||||
|
||||
// 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_RSA_2048 = `-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIDJDCCAgwCAQAwcjELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBlp1cmljaDEPMA0G
|
||||
A1UEBwwGWnVyaWNoMRMwEQYDVQQKDApFeGFtcGxlIFJFMRYwFAYDVQQLDA1JVCBE
|
||||
ZXBhcnRtZW50MRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEB
|
||||
BQADggEPADCCAQoCggEBAKPogLmWPuK/IGdct2v/3MFKVaVeKp2Hl5at/zDFLCAe
|
||||
51bwh7BqNVJEci4ApwlXA1WVmQPBFBJlYwQZVjz5UAN2CmNHxud5nV03YmZ2/Iml
|
||||
RzpKcZMPqU+liJCC04L+XIbOdx+Vz52dF++Cc+FuSFq803yW+qefK8JsJNO9KuPx
|
||||
RLYKSAADa9MIJisru1PzcBAOcimOmNnFWuo+LKsd4lU30OExDdKHwtyt62Mj1c3o
|
||||
lO1JjvkjtWWjwHI+0EgTjvkeXlcUYZvvLlysdKERMRozvMTGqqoHWCgWl+Rq9Z6P
|
||||
TgNsRO4CKug1Zwmh8y6acZ7sYb/dar8HOeqJnc0pCv8CAwEAAaBtMGsGCSqGSIb3
|
||||
DQEJDjFeMFwwJwYDVR0RBCAwHoILZXhhbXBsZS5jb22CD3d3dy5leGFtcGxlLmNv
|
||||
bTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEF
|
||||
BQcDATANBgkqhkiG9w0BAQsFAAOCAQEAG0cjfRBY1pBzu+jf7yMQrK5mQrh72air
|
||||
VuXHmochmyUxyt0G7ovnNhKEr+X9snShJLi5qlyvnb2roiwlCmuwGIZxErN1svQL
|
||||
Z3kQNZgH+Vyu5IRL2DlPs5AAxVmzPpbnbXNhMHyAK/ziLcU031O1PoCpxwfvPsjW
|
||||
HWOCjbZUVaJnxdp8AHqImoGAiVhJwc37feFvb2UQlLedUypQkPg/poNWduaRDoj8
|
||||
m9cpVxuxGLtONBnohzohnFECytSXWEXPIj8L9SpYK97G02nJYYCAcb5BF11Alfux
|
||||
sNxtsr6zgPaLRrvOBT11WxJVKerbhfezAJ3naem1eM3VLxCGWwMwxg==
|
||||
-----END CERTIFICATE REQUEST-----`;
|
||||
|
||||
const OUT_EXAMPLE_COM_RSA_2048 = `Version: 1 (0x00)
|
||||
Subject
|
||||
C = CH
|
||||
ST = Zurich
|
||||
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
|
||||
Exponent: 65537 (0x10001)
|
||||
Signature
|
||||
Algorithm: sha256WithRSAEncryption
|
||||
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:
|
||||
24:b8:b9:aa:5c:af:9d:bd:ab:a2:2c:25:0a:6b:b0:18:
|
||||
86:71:12:b3:75:b2:f4:0b:67:79:10:35:98:07:f9:5c:
|
||||
ae:e4:84:4b:d8:39:4f:b3:90:00:c5:59:b3:3e:96:e7:
|
||||
6d:73:61:30:7c:80:2b:fc:e2:2d:c5:34:df:53:b5:3e:
|
||||
80:a9:c7:07:ef:3e:c8:d6:1d:63:82:8d:b6:54:55:a2:
|
||||
67:c5:da:7c:00:7a:88:9a:81:80:89:58:49:c1:cd:fb:
|
||||
7d:e1:6f:6f:65:10:94:b7:9d:53:2a:50:90:f8:3f:a6:
|
||||
83:56:76:e6:91:0e:88:fc:9b:d7:29:57:1b:b1:18:bb:
|
||||
4e:34:19:e8:87:3a:21:9c:51:02:ca:d4:97:58:45:cf:
|
||||
22:3f:0b:f5:2a:58:2b:de:c6:d3:69:c9:61:80:80:71:
|
||||
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:
|
||||
CA = false
|
||||
keyUsage CRITICAL:
|
||||
Digital signature
|
||||
Key encipherment
|
||||
extKeyUsage:
|
||||
TLS Web Server Authentication`;
|
||||
|
||||
// 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 \
|
||||
// -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 = `-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIBmzCCAUECAQAwcjELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBlp1cmljaDEPMA0G
|
||||
A1UEBwwGWnVyaWNoMRMwEQYDVQQKDApFeGFtcGxlIFJFMRYwFAYDVQQLDA1JVCBE
|
||||
ZXBhcnRtZW50MRQwEgYDVQQDDAtleGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqG
|
||||
SM49AwEHA0IABAmpYXNh+L9E0Q3sLhrO+MF1XgKCfqJntrOyIkrGwoiQftHbJWTA
|
||||
6duxQhU/3d9B+SN/ibeKY+xeiNBrs2eTYZ6gbTBrBgkqhkiG9w0BCQ4xXjBcMCcG
|
||||
A1UdEQQgMB6CC2V4YW1wbGUuY29tgg93d3cuZXhhbXBsZS5jb20wDAYDVR0TAQH/
|
||||
BAIwADAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwCgYIKoZI
|
||||
zj0EAwIDSAAwRQIgQkum/qaLzE3QZ3WD00uLpalUn113FObd7rM5Mr3HQwQCIQCr
|
||||
7OjzYI9v7qIJp/E9N16XfJN87G2ZVIZ4FuPXVjokCQ==
|
||||
-----END CERTIFICATE REQUEST-----`;
|
||||
|
||||
const OUT_EXAMPLE_COM_EC = `Parse CSR - Cannot read public key. OID is not RSA.`;
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Parse CSR: Example Certificate Signing Request (CSR) with RSA 1024",
|
||||
input: IN_EXAMPLE_COM_RSA_1024,
|
||||
expectedOutput: OUT_EXAMPLE_COM_RSA_1024,
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse CSR",
|
||||
"args": ["PEM", true]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Parse CSR: Example Certificate Signing Request (CSR) with RSA 2048",
|
||||
input: IN_EXAMPLE_COM_RSA_2048,
|
||||
expectedOutput: OUT_EXAMPLE_COM_RSA_2048,
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse CSR",
|
||||
"args": ["PEM", true]
|
||||
}
|
||||
]
|
||||
},
|
||||
// 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,
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Parse CSR",
|
||||
"args": ["PEM", true]
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
Loading…
Reference in New Issue
Block a user