summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVirendra Thakur <virendra.thakur@kpit.com>2022-02-06 19:26:14 +0530
committerArmin Kuster <akuster808@gmail.com>2022-02-06 11:01:44 -0800
commitec978232732edbdd875ac367b5a9c04b881f2e19 (patch)
treef342b9db77cf714013467fc3866d58d1d55a574d
parent872e60a774b763b4fbebc2b902ea3570bf81939d (diff)
downloadmeta-openembedded-ec978232732edbdd875ac367b5a9c04b881f2e19.tar.gz
nodejs: Fix for CVE-2021-44532
Add patch to fix CVE-2021-44532 Signed-off-by: Virendra Thakur <virendra.thakur@kpit.com> Signed-off-by: virendra thakur <thakur.virendra1810@gmail.com> Signed-off-by: Armin Kuster <akuster808@gmail.com>
-rw-r--r--meta-oe/recipes-devtools/nodejs/nodejs/CVE-2021-44532.patch3090
-rw-r--r--meta-oe/recipes-devtools/nodejs/nodejs_12.21.0.bb1
2 files changed, 3091 insertions, 0 deletions
diff --git a/meta-oe/recipes-devtools/nodejs/nodejs/CVE-2021-44532.patch b/meta-oe/recipes-devtools/nodejs/nodejs/CVE-2021-44532.patch
new file mode 100644
index 0000000000..dff7fe23a2
--- /dev/null
+++ b/meta-oe/recipes-devtools/nodejs/nodejs/CVE-2021-44532.patch
@@ -0,0 +1,3090 @@
1From 19873abfb24dce75ffff042efe76dc5633052677 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= <tniessen@tnie.de>
3Date: Wed, 29 Dec 2021 19:30:57 -0500
4Subject: [PATCH] crypto,tls: implement safe x509 GeneralName format
5
6This change introduces JSON-compatible escaping rules for strings that
7include X.509 GeneralName components (see RFC 5280). This non-standard
8format avoids ambiguities and prevents injection attacks that could
9previously lead to X.509 certificates being accepted even though they
10were not valid for the target hostname.
11
12These changes affect the format of subject alternative names and the
13format of authority information access. The checkServerIdentity function
14has been modified to safely handle the new format, eliminating the
15possibility of injecting subject alternative names into the verification
16logic.
17
18Because each subject alternative name is only encoded as a JSON string
19literal if necessary for security purposes, this change will only be
20visible in rare cases.
21
22This addresses CVE-2021-44532.
23
24Co-authored-by: Akshay K <iit.akshay@gmail.com>
25CVE-ID: CVE-2021-44532
26Backport-PR-URL: https://github.com/nodejs-private/node-private/pull/306
27PR-URL: https://github.com/nodejs-private/node-private/pull/300
28Reviewed-By: Michael Dawson <midawson@redhat.com>
29Reviewed-By: Rich Trott <rtrott@gmail.com>
30
31Upstream-Status: Backport [https://github.com/nodejs/node/commit/19873abfb24dce75ffff042efe76dc5633052677]
32
33CVE: CVE-2021-44532
34
35Signed-off-by: Virendra Thakur <virendra.thakur@kpit.com>
36
37---
38 doc/api/errors.md | 8 +
39 lib/_tls_common.js | 9 +
40 lib/internal/errors.js | 2 +
41 lib/tls.js | 52 +-
42 src/node_crypto_common.cc | 340 ++++++++++--
43 test/common/index.js | 7 +
44 test/fixtures/keys/Makefile | 14 +
45 .../incorrect_san_correct_subject-cert.pem | 11 +
46 .../incorrect_san_correct_subject-key.pem | 5 +
47 test/fixtures/x509-escaping/.gitignore | 2 +
48 test/fixtures/x509-escaping/alt-0-cert.pem | 29 +
49 test/fixtures/x509-escaping/alt-1-cert.pem | 28 +
50 test/fixtures/x509-escaping/alt-10-cert.pem | 28 +
51 test/fixtures/x509-escaping/alt-11-cert.pem | 28 +
52 test/fixtures/x509-escaping/alt-12-cert.pem | 28 +
53 test/fixtures/x509-escaping/alt-13-cert.pem | 28 +
54 test/fixtures/x509-escaping/alt-14-cert.pem | 29 +
55 test/fixtures/x509-escaping/alt-15-cert.pem | 29 +
56 test/fixtures/x509-escaping/alt-16-cert.pem | 29 +
57 test/fixtures/x509-escaping/alt-17-cert.pem | 29 +
58 test/fixtures/x509-escaping/alt-18-cert.pem | 29 +
59 test/fixtures/x509-escaping/alt-19-cert.pem | 29 +
60 test/fixtures/x509-escaping/alt-2-cert.pem | 28 +
61 test/fixtures/x509-escaping/alt-20-cert.pem | 29 +
62 test/fixtures/x509-escaping/alt-21-cert.pem | 29 +
63 test/fixtures/x509-escaping/alt-22-cert.pem | 28 +
64 test/fixtures/x509-escaping/alt-23-cert.pem | 28 +
65 test/fixtures/x509-escaping/alt-24-cert.pem | 28 +
66 test/fixtures/x509-escaping/alt-25-cert.pem | 29 +
67 test/fixtures/x509-escaping/alt-26-cert.pem | 29 +
68 test/fixtures/x509-escaping/alt-27-cert.pem | 28 +
69 test/fixtures/x509-escaping/alt-28-cert.pem | 28 +
70 test/fixtures/x509-escaping/alt-29-cert.pem | 28 +
71 test/fixtures/x509-escaping/alt-3-cert.pem | 28 +
72 test/fixtures/x509-escaping/alt-30-cert.pem | 28 +
73 test/fixtures/x509-escaping/alt-4-cert.pem | 28 +
74 test/fixtures/x509-escaping/alt-5-cert.pem | 29 +
75 test/fixtures/x509-escaping/alt-6-cert.pem | 28 +
76 test/fixtures/x509-escaping/alt-7-cert.pem | 28 +
77 test/fixtures/x509-escaping/alt-8-cert.pem | 28 +
78 test/fixtures/x509-escaping/alt-9-cert.pem | 28 +
79 test/fixtures/x509-escaping/create-certs.js | 502 ++++++++++++++++++
80 .../x509-escaping/google/intermediate.pem | 11 +
81 test/fixtures/x509-escaping/google/key.pem | 5 +
82 test/fixtures/x509-escaping/google/leaf0.pem | 10 +
83 test/fixtures/x509-escaping/google/leaf1.pem | 10 +
84 test/fixtures/x509-escaping/google/leaf2.pem | 10 +
85 test/fixtures/x509-escaping/google/leaf3.pem | 10 +
86 test/fixtures/x509-escaping/google/leaf4.pem | 10 +
87 test/fixtures/x509-escaping/google/root.pem | 9 +
88 test/fixtures/x509-escaping/info-0-cert.pem | 30 ++
89 test/fixtures/x509-escaping/info-1-cert.pem | 31 ++
90 test/fixtures/x509-escaping/info-2-cert.pem | 29 +
91 test/fixtures/x509-escaping/info-3-cert.pem | 30 ++
92 test/fixtures/x509-escaping/info-4-cert.pem | 29 +
93 test/fixtures/x509-escaping/package.json | 12 +
94 test/fixtures/x509-escaping/server-key.pem | 52 ++
95 test/parallel/test-tls-0-dns-altname.js | 2 +-
96 test/parallel/test-x509-escaping.js | 349 ++++++++++++
97 59 files changed, 2429 insertions(+), 42 deletions(-)
98 create mode 100644 test/fixtures/keys/incorrect_san_correct_subject-cert.pem
99 create mode 100644 test/fixtures/keys/incorrect_san_correct_subject-key.pem
100 create mode 100644 test/fixtures/x509-escaping/.gitignore
101 create mode 100644 test/fixtures/x509-escaping/alt-0-cert.pem
102 create mode 100644 test/fixtures/x509-escaping/alt-1-cert.pem
103 create mode 100644 test/fixtures/x509-escaping/alt-10-cert.pem
104 create mode 100644 test/fixtures/x509-escaping/alt-11-cert.pem
105 create mode 100644 test/fixtures/x509-escaping/alt-12-cert.pem
106 create mode 100644 test/fixtures/x509-escaping/alt-13-cert.pem
107 create mode 100644 test/fixtures/x509-escaping/alt-14-cert.pem
108 create mode 100644 test/fixtures/x509-escaping/alt-15-cert.pem
109 create mode 100644 test/fixtures/x509-escaping/alt-16-cert.pem
110 create mode 100644 test/fixtures/x509-escaping/alt-17-cert.pem
111 create mode 100644 test/fixtures/x509-escaping/alt-18-cert.pem
112 create mode 100644 test/fixtures/x509-escaping/alt-19-cert.pem
113 create mode 100644 test/fixtures/x509-escaping/alt-2-cert.pem
114 create mode 100644 test/fixtures/x509-escaping/alt-20-cert.pem
115 create mode 100644 test/fixtures/x509-escaping/alt-21-cert.pem
116 create mode 100644 test/fixtures/x509-escaping/alt-22-cert.pem
117 create mode 100644 test/fixtures/x509-escaping/alt-23-cert.pem
118 create mode 100644 test/fixtures/x509-escaping/alt-24-cert.pem
119 create mode 100644 test/fixtures/x509-escaping/alt-25-cert.pem
120 create mode 100644 test/fixtures/x509-escaping/alt-26-cert.pem
121 create mode 100644 test/fixtures/x509-escaping/alt-27-cert.pem
122 create mode 100644 test/fixtures/x509-escaping/alt-28-cert.pem
123 create mode 100644 test/fixtures/x509-escaping/alt-29-cert.pem
124 create mode 100644 test/fixtures/x509-escaping/alt-3-cert.pem
125 create mode 100644 test/fixtures/x509-escaping/alt-30-cert.pem
126 create mode 100644 test/fixtures/x509-escaping/alt-4-cert.pem
127 create mode 100644 test/fixtures/x509-escaping/alt-5-cert.pem
128 create mode 100644 test/fixtures/x509-escaping/alt-6-cert.pem
129 create mode 100644 test/fixtures/x509-escaping/alt-7-cert.pem
130 create mode 100644 test/fixtures/x509-escaping/alt-8-cert.pem
131 create mode 100644 test/fixtures/x509-escaping/alt-9-cert.pem
132 create mode 100644 test/fixtures/x509-escaping/create-certs.js
133 create mode 100644 test/fixtures/x509-escaping/google/intermediate.pem
134 create mode 100644 test/fixtures/x509-escaping/google/key.pem
135 create mode 100644 test/fixtures/x509-escaping/google/leaf0.pem
136 create mode 100644 test/fixtures/x509-escaping/google/leaf1.pem
137 create mode 100644 test/fixtures/x509-escaping/google/leaf2.pem
138 create mode 100644 test/fixtures/x509-escaping/google/leaf3.pem
139 create mode 100644 test/fixtures/x509-escaping/google/leaf4.pem
140 create mode 100644 test/fixtures/x509-escaping/google/root.pem
141 create mode 100644 test/fixtures/x509-escaping/info-0-cert.pem
142 create mode 100644 test/fixtures/x509-escaping/info-1-cert.pem
143 create mode 100644 test/fixtures/x509-escaping/info-2-cert.pem
144 create mode 100644 test/fixtures/x509-escaping/info-3-cert.pem
145 create mode 100644 test/fixtures/x509-escaping/info-4-cert.pem
146 create mode 100644 test/fixtures/x509-escaping/package.json
147 create mode 100644 test/fixtures/x509-escaping/server-key.pem
148 create mode 100644 test/parallel/test-x509-escaping.js
149
150diff --git a/doc/api/errors.md b/doc/api/errors.md
151index d5d8e1efa7..9d176d9048 100644
152--- a/doc/api/errors.md
153+++ b/doc/api/errors.md
154@@ -1869,6 +1869,14 @@ An unspecified or non-specific system error has occurred within the Node.js
155 process. The error object will have an `err.info` object property with
156 additional details.
157
158+<a id="ERR_TLS_CERT_ALTNAME_FORMAT"></a>
159+### `ERR_TLS_CERT_ALTNAME_FORMAT`
160+
161+This error is thrown by `checkServerIdentity` if a user-supplied
162+`subjectaltname` property violates encoding rules. Certificate objects produced
163+by Node.js itself always comply with encoding rules and will never cause
164+this error.
165+
166 <a id="ERR_TLS_CERT_ALTNAME_INVALID"></a>
167 ### `ERR_TLS_CERT_ALTNAME_INVALID`
168
169diff --git a/lib/_tls_common.js b/lib/_tls_common.js
170index b7a3b70a24..a2a74813f1 100644
171--- a/lib/_tls_common.js
172+++ b/lib/_tls_common.js
173@@ -23,6 +23,7 @@
174
175 const {
176 ArrayIsArray,
177+ JSONParse,
178 ObjectCreate,
179 } = primordials;
180
181@@ -323,6 +324,14 @@ exports.translatePeerCertificate = function translatePeerCertificate(c) {
182
183 // XXX: More key validation?
184 info.replace(/([^\n:]*):([^\n]*)(?:\n|$)/g, (all, key, val) => {
185+ if (val.charCodeAt(0) === 0x22) {
186+ // The translatePeerCertificate function is only
187+ // used on internally created legacy certificate
188+ // objects, and any value that contains a quote
189+ // will always be a valid JSON string literal,
190+ // so this should never throw.
191+ val = JSONParse(val);
192+ }
193 if (key in c.infoAccess)
194 c.infoAccess[key].push(val);
195 else
196diff --git a/lib/internal/errors.js b/lib/internal/errors.js
197index 2cf7df436b..cd7153ad1a 100644
198--- a/lib/internal/errors.js
199+++ b/lib/internal/errors.js
200@@ -1345,6 +1345,8 @@ E('ERR_STREAM_WRAP', 'Stream has StringDecoder set or is in objectMode', Error);
201 E('ERR_STREAM_WRITE_AFTER_END', 'write after end', Error);
202 E('ERR_SYNTHETIC', 'JavaScript Callstack', Error);
203 E('ERR_SYSTEM_ERROR', 'A system error occurred', SystemError);
204+E('ERR_TLS_CERT_ALTNAME_FORMAT', 'Invalid subject alternative name string',
205+ SyntaxError);
206 E('ERR_TLS_CERT_ALTNAME_INVALID', function(reason, host, cert) {
207 this.reason = reason;
208 this.host = host;
209diff --git a/lib/tls.js b/lib/tls.js
210index 2ccbe409c9..cefb47d10f 100644
211--- a/lib/tls.js
212+++ b/lib/tls.js
213@@ -24,11 +24,19 @@
214 const {
215 Array,
216 ArrayIsArray,
217+ ArrayPrototypePush,
218+ JSONParse,
219 ObjectDefineProperty,
220 ObjectFreeze,
221+ RegExpPrototypeExec,
222+ StringPrototypeIncludes,
223+ StringPrototypeIndexOf,
224+ StringPrototypeSplit,
225+ StringPrototypeSubstring,
226 } = primordials;
227
228 const {
229+ ERR_TLS_CERT_ALTNAME_FORMAT,
230 ERR_TLS_CERT_ALTNAME_INVALID,
231 ERR_OUT_OF_RANGE
232 } = require('internal/errors').codes;
233@@ -207,6 +215,45 @@ function check(hostParts, pattern, wildcards) {
234 return true;
235 }
236
237+// This pattern is used to determine the length of escaped sequences within
238+// the subject alt names string. It allows any valid JSON string literal.
239+// This MUST match the JSON specification (ECMA-404 / RFC8259) exactly.
240+const jsonStringPattern =
241+ // eslint-disable-next-line no-control-regex
242+ /^"(?:[^"\\\u0000-\u001f]|\\(?:["\\/bfnrt]|u[0-9a-fA-F]{4}))*"/;
243+
244+function splitEscapedAltNames(altNames) {
245+ const result = [];
246+ let currentToken = '';
247+ let offset = 0;
248+ while (offset !== altNames.length) {
249+ const nextSep = StringPrototypeIndexOf(altNames, ', ', offset);
250+ const nextQuote = StringPrototypeIndexOf(altNames, '"', offset);
251+ if (nextQuote !== -1 && (nextSep === -1 || nextQuote < nextSep)) {
252+ // There is a quote character and there is no separator before the quote.
253+ currentToken += StringPrototypeSubstring(altNames, offset, nextQuote);
254+ const match = RegExpPrototypeExec(
255+ jsonStringPattern, StringPrototypeSubstring(altNames, nextQuote));
256+ if (!match) {
257+ throw new ERR_TLS_CERT_ALTNAME_FORMAT();
258+ }
259+ currentToken += JSONParse(match[0]);
260+ offset = nextQuote + match[0].length;
261+ } else if (nextSep !== -1) {
262+ // There is a separator and no quote before it.
263+ currentToken += StringPrototypeSubstring(altNames, offset, nextSep);
264+ ArrayPrototypePush(result, currentToken);
265+ currentToken = '';
266+ offset = nextSep + 2;
267+ } else {
268+ currentToken += StringPrototypeSubstring(altNames, offset);
269+ offset = altNames.length;
270+ }
271+ }
272+ ArrayPrototypePush(result, currentToken);
273+ return result;
274+}
275+
276 let urlWarningEmitted = false;
277 exports.checkServerIdentity = function checkServerIdentity(hostname, cert) {
278 const subject = cert.subject;
279@@ -218,7 +265,10 @@ exports.checkServerIdentity = function checkServerIdentity(hostname, cert) {
280 hostname = '' + hostname;
281
282 if (altNames) {
283- for (const name of altNames.split(', ')) {
284+ const splitAltNames = StringPrototypeIncludes(altNames, '"') ?
285+ splitEscapedAltNames(altNames) :
286+ StringPrototypeSplit(altNames, ', ');
287+ for (const name of splitAltNames) {
288 if (name.startsWith('DNS:')) {
289 dnsNames.push(name.slice(4));
290 } else if (name.startsWith('URI:')) {
291diff --git a/src/node_crypto_common.cc b/src/node_crypto_common.cc
292index 74bc0a9756..53fbc576ef 100644
293--- a/src/node_crypto_common.cc
294+++ b/src/node_crypto_common.cc
295@@ -480,39 +480,320 @@ void AddFingerprintDigest(
296 }
297 }
298
299-bool SafeX509ExtPrint(const BIOPointer& out, X509_EXTENSION* ext) {
300- const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
301+static inline bool IsSafeAltName(const char* name, size_t length, bool utf8) {
302+ for (size_t i = 0; i < length; i++) {
303+ char c = name[i];
304+ switch (c) {
305+ case '"':
306+ case '\\':
307+ // These mess with encoding rules.
308+ // Fall through.
309+ case ',':
310+ // Commas make it impossible to split the list of subject alternative
311+ // names unambiguously, which is why we have to escape.
312+ // Fall through.
313+ case '\'':
314+ // Single quotes are unlikely to appear in any legitimate values, but they
315+ // could be used to make a value look like it was escaped (i.e., enclosed
316+ // in single/double quotes).
317+ return false;
318+ default:
319+ if (utf8) {
320+ // In UTF8 strings, we require escaping for any ASCII control character,
321+ // but NOT for non-ASCII characters. Note that all bytes of any code
322+ // point that consists of more than a single byte have their MSB set.
323+ if (static_cast<unsigned char>(c) < ' ' || c == '\x7f') {
324+ return false;
325+ }
326+ } else {
327+ // Check if the char is a control character or non-ASCII character. Note
328+ // that char may or may not be a signed type. Regardless, non-ASCII
329+ // values will always be outside of this range.
330+ if (c < ' ' || c > '~') {
331+ return false;
332+ }
333+ }
334+ }
335+ }
336+ return true;
337+}
338
339- if (method != X509V3_EXT_get_nid(NID_subject_alt_name))
340- return false;
341+static inline void PrintAltName(const BIOPointer& out, const char* name,
342+ size_t length, bool utf8,
343+ const char* safe_prefix) {
344+ if (IsSafeAltName(name, length, utf8)) {
345+ // For backward-compatibility, append "safe" names without any
346+ // modifications.
347+ if (safe_prefix != nullptr) {
348+ BIO_printf(out.get(), "%s:", safe_prefix);
349+ }
350+ BIO_write(out.get(), name, length);
351+ } else {
352+ // If a name is not "safe", we cannot embed it without special
353+ // encoding. This does not usually happen, but we don't want to hide
354+ // it from the user either. We use JSON compatible escaping here.
355+ BIO_write(out.get(), "\"", 1);
356+ if (safe_prefix != nullptr) {
357+ BIO_printf(out.get(), "%s:", safe_prefix);
358+ }
359+ for (size_t j = 0; j < length; j++) {
360+ char c = static_cast<char>(name[j]);
361+ if (c == '\\') {
362+ BIO_write(out.get(), "\\\\", 2);
363+ } else if (c == '"') {
364+ BIO_write(out.get(), "\\\"", 2);
365+ } else if ((c >= ' ' && c != ',' && c <= '~') || (utf8 && (c & 0x80))) {
366+ // Note that the above condition explicitly excludes commas, which means
367+ // that those are encoded as Unicode escape sequences in the "else"
368+ // block. That is not strictly necessary, and Node.js itself would parse
369+ // it correctly either way. We only do this to account for third-party
370+ // code that might be splitting the string at commas (as Node.js itself
371+ // used to do).
372+ BIO_write(out.get(), &c, 1);
373+ } else {
374+ // Control character or non-ASCII character. We treat everything as
375+ // Latin-1, which corresponds to the first 255 Unicode code points.
376+ const char hex[] = "0123456789abcdef";
377+ char u[] = { '\\', 'u', '0', '0', hex[(c & 0xf0) >> 4], hex[c & 0x0f] };
378+ BIO_write(out.get(), u, sizeof(u));
379+ }
380+ }
381+ BIO_write(out.get(), "\"", 1);
382+ }
383+}
384+
385+static inline void PrintLatin1AltName(const BIOPointer& out,
386+ const ASN1_IA5STRING* name,
387+ const char* safe_prefix = nullptr) {
388+ PrintAltName(out, reinterpret_cast<const char*>(name->data), name->length,
389+ false, safe_prefix);
390+}
391+
392+static inline void PrintUtf8AltName(const BIOPointer& out,
393+ const ASN1_UTF8STRING* name,
394+ const char* safe_prefix = nullptr) {
395+ PrintAltName(out, reinterpret_cast<const char*>(name->data), name->length,
396+ true, safe_prefix);
397+}
398+
399+// This function currently emulates the behavior of i2v_GENERAL_NAME in a safer
400+// and less ambiguous way.
401+// TODO(tniessen): gradually improve the format in the next major version(s)
402+static bool PrintGeneralName(const BIOPointer& out, const GENERAL_NAME* gen) {
403+ if (gen->type == GEN_DNS) {
404+ ASN1_IA5STRING* name = gen->d.dNSName;
405+ BIO_write(out.get(), "DNS:", 4);
406+ // Note that the preferred name syntax (see RFCs 5280 and 1034) with
407+ // wildcards is a subset of what we consider "safe", so spec-compliant DNS
408+ // names will never need to be escaped.
409+ PrintLatin1AltName(out, name);
410+ } else if (gen->type == GEN_EMAIL) {
411+ ASN1_IA5STRING* name = gen->d.rfc822Name;
412+ BIO_write(out.get(), "email:", 6);
413+ PrintLatin1AltName(out, name);
414+ } else if (gen->type == GEN_URI) {
415+ ASN1_IA5STRING* name = gen->d.uniformResourceIdentifier;
416+ BIO_write(out.get(), "URI:", 4);
417+ // The set of "safe" names was designed to include just about any URI,
418+ // with a few exceptions, most notably URIs that contains commas (see
419+ // RFC 2396). In other words, most legitimate URIs will not require
420+ // escaping.
421+ PrintLatin1AltName(out, name);
422+ } else if (gen->type == GEN_DIRNAME) {
423+ // For backward compatibility, use X509_NAME_oneline to print the
424+ // X509_NAME object. The format is non standard and should be avoided
425+ // elsewhere, but conveniently, the function produces ASCII and the output
426+ // is unlikely to contains commas or other characters that would require
427+ // escaping. With that in mind, note that it SHOULD NOT produce ASCII
428+ // output since an RFC5280 AttributeValue may be a UTF8String.
429+ // TODO(tniessen): switch to RFC2253 rules in a major release
430+ BIO_printf(out.get(), "DirName:");
431+ char oline[256];
432+ if (X509_NAME_oneline(gen->d.dirn, oline, sizeof(oline)) != nullptr) {
433+ PrintAltName(out, oline, strlen(oline), false, nullptr);
434+ } else {
435+ return false;
436+ }
437+ } else if (gen->type == GEN_IPADD) {
438+ BIO_printf(out.get(), "IP Address:");
439+ const ASN1_OCTET_STRING* ip = gen->d.ip;
440+ const unsigned char* b = ip->data;
441+ if (ip->length == 4) {
442+ BIO_printf(out.get(), "%d.%d.%d.%d", b[0], b[1], b[2], b[3]);
443+ } else if (ip->length == 16) {
444+ for (unsigned int j = 0; j < 8; j++) {
445+ uint16_t pair = (b[2 * j] << 8) | b[2 * j + 1];
446+ BIO_printf(out.get(), (j == 0) ? "%X" : ":%X", pair);
447+ }
448+ } else {
449+#if OPENSSL_VERSION_MAJOR >= 3
450+ BIO_printf(out.get(), "<invalid length=%d>", ip->length);
451+#else
452+ BIO_printf(out.get(), "<invalid>");
453+#endif
454+ }
455+ } else if (gen->type == GEN_RID) {
456+ // TODO(tniessen): unlike OpenSSL's default implementation, never print the
457+ // OID as text and instead always print its numeric representation, which is
458+ // backward compatible in practice and more future proof (see OBJ_obj2txt).
459+ char oline[256];
460+ i2t_ASN1_OBJECT(oline, sizeof(oline), gen->d.rid);
461+ BIO_printf(out.get(), "Registered ID:%s", oline);
462+ } else if (gen->type == GEN_OTHERNAME) {
463+ // TODO(tniessen): the format that is used here is based on OpenSSL's
464+ // implementation of i2v_GENERAL_NAME (as of OpenSSL 3.0.1), mostly for
465+ // backward compatibility. It is somewhat awkward, especially when passed to
466+ // translatePeerCertificate, and should be changed in the future, probably
467+ // to the format used by GENERAL_NAME_print (in a major release).
468+ bool unicode = true;
469+ const char* prefix = nullptr;
470+ // OpenSSL 1.1.1 does not support othername in i2v_GENERAL_NAME and may not
471+ // define these NIDs.
472+#if OPENSSL_VERSION_MAJOR >= 3
473+ int nid = OBJ_obj2nid(gen->d.otherName->type_id);
474+ switch (nid) {
475+ case NID_id_on_SmtpUTF8Mailbox:
476+ prefix = " SmtpUTF8Mailbox:";
477+ break;
478+ case NID_XmppAddr:
479+ prefix = " XmppAddr:";
480+ break;
481+ case NID_SRVName:
482+ prefix = " SRVName:";
483+ unicode = false;
484+ break;
485+ case NID_ms_upn:
486+ prefix = " UPN:";
487+ break;
488+ case NID_NAIRealm:
489+ prefix = " NAIRealm:";
490+ break;
491+ }
492+#endif // OPENSSL_VERSION_MAJOR >= 3
493+ int val_type = gen->d.otherName->value->type;
494+ if (prefix == nullptr ||
495+ (unicode && val_type != V_ASN1_UTF8STRING) ||
496+ (!unicode && val_type != V_ASN1_IA5STRING)) {
497+ BIO_printf(out.get(), "othername:<unsupported>");
498+ } else {
499+ BIO_printf(out.get(), "othername:");
500+ if (unicode) {
501+ PrintUtf8AltName(out, gen->d.otherName->value->value.utf8string,
502+ prefix);
503+ } else {
504+ PrintLatin1AltName(out, gen->d.otherName->value->value.ia5string,
505+ prefix);
506+ }
507+ }
508+ } else if (gen->type == GEN_X400) {
509+ // TODO(tniessen): this is what OpenSSL does, implement properly instead
510+ BIO_printf(out.get(), "X400Name:<unsupported>");
511+ } else if (gen->type == GEN_EDIPARTY) {
512+ // TODO(tniessen): this is what OpenSSL does, implement properly instead
513+ BIO_printf(out.get(), "EdiPartyName:<unsupported>");
514+ } else {
515+ // This is safe because X509V3_EXT_d2i would have returned nullptr in this
516+ // case already.
517+ UNREACHABLE();
518+ }
519+
520+ return true;
521+}
522+
523+bool SafeX509SubjectAltNamePrint(const BIOPointer& out, X509_EXTENSION* ext) {
524+ const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
525+ CHECK(method == X509V3_EXT_get_nid(NID_subject_alt_name));
526
527 GENERAL_NAMES* names = static_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(ext));
528 if (names == nullptr)
529 return false;
530
531+ bool ok = true;
532+
533 for (int i = 0; i < sk_GENERAL_NAME_num(names); i++) {
534 GENERAL_NAME* gen = sk_GENERAL_NAME_value(names, i);
535
536 if (i != 0)
537 BIO_write(out.get(), ", ", 2);
538
539- if (gen->type == GEN_DNS) {
540- ASN1_IA5STRING* name = gen->d.dNSName;
541-
542- BIO_write(out.get(), "DNS:", 4);
543- BIO_write(out.get(), name->data, name->length);
544- } else {
545- STACK_OF(CONF_VALUE)* nval = i2v_GENERAL_NAME(
546- const_cast<X509V3_EXT_METHOD*>(method), gen, nullptr);
547- if (nval == nullptr)
548- return false;
549- X509V3_EXT_val_prn(out.get(), nval, 0, 0);
550- sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
551+ if (!(ok = PrintGeneralName(out, gen))) {
552+ break;
553 }
554 }
555 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
556
557- return true;
558+ return ok;
559+}
560+
561+bool SafeX509InfoAccessPrint(const BIOPointer& out, X509_EXTENSION* ext) {
562+ const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
563+ CHECK(method == X509V3_EXT_get_nid(NID_info_access));
564+
565+ AUTHORITY_INFO_ACCESS* descs =
566+ static_cast<AUTHORITY_INFO_ACCESS*>(X509V3_EXT_d2i(ext));
567+ if (descs == nullptr)
568+ return false;
569+
570+ bool ok = true;
571+
572+ for (int i = 0; i < sk_ACCESS_DESCRIPTION_num(descs); i++) {
573+ ACCESS_DESCRIPTION* desc = sk_ACCESS_DESCRIPTION_value(descs, i);
574+
575+ if (i != 0)
576+ BIO_write(out.get(), "\n", 1);
577+
578+ char objtmp[80];
579+ i2t_ASN1_OBJECT(objtmp, sizeof(objtmp), desc->method);
580+ BIO_printf(out.get(), "%s - ", objtmp);
581+ if (!(ok = PrintGeneralName(out, desc->location))) {
582+ break;
583+ }
584+ }
585+ sk_ACCESS_DESCRIPTION_pop_free(descs, ACCESS_DESCRIPTION_free);
586+
587+#if OPENSSL_VERSION_MAJOR < 3
588+ BIO_write(out.get(), "\n", 1);
589+#endif
590+
591+ return ok;
592+}
593+
594+v8::MaybeLocal<v8::Value> GetSubjectAltNameString(
595+ Environment* env,
596+ const BIOPointer& bio,
597+ X509* cert) {
598+ int index = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
599+ if (index < 0)
600+ return Undefined(env->isolate());
601+
602+ X509_EXTENSION* ext = X509_get_ext(cert, index);
603+ CHECK_NOT_NULL(ext);
604+
605+ if (!SafeX509SubjectAltNamePrint(bio, ext)) {
606+ USE(BIO_reset(bio.get()));
607+ return v8::Null(env->isolate());
608+ }
609+
610+ return ToV8Value(env, bio);
611+}
612+
613+v8::MaybeLocal<v8::Value> GetInfoAccessString(
614+ Environment* env,
615+ const BIOPointer& bio,
616+ X509* cert) {
617+ int index = X509_get_ext_by_NID(cert, NID_info_access, -1);
618+ if (index < 0)
619+ return Undefined(env->isolate());
620+
621+ X509_EXTENSION* ext = X509_get_ext(cert, index);
622+ CHECK_NOT_NULL(ext);
623+
624+ if (!SafeX509InfoAccessPrint(bio, ext)) {
625+ USE(BIO_reset(bio.get()));
626+ return v8::Null(env->isolate());
627+ }
628+
629+ return ToV8Value(env, bio);
630 }
631
632 MaybeLocal<Value> GetFingerprintDigest(
633@@ -628,27 +909,6 @@ MaybeLocal<Value> GetModulusString(
634 return ToV8Value(env, bio);
635 }
636
637-template <int nid>
638-MaybeLocal<Value> GetInfoString(
639- Environment* env,
640- const BIOPointer& bio,
641- X509* cert) {
642- int index = X509_get_ext_by_NID(cert, nid, -1);
643- if (index < 0)
644- return Undefined(env->isolate());
645-
646- X509_EXTENSION* ext = X509_get_ext(cert, index);
647- CHECK_NOT_NULL(ext);
648-
649- if (!SafeX509ExtPrint(bio, ext) &&
650- X509V3_EXT_print(bio.get(), ext, 0, 0) != 1) {
651- USE(BIO_reset(bio.get()));
652- return Null(env->isolate());
653- }
654-
655- return ToV8Value(env, bio);
656-}
657-
658 MaybeLocal<Value> GetIssuerString(
659 Environment* env,
660 const BIOPointer& bio,
661@@ -917,11 +1177,11 @@ MaybeLocal<Object> X509ToObject(Environment* env, X509* cert) {
662 !Set<Value>(context,
663 info,
664 env->subjectaltname_string(),
665- GetInfoString<NID_subject_alt_name>(env, bio, cert)) ||
666+ GetSubjectAltNameString(env, bio, cert)) ||
667 !Set<Value>(context,
668 info,
669 env->infoaccess_string(),
670- GetInfoString<NID_info_access>(env, bio, cert))) {
671+ GetInfoAccessString(env, bio, cert))) {
672 return MaybeLocal<Object>();
673 }
674
675diff --git a/test/common/index.js b/test/common/index.js
676index 8cd9841527..98b586cafd 100644
677--- a/test/common/index.js
678+++ b/test/common/index.js
679@@ -51,6 +51,11 @@ const noop = () => {};
680 const hasCrypto = Boolean(process.versions.openssl) &&
681 !process.env.NODE_SKIP_CRYPTO;
682
683+const hasOpenSSL3 = hasCrypto &&
684+ require('crypto').constants.OPENSSL_VERSION_NUMBER >= 805306368;
685+
686+const hasQuic = hasCrypto && !!process.config.variables.openssl_quic;
687+
688 // Check for flags. Skip this for workers (both, the `cluster` module and
689 // `worker_threads`) and child processes.
690 // If the binary was built without-ssl then the crypto flags are
691@@ -714,6 +719,8 @@ const common = {
692 getTTYfd,
693 hasIntl,
694 hasCrypto,
695+ hasOpenSSL3,
696+ hasQuic,
697 hasMultiLocalhost,
698 invalidArgTypeHelper,
699 isAIX,
700diff --git a/test/fixtures/keys/Makefile b/test/fixtures/keys/Makefile
701index 824704c724..49cc29ad1c 100644
702--- a/test/fixtures/keys/Makefile
703+++ b/test/fixtures/keys/Makefile
704@@ -75,6 +75,8 @@ all: \
705 ed448_public.pem \
706 x448_private.pem \
707 x448_public.pem \
708+ incorrect_san_correct_subject-cert.pem \
709+ incorrect_san_correct_subject-key.pem \
710
711 #
712 # Create Certificate Authority: ca1
713@@ -733,6 +735,18 @@ x448_private.pem:
714 x448_public.pem: x448_private.pem
715 openssl pkey -in x448_private.pem -pubout -out x448_public.pem
716
717+incorrect_san_correct_subject-cert.pem: incorrect_san_correct_subject-key.pem
718+ openssl req -x509 \
719+ -key incorrect_san_correct_subject-key.pem \
720+ -out incorrect_san_correct_subject-cert.pem \
721+ -sha256 \
722+ -days 3650 \
723+ -subj "/CN=good.example.com" \
724+ -addext "subjectAltName = DNS:evil.example.com"
725+
726+incorrect_san_correct_subject-key.pem:
727+ openssl ecparam -name prime256v1 -genkey -noout -out incorrect_san_correct_subject-key.pem
728+
729 clean:
730 rm -f *.pfx *.pem *.srl ca2-database.txt ca2-serial fake-startcom-root-serial *.print *.old fake-startcom-root-issued-certs/*.pem
731 @> fake-startcom-root-database.txt
732diff --git a/test/fixtures/keys/incorrect_san_correct_subject-cert.pem b/test/fixtures/keys/incorrect_san_correct_subject-cert.pem
733new file mode 100644
734index 0000000000..787d9f1135
735--- /dev/null
736+++ b/test/fixtures/keys/incorrect_san_correct_subject-cert.pem
737@@ -0,0 +1,11 @@
738+-----BEGIN CERTIFICATE-----
739+MIIBqDCCAU6gAwIBAgIUE3Kx4WUjkwuKy/fBOM+UJkb9aSAwCgYIKoZIzj0EAwIw
740+GzEZMBcGA1UEAwwQZ29vZC5leGFtcGxlLmNvbTAeFw0yMTEyMTExNjUxNDVaFw0z
741+MTEyMDkxNjUxNDVaMBsxGTAXBgNVBAMMEGdvb2QuZXhhbXBsZS5jb20wWTATBgcq
742+hkjOPQIBBggqhkjOPQMBBwNCAASQ/CKa5uMZuLYssnNOm7DPdw3I5Doa0Qpyf3cS
743+7aGatfK3tuY8qG7nJ5OGtl1WOL/gN0vRRN0/KA/iRJyjafzzo3AwbjAdBgNVHQ4E
744+FgQUFkpgPzE1ePjK5UsPcR0gk5uLsTUwHwYDVR0jBBgwFoAUFkpgPzE1ePjK5UsP
745+cR0gk5uLsTUwDwYDVR0TAQH/BAUwAwEB/zAbBgNVHREEFDASghBldmlsLmV4YW1w
746+bGUuY29tMAoGCCqGSM49BAMCA0gAMEUCIQCMZAinQXkOEhfp+moxVnLbcUPAAqsl
747+1KCq3NRG91TGCgIgC4grmOhCRqJMF1RPNWobGogX/yNrYNjiGzNVyJzMR0s=
748+-----END CERTIFICATE-----
749diff --git a/test/fixtures/keys/incorrect_san_correct_subject-key.pem b/test/fixtures/keys/incorrect_san_correct_subject-key.pem
750new file mode 100644
751index 0000000000..f7f51253a8
752--- /dev/null
753+++ b/test/fixtures/keys/incorrect_san_correct_subject-key.pem
754@@ -0,0 +1,5 @@
755+-----BEGIN EC PRIVATE KEY-----
756+MHcCAQEEIOOVRgLS3H2T2fUhj4ASCFq60ySwO6yvSK6rvZHldAHuoAoGCCqGSM49
757+AwEHoUQDQgAEkPwimubjGbi2LLJzTpuwz3cNyOQ6GtEKcn93Eu2hmrXyt7bmPKhu
758+5yeThrZdVji/4DdL0UTdPygP4kSco2n88w==
759+-----END EC PRIVATE KEY-----
760diff --git a/test/fixtures/x509-escaping/.gitignore b/test/fixtures/x509-escaping/.gitignore
761new file mode 100644
762index 0000000000..504afef81f
763--- /dev/null
764+++ b/test/fixtures/x509-escaping/.gitignore
765@@ -0,0 +1,2 @@
766+node_modules/
767+package-lock.json
768diff --git a/test/fixtures/x509-escaping/alt-0-cert.pem b/test/fixtures/x509-escaping/alt-0-cert.pem
769new file mode 100644
770index 0000000000..30e6fa6c3f
771--- /dev/null
772+++ b/test/fixtures/x509-escaping/alt-0-cert.pem
773@@ -0,0 +1,29 @@
774+-----BEGIN CERTIFICATE-----
775+MIIE5jCCAs6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
776+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
777+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
778+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
779+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
780+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
781+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
782+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
783+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
784+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
785+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
786+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
787+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
788+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
789+NTAzMDEGA1UdEQQqMCiCJmdvb2QuZXhhbXBsZS5jb20sIEROUzpldmlsLmV4YW1w
790+bGUuY29tMA0GCSqGSIb3DQEBCwUAA4ICAQAcsy+PIduM8NRrdqcTqufiajsAajQz
791+eB5+5+lZLi9MliXqoS4HsdrDMDevMa2cC+wB+XZW9SJXjtqrwXAxTAHtEyhsCi25
792+XV0sJPWmZM+OQkGTtp7Ain12htr/t/DJ13YJpT03W6kYogA1kKJ5OMYMTcGT+7UB
793+zM4G2LUSrrSisxhfz9bF8Q9s1piG2gb5ACEQUiMLRrZXl8WLlaY59lloKyMa/9g6
794+i3TgLxhp7XNS/bh/f2tDx+7ZgdtHUlkNhl1MycIVQRGK3BaZBEd+sDxS52kwym5I
795+CWLXGLutU3OeaNgqyvZuMvy//2oER3PysizyjwNoFlUbIz3zMnXvBeEjeGtEHsCJ
796+EBtX+xBWwMhUKE2QcMLxQaZNJCZFVFw8fDeEgFjTdEBcLsZ1PngT3jgXSHEWA+YL
797+C3rQhFMjyjy2h8u1sjySFrTlbZPm8gC3q/+LaXxhf5i5xiZOOcVfeYiWFUa5gQal
798+FaWj2SlQFaN2nidPaQO62vRIYn0Y/qbtUQAPkq4VVeycgxiuZaVVWCdct8UCYb9F
799+b9QSMpK4r99MKy+s41RiJodDJy0XraOxy7hUDjyObL2fuuPUK6mQAFGwWtajv3qq
800+vrRMvBEXdOPVmbETyzIosUHvOXT+v8WoCbC14mqMZTWVywRg7bD/NTHJDRIBrqvi
801+O6Zqbod3EImVnQ==
802+-----END CERTIFICATE-----
803diff --git a/test/fixtures/x509-escaping/alt-1-cert.pem b/test/fixtures/x509-escaping/alt-1-cert.pem
804new file mode 100644
805index 0000000000..63883c2bbf
806--- /dev/null
807+++ b/test/fixtures/x509-escaping/alt-1-cert.pem
808@@ -0,0 +1,28 @@
809+-----BEGIN CERTIFICATE-----
810+MIIE0zCCArugAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
811+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
812+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
813+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
814+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
815+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
816+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
817+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
818+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
819+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
820+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
821+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
822+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
823+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
824+IjAgMB4GA1UdEQQXMBWGE2h0dHA6Ly9leGFtcGxlLmNvbS8wDQYJKoZIhvcNAQEL
825+BQADggIBACFwNHWQ5w3UBbyq17emn7Z0BT0Zm5iFr8Qeik75WzbyzXd5QIeFWewB
826+qmiuaoKGGZ674sGcuomnIwoZBCoqvzbBBqBHp+O3/6pq59THQxeE6vhjKAe8oaih
827+emdigRmkX+Qi8UwUh76B51wHtkp6zAZnLDn8M67qmP7bjNrrMQeE81wRWYz9ssfd
828+N63dzu2BdD3EGl4CepdszpfUYLkz6iiDwFkc1NaBcQbBDoGqn2ubNXTHAyGGeL5a
829+ulDCND0FQtg+jhHHE3zXBqh1nPg/cXXRUG2zjxzUnaU2eMs5b4yqoLN/2n7fb7mV
830+HRh0T6X1HZcYpf5BSsgmr3Ngd/9b3sYRvNXBkVmKAu8dH7zguksczsvbL9r/u2YX
831+hgGjNT3xSphJbZTzqsACcoDo67EFkJ5p25f0N1i/rxk7O6uLMtrUqnzOXs6NXgEQ
832+8lyfVEgLFrXzdKXuk2l/6bwym80Eqdpjv5yCckCl24cFVpc15MRP3MPwIHrtoOLw
833+bdNZA5NUAnppLmG6zTdPPgBWEmf5+4ei9WjmpG1hq72/nJ1qM2dLIgV5nLggr1UH
834+i+vih+ujceBLVumAu/naP440xO5HRvpPfDWI+eU/wuXjUyAqe6YlYS+Txu/5YnFh
835+aMHO+PIgudWwGPhkABtrc/1jC+Yfy+GCtih10zBagoN9/DSugh0H
836+-----END CERTIFICATE-----
837diff --git a/test/fixtures/x509-escaping/alt-10-cert.pem b/test/fixtures/x509-escaping/alt-10-cert.pem
838new file mode 100644
839index 0000000000..14bec45d28
840--- /dev/null
841+++ b/test/fixtures/x509-escaping/alt-10-cert.pem
842@@ -0,0 +1,28 @@
843+-----BEGIN CERTIFICATE-----
844+MIIExTCCAq2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
845+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
846+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
847+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
848+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
849+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
850+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
851+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
852+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
853+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
854+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
855+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
856+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
857+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
858+FDASMBAGA1UdEQQJMAeHBQAICAQEMA0GCSqGSIb3DQEBCwUAA4ICAQA+jnyjJ/9X
859+ENWXApq2g+GlWBM07KpsrxzwDXc6wsOnZCIiMoDqpcH96X8Q2Lahc4mZuz4yOZtv
860+z8Q9YUDTnJY+RtKYNDbxlz7wI1ASxKdP0X1qdzkYtHH752tG/zwVU2FSvqJLw+nl
861+rPJvQQ82/30BspejbW0JIfO7JnfN5BHPzzJp/V5tI1KQe+Wh0gEq6UvXjFrkCoeU
862+gaedPaG2RYDi1LWawRque7pnYzrcJCtc+wb8wiL1dRv7fDDmI7fFm3Bj6Rnid4/6
863+/CxK3WqLBQrXoGnPGwI4iR17Rx08hPCL2V8NvDuJlagJe/Vc6LzOEixofoHGx4rG
864+Cm0AKubKbak/ML/rjyP2TiUmOhhm3Xdml3xexedErkgTLtlvmC0jesYuc4MeypNx
865+Q0eKRnChRGZYT9kaNgXZG1Scq63vpxKhayVvwU4ahGQS+nmuZdbRMEMIH6YkGxo/
866+i5qmNxQPLMLE6HclSdDtUxN4ywQAQ49CaTCxVYq7dLTzpII3ldQ+KuefenaXrYGE
867+7TyqJBVdsTq0Bg2Ftf7GaoidJ/ZjjkB3Sj5uVQFMfU8uSATOolBOzh6fSiQJ60Zn
868+CtAAkb9uOwTl67Qijo4qAe9JRNqR9H5d65D0Vx+gdhcZVEriqIVhXVcgsvYQ55Ju
869+VGhc/foVd+vBuM3jXEdGR+DN/dEu+HZrhQ==
870+-----END CERTIFICATE-----
871diff --git a/test/fixtures/x509-escaping/alt-11-cert.pem b/test/fixtures/x509-escaping/alt-11-cert.pem
872new file mode 100644
873index 0000000000..694cb7e9d8
874--- /dev/null
875+++ b/test/fixtures/x509-escaping/alt-11-cert.pem
876@@ -0,0 +1,28 @@
877+-----BEGIN CERTIFICATE-----
878+MIIExjCCAq6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
879+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
880+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
881+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
882+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
883+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
884+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
885+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
886+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
887+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
888+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
889+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
890+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
891+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
892+FTATMBEGA1UdEQQKMAiHBgABAgMEBTANBgkqhkiG9w0BAQsFAAOCAgEAp2nxfYla
893+giNJ9S2owtp/5DxB3jIhQJzmdSxuUKVwWBffmzxrTkOoK/IcGkq3hu27GIy+ICFc
894+YkSsAE3DfboSTStxhkVZKMVv+e5tXPQ0i+Z+CSgHZbrnaA7nH0UPEgFFddhqogGw
895+LGE54iZ3D7ZYebTw/ELCIHNu9KeOStF7j04WXG7qRrqza5NmKqlxTC5tGoWAljzN
896+cdC2BdK7H2+6de3c4dBsYqcL2IgwNhA1uKIsDjJwwkOPmCEPl+7DjleI3IAKpROh
897+vX66DLaAsLEkoHsN7XTienHF8o/avIMGUfb0rtNLbwW8tzfjeAaJ7iTSm7ibhBLP
898+fK+n7Osh9QH+lG0K7M2zez7Kd3u+eNgTEG63gVR+zDZQwkA2Hy1o4zmZ+a3iCtdi
899+w6JGq3TT8nfPNO4kSoq7EYs6daPnGi3sqNRC20t4FZw0jOpvI4Uw7rPcTTqmAeAw
900+9H37WU3URD2EP8BpkoZiOShMHzNGqlC9qbqr5dd83Lkdz9gN4w3ipdbiiGFGPXhT
901+YubUecjwXoBUUI+be/edVbg7RtSSuplDv5l4bBSy+BG8JEUL6CKAUEtt2Tpt2SVD
902+AIaj0B19/DSYq1e4x8IBVBsI2RnEEpP70bdLiSYLhVhMdzp0PRqDVDE+zt4mm0lx
903+NRDSdNS1/rJEH1gLQEh4SGMs9iY5Vv+kx28=
904+-----END CERTIFICATE-----
905diff --git a/test/fixtures/x509-escaping/alt-12-cert.pem b/test/fixtures/x509-escaping/alt-12-cert.pem
906new file mode 100644
907index 0000000000..7e48ebdf05
908--- /dev/null
909+++ b/test/fixtures/x509-escaping/alt-12-cert.pem
910@@ -0,0 +1,28 @@
911+-----BEGIN CERTIFICATE-----
912+MIIE0DCCArigAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
913+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
914+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
915+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
916+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
917+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
918+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
919+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
920+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
921+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
922+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
923+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
924+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
925+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
926+HzAdMBsGA1UdEQQUMBKHEAoLDA0ODwAAAAAAAHp7fH0wDQYJKoZIhvcNAQELBQAD
927+ggIBAEMU6XcjSdQ+EG22BsyAYin2d3g9Fd0gljsuyEyw2qwFE1zeNqz2sFX7GdmP
928+hEmUVdzQ0EQsHtKiO2BIhU5fkLoGIkJQT0MY/Tkc3xCLjVBG9ryHNjhv4aYfcvZ2
929+K8LwWu5na5YtpmEHppFTmhQFHK9Yf2Jeh5Ms1VH2jwKR8iFM9dk0wcB74Y1WqyX0
930+bhNUzv0ISvz/DK6rN0CM0OiZ7D1toMFJIslEcZD/MCZ0icFwRgGLzooDbm1xtixo
931+NjgdswdiL0cS/wgSdzu9eIugUQZU2KvUWYXGqYMDpn7iukiZSKQuFhZGcuK17zyR
932+y6TkDFe9rTxVtw9SAxjlo94rEqWN9Cns0n7tqAI/Wg6ILHUjUFwqSdrZQTEgH4O3
933+tfhRkV4HCgP1Tzfz/20uMBqjCLbdt7xcSfLIiHgaxgwM0LGhH2Uk3oYinL2WIUDi
934+bZPI+1bzeyZ/tHw4sDxkGn3W3Nr44Td/5DAFz1lRMxAliVwHNzFTiY7IjCqmB0DL
935+z91agdgPMdh/huFvGJZHS/v7EXMSXyNLyIw+5JO12iwf4+pu8NLnOtMoHDB4yY0w
936+MEerc4e8SmygBQGF0MrcmirdT+7yiKRktZZFuyQoj4fBSKeBaBKUrnnk4UYw9H8f
937+j/EQwM87PmYjTwYPrJ0Kz5r4dmAUvq4z2ReLgM08Ve4SPa79
938+-----END CERTIFICATE-----
939diff --git a/test/fixtures/x509-escaping/alt-13-cert.pem b/test/fixtures/x509-escaping/alt-13-cert.pem
940new file mode 100644
941index 0000000000..574ad1ca8f
942--- /dev/null
943+++ b/test/fixtures/x509-escaping/alt-13-cert.pem
944@@ -0,0 +1,28 @@
945+-----BEGIN CERTIFICATE-----
946+MIIEzzCCAregAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
947+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
948+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
949+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
950+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
951+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
952+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
953+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
954+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
955+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
956+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
957+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
958+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
959+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
960+HjAcMBoGA1UdEQQTMBGBD2Zvb0BleGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOC
961+AgEAkx9jG86PMjL+/UxlhX0B/gIKHyTVrEt8j+/fn74uMnd7CV7toK6f5DANIxYp
962+3OJWAFYZ2lNS3MQMxpbjpd7D0BeNwhiJyBnRPhJ9KdsvdXnupF5ANNzr3oMioWwL
963+3WxvmQDEz35sorae5nzuZu8EpuwgodR0NCEmoPdW9JOUiB7k3Ku5goZHqlrdzM8f
964+YPbRDNOxSIpRqr5eqhEM9tEf+TF6qOM/NZJlXxtGDVdaDTbaULuCJGEW8TdVajnY
965+FfWWtIHwF64G5qJTgENqJjR1kkJy5vg2lFoDXE8MG+LvTHfyY0rMilncD2YOBLcj
966+gb3mBTxZGI2w2KZbchgEvA9+0heumAVJQPfdGs+pCUdvlhwWh8FCvu3aQb5X57OU
967+3D97vwvEs8Mxm0KHf0o0ZnTvaBWN5htX2bbpvYxGGB0SsWM8r1LIXj8bwGNdViV8
968+UWNrg37XyGCppL1jXJ1q+DDKOvi0JR384ocRmS8mWUf9qiAMOqveix38rHezWlEm
969+4TCscq4tv135nM194D6uilzv4mUxLAMTX8Lvag1R3aKuOHio9lCGep4v776kALE6
970+9/rekRGoMwNApoaC96x+V/dkbfnjWcxRXL5TvjDwVInl+RCcn6ijYZM0HYc+U1Dw
971+MwqBCbP2Y9Ee7xcnAgPbqH2svWG7XadQHAcOEDc/DFsPRG8=
972+-----END CERTIFICATE-----
973diff --git a/test/fixtures/x509-escaping/alt-14-cert.pem b/test/fixtures/x509-escaping/alt-14-cert.pem
974new file mode 100644
975index 0000000000..0265b5992c
976--- /dev/null
977+++ b/test/fixtures/x509-escaping/alt-14-cert.pem
978@@ -0,0 +1,29 @@
979+-----BEGIN CERTIFICATE-----
980+MIIE5TCCAs2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
981+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
982+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
983+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
984+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
985+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
986+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
987+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
988+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
989+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
990+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
991+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
992+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
993+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
994+NDAyMDAGA1UdEQQpMCeBJWZvb0BleGFtcGxlLmNvbSwgRE5TOmdvb2QuZXhhbXBs
995+ZS5jb20wDQYJKoZIhvcNAQELBQADggIBABf7bojDeoFEFyk/Xzo50sAL+5irJYzV
996+n//5aEvUotYxQt5coi7UnkKUgdiUhIXD8WaxD9KP3nUH+C3cxAQ+I7iVjFhjqFQB
997+X4c/ZjJA2QIX7VMWA3kpOFvR5N0HHest097Fi/HUEEXNkcUtCkRNtI2Msse9uz09
998+DIv9P0IQ2TFgBRCTJwq2ZfVebHk/xoQ5fV9b0b39ts6ToiuMvGJVng2zz8fVNMah
999+hycCn0WSb6dPi9k0ItSvRTYL6vp9X842+Q0Xkq0FxQPUcvzN7D1tSmHXDM7nYXp3
1000+FB6DKASp0+nn+J88RXVSpO0JedEyRDEluxHJcan+hqhWJ4DgamlVTEPN3q5yE4lt
1001+Jr/R5tnx0Lv0CxDTAfZLaFiKb2jz9nVhzbCh7t21mxyb2mOM+GAxRaIgxodeNJoY
1002+QA6Ezz4cbjjA72Rgi+tBxy2abXpbbJ/vX7FUhs0ICFKZJHvFoxazgtSGgHHYNxhc
1003+/+9o6Y9jhunwGn/MaoxWJsdSjZ8VX7HY0iOSU3z4d4PWvIz05n4sGoJET6s1JuKe
1004+dZAAeQy0V5/EzxIu4GPGrzVtk2SQhNHVJZKponZeCRruruGT5Z1T+gF5YSqVM6BA
1005+XA0ZVXwOEbZ5XRIzBBbaiX3Eeful50ILOiP/uxLlcZtTtOyT4wNBgijfJehRHbED
1006+ppJk42EFZKb2
1007+-----END CERTIFICATE-----
1008diff --git a/test/fixtures/x509-escaping/alt-15-cert.pem b/test/fixtures/x509-escaping/alt-15-cert.pem
1009new file mode 100644
1010index 0000000000..70a98fb90b
1011--- /dev/null
1012+++ b/test/fixtures/x509-escaping/alt-15-cert.pem
1013@@ -0,0 +1,29 @@
1014+-----BEGIN CERTIFICATE-----
1015+MIIE4jCCAsqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1016+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1017+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1018+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1019+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1020+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1021+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1022+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1023+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1024+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1025+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1026+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1027+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1028+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1029+MTAvMC0GA1UdEQQmMCSkIjAgMQswCQYDVQQGEwJERTERMA8GA1UEBwwISGFubm92
1030+ZXIwDQYJKoZIhvcNAQELBQADggIBABIv7Wlg5F1gh0+0v/+LnushmLeypcXQGqkg
1031+E2IxXC2VnZxq8xTFCHy/m1qTBLPJK5VIg5qmtstL9zIk9rOUshQvusvNLplC0j3o
1032+GuQdQJNKV7rrzYYpUZO1en11q27AgDsO6lwSNg4U+mqzJxxIHc8IMeJpfaGTkUz/
1033+ZXXNz04JJalUff+W2436vSvu8Y82fD72/qNu6EMiOl0EHJFQ/7eCAlz6hSNleLT/
1034+N2GztApNzujbPgH7+PHOeVpwppDuXY1rkmPJMxCqkY8yOwyM5dMov0bjIN1f+QXv
1035+7voxVGMTefUajKADaNGMShH5rhgjIWBgujvdCyLPr6W2R4S1QPzjx4X26eTX1G8V
1036+/eTsJ6mMc+3cd6CEmEahUnc6LdEdwm+1SMRG2nejea4o8c+crwYX5KQVrqx92FqB
1037+SdkdCtS6qlnxJVvSz+HW6lEM0EShvjKEz/udsnttALQjhxfB7AHNWA073o/OiH25
1038+Y9QpUudmWJjOoqRokN0SV4rDQnfNcLKIoVFPu+rG2CpBDjUsoxG3/aC8Owcd8Ceh
1039+w+O/DqQXudXFS3RsePbz4rPfID9YtBHrihCE10B70DUutWPsbe5lKie3wJpQbqvl
1040+zp5kkI5RffVU7OFD6os3+wPomdIG21Cf/fru56nV3FmkINCabLQddes7OarQcZ5y
1041+xsumEzq+
1042+-----END CERTIFICATE-----
1043diff --git a/test/fixtures/x509-escaping/alt-16-cert.pem b/test/fixtures/x509-escaping/alt-16-cert.pem
1044new file mode 100644
1045index 0000000000..64f852ceeb
1046--- /dev/null
1047+++ b/test/fixtures/x509-escaping/alt-16-cert.pem
1048@@ -0,0 +1,29 @@
1049+-----BEGIN CERTIFICATE-----
1050+MIIE4jCCAsqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1051+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1052+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1053+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1054+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1055+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1056+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1057+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1058+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1059+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1060+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1061+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1062+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1063+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1064+MTAvMC0GA1UdEQQmMCSkIjAgMQswCQYDVQQGEwJERTERMA8GA1UEBwwITcO8bmNo
1065+ZW4wDQYJKoZIhvcNAQELBQADggIBAEID22h5WK1YJrKUmmO0owley+tL519YwJbs
1066+FwbwPz7+SJKA+UQNqVXYOGLwDJ6A6OzsV1TnJuwGotTmvNwr7eOVyLf03qggIYEj
1067+5Twgk57gJmqE+Q8UXUq2ocALUcgReZhluhNoL1XYQMbDaHYwh9HSOP7udEszVQoE
1068+m1D74cSiW803XnqPJGj0i1s9mD6AEewPl2k0mQ0hTMM3rlE1jOCj4Jx81tWH5KNY
1069+LXn/LhFomeo/LAU4PCFTt65tAomKTNXq0GwuunU62fy8pwh9QUpD3Vfrkm4+08uz
1070+WXSk9PeaF8tOs5pRwVMRr0GIdnQHa9GKuBBSZEvkGTxLM+cxO7jp5qSs2IRVpI5s
1071+ztlJQcJpeTRNCEF7gM98nMqDqve/IySGle9s1RjpnBuSD9UKzbMGeBuZK8d0JfBt
1072+7XF3i6Tu74EbBL/mP/0xoHausW9Yo8HZhXjm5k9P7m9xxlq2JSSXeQCLbKFT/SN+
1073+Q3bS6rh0HaqLP8Gd3OyU+aOOy13Tr167LEFNK6DlfSadITuHwRMNvCk8UIDRDzAZ
1074+kXVXdT5UfUe4IJU6OPVsFfntTX6G8s2/K4WropnjD5NjBJ0ppvPgCBqEA03mCGVt
1075+IunRhQypiA0+SilM7BX6jD97IcmnbSyQ6fUkIdDBTMlX3MoYXkT00gDT3y8D/aKw
1076+KTd5SKbD
1077+-----END CERTIFICATE-----
1078diff --git a/test/fixtures/x509-escaping/alt-17-cert.pem b/test/fixtures/x509-escaping/alt-17-cert.pem
1079new file mode 100644
1080index 0000000000..f09f41b918
1081--- /dev/null
1082+++ b/test/fixtures/x509-escaping/alt-17-cert.pem
1083@@ -0,0 +1,29 @@
1084+-----BEGIN CERTIFICATE-----
1085+MIIE9jCCAt6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1086+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1087+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1088+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1089+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1090+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1091+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1092+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1093+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1094+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1095+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1096+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1097+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1098+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1099+RTBDMEEGA1UdEQQ6MDikNjA0MQswCQYDVQQGEwJERTElMCMGA1UEBwwcQmVybGlu
1100+LCBETlM6Z29vZC5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAgEAchR9+hds
1101+zMK0NKgiX32XxJJ79tlo2sRMCZqij8Lqfyz7JDlTMSvIVqcrmimlAMX5u8BxKRXG
1102+99KzXhbJb6Hnj2i6fQobxpD6nKnPSUcoiiWccmp8jmcKQW7M6TuqOfEdEnKpf0BF
1103+vNFBjXGxs0KqOArX/1d0DqYS1LTnxaC6NimgvjAqKVRm9mqj62pc9//ixCgHkqLJ
1104+stuoSerbo/mO0ieY1wq9r9TZT1epacVrQpJFWeJWhow94WutMNesJSWLcxX63mH4
1105+j0LHEEkHLa1UkMzM2RkHTVhKrthCiuyrtqrglLsdPInU7ZYVONyUrR2D1tMy52mB
1106+b1HzzP43pomBJtp3OeEZtBDwmmGgD8RBdVK/T9hcK02cvB1w1yr4LHUeYLMqrZaP
1107+SJHQ7kv9AV5Os64SYW9+7cqjt1q4VmaEqcuCqvB6mORHWHnsa6PQ19myA7OdqNpT
1108+WAK3D94tpbGPTzfhUCHk0w0fPzJ4A1+S6g4eHX4iQQxxDg9sXV4ZRvAEKnJhs2S7
1109+OhtXdfyu/1+lfaunN13SyxMwyyxHzylEU707Sisxse2usX1Zy2zxqD+LO/9iIu1S
1110+76/rquhiOFRWxSpjb7ewpH97OGFmtzfH70vBBukn0alT4xjkje10NlBfzcFwHWQH
1111+59nxPd5sUEqq+DxTjoAgwO91woU7UTs98lw=
1112+-----END CERTIFICATE-----
1113diff --git a/test/fixtures/x509-escaping/alt-18-cert.pem b/test/fixtures/x509-escaping/alt-18-cert.pem
1114new file mode 100644
1115index 0000000000..341ac0b7ce
1116--- /dev/null
1117+++ b/test/fixtures/x509-escaping/alt-18-cert.pem
1118@@ -0,0 +1,29 @@
1119+-----BEGIN CERTIFICATE-----
1120+MIIFBzCCAu+gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1121+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1122+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1123+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1124+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1125+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1126+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1127+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1128+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1129+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1130+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1131+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1132+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1133+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1134+VjBUMFIGA1UdEQRLMEmkRzBFMQswCQYDVQQGEwJERTE2MDQGA1UEBwwtQmVybGlu
1135+LCBETlM6Z29vZC5leGFtcGxlLmNvbQBldmlsLmV4YW1wbGUuY29tMA0GCSqGSIb3
1136+DQEBCwUAA4ICAQBFUk2Z1E5Q4mW7S8dLz5h78AmfNbwx9eNtECc8iLQq2Q0MuIzQ
1137+noURyNSHhH2hkohU4afXjolCr54DkJNYogrBwHaNDt3Y3wqGQXc+BKRnqblfr1+A
1138+1EoIaqRFjv/Mu2gB0H4U3vBRYriZu7BhQFXiQHAr6hWLG91B1eN1i+my9zOSoSZF
1139+7BuemB/9F4wjvwmDJieSwOgGk3FhNV64Ce9M95RwDKNSJBTBqOTLoyvOw2jgs22m
1140+MntqW9oRywGeHdJ5EucPBrZQKDNysNFj3We8H7PedGNlnG/QknE6pzpRgqbRCAax
1141+hcvGQIaMcUJ3oWhJuPNscjsJ/nfaitz58nH5raj4O8JhlS1h49NpbJO/pAWMHh0d
1142+ZruXspxdEwW17aMJJ365q0XyVysRHiwQuIQYCo8L7oVUsH5FUJ9xxPH22b+PG05r
1143+EABdID+aDV7X/MNwBxgeBOFVOgE5bfrH8NBjkx/F7ID/hjcQDLVWWoFnpIjekebC
1144+EeqTRl5TcnoN9Dc7zkfwmuYGoaYJrGhj7WRvfFgcw1Cr1xujiJtoKbEbMoeD45+H
1145+SQ8MwBb37Gm3aBNakpVmJlp/QZSJY403hA8QrZdjnqoS4THrC0+gN2q71aZ9ZCZY
1146+3+OPNg659ZcYvo1onBSA0p1WGKEAWdHKqZCVRdsl5LnRg4H5gEVW4gmhjA==
1147+-----END CERTIFICATE-----
1148diff --git a/test/fixtures/x509-escaping/alt-19-cert.pem b/test/fixtures/x509-escaping/alt-19-cert.pem
1149new file mode 100644
1150index 0000000000..f163184204
1151--- /dev/null
1152+++ b/test/fixtures/x509-escaping/alt-19-cert.pem
1153@@ -0,0 +1,29 @@
1154+-----BEGIN CERTIFICATE-----
1155+MIIFCDCCAvCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1156+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1157+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1158+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1159+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1160+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1161+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1162+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1163+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1164+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1165+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1166+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1167+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1168+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1169+VzBVMFMGA1UdEQRMMEqkSDBGMQswCQYDVQQGEwJERTE3MDUGA1UEBwwuQmVybGlu
1170+LCBETlM6Z29vZC5leGFtcGxlLmNvbVwAZXZpbC5leGFtcGxlLmNvbTANBgkqhkiG
1171+9w0BAQsFAAOCAgEAWtSJOhwRpYdB/aq/AixRTIpwf5VR3MWaDNh7clpnpYhYoLDY
1172+7dJ8cv3AR5dOScFXLrCZ2UYVD+tTPyt18opnYDT4h6If/U9TTHVu5tRSX0wGIdPc
1173+j3zVVegty/HWMA5LfwygNTvZjgXhocckNND7hC42+BuXE2bqoqnkqMRer/R+9PmU
1174+FXpyLk0aDl2QmspDAz86FYpEuxpMfmDNmM1nWDz+n+uBbeuriTttsFqFWkfOGoNN
1175+/3tAmUjAt5IqkL+7rnDt6Lc9inY0z3uYGJEdqa0GJJFJ7U+8wcw8rUwvKETqAtW1
1176+mBOswkoCImPeNDpiqiotwl4cfrsb1+j9gNpYTP2oSurh/bF0mxGLoJa1iDeibwqg
1177++f6oWcCdYQ94ItvS3d+lNXT0MWM6HU6sHXf3+5SqvsvsKjUBRyy1Nvnug1bha6Qv
1178+bdeErN0ZSGy12Vc90Y5fpl8kebmYiJc79OqvuTNDeRfgBm+U4ASAj/AEhtbN+wDd
1179+HrUHbk/9U9h0UFRZ5s7Pqoy5PEoLRoFeA/jQQa/fLC8nl7YTSwidVgj8cyAy36sV
1180+uaBNXrcgelqlR26SBynXM3APaFlv5IdSlF199swMCusQrGbiNajl21TUm+Iv+84g
1181+x7rnUPnQ1grkLpMOBtGaraKc93e2VfH5bAZvyaIq99qdA10ERCtE2grvjik=
1182+-----END CERTIFICATE-----
1183diff --git a/test/fixtures/x509-escaping/alt-2-cert.pem b/test/fixtures/x509-escaping/alt-2-cert.pem
1184new file mode 100644
1185index 0000000000..6ae58f5636
1186--- /dev/null
1187+++ b/test/fixtures/x509-escaping/alt-2-cert.pem
1188@@ -0,0 +1,28 @@
1189+-----BEGIN CERTIFICATE-----
1190+MIIE2zCCAsOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1191+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1192+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1193+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1194+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1195+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1196+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1197+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1198+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1199+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1200+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1201+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1202+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1203+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1204+KjAoMCYGA1UdEQQfMB2GG2h0dHA6Ly9leGFtcGxlLmNvbS8/YT1iJmM9ZDANBgkq
1205+hkiG9w0BAQsFAAOCAgEANTZFCjNmspLkZaVYkcAXfT2poPPWAu7wS/wG4VEmKwPV
1206+A4dnFV2McXNW/iyABeoofeIjsjiYLpxTvz3teD2JJh+hidNED77PV7f4hj7vs4Dn
1207+DGB3HKJvTD63AVOiPJ4bbfUyiuvLO5TwdxAGm+q9lsf/fWFraTF2qlnFwyWf6Qul
1208++NQo3bM8mErvntZMscq7wo0cOdAXA0bNqxKS+IDnc+HLxoEr2egbRJmEagMgV4/U
1209++AGVQ1sY+HrEszOPUA6NZ/OzLuXUT3swm+4rqJZEQ3AVr2BdqSzoiGHqqzmfKO33
1210+sODcYXuED0sUkIhRZE1vW+wXR94WQsT5C4MtHabNjpPLSH7cVjGvEfTX8DJH/F7p
1211+OdMmXxvPey0wLGJwoZMMhG/XC8Nb1g+qCLLou9WuA7KHMibfiYdBnPcMDg3fwWwg
1212+pYzrvK/S6f5h6TS8y9zKxCJwTdfC7f4KT6EjxQFhgHCm8oFupOLSEZKF0UmLMeOA
1213+J504ZnGdhEG5p9AqQNBlyBsGGmSyQkSJg1BPB6U7wFBSwrXS+3b2ph4J5RivH68O
1214+CKjR7yWl7M75LOa1dt133GmhPUUGHLsjHTnuCDVB0eHcgboonKTjCSAmckNKm/uw
1215+tAUMkO3puty5JM38b8AwFRDXLnlWdSsNr9j243SHOfKyFWidjwglRpVGBhoECtA=
1216+-----END CERTIFICATE-----
1217diff --git a/test/fixtures/x509-escaping/alt-20-cert.pem b/test/fixtures/x509-escaping/alt-20-cert.pem
1218new file mode 100644
1219index 0000000000..eca176f2df
1220--- /dev/null
1221+++ b/test/fixtures/x509-escaping/alt-20-cert.pem
1222@@ -0,0 +1,29 @@
1223+-----BEGIN CERTIFICATE-----
1224+MIIE4jCCAsqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1225+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1226+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1227+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1228+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1229+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1230+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1231+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1232+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1233+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1234+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1235+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1236+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1237+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1238+MTAvMC0GA1UdEQQmMCSkIjAgMQswCQYDVQQGEwJERTERMA8GA1UEBwwIQmVybGlu
1239+DQowDQYJKoZIhvcNAQELBQADggIBAKvkEHjR6lk0AlKiC7oltE+gp7SpVHdKs7I4
1240+zswnbZ1EcddA9D6hjemU+nIUriLkt8BxY+KxNtkwDm5mvXZn5E4XDXzRDsCdNZXE
1241+qx9og9LhkhfGbPJ1LPutQ0VmqPwY17mRUeaLhNIwOmD7g++oVHYmZWqA8tHVB9f+
1242+gP5Ni2x/PX772Vt/hIpI14VoYIsMFs4Ewjc0Gc02DvOdsDT9eUmAo6GNOAbxeRS/
1243+D2D0w6CQhwJ+cemcAo0lGw8KemCYfqzL+MQd8wUGPsiZgm5wQACOp+ImL4guy2gX
1244+h60W9Gtxu77jsjF7n0n4LlInylrZAgw09CkehUfF4+cP2kZDTcsuqOoCVYATAGxa
1245+49ZvuRHoo5Ine5PcfuARS09LmxgI0fdsjaRvRELYIRWHTvE+zCLlNkxkpwXULgZZ
1246+bpJ08L52P+jz+HJPeiHZnYKXgtXyGLpwG1danS600tqiMmDh0G9Ss+UzwhS+jhN5
1247+viIvpmns0zvI1Z1IWPw3y27pw7rmLVcFMbEZFK5mwHiT10iRrT4sxihWIT+sn6n5
1248+5baup/od4kSJABQy9LAuhhuZHyCfxC2yPYz70sP8qGVtY+rA3LNe0ns6pY1L77DR
1249+QIRD/Mm2hql91+U222mxikdT4WQEheh2cLwdg/T1uo/SQDruliNZncdNbTGDmnhc
1250+cg1mw5tk
1251+-----END CERTIFICATE-----
1252diff --git a/test/fixtures/x509-escaping/alt-21-cert.pem b/test/fixtures/x509-escaping/alt-21-cert.pem
1253new file mode 100644
1254index 0000000000..16d5e7265b
1255--- /dev/null
1256+++ b/test/fixtures/x509-escaping/alt-21-cert.pem
1257@@ -0,0 +1,29 @@
1258+-----BEGIN CERTIFICATE-----
1259+MIIE9DCCAtygAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1260+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1261+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1262+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1263+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1264+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1265+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1266+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1267+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1268+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1269+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1270+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1271+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1272+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1273+QzBBMD8GA1UdEQQ4MDakNDAyMQswCQYDVQQGEwJERTEjMCEGA1UEBwwaQmVybGlu
1274+L0NOPWdvb2QuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggIBAHdccJEkqezS
1275+GSNNVIWv9XffNTrZnejms90h66UDC4O9shHMy0aNWgmGuu7uFi1BK4sTciXT+ZR5
1276+3+1ni3WKMhJ5Iu1aNlNeXULOlmuHKVJKrAj8BR7lflSFqj/MHnw22HU+BTmddZPj
1277+F/OCl2W+O+eUNBTTmYI2+pZgmyyU9v8qEwLZn57qlpAJa4gpnSRYQS1xfSaUgAcM
1278+xtZM/AE4F9mDFOdO86/RxXsYRyT0+sOGmaoJrlTWoKduoI7fhzQAIGHnhn9yBT60
1279+0K6LmCR2dXRyLxxVTy0Laiz487IXpQTJ8jo6c0wT6SeiQBlE0W3FTH3IM8Shzd7b
1280+5tbix0bCR1pUT2Q46oaB4xkEweKNGKS46kIps6mpTav3TMhNDVyalUfF4fOu4FQu
1281+RLB6B/I1TI1KHiTeD9xfNInBAdO9ewjWQ9spFei3EExZmvnnWKZIA82mjG/9Wcdh
1282+HFK/uEylzo1Nsxujv2V6ueMYc0pF4XH2U1Azjxb0+pWUZhoy537Nlf8b+PO/GSG8
1283+del0yPwf6JP5AZdXfiV8vNqwEGCC/BEIPrbZ6Zz1q6lT+7GZAGkzbMYlfkzA1lXh
1284+JteRIracA38WfQOHf3FOPYvTBOPlVHWB+tJbwlalYQqCPupMaaxxizCLPIsNvqdy
1285+TAtC5Jbx6N1DdeyHpRuKRUe1M926oKTp
1286+-----END CERTIFICATE-----
1287diff --git a/test/fixtures/x509-escaping/alt-22-cert.pem b/test/fixtures/x509-escaping/alt-22-cert.pem
1288new file mode 100644
1289index 0000000000..5f89b00dfd
1290--- /dev/null
1291+++ b/test/fixtures/x509-escaping/alt-22-cert.pem
1292@@ -0,0 +1,28 @@
1293+-----BEGIN CERTIFICATE-----
1294+MIIEyTCCArGgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1295+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1296+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1297+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1298+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1299+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1300+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1301+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1302+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1303+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1304+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1305+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1306+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1307+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1308+GDAWMBQGA1UdEQQNMAuICSqGSIb3DQEBCzANBgkqhkiG9w0BAQsFAAOCAgEAE8vG
1309+nLYo/G+3Cuzir4toX726vLOkCEqZrkRE18dc3px/CgmEI/6+4lWjp3u/9MxER+kT
1310+t5o5Xin+vmg5F+hocR16mMeX6pjD6tXJ+uzDacTxDgRBFdbqX4x8Fjiig0FXsr3H
1311+jFBY2c4UcKszFlCTqjH1/RfwLYJPU6Q1WZM+1iJotSKnhK7y4A/3jho7sL0PPuMG
1312+WEoxbTBmpAf+jPT+LRe2MY++VnVJHjlPba+S4Y9PHOzizQuIJs7YnhNIqA9So7Iv
1313+eA7Lp8GID+w/eY4DEq4z6CIuCplKZTrrWH0kQbG1sV4J5+W+JL0DOXDk91JwkOPH
1314+rWf6aOb3akFRk5Z/PrrcTAlqtApPQF4uGycQBo8KgcatZyP/3HZZHyyxhEjF9sw/
1315+STHm93GlCIwocJ+SkwjBmdupv6Yk8fRmA7LinjVvi7EnQQ7qcRE3oUCPPReDD96G
1316+TuDsGkQbv5WQSh+0mBAiTFze3C6FSNcldQBrlWReqOj6pVWtUN49lpYOJ2XfLCQe
1317+RjS7IUYNn7Ku3xXi2etgNzmJXcSnNXZkh+3henpFqkwEFJ5b5RgOHXULTwoqo9KS
1318+YMs3eKHp62J6l0pQD+wTGUyVU8cJghJ0hR1WnNR7o32Bos2dfBmIQgET4ZH/P2+H
1319+A2gtbJO5mRsTvuD+kZut1jxJvUzuO0yZoNpuUVQ=
1320+-----END CERTIFICATE-----
1321diff --git a/test/fixtures/x509-escaping/alt-23-cert.pem b/test/fixtures/x509-escaping/alt-23-cert.pem
1322new file mode 100644
1323index 0000000000..5cd6795cde
1324--- /dev/null
1325+++ b/test/fixtures/x509-escaping/alt-23-cert.pem
1326@@ -0,0 +1,28 @@
1327+-----BEGIN CERTIFICATE-----
1328+MIIExTCCAq2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1329+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1330+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1331+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1332+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1333+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1334+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1335+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1336+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1337+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1338+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1339+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1340+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1341+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1342+FDASMBAGA1UdEQQJMAeIBSvODwwiMA0GCSqGSIb3DQEBCwUAA4ICAQBps3VQshvW
1343+9HDR2oDXSldWNW2SWksa+9npI4IEMDusiDbLdR0VBphw2R3iUuJ4IAPDc1s/SMi0
1344+1t1o92lC5zVeTq9LvOOC1KxwbZXDubFDmdsuJ/DYPDkaRoDqoH7eFsJuIyD/TKqm
1345+HXPYmWmjUNv51SSLTTqPRz2TmLQVA1Iw7J7H3fz2LExsAtczx6gRZJPIZGdMx6do
1346+E67SUp/2RPYtkEmmCELOxCAh/Pzm6pBPncI86AMTNwppl+FpqaH0LPrqMre40tTt
1347+cQq/0XrMWRoWsS3VU8uor+aGTnNp5VT3ZLVmXZNyG7nISW7ERaGCeTZJRcqwjeH/
1348+yPxhQc7IpYCm5x+HN2sDuvVC7l/q1A7+CbO3jNR5Gb7aEEyGiKb5ZkElbsulfwom
1349+JOg1K8+SBDGrErEf0MDCenKY2g0lhpKGBwu6O+RVmKbhlHEjt2/31/NCSBMLopdU
1350+AmCNoBo3+KaRljo1lVf7tWbffNRCqsbPZPHtq9uXs0DliJTUroaJ584h92VrSLJB
1351+SdAUVLAwzmwu2Pa4bp0STv5tJy1hFNJdVFQ4rgAfaFudXy41K9zqrDCB7RbzX7Yi
1352+97TCDu/phzkoFpOZabqTrvcP13N0wfDeOx4Y9nx77aeqTAaQ0ooTG9IWrHmjuUKF
1353+wpEXQBfkuXug5+xq/hlCllkPj67cIaldDQ==
1354+-----END CERTIFICATE-----
1355diff --git a/test/fixtures/x509-escaping/alt-24-cert.pem b/test/fixtures/x509-escaping/alt-24-cert.pem
1356new file mode 100644
1357index 0000000000..2a858dd39a
1358--- /dev/null
1359+++ b/test/fixtures/x509-escaping/alt-24-cert.pem
1360@@ -0,0 +1,28 @@
1361+-----BEGIN CERTIFICATE-----
1362+MIIE1DCCArygAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1363+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1364+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1365+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1366+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1367+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1368+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1369+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1370+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1371+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1372+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1373+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1374+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1375+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1376+IzAhMB8GA1UdEQQYMBagFAYIKwYBBQUHCAWgCAwGYWJjMTIzMA0GCSqGSIb3DQEB
1377+CwUAA4ICAQCKRaPaQO4+oztra70h3g1qwmJurQ1vGBdcXh27nf9epFAwhU1zL5v7
1378+7wN7iclY15BX3w3WrZ+ag74AvQLG6WQkDY1JCmidEjjt2bmVTxIus0H9Bb2AlUEw
1379+BtVYMJrr+fiWbfSwRxhMQa9BQ6ZcUA7EluYQFApo2m7GIcMc4x51L/bwzmsXYj4t
1380+2tjnkU7clL+7GR/w/+ZB7nIe80j7wYvIbOfMS3Yxh+uu0aQCNdoh9Tsdtu1jtmJv
1381+4lJ5aZIDABE/XIFVkWRyHv2ou14J/LXUKE3HPEhSKWu7GShrdTeS+gZpOixM+uPG
1382+ieHah1GfJMS69P82Z72Cr7XWpQY0NKwMB+ePhTzz1LMBHQ5ySXQCViQRClRMc5K+
1383+cXZm8cs6oe4IEhMcf3kc/9xblgRWqxX7vsb6Gcrn1eXsfxco17S1yNBzTt75ybt9
1384+kvPmrWqpg+sQ0r4473DjEASoSCPwlzCpd7AHOw+XxSwsOUNXkEnXMa2v2VHBjx06
1385+QnrLenB/n7EQ5Vo9JLDMLM6ie4gfehHxfdyoBg21jN9eUPpKGnjARVvyfDWV+7rI
1386+ZHU7wc2iMnqroAqm9FZ0YBqZ/eI8M4ZAYSvDKnGZQlUWfhdNDhI4FsHBPymMFtjW
1387+ln5eFUNLMoitMGs12Ib+omr9WSTxRj97GvRkRTNK5Gxmo9Mi/Pkxng==
1388+-----END CERTIFICATE-----
1389diff --git a/test/fixtures/x509-escaping/alt-25-cert.pem b/test/fixtures/x509-escaping/alt-25-cert.pem
1390new file mode 100644
1391index 0000000000..695b8ebba8
1392--- /dev/null
1393+++ b/test/fixtures/x509-escaping/alt-25-cert.pem
1394@@ -0,0 +1,29 @@
1395+-----BEGIN CERTIFICATE-----
1396+MIIE6jCCAtKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1397+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1398+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1399+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1400+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1401+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1402+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1403+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1404+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1405+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1406+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1407+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1408+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1409+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1410+OTA3MDUGA1UdEQQuMCygKgYIKwYBBQUHCAWgHgwcYWJjMTIzLCBETlM6Z29vZC5l
1411+eGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAgEAIgp7IrYYdLCoUqg7E4igLD3u
1412+C68B896uoeenMmTKDfCzvB5svYKZlfIi3njJUZ2G6kgBNcSd/mwQ2ggex9AEUiGp
1413+uaT7Dpev3RpwtCz5zpOZxN+B0LJk4hPzzE4sjJFrmHRgJVzADL5RdcEF7+GV81nP
1414+X/cXviffkxSihAFALArAaOA6/hBoT6unvlDsY3cxgZWFl3ao76vTQFLs7ZNHYbHe
1415+WDkkNpheWmNlOrVTEz0vjNCQz5wYOM6HJ0O3cxzR/6+OnhPQagZRCWApPopYGuxc
1416+kXHAPbEkXpVzJTrNgHIvZ3l3JdJSHsh+DdGVz1NY4bogQNKCVa3xt+zLpUrr34XM
1417+61Z91MekMijfjOsy7LGLSBdCPCZ00enXPkflDEhv1kRlbo/ZdYGHynzl6Xzu1A5B
1418+nuwDbpsCzR6ij8fZDXGUS7F8Iemdfag4XTtrXnVXLgPpD/FMzJUx4kCIAjgh2MaP
1419+0nUvZDVYt+GKGohCNDrSt2ByFtbYGaX5GeMIp8zW+GT8KUW/K7pp9PjsmzG6vvQd
1420+kqxB45ddf87E8NoDWh/ptdj3pjfbDc5A1SeXKGXrt1TwgWHtUNW0zF8qOuG+PZ1P
1421+u10lUx4gayyF3unaSLZwYu8nYq5C7mC9DjjnbjLhsh0VOIEEh+Q8vJH8OvZFkyti
1422+l2ADXC+6evQTvqLwXi8=
1423+-----END CERTIFICATE-----
1424diff --git a/test/fixtures/x509-escaping/alt-26-cert.pem b/test/fixtures/x509-escaping/alt-26-cert.pem
1425new file mode 100644
1426index 0000000000..1204d95a8a
1427--- /dev/null
1428+++ b/test/fixtures/x509-escaping/alt-26-cert.pem
1429@@ -0,0 +1,29 @@
1430+-----BEGIN CERTIFICATE-----
1431+MIIE5TCCAs2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1432+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1433+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1434+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1435+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1436+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1437+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1438+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1439+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1440+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1441+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1442+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1443+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1444+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1445+NDAyMDAGA1UdEQQpMCegJQYIKwYBBQUHCAWgGQwXZ29vZC5leGFtcGxlLmNvbQBh
1446+YmMxMjMwDQYJKoZIhvcNAQELBQADggIBAKmgEHc9b/bscpyO5mTKrITyoYtbhz/P
1447+0Uz2Uc4tKokUI9EBuuD/XX4EjtVzne9mssAAs9EhBSFmNhDjpAUYh9n2cFvAJQit
1448+4d9EbaNbB3SuzG5onu8ZBtfLsABr5L5tQspO3tinamSM2ZuRo4dvcQ2a38C38LAQ
1449+HBnvZ744Th3LckPMLTWNChe3E2jAt8Av0XA2yVJ/B+EeEaqSYDALKhI49CLeq96L
1450+m/Vq/mqADborW51pMNFn7CAF1jxizQNHy6K0E95ziq8q/OL7j4+j8Erh4x7bcjrQ
1451+X04Z+hrA9q5AjG++ieztKqGuGxHeSclqBhOdnU0UI528Vn0OXRxeMmbqMF+qhx17
1452+nHuxxs4z5CIdTwHA6LgMUpDxcOhdUctIj32gwZM3UHI8lmdRTWn13y/Ht6CpIXCL
1453+1ohSXne5y34z4AKeJQpdUfwQD552Ui8B+bhH1JBm5phjLn1fboXCYiCgnPQ+SJzx
1454+3hsIv7Fji7lfk1UPkr0s7Ze8b/seYS8nVB5rg4qXEwFDMo9zsjCEIyg0tKwj5Ani
1455+HlYzqjjsIK50TPjXYOA9J+NHcBDCDa3r8TBtRGtQqOXQGzvWTqAyT8Uwn7jimmh+
1456+EGDr4PJSTJxv43EYL+of0sRHkOhnfFfJYF9vQLT+wD6l+6T1xNPE/gjX8DyQS9a3
1457+zOgdOiTp0AKH
1458+-----END CERTIFICATE-----
1459diff --git a/test/fixtures/x509-escaping/alt-27-cert.pem b/test/fixtures/x509-escaping/alt-27-cert.pem
1460new file mode 100644
1461index 0000000000..268abdd300
1462--- /dev/null
1463+++ b/test/fixtures/x509-escaping/alt-27-cert.pem
1464@@ -0,0 +1,28 @@
1465+-----BEGIN CERTIFICATE-----
1466+MIIE0TCCArmgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1467+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1468+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1469+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1470+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1471+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1472+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1473+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1474+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1475+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1476+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1477+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1478+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1479+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1480+IDAeMBwGA1UdEQQVMBOgEQYFK84PDCKgCAwGYWJjMTIzMA0GCSqGSIb3DQEBCwUA
1481+A4ICAQBtXT+t0fuBRClJdY6y01k1jqcsXEkmKOr4czznuiloGVEjpbjmxzxsgvzw
1482+nz3od6Sx56SHG1xYbKDCapX9Ld2IDsPvpF2wdH2wpIS5DI7tQdBpLm7vr3vTYKwm
1483+Wns+WKO5VBHDLCyuYvHNo37MJCAfBlr1ni7BCLOg3eycPiANJHPD2T9BnXlJm49K
1484+166VMviuiLBEyO9tadhvQHGqCX3D4pW31zwsKHvS4wau15N4yt053Iac6eaysdTp
1485+mspw5jX85tlQ9XxKNTftUVJU9Uzk2ll4A0Gvnq2FEjiqf6m3tye2nsqDI3C81Dwb
1486+Y/+AeO7ZsVyLpIstfUBFmpLGPUoZ5MNmgrboGf8K8dPPgVbmbS0msrsI4LWSQb8P
1487+R2hzj0F7bFvgbZad7rFXJW9FQOqTwvJrZBkkDpZpeNbhah14avV2Ftrc5+PtVfP0
1488+jB1L3nhc5KGpGL4xqE19K+GVR/KBREgiFD7B7NYUOPt9NjFTrbbC3XA8L0MC7PNh
1489+ySDN/NCiIF9K9MtpC8BYuNBlRt5C82L37qPY4Tw3z9sCyXK5oOQ4xdbdDEWdwzc5
1490+F2S4zfQiB7y+C9RigOyGPChxBqDK/bCExrG1S2b95oP4QMuaL55iXnaG9ME8sCoa
1491+cUd62cMPk7piQW29oFiQPYsStfo09u9JXbalKhol9oPrDtQfrQ==
1492+-----END CERTIFICATE-----
1493diff --git a/test/fixtures/x509-escaping/alt-28-cert.pem b/test/fixtures/x509-escaping/alt-28-cert.pem
1494new file mode 100644
1495index 0000000000..147fba3aff
1496--- /dev/null
1497+++ b/test/fixtures/x509-escaping/alt-28-cert.pem
1498@@ -0,0 +1,28 @@
1499+-----BEGIN CERTIFICATE-----
1500+MIIE1DCCArygAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1501+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1502+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1503+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1504+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1505+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1506+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1507+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1508+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1509+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1510+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1511+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1512+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1513+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1514+IzAhMB8GA1UdEQQYMBagFAYIKwYBBQUHCAegCBYGYWJjMTIzMA0GCSqGSIb3DQEB
1515+CwUAA4ICAQA2KjgKCSLg/rDajrBTtVIu14rAP1pMwFZWrxcpTbN+fOs2dYQXZf7d
1516+/GaozSMSchjPAJ8lTFfEB20Mur/E284LlQPuQKqHHn3gIh92VkHHBHjj0ohnfigg
1517+eBHNMUisuGyNzKV7VI1+iwCoPBZC7ptbE4X08osVxxRESj+IT0TwtKDONTIIeogW
1518+6VhsKTQ1HM6AMbhVe0Led/ENxFFMquB25GG/hVB4ZzPmsJZzNdZYNNMa34kNcMN3
1519+5OFcxWV/4Hc77JYsqM9fE9gBaKC9pQE0XwIrOMQSaGYx+GO8Ty33YlM+oYBt6TMH
1520+/9oU8HVvEYW9GAyptNbXPOwyv/wikNBsJyDGfvuDoiTZ9iMFb/bEoWHSK/rYmAgk
1521+D272zxiPS3YgaZkvhlYZ+60w5CCgXoN5L0Zq9yAOTv92/VHFnMPrTP7zfD+4eUHY
1522+lg+A7pOCIUK4cIDUXQefn1dU5/8DHJ8aM+KQDBfkKOH3me3GzIKjtKQjhwYFiJ8L
1523+vD4V6+nq90GasShQDKUbMVbCxfyqlvrXOP0an+FxdknadnD5hRT3UsU9SRxAdkXi
1524+3er2sXpuULYqOst55Ahnj7D5uDN4KBoatZwFd1iw0CVPoox7ixZ2zOAkwVqzaEAq
1525+0yWyIlELm9/FdF78fu6LPrFKI1H4MH+0TQrF4MiyJWPvET7t8WKJsA==
1526+-----END CERTIFICATE-----
1527diff --git a/test/fixtures/x509-escaping/alt-29-cert.pem b/test/fixtures/x509-escaping/alt-29-cert.pem
1528new file mode 100644
1529index 0000000000..434bda3e8e
1530--- /dev/null
1531+++ b/test/fixtures/x509-escaping/alt-29-cert.pem
1532@@ -0,0 +1,28 @@
1533+-----BEGIN CERTIFICATE-----
1534+MIIE1DCCArygAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1535+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1536+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1537+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1538+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1539+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1540+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1541+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1542+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1543+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1544+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1545+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1546+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1547+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1548+IzAhMB8GA1UdEQQYMBagFAYIKwYBBQUHCAegCAwGYWJjMTIzMA0GCSqGSIb3DQEB
1549+CwUAA4ICAQCIFfHE09aftJrS629ZBBRKjRiVcxN0/FjeEHWbnb+3Re/LoU/Y64BT
1550+LmjMBB6wik3JxxUtLs2UYExQKfz3zmB+O99lR94of3V3RXPCe9Dz8C12iohYBvVO
1551+q+WzXyg8g4zoIndn9+ByR+JJsuk+WVTZd50wRaRvssUB5yhpLaFdZpnLUBdV5J2d
1552+shmefZxr0NgMb9p75wvWgZ2BiZQDeTR93+PWaZTMdSxZh6ynfG//5sxxw5fLm3pv
1553+eVo3oQQ8px9j8G83ouiDZJn7XZgNfXYNq7wo3yaqXX0zlCE00K6tXGI6FkKJnVdQ
1554+si+JYfGjzTM39JqFU9YYOOc3Gfw20iKIEQ0jnE0Z+z9Pv2GAel0UNdovluttxu9R
1555+CJcPJOLS+TMd/sAwCAELvhPpeWsDLhfd+lG7ofE/nM6hzec6apWYyCqqlYIdE8WK
1556+rtHXBIMGk/5Eo+2KDGQHgpMs/P8fNUL6FBx/i1pjm5nSHveDQryepEmOJq9NJCBW
1557+1AJhE4jCXMv+43Fnr1OSATNiOd+1KfQ7KC5PFkpZLY4GDFZcbLBKYj1TWx4WzRnm
1558+EW7cC/00Z3Cd76L5i+y1Xr44nbQcAMw6TlT6vvZjFCbCO+ZDUJSZBZMpWwBI/gAf
1559+MNzYPltOGm+GZUuxib2MSF9Qy8c9NegENmsK+zyPT3N9mUHCl9nknA==
1560+-----END CERTIFICATE-----
1561diff --git a/test/fixtures/x509-escaping/alt-3-cert.pem b/test/fixtures/x509-escaping/alt-3-cert.pem
1562new file mode 100644
1563index 0000000000..59185b64a4
1564--- /dev/null
1565+++ b/test/fixtures/x509-escaping/alt-3-cert.pem
1566@@ -0,0 +1,28 @@
1567+-----BEGIN CERTIFICATE-----
1568+MIIE1jCCAr6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1569+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1570+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1571+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1572+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1573+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1574+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1575+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1576+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1577+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1578+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1579+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1580+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1581+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1582+JTAjMCEGA1UdEQQaMBiGFmh0dHA6Ly9leGFtcGxlLmNvbS9hLGIwDQYJKoZIhvcN
1583+AQELBQADggIBAEKwv45Zp5xJEGENPrOIwrGmuBDMtBPmXtSKydKSNUgrv08u4dHL
1584+n295L7jIwQ3SnRjS8PrZWD8RQ46hgFRY9pqk1uTys4jB7lki0eAUBC7oPn7q0GUv
1585+ojdSwOEjp5bfXyuRv7Z+3y2gD8pcCZsqcCjF5Svim6Q3pXMLRKQFhzhzL9k/gsNF
1586+lJ8KcLBECJSm5nUrZIRHPdIGYmWJG+t8CfS3E6OIyHILK1xCc1MasEpmYVoY9uzT
1587+2W2z+3pvwQqfdXO+lEOsT9dnjM/WbnkQMTWAn+++YFtkvA4kON4b/cp9imnXok02
1588+vq7MCbN+b5CJXIhKMC5eNA36ez5hou0MUmnsNo9ai1gVJXRoL67YgUh1yMfcAaSM
1589+Sfy3UBF++Az/yQo4AWtqWk4KPePdcsrYo9Fke1inUl+M12gkdIz+efbElHMqehbt
1590+lunbyFI/7CY6/Tno+T1cDkQlTouHK8Ddb1cPhkJbE4euRuLGdtn2AcFSemYGtib0
1591+ffuhnEBF8M8enPVyLjYA/3sELkmmaHMtgDTm0+XYQJtjIbvGcY7+bftPZgbXPVGv
1592+7+tiYjwarIexXN5yzMasgFI5+7qLSQJHcmwrzOm8K+Bzx34f20vwR4M2FJ6cqUeN
1593+qzdN1HSNp8aYNilaFa3+hfGRG9CZnVP8up8BwYx736EMu0G3yAp6UqqJ
1594+-----END CERTIFICATE-----
1595diff --git a/test/fixtures/x509-escaping/alt-30-cert.pem b/test/fixtures/x509-escaping/alt-30-cert.pem
1596new file mode 100644
1597index 0000000000..1b67d1f782
1598--- /dev/null
1599+++ b/test/fixtures/x509-escaping/alt-30-cert.pem
1600@@ -0,0 +1,28 @@
1601+-----BEGIN CERTIFICATE-----
1602+MIIE1TCCAr2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1603+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1604+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1605+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1606+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1607+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1608+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1609+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1610+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1611+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1612+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1613+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1614+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1615+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1616+JDAiMCAGA1UdEQQZMBegFQYIKwYBBQUHCAegCRYHYWJjAGRlZjANBgkqhkiG9w0B
1617+AQsFAAOCAgEAgG06c7GRpPohHa1X/YQVQGWa/J/f3qok3cu1nrD2H5Dkw1eAVPcQ
1618+lsng08lOxwSI0OgqJw0jl+ljLKuhHI3U68KbFmUO3Jw7uLDk1+UniRSNkfxVOrlc
1619+7YTlmsxiDgQdX6/TAHu6bERx147NqVzB4/I6qpX7ouLv4E7xdQgjKuvhWlJ+Fg/0
1620+pQ7EleQymRN6Y8qO6RwEWYao5pypg8/22cE3jgXleLM+5qWHqJs2ZewPQf7uo4Bf
1621+IwSUV5H0weftiSN+kOLYiNfUago108VHuk5sCIKr92q4WAJgA5C6ylcUWaJCKbCv
1622+HQYR/QG10Mrn4JCzzni90aBHrQoYQ8msEDH1QKyMJiNz6XXzwBP6bvgPlB2f7nPW
1623+ERpH45M2I4Z3dZYFw8bF7CcOIUuR0/Zu2WN22IhqhjVQSZPzdRWJt5Rr1mFUz+Nv
1624+Ymdi0w68KyRUiuOpKNLczDDnYpc9EqGBprnMOxALS4mQn1ySBXbZAXnTTdEzN5fM
1625+L4CXWUzIBVKv56Mn5YskhbCd+N8GV9Nj/A6dBwa004CQxbgAj+ndNWc7+h4iSNlz
1626+9VPHK2Kju6j4fVpe10jzSoEs0nnrsPy5Lxa6C4KhXBBJ3cPl6wWNe2mgbEqG9Pq2
1627+KrCizuFkIfZTAeSrR+prZXLw6cjmKPPEtNbK2JbteL2SEDT/3AjmmZE=
1628+-----END CERTIFICATE-----
1629diff --git a/test/fixtures/x509-escaping/alt-4-cert.pem b/test/fixtures/x509-escaping/alt-4-cert.pem
1630new file mode 100644
1631index 0000000000..086af8e02e
1632--- /dev/null
1633+++ b/test/fixtures/x509-escaping/alt-4-cert.pem
1634@@ -0,0 +1,28 @@
1635+-----BEGIN CERTIFICATE-----
1636+MIIE2DCCAsCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1637+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1638+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1639+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1640+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1641+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1642+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1643+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1644+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1645+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1646+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1647+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1648+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1649+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1650+JzAlMCMGA1UdEQQcMBqGGGh0dHA6Ly9leGFtcGxlLmNvbS9hJTJDYjANBgkqhkiG
1651+9w0BAQsFAAOCAgEAPu7ubyZw1rOQJhFX6nBHyCYaBzaKxRZOHOFCjMrD/YQXPUNM
1652+Hs+8ChOeQ4M82jTyiP7XgF8EumDcckDIlIYvGXGrCB/6VcCVL1vPPtzjSaiF3PlG
1653+/dh0OlPvevr5Ajz7ZtFFwxeQ2EfsHiry8qnlDJSEjrh4Trcx9YzdkSZz8DaoODXz
1654+ctR/p1JEnQ6h/Axa6hdqTzbzTsINN7gD5Wi3ObfQbK6Ug/CuH6Zr8bdTsmeGcnD0
1655+fqHptuLVNcROykneYziXDzcqGwrZnYaOF54a4ibV/OfrBcgEKeDwsCrLs3nztSC4
1656+whV7DXZwaLl2KWl4/suBNI1cIKbxII1xTFLTog+UYz0zSZGPrtbt7zrlM4yG033t
1657+h9xIGUKebaNpQYkoxOc/+kKhbKCeL3klfxJoX+6Gf8DkTP7byX2HovfWV1rJbh57
1658+YZ04Bh69VmyxE4iyb1tAh5xh1bArCR9m96eXS/0KIZbykxltQGyHf1jpWw/4Wi3n
1659+oadkpMcyNX76M1xBJ5u03JL8+LWrXuzf/ScWdmPUWulAEhbo4fn4oRwP2C3l0vVQ
1660+iL482cIq1zF91lssRwQ17k38phulRdm+7W65/VI7hLoG6lXiSiHLH8e39hHO8Jey
1661+Z+BBvn8x+aFgIvpBK/MX35s0gSrl/UiIZPU9glnktSsX5D+aaQynbuvbOW8=
1662+-----END CERTIFICATE-----
1663diff --git a/test/fixtures/x509-escaping/alt-5-cert.pem b/test/fixtures/x509-escaping/alt-5-cert.pem
1664new file mode 100644
1665index 0000000000..04a918008c
1666--- /dev/null
1667+++ b/test/fixtures/x509-escaping/alt-5-cert.pem
1668@@ -0,0 +1,29 @@
1669+-----BEGIN CERTIFICATE-----
1670+MIIE6jCCAtKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1671+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1672+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1673+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1674+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1675+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1676+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1677+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1678+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1679+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1680+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1681+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1682+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1683+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1684+OTA3MDUGA1UdEQQuMCyGKmh0dHA6Ly9leGFtcGxlLmNvbS9hLCBETlM6Z29vZC5l
1685+eGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAgEANAyZnL8f81Aax/0Rhw3CCdcQ
1686+SXF3dpAolObQB8rlirRZ7yOY1v3Poj411aV0x9zM6mjOJZwarUTL7kbO7odQxGhB
1687+x7O0DvUoG15VTvs0XLNHTPgnXtNjKOZ7XXVMzb46APfYSqdzMqhRWfy+Iaikp494
1688+urtqkVt05q2amzq7EXbXI8JQWhkJkhjBTowfZnpZUw4JeeqMNRZT9Ldv2XDZjaYS
1689+lkHOLzTmSmm2mf1oxhKGcRCgUCr/pzVUfDA3RBz25a6PWAQt4b2r8k5jydWyOeCZ
1690++sjacoK5/E1PcdaOFJAjuAfbRMeK/gz2+yJwaB39Yh77t/9vQC0G6aiAmO0HxjJE
1691+L6Lb8BG/QNYBS7gGhzKFVXVVv5yXRioO9vMv0i8uxShqD2Lo/MbrNtRgi3eMFESd
1692+3NxUPXS1jMq2/SaXrENdKqNNi06LbnLaYpI3BLZ/Katq0V9ESlhcC2nT5uNBPiLr
1693+DNSekaIGobbTDkuV896L7jqsQpU+sgs4XqaISGgk2wAfnwbfpeiBCL8oH9yCYAO0
1694+1YlevrMGjBNvhysoABv7qaorqeL97ffRhjOZ72/fm2axD5l9MvWEFIf7L5uOah0f
1695+hF5vScQYgyWNuK8wjzT2tl0CuxvEyI7N4fkUEk+ZMkyI1Obx17p+d4SFyuq7wTXR
1696+05oWMsCMDyzxvFDv92w=
1697+-----END CERTIFICATE-----
1698diff --git a/test/fixtures/x509-escaping/alt-6-cert.pem b/test/fixtures/x509-escaping/alt-6-cert.pem
1699new file mode 100644
1700index 0000000000..6643519957
1701--- /dev/null
1702+++ b/test/fixtures/x509-escaping/alt-6-cert.pem
1703@@ -0,0 +1,28 @@
1704+-----BEGIN CERTIFICATE-----
1705+MIIEyzCCArOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1706+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1707+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1708+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1709+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1710+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1711+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1712+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1713+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1714+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1715+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1716+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1717+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1718+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1719+GjAYMBYGA1UdEQQPMA2CC2V45G1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4ICAQBB
1720+lBfIjUH7/PbpC00TWTOSR6sAzyBr681lSxYAgFLduDdfR/bTkI1p7txIAgennoUq
1721++9slIIMaR799BUtQDfAQRYdbsWiG/+5Lj3JXs33LPPTdW1C97LOPlnnbRJh1sjbi
1722+UfGdxvdPA6iuyWhfwPZd+4IrcN+kefkvEnRkvDMGwmfmKQDjbu2mSIAIe+ECyLLu
1723+wdSI2sPBSUKQEKk+dABYq9TcdxlA+OSPjgs5ZF3NK3s/or7ay2r/i8be5TswY4Up
1724+IwByEk+7AST6ijwi3P8EN0HAyyuOfpBelWZCQgdEGt40Mpa58AwBGqdrCZ5wDAz5
1725+nBx6GscZUsqG9sVM71Tgq7Bc1b69FXUYAhmFucnXizHv1Ys0oGQVza1tkKbaLEFQ
1726+WvXWc7zW/0hTzvmtogKn/oM6GoNcQiW8KCwaCJq1TTv7Tip9znfB496tDruOr+2w
1727+HoqZTJ7ERklz0mlZ38ISTuaz+Qkn1KjBYh4tgP/wZIjIyppAaAr+JdqXzBejfb4M
1728+6x0S1AG9QgvyR1xDv3Vljjkh3m55kktTWSOfjS6aSzomaAyVAgi/vhHkxhsoBhgQ
1729+41+ffkhM9ps9wkmguwqOXsByQAZUQEJQigO39qYuGuJEDV8Bu8i/T5BuuJWP4BRF
1730+X+now5ObP73ufyFwYGsSgblivHUX4z/zAt4kp4AMXw==
1731+-----END CERTIFICATE-----
1732diff --git a/test/fixtures/x509-escaping/alt-7-cert.pem b/test/fixtures/x509-escaping/alt-7-cert.pem
1733new file mode 100644
1734index 0000000000..6c0f287a1b
1735--- /dev/null
1736+++ b/test/fixtures/x509-escaping/alt-7-cert.pem
1737@@ -0,0 +1,28 @@
1738+-----BEGIN CERTIFICATE-----
1739+MIIE0jCCArqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1740+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1741+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1742+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1743+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1744+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1745+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1746+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1747+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1748+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1749+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1750+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1751+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1752+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1753+ITAfMB0GA1UdEQQWMBSCEiJldmlsLmV4YW1wbGUuY29tIjANBgkqhkiG9w0BAQsF
1754+AAOCAgEAKmYr4QEnNq1Sy9lYePNRR60jufFXk44bczNT/wA6kvXKgv472V9wltVb
1755+yJVvYUWkTO8ahlELNLfqRcuih6myV64WJoewog8mwby0lBYr6bAz86DdeN/B9rFD
1756+OYnev1Ux4um45l42XP8acgJCoqn8+EE+H4AeMrz2xxHt+IDy4vUOowZna82f1Pcp
1757+O+vhod2uXlukfnhofVK4lMHl4++4kECkmUYl8U+L/zXwzOb4S3Yksffmadgo7ERk
1758+rJYLMLztvCk6TtP+p4NcvrE90dmss7R8hfw3asfjXsRbAMigdfSMKzGB2IHoHeV6
1759+fpmJy6kotfwulDrbr2QtrWOYdMrm1wT6ohT355KZQxcZr3VcK9gqEjcYafqIsXtA
1760+wYAaorKXaz7UkmFCDbk/24UuHgNgCl4KkGsFNwW6whTMpb9WnvPR7F798tiIbOL+
1761+FK6yA1q3Z2500lmloQWcUFBX48DViG3bsTJ9wmQ28aPqHVd5gTmTm/7W2iRGx36N
1762+PmbAk17J/bUzUSORgrPi2FLNNFg64x40pfdAyrF9ZBNcsVCFCUgOQHgMh4OjX/n7
1763+khmNbMYiOvJEoUbZ9flNr4AYY3ucpxQ2peTl4DNsVZZ8Xyh96h3URu63Ji9+xLrQ
1764+jSUtNHUCJaC3E9yTaIDc8jMli9s5/ElDZRkPxRP8o4VOt9KcLvU=
1765+-----END CERTIFICATE-----
1766diff --git a/test/fixtures/x509-escaping/alt-8-cert.pem b/test/fixtures/x509-escaping/alt-8-cert.pem
1767new file mode 100644
1768index 0000000000..201b520f8b
1769--- /dev/null
1770+++ b/test/fixtures/x509-escaping/alt-8-cert.pem
1771@@ -0,0 +1,28 @@
1772+-----BEGIN CERTIFICATE-----
1773+MIIExDCCAqygAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1774+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1775+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1776+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1777+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1778+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1779+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1780+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1781+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1782+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1783+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1784+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1785+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1786+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1787+EzARMA8GA1UdEQQIMAaHBAgICAgwDQYJKoZIhvcNAQELBQADggIBAHfvavrzBLuS
1788+MMJwNkJGVt1W856zeZ6NZJ5vx2ZXziYxAkzw9N0pLHwgfzS8pXEPSZ6vMoeYMaH0
1789+zr/S5tHSMGEwOp/dIoxE4Hm1uMzugHFxNp34hvqsaDbwKMpQQzEPhN1QvAkD9IXL
1790+H2wOLqm+ZaTkT3OvOyJoml56wyUJ0nU746RuXgJHTFiWsUTPqT9bvofedC80MUyH
1791+MX2lA1oy8nzJa9h7JqsxOE4uccRhpCRf+PxeYvOdsUxyDWw8+rjwe4Ulr0yVjwnD
1792+x9ha/fTl96mYXyJGLtQvZmkllrctxcs0o82+wMZWBw4iPH/VnI7dj36b2uIHdrrf
1793+cVurEPcVE03zLwukjQPZh9otleTwmQI1wqg/Gm2OahXy/0f0fpBDQnPycczn8nFw
1794+nj6avmHubWVvzmEoKmOtavGEAbUn7ntQfsvM5JpiM+ck3MDMP9i9cMZvWKH8Eial
1795+ZnYcXkgAatWwp4Cbsv4H7LMNisKjrcY+r+MpaYYIpTRNp/s/P5bMCIVt07yosePg
1796+m9VWy03+hQJmD4/THeJsjuczPSBtsoJiKoTJ5TndmpFaG6J6lBVvpXJhoiW/QIgX
1797+u2QIb8Z6bRK/eQ8UVYm0/ZQLN+OOzYiQfm0AFbFpYhl46o6QNZ03P6GRLshv+N3E
1798+CX66ucPLd4QJitUy39LZjMlC0YxTZUry
1799+-----END CERTIFICATE-----
1800diff --git a/test/fixtures/x509-escaping/alt-9-cert.pem b/test/fixtures/x509-escaping/alt-9-cert.pem
1801new file mode 100644
1802index 0000000000..660e65b8ed
1803--- /dev/null
1804+++ b/test/fixtures/x509-escaping/alt-9-cert.pem
1805@@ -0,0 +1,28 @@
1806+-----BEGIN CERTIFICATE-----
1807+MIIExDCCAqygAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
1808+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
1809+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
1810+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
1811+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
1812+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
1813+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
1814+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
1815+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
1816+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
1817+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
1818+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
1819+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
1820+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
1821+EzARMA8GA1UdEQQIMAaHBAgIBAQwDQYJKoZIhvcNAQELBQADggIBAIefUJjnOtt8
1822+viFkr3lupabUMwSgtBXVCp+M9xhKqcSnYReSgg/LcqVDaXmU4s23n0Bc0M51HQMG
1823+puTpfr34ZUSQiLup9huELm5L+lcpYANJsKrBo+vz1w+fkPlcxXvXHpLzgb393XSJ
1824+/Prn7lNBrrh9b74azUEhz1KPmFbbMs7IwlhE1+stQ107VeSGvKlAOmaYdnVG1PXl
1825+AG7KJynpE5Ex8XF1ONQLneTdvo8gXZueb07SY+my5wrCQhSlh4/6Y2MnE9h+9ugx
1826+BfdU72okDaYRH1MAfFeAsUE7Y52cQqm26b7nBz0+IeP+uk7oqDLF+PGHfjeUGXGW
1827+aGFfaLk8Dl2gMg1DsRE8zcT215Dl4rqOtwbhW8kX7XzYE0sA7cnyZ0daLrrtxwe6
1828+MhrAOjYklRZpwUvy6E2IyipKwWSuKHLUk3mVxPrxVqvye2enZWW1PJeHNdL//Ogx
1829+5Mm++BOTNR+61pg/UrATlO3GMK6ggAfkP8H1r3jp24hc/TkXRkoUuWZqtjC5+qwB
1830+KVIPlr+/0zIhzDjNbN0TMgqv/Yz4/wCUjsmCPJu21C3+BP2O5ZD2e4hYe/X9kuhC
1831+YGWTf8dpq0LgYgVHqwXo0gCU/Ich9KtaJmCgZRUrzMl1aIYhqpuR2EW8H1bs3a0P
1832+/7wXhGudHCwm6j2H5/tbsREeYInl3mv4
1833+-----END CERTIFICATE-----
1834diff --git a/test/fixtures/x509-escaping/create-certs.js b/test/fixtures/x509-escaping/create-certs.js
1835new file mode 100644
1836index 0000000000..b84547e1d0
1837--- /dev/null
1838+++ b/test/fixtures/x509-escaping/create-certs.js
1839@@ -0,0 +1,502 @@
1840+'use strict';
1841+
1842+const asn1 = require('asn1.js');
1843+const crypto = require('crypto');
1844+const { writeFileSync } = require('fs');
1845+const rfc5280 = require('asn1.js-rfc5280');
1846+const BN = asn1.bignum;
1847+
1848+const oid = {
1849+ commonName: [2, 5, 4, 3],
1850+ countryName: [2, 5, 4, 6],
1851+ localityName: [2, 5, 4, 7],
1852+ rsaEncryption: [1, 2, 840, 113549, 1, 1, 1],
1853+ sha256WithRSAEncryption: [1, 2, 840, 113549, 1, 1, 11],
1854+ xmppAddr: [1, 3, 6, 1, 5, 5, 7, 8, 5],
1855+ srvName: [1, 3, 6, 1, 5, 5, 7, 8, 7],
1856+ ocsp: [1, 3, 6, 1, 5, 5, 7, 48, 1],
1857+ caIssuers: [1, 3, 6, 1, 5, 5, 7, 48, 2],
1858+ privateUnrecognized: [1, 3, 9999, 12, 34]
1859+};
1860+
1861+const digest = 'SHA256';
1862+
1863+const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {
1864+ modulusLength: 4096,
1865+ publicKeyEncoding: {
1866+ type: 'pkcs1',
1867+ format: 'der'
1868+ }
1869+});
1870+
1871+writeFileSync('server-key.pem', privateKey.export({
1872+ type: 'pkcs8',
1873+ format: 'pem'
1874+}));
1875+
1876+const now = Date.now();
1877+const days = 3650;
1878+
1879+function utilType(name, fn) {
1880+ return asn1.define(name, function() {
1881+ this[fn]();
1882+ });
1883+}
1884+
1885+const Null_ = utilType('Null_', 'null_');
1886+const null_ = Null_.encode('der');
1887+
1888+const IA5String = utilType('IA5String', 'ia5str');
1889+const PrintableString = utilType('PrintableString', 'printstr');
1890+const UTF8String = utilType('UTF8String', 'utf8str');
1891+
1892+const subjectCommonName = PrintableString.encode('evil.example.com', 'der');
1893+
1894+const sans = [
1895+ { type: 'dNSName', value: 'good.example.com, DNS:evil.example.com' },
1896+ { type: 'uniformResourceIdentifier', value: 'http://example.com/' },
1897+ { type: 'uniformResourceIdentifier', value: 'http://example.com/?a=b&c=d' },
1898+ { type: 'uniformResourceIdentifier', value: 'http://example.com/a,b' },
1899+ { type: 'uniformResourceIdentifier', value: 'http://example.com/a%2Cb' },
1900+ {
1901+ type: 'uniformResourceIdentifier',
1902+ value: 'http://example.com/a, DNS:good.example.com'
1903+ },
1904+ { type: 'dNSName', value: Buffer.from('exämple.com', 'latin1') },
1905+ { type: 'dNSName', value: '"evil.example.com"' },
1906+ { type: 'iPAddress', value: Buffer.from('08080808', 'hex') },
1907+ { type: 'iPAddress', value: Buffer.from('08080404', 'hex') },
1908+ { type: 'iPAddress', value: Buffer.from('0008080404', 'hex') },
1909+ { type: 'iPAddress', value: Buffer.from('000102030405', 'hex') },
1910+ {
1911+ type: 'iPAddress',
1912+ value: Buffer.from('0a0b0c0d0e0f0000000000007a7b7c7d', 'hex')
1913+ },
1914+ { type: 'rfc822Name', value: 'foo@example.com' },
1915+ { type: 'rfc822Name', value: 'foo@example.com, DNS:good.example.com' },
1916+ {
1917+ type: 'directoryName',
1918+ value: {
1919+ type: 'rdnSequence',
1920+ value: [
1921+ [
1922+ {
1923+ type: oid.countryName,
1924+ value: PrintableString.encode('DE', 'der')
1925+ }
1926+ ],
1927+ [
1928+ {
1929+ type: oid.localityName,
1930+ value: UTF8String.encode('Hannover', 'der')
1931+ }
1932+ ]
1933+ ]
1934+ }
1935+ },
1936+ {
1937+ type: 'directoryName',
1938+ value: {
1939+ type: 'rdnSequence',
1940+ value: [
1941+ [
1942+ {
1943+ type: oid.countryName,
1944+ value: PrintableString.encode('DE', 'der')
1945+ }
1946+ ],
1947+ [
1948+ {
1949+ type: oid.localityName,
1950+ value: UTF8String.encode('München', 'der')
1951+ }
1952+ ]
1953+ ]
1954+ }
1955+ },
1956+ {
1957+ type: 'directoryName',
1958+ value: {
1959+ type: 'rdnSequence',
1960+ value: [
1961+ [
1962+ {
1963+ type: oid.countryName,
1964+ value: PrintableString.encode('DE', 'der')
1965+ }
1966+ ],
1967+ [
1968+ {
1969+ type: oid.localityName,
1970+ value: UTF8String.encode('Berlin, DNS:good.example.com', 'der')
1971+ }
1972+ ]
1973+ ]
1974+ }
1975+ },
1976+ {
1977+ type: 'directoryName',
1978+ value: {
1979+ type: 'rdnSequence',
1980+ value: [
1981+ [
1982+ {
1983+ type: oid.countryName,
1984+ value: PrintableString.encode('DE', 'der')
1985+ }
1986+ ],
1987+ [
1988+ {
1989+ type: oid.localityName,
1990+ value: UTF8String.encode('Berlin, DNS:good.example.com\0evil.example.com', 'der')
1991+ }
1992+ ]
1993+ ]
1994+ }
1995+ },
1996+ {
1997+ type: 'directoryName',
1998+ value: {
1999+ type: 'rdnSequence',
2000+ value: [
2001+ [
2002+ {
2003+ type: oid.countryName,
2004+ value: PrintableString.encode('DE', 'der')
2005+ }
2006+ ],
2007+ [
2008+ {
2009+ type: oid.localityName,
2010+ value: UTF8String.encode(
2011+ 'Berlin, DNS:good.example.com\\\0evil.example.com', 'der')
2012+ }
2013+ ]
2014+ ]
2015+ }
2016+ },
2017+ {
2018+ type: 'directoryName',
2019+ value: {
2020+ type: 'rdnSequence',
2021+ value: [
2022+ [
2023+ {
2024+ type: oid.countryName,
2025+ value: PrintableString.encode('DE', 'der')
2026+ }
2027+ ],
2028+ [
2029+ {
2030+ type: oid.localityName,
2031+ value: UTF8String.encode('Berlin\r\n', 'der')
2032+ }
2033+ ]
2034+ ]
2035+ }
2036+ },
2037+ {
2038+ type: 'directoryName',
2039+ value: {
2040+ type: 'rdnSequence',
2041+ value: [
2042+ [
2043+ {
2044+ type: oid.countryName,
2045+ value: PrintableString.encode('DE', 'der')
2046+ }
2047+ ],
2048+ [
2049+ {
2050+ type: oid.localityName,
2051+ value: UTF8String.encode('Berlin/CN=good.example.com', 'der')
2052+ }
2053+ ]
2054+ ]
2055+ }
2056+ },
2057+ {
2058+ type: 'registeredID',
2059+ value: oid.sha256WithRSAEncryption
2060+ },
2061+ {
2062+ type: 'registeredID',
2063+ value: oid.privateUnrecognized
2064+ },
2065+ {
2066+ type: 'otherName',
2067+ value: {
2068+ 'type-id': oid.xmppAddr,
2069+ value: UTF8String.encode('abc123', 'der')
2070+ }
2071+ },
2072+ {
2073+ type: 'otherName',
2074+ value: {
2075+ 'type-id': oid.xmppAddr,
2076+ value: UTF8String.encode('abc123, DNS:good.example.com', 'der')
2077+ }
2078+ },
2079+ {
2080+ type: 'otherName',
2081+ value: {
2082+ 'type-id': oid.xmppAddr,
2083+ value: UTF8String.encode('good.example.com\0abc123', 'der')
2084+ }
2085+ },
2086+ {
2087+ type: 'otherName',
2088+ value: {
2089+ 'type-id': oid.privateUnrecognized,
2090+ value: UTF8String.encode('abc123', 'der')
2091+ }
2092+ },
2093+ {
2094+ type: 'otherName',
2095+ value: {
2096+ 'type-id': oid.srvName,
2097+ value: IA5String.encode('abc123', 'der')
2098+ }
2099+ },
2100+ {
2101+ type: 'otherName',
2102+ value: {
2103+ 'type-id': oid.srvName,
2104+ value: UTF8String.encode('abc123', 'der')
2105+ }
2106+ },
2107+ {
2108+ type: 'otherName',
2109+ value: {
2110+ 'type-id': oid.srvName,
2111+ value: IA5String.encode('abc\0def', 'der')
2112+ }
2113+ }
2114+];
2115+
2116+for (let i = 0; i < sans.length; i++) {
2117+ const san = sans[i];
2118+
2119+ const tbs = {
2120+ version: 'v3',
2121+ serialNumber: new BN('01', 16),
2122+ signature: {
2123+ algorithm: oid.sha256WithRSAEncryption,
2124+ parameters: null_
2125+ },
2126+ issuer: {
2127+ type: 'rdnSequence',
2128+ value: [
2129+ [
2130+ { type: oid.commonName, value: subjectCommonName }
2131+ ]
2132+ ]
2133+ },
2134+ validity: {
2135+ notBefore: { type: 'utcTime', value: now },
2136+ notAfter: { type: 'utcTime', value: now + days * 86400000 }
2137+ },
2138+ subject: {
2139+ type: 'rdnSequence',
2140+ value: [
2141+ [
2142+ { type: oid.commonName, value: subjectCommonName }
2143+ ]
2144+ ]
2145+ },
2146+ subjectPublicKeyInfo: {
2147+ algorithm: {
2148+ algorithm: oid.rsaEncryption,
2149+ parameters: null_
2150+ },
2151+ subjectPublicKey: {
2152+ unused: 0,
2153+ data: publicKey
2154+ }
2155+ },
2156+ extensions: [
2157+ {
2158+ extnID: 'subjectAlternativeName',
2159+ critical: false,
2160+ extnValue: [san]
2161+ }
2162+ ]
2163+ };
2164+
2165+ // Self-sign the certificate.
2166+ const tbsDer = rfc5280.TBSCertificate.encode(tbs, 'der');
2167+ const signature = crypto.createSign(digest).update(tbsDer).sign(privateKey);
2168+
2169+ // Construct the signed certificate.
2170+ const cert = {
2171+ tbsCertificate: tbs,
2172+ signatureAlgorithm: {
2173+ algorithm: oid.sha256WithRSAEncryption,
2174+ parameters: null_
2175+ },
2176+ signature: {
2177+ unused: 0,
2178+ data: signature
2179+ }
2180+ };
2181+
2182+ // Store the signed certificate.
2183+ const pem = rfc5280.Certificate.encode(cert, 'pem', {
2184+ label: 'CERTIFICATE'
2185+ });
2186+ writeFileSync(`./alt-${i}-cert.pem`, `${pem}\n`);
2187+}
2188+
2189+const infoAccessExtensions = [
2190+ [
2191+ {
2192+ accessMethod: oid.ocsp,
2193+ accessLocation: {
2194+ type: 'uniformResourceIdentifier',
2195+ value: 'http://good.example.com/\nOCSP - URI:http://evil.example.com/',
2196+ },
2197+ },
2198+ ],
2199+ [
2200+ {
2201+ accessMethod: oid.caIssuers,
2202+ accessLocation: {
2203+ type: 'uniformResourceIdentifier',
2204+ value: 'http://ca.example.com/\nOCSP - URI:http://evil.example.com',
2205+ },
2206+ },
2207+ {
2208+ accessMethod: oid.ocsp,
2209+ accessLocation: {
2210+ type: 'dNSName',
2211+ value: 'good.example.com\nOCSP - URI:http://ca.nodejs.org/ca.cert',
2212+ },
2213+ },
2214+ ],
2215+ [
2216+ {
2217+ accessMethod: oid.privateUnrecognized,
2218+ accessLocation: {
2219+ type: 'uniformResourceIdentifier',
2220+ value: 'http://ca.example.com/',
2221+ },
2222+ },
2223+ ],
2224+ [
2225+ {
2226+ accessMethod: oid.ocsp,
2227+ accessLocation: {
2228+ type: 'otherName',
2229+ value: {
2230+ 'type-id': oid.xmppAddr,
2231+ value: UTF8String.encode('good.example.com', 'der'),
2232+ },
2233+ },
2234+ },
2235+ {
2236+ accessMethod: oid.ocsp,
2237+ accessLocation: {
2238+ type: 'otherName',
2239+ value: {
2240+ 'type-id': oid.privateUnrecognized,
2241+ value: UTF8String.encode('abc123', 'der')
2242+ },
2243+ },
2244+ },
2245+ {
2246+ accessMethod: oid.ocsp,
2247+ accessLocation: {
2248+ type: 'otherName',
2249+ value: {
2250+ 'type-id': oid.srvName,
2251+ value: IA5String.encode('abc123', 'der')
2252+ }
2253+ }
2254+ },
2255+ ],
2256+ [
2257+ {
2258+ accessMethod: oid.ocsp,
2259+ accessLocation: {
2260+ type: 'otherName',
2261+ value: {
2262+ 'type-id': oid.xmppAddr,
2263+ value: UTF8String.encode('good.example.com\0abc123', 'der'),
2264+ },
2265+ },
2266+ },
2267+ ],
2268+];
2269+
2270+for (let i = 0; i < infoAccessExtensions.length; i++) {
2271+ const infoAccess = infoAccessExtensions[i];
2272+
2273+ const tbs = {
2274+ version: 'v3',
2275+ serialNumber: new BN('01', 16),
2276+ signature: {
2277+ algorithm: oid.sha256WithRSAEncryption,
2278+ parameters: null_
2279+ },
2280+ issuer: {
2281+ type: 'rdnSequence',
2282+ value: [
2283+ [
2284+ { type: oid.commonName, value: subjectCommonName }
2285+ ]
2286+ ]
2287+ },
2288+ validity: {
2289+ notBefore: { type: 'utcTime', value: now },
2290+ notAfter: { type: 'utcTime', value: now + days * 86400000 }
2291+ },
2292+ subject: {
2293+ type: 'rdnSequence',
2294+ value: [
2295+ [
2296+ { type: oid.commonName, value: subjectCommonName }
2297+ ]
2298+ ]
2299+ },
2300+ subjectPublicKeyInfo: {
2301+ algorithm: {
2302+ algorithm: oid.rsaEncryption,
2303+ parameters: null_
2304+ },
2305+ subjectPublicKey: {
2306+ unused: 0,
2307+ data: publicKey
2308+ }
2309+ },
2310+ extensions: [
2311+ {
2312+ extnID: 'authorityInformationAccess',
2313+ critical: false,
2314+ extnValue: infoAccess
2315+ }
2316+ ]
2317+ };
2318+
2319+ // Self-sign the certificate.
2320+ const tbsDer = rfc5280.TBSCertificate.encode(tbs, 'der');
2321+ const signature = crypto.createSign(digest).update(tbsDer).sign(privateKey);
2322+
2323+ // Construct the signed certificate.
2324+ const cert = {
2325+ tbsCertificate: tbs,
2326+ signatureAlgorithm: {
2327+ algorithm: oid.sha256WithRSAEncryption,
2328+ parameters: null_
2329+ },
2330+ signature: {
2331+ unused: 0,
2332+ data: signature
2333+ }
2334+ };
2335+
2336+ // Store the signed certificate.
2337+ const pem = rfc5280.Certificate.encode(cert, 'pem', {
2338+ label: 'CERTIFICATE'
2339+ });
2340+ writeFileSync(`./info-${i}-cert.pem`, `${pem}\n`);
2341+}
2342diff --git a/test/fixtures/x509-escaping/google/intermediate.pem b/test/fixtures/x509-escaping/google/intermediate.pem
2343new file mode 100644
2344index 0000000000..9d2aeb32c4
2345--- /dev/null
2346+++ b/test/fixtures/x509-escaping/google/intermediate.pem
2347@@ -0,0 +1,11 @@
2348+-----BEGIN CERTIFICATE-----
2349+MIIBjjCCATSgAwIBAgIBAjAKBggqhkjOPQQDAjAPMQ0wCwYDVQQDEwRSb290MCAX
2350+DTAwMDEwMTAwMDAwMFoYDzIwOTkwMTAxMDAwMDAwWjAXMRUwEwYDVQQDEwxJbnRl
2351+cm1lZGlhdGUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR7DaOQvpvA47q2XxjM
2352+qxJVf/FvZm2ftiFRXNJMe/fhSlDh2CybdkFIw2mE5g4ShW5UBJe+sohqy5V9WRkY
2353+tM/Bo3cwdTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQlGcYbYohaK3S+XGeq
2354+CTi4LLHeLTAfBgNVHSMEGDAWgBQlGcYbYohaK3S+XGeqCTi4LLHeLTAiBgNVHR4B
2355+Af8EGDAWoBQwEoIQYXR0YWNrZXIuZXhhbXBsZTAKBggqhkjOPQQDAgNIADBFAiEA
2356+uZhmF3buUdhzHjXLZQSOyT41DqUUX/VKBEraDu+gj+wCIG/R1arbHFRFnEuoVgZI
2357+bihwUpUZjIZ5YwJcBu6yuXlZ
2358+-----END CERTIFICATE-----
2359diff --git a/test/fixtures/x509-escaping/google/key.pem b/test/fixtures/x509-escaping/google/key.pem
2360new file mode 100644
2361index 0000000000..102a9d8816
2362--- /dev/null
2363+++ b/test/fixtures/x509-escaping/google/key.pem
2364@@ -0,0 +1,5 @@
2365+-----BEGIN PRIVATE KEY-----
2366+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgaNbpDxJET5xVHxd/
2367+ig5x2u2KUIe0jaCVWqarpIN/582hRANCAAR7DaOQvpvA47q2XxjMqxJVf/FvZm2f
2368+tiFRXNJMe/fhSlDh2CybdkFIw2mE5g4ShW5UBJe+sohqy5V9WRkYtM/B
2369+-----END PRIVATE KEY-----
2370diff --git a/test/fixtures/x509-escaping/google/leaf0.pem b/test/fixtures/x509-escaping/google/leaf0.pem
2371new file mode 100644
2372index 0000000000..ce19dc9699
2373--- /dev/null
2374+++ b/test/fixtures/x509-escaping/google/leaf0.pem
2375@@ -0,0 +1,10 @@
2376+-----BEGIN CERTIFICATE-----
2377+MIIBajCCARCgAwIBAgIBAzAKBggqhkjOPQQDAjAXMRUwEwYDVQQDEwxJbnRlcm1l
2378+ZGlhdGUwIBcNMDAwMTAxMDAwMDAwWhgPMjA5OTAxMDEwMDAwMDBaMA8xDTALBgNV
2379+BAMTBExlYWYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR7DaOQvpvA47q2XxjM
2380+qxJVf/FvZm2ftiFRXNJMe/fhSlDh2CybdkFIw2mE5g4ShW5UBJe+sohqy5V9WRkY
2381+tM/Bo1MwUTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFCUZxhtiiFordL5cZ6oJ
2382+OLgssd4tMCAGA1UdEQQZMBeCFWJsYWguYXR0YWNrZXIuZXhhbXBsZTAKBggqhkjO
2383+PQQDAgNIADBFAiEA4NgHDxVrBjNW+So4MrRZMwDknvjRaBsB4j2IwVRKl4sCIDpg
2384+Bhm4ZdHwlUYrALkXa3dFBy8kXBkVumY7UJpbB2mO
2385+-----END CERTIFICATE-----
2386diff --git a/test/fixtures/x509-escaping/google/leaf1.pem b/test/fixtures/x509-escaping/google/leaf1.pem
2387new file mode 100644
2388index 0000000000..0b45056656
2389--- /dev/null
2390+++ b/test/fixtures/x509-escaping/google/leaf1.pem
2391@@ -0,0 +1,10 @@
2392+-----BEGIN CERTIFICATE-----
2393+MIIBdTCCARygAwIBAgIBBDAKBggqhkjOPQQDAjAXMRUwEwYDVQQDEwxJbnRlcm1l
2394+ZGlhdGUwIBcNMDAwMTAxMDAwMDAwWhgPMjA5OTAxMDEwMDAwMDBaMA8xDTALBgNV
2395+BAMTBExlYWYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR7DaOQvpvA47q2XxjM
2396+qxJVf/FvZm2ftiFRXNJMe/fhSlDh2CybdkFIw2mE5g4ShW5UBJe+sohqy5V9WRkY
2397+tM/Bo18wXTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFCUZxhtiiFordL5cZ6oJ
2398+OLgssd4tMCwGA1UdEQQlMCOCCm5vZGVqcy5vcmeCFWJsYWguYXR0YWNrZXIuZXhh
2399+bXBsZTAKBggqhkjOPQQDAgNHADBEAiAOFFOCfA6c/iZWxbDn5QMjNdtZbtJPBcRv
2400+uEgSqWrGTAIgK5RK0xGK8UZb2aM2VjGNTYozlcwKaLgQukA+UnKrrJg=
2401+-----END CERTIFICATE-----
2402diff --git a/test/fixtures/x509-escaping/google/leaf2.pem b/test/fixtures/x509-escaping/google/leaf2.pem
2403new file mode 100644
2404index 0000000000..9cf03fae7d
2405--- /dev/null
2406+++ b/test/fixtures/x509-escaping/google/leaf2.pem
2407@@ -0,0 +1,10 @@
2408+-----BEGIN CERTIFICATE-----
2409+MIIBejCCASCgAwIBAgIBBTAKBggqhkjOPQQDAjAXMRUwEwYDVQQDEwxJbnRlcm1l
2410+ZGlhdGUwIBcNMDAwMTAxMDAwMDAwWhgPMjA5OTAxMDEwMDAwMDBaMA8xDTALBgNV
2411+BAMTBExlYWYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR7DaOQvpvA47q2XxjM
2412+qxJVf/FvZm2ftiFRXNJMe/fhSlDh2CybdkFIw2mE5g4ShW5UBJe+sohqy5V9WRkY
2413+tM/Bo2MwYTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFCUZxhtiiFordL5cZ6oJ
2414+OLgssd4tMDAGA1UdEQQpMCeCJW5vZGVqcy5vcmcsIEROUzpibGFoLmF0dGFja2Vy
2415+LmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIgWfT1VXQA79PxgM0DsfeoiwZCc2Be
2416+v3/RCRYoRky9DgICIQDUTjndnBQ0KeIWhuMjtSz1C5uPUYofKe7pV2qb/57kvA==
2417+-----END CERTIFICATE-----
2418diff --git a/test/fixtures/x509-escaping/google/leaf3.pem b/test/fixtures/x509-escaping/google/leaf3.pem
2419new file mode 100644
2420index 0000000000..55a64fdc89
2421--- /dev/null
2422+++ b/test/fixtures/x509-escaping/google/leaf3.pem
2423@@ -0,0 +1,10 @@
2424+-----BEGIN CERTIFICATE-----
2425+MIIBZzCCAQ2gAwIBAgIBBjAKBggqhkjOPQQDAjAXMRUwEwYDVQQDEwxJbnRlcm1l
2426+ZGlhdGUwIBcNMDAwMTAxMDAwMDAwWhgPMjA5OTAxMDEwMDAwMDBaMA8xDTALBgNV
2427+BAMTBExlYWYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR7DaOQvpvA47q2XxjM
2428+qxJVf/FvZm2ftiFRXNJMe/fhSlDh2CybdkFIw2mE5g4ShW5UBJe+sohqy5V9WRkY
2429+tM/Bo1AwTjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFCUZxhtiiFordL5cZ6oJ
2430+OLgssd4tMB0GA1UdEQQWMBSGEmh0dHBzOi8vbm9kZWpzLm9yZzAKBggqhkjOPQQD
2431+AgNIADBFAiEArZgaxFBuPYFWCXeFTkXhV57MKxG/tIJ2Z3Wzts2Im7QCICoukuRf
2432+EsQN7g6h30fRuLOIdbfCCduc7YVpkkSlwe99
2433+-----END CERTIFICATE-----
2434diff --git a/test/fixtures/x509-escaping/google/leaf4.pem b/test/fixtures/x509-escaping/google/leaf4.pem
2435new file mode 100644
2436index 0000000000..668a659f45
2437--- /dev/null
2438+++ b/test/fixtures/x509-escaping/google/leaf4.pem
2439@@ -0,0 +1,10 @@
2440+-----BEGIN CERTIFICATE-----
2441+MIIBdTCCARugAwIBAgIBBzAKBggqhkjOPQQDAjAXMRUwEwYDVQQDEwxJbnRlcm1l
2442+ZGlhdGUwIBcNMDAwMTAxMDAwMDAwWhgPMjA5OTAxMDEwMDAwMDBaMDwxHzAdBgNV
2443+BAsMFm9yZyB1bml0CkNOPW5vZGVqcy5vcmcxGTAXBgNVBAMTEGF0dGFja2VyLmV4
2444+YW1wbGUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR7DaOQvpvA47q2XxjMqxJV
2445+f/FvZm2ftiFRXNJMe/fhSlDh2CybdkFIw2mE5g4ShW5UBJe+sohqy5V9WRkYtM/B
2446+ozEwLzAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFCUZxhtiiFordL5cZ6oJOLgs
2447+sd4tMAoGCCqGSM49BAMCA0gAMEUCIQCpchwik2NT0v8ifDT8aMqOLv5YwqB7oeOu
2448+LincYQYMagIgZc2U7DBrdEAWNfuAJx4I+ZkluIcswcdnOhbriOrTSHg=
2449+-----END CERTIFICATE-----
2450diff --git a/test/fixtures/x509-escaping/google/root.pem b/test/fixtures/x509-escaping/google/root.pem
2451new file mode 100644
2452index 0000000000..68eb00ae86
2453--- /dev/null
2454+++ b/test/fixtures/x509-escaping/google/root.pem
2455@@ -0,0 +1,9 @@
2456+-----BEGIN CERTIFICATE-----
2457+MIIBQTCB56ADAgECAgEBMAoGCCqGSM49BAMCMA8xDTALBgNVBAMTBFJvb3QwIBcN
2458+MDAwMTAxMDAwMDAwWhgPMjA5OTAxMDEwMDAwMDBaMA8xDTALBgNVBAMTBFJvb3Qw
2459+WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR7DaOQvpvA47q2XxjMqxJVf/FvZm2f
2460+tiFRXNJMe/fhSlDh2CybdkFIw2mE5g4ShW5UBJe+sohqy5V9WRkYtM/BozIwMDAP
2461+BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQlGcYbYohaK3S+XGeqCTi4LLHeLTAK
2462+BggqhkjOPQQDAgNJADBGAiEA+Y5oEpcG6aRK5qQFLYRi2FrOSSLF1/dI4HtBh0mk
2463+GFoCIQD1DpNg6m5ZaogRW1mY1wmR5HFIr3gG8PYDRimQogXUxg==
2464+-----END CERTIFICATE-----
2465diff --git a/test/fixtures/x509-escaping/info-0-cert.pem b/test/fixtures/x509-escaping/info-0-cert.pem
2466new file mode 100644
2467index 0000000000..6872b9870a
2468--- /dev/null
2469+++ b/test/fixtures/x509-escaping/info-0-cert.pem
2470@@ -0,0 +1,30 @@
2471+-----BEGIN CERTIFICATE-----
2472+MIIFDTCCAvWgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
2473+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
2474+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
2475+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
2476+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
2477+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
2478+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
2479+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
2480+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
2481+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
2482+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
2483+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
2484+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
2485+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
2486+XDBaMFgGCCsGAQUFBwEBBEwwSjBIBggrBgEFBQcwAYY8aHR0cDovL2dvb2QuZXhh
2487+bXBsZS5jb20vCk9DU1AgLSBVUkk6aHR0cDovL2V2aWwuZXhhbXBsZS5jb20vMA0G
2488+CSqGSIb3DQEBCwUAA4ICAQAAd/bIBmSIOJg+Rp96/BDpsZQYgYTyBNWrnBkuHQ0M
2489+bovgqEEI/5xiYGEzXhrzmWrUoG40PDeVrpCSsW5m+bsO4zDQeWW5mXejbr0Iwflf
2490+TYDxwGUUakAcZ1c5yJ/ABjKy0Tocb9bSzln+tc+HNStp86bbgrhb/wjddn6ca21V
2491+cuNFZbN+0SM0LxcWO8oGKXF0HFo0durGhamcH5B/D38FYkaVR5QXoOsWVqtPFjW2
2492+t67rmKS6XKaz2JhZDpWDZmDofCoFu/zlkPHXkq7yyrkJ/8qpJCznkZmLn+B1WA+y
2493+SrSOYMpQ6RnzMx7wK5UafX5J+lMv16+LTb/n1KAd4zElcqt5eRPLcEuknIEgC2X/
2494+AY1ooyN/Xb4QnqvtTmhzIDb7lzzMowi5QrG3rRYMldxG2Rdqwjc8qa5Tgh7EsiU8
2495+A/n5X/6cxA1zoyakSHFXzGtazIkPc+zFfOaV1+gpJtd2vD2T+FrmkL1fgazuHXNZ
2496+hAQq0RGZWPsCdxm7dG4w5bd3YgRKfD2ck+b9Imu0ta4pqMDHZYgncaeOuuHzHgXA
2497+MIvxIG5JfwYUJLUqBUz8hwDVcNMpnscyn2msdpiwXK0AahucBQjbyZ6sovoxmgk5
2498+xLdnq2GTtdghwdkF9DYK0ZekDlk1XWbP0tR5Cevo6WlMx+cbEBG+OSfNd8/dFrkd
2499+aw==
2500+-----END CERTIFICATE-----
2501diff --git a/test/fixtures/x509-escaping/info-1-cert.pem b/test/fixtures/x509-escaping/info-1-cert.pem
2502new file mode 100644
2503index 0000000000..05247873d8
2504--- /dev/null
2505+++ b/test/fixtures/x509-escaping/info-1-cert.pem
2506@@ -0,0 +1,31 @@
2507+-----BEGIN CERTIFICATE-----
2508+MIIFVTCCAz2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
2509+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
2510+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
2511+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
2512+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
2513+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
2514+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
2515+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
2516+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
2517+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
2518+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
2519+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
2520+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
2521+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
2522+gaMwgaAwgZ0GCCsGAQUFBwEBBIGQMIGNMEUGCCsGAQUFBzAChjlodHRwOi8vY2Eu
2523+ZXhhbXBsZS5jb20vCk9DU1AgLSBVUkk6aHR0cDovL2V2aWwuZXhhbXBsZS5jb20w
2524+RAYIKwYBBQUHMAGCOGdvb2QuZXhhbXBsZS5jb20KT0NTUCAtIFVSSTpodHRwOi8v
2525+Y2Eubm9kZWpzLm9yZy9jYS5jZXJ0MA0GCSqGSIb3DQEBCwUAA4ICAQCbwqw8YKIt
2526+Ht9qegR076xpnxuiH0THPGsgazvhCmEr5YHJ68sR1LexjneQDhpNXcnpYpfk6J4d
2527+Tu0ApMSbVypFyHcd88g0qVYI9JF+CTNnzut/Zn6xgnUjVjrSz6SZPhkMcBX9ahtY
2528+tzswzcyTzso5Do5pxvCWDI+bshgIhC3CYNyAjyOyyhnQrwcOcoatlhDmX1fCk+dC
2529+fhmzurBFNIz2gwDC7aRjcaUdTIlYnd6qHk5xLs3neBm44gNk17GazPIPo04LTKXs
2530+ZYzvDEUAdJ2FJMiYqSvvEv4k9ozx5HtwtncZpu46El2PQRANgj1UhemYVmHfbdU+
2531+7Q+rCv+Loq2v76fddhc1cM3gCQ+6SW2QmRo2rShRGxpuSuZiTngwgdQEGrkQq7Sv
2532+r695V7NlHWJgvv1r49wGmqWkviH5l6A0QdzL6TNYhwqCRsjxgsvCZUpOlZPASiME
2533+jhwBIOMy1YUSdEMnBrbuemawvbfocSuUlHaodwLZvwMgqHvNz/8ebMyRyyZrnmCx
2534+TYh8d0JIcA57VvfaZvvsPPV7TO7WLoJgbmuqM02JzzkJMh0fbt2oi1cqJL65V5Sn
2535+z0sXh/A/BzB4QawI93f9m0hX7RtuT1SolTNVyhg7dm1MwfO8khpfz5LLgflVwgN8
2536+6egKc6L755SlqZRMT03txH2UCBizLz1gjA==
2537+-----END CERTIFICATE-----
2538diff --git a/test/fixtures/x509-escaping/info-2-cert.pem b/test/fixtures/x509-escaping/info-2-cert.pem
2539new file mode 100644
2540index 0000000000..06212d4e12
2541--- /dev/null
2542+++ b/test/fixtures/x509-escaping/info-2-cert.pem
2543@@ -0,0 +1,29 @@
2544+-----BEGIN CERTIFICATE-----
2545+MIIE5DCCAsygAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
2546+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
2547+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
2548+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
2549+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
2550+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
2551+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
2552+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
2553+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
2554+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
2555+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
2556+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
2557+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
2558+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
2559+MzAxMC8GCCsGAQUFBwEBBCMwITAfBgUrzg8MIoYWaHR0cDovL2NhLmV4YW1wbGUu
2560+Y29tLzANBgkqhkiG9w0BAQsFAAOCAgEABR5VyTZEQ0AQvdqlk+IDQT85qyf891eN
2561+BREiSg5KCei9Kmubv3ZJGoNVwZgybr5sCi5GqWOtG7S0GXvzS6c2Qy+cW0R4DDYs
2562+s6IIUn+ex1XygGrRHTDHu6tEUwSJMmOMKBh+iLjhtamD+YHjgOLG3MfadO5/9mvp
2563+r412MPhU1VvQ3FC3dZmBUW2gIKNEU4mzwISgPkLJXmBsnxu8F9YqHPgppqsfJ9AF
2564+KIc2nX7N3s8w9fCc03FrihdkE2C802jy71px5aPqa1xrIT/YBq/1fKTcYRAWF/pd
2565+iy2G1v0pz0kYu2/yPIC/xlFcUgeFqR/biwxAD9T9rp7rq+dpIJA5BUCpXVULqhY1
2566+SVZ22WKS0NR5rbu4BPDMShTOiwaDSwFQtI0OxM0g5zVFVjFOc6YbFu7ZyfLQ582S
2567+vgVU5/vaHANnEsCSUegXyLofqxTMPbM1rqibFmv2A4pm1Mp18ZFmqwh8cm6C0f7F
2568+qjdzBuSkcktTCq/dLX5yTm9aocyzye9cfNBjiGUregJEF7sD3nzsokEGj+S320w2
2569+5yUl95xgrHr+5bdDUEox+trTeBnddC4VxrieeH+Wv45try0Go48yK7b1Aqfu9G4B
2570+B/as+upQ+YjMG8mAe6JJ9JibpTvTmatYAsssEKT1vDZ5trqo4C5/utfbuyaf7qtx
2571+O+jFfYToPtE=
2572+-----END CERTIFICATE-----
2573diff --git a/test/fixtures/x509-escaping/info-3-cert.pem b/test/fixtures/x509-escaping/info-3-cert.pem
2574new file mode 100644
2575index 0000000000..1825949bd3
2576--- /dev/null
2577+++ b/test/fixtures/x509-escaping/info-3-cert.pem
2578@@ -0,0 +1,30 @@
2579+-----BEGIN CERTIFICATE-----
2580+MIIFMDCCAxigAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
2581+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
2582+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
2583+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
2584+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
2585+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
2586+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
2587+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
2588+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
2589+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
2590+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
2591+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
2592+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
2593+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
2594+fzB9MHsGCCsGAQUFBwEBBG8wbTAqBggrBgEFBQcwAaAeBggrBgEFBQcIBaASDBBn
2595+b29kLmV4YW1wbGUuY29tMB0GCCsGAQUFBzABoBEGBSvODwwioAgMBmFiYzEyMzAg
2596+BggrBgEFBQcwAaAUBggrBgEFBQcIB6AIFgZhYmMxMjMwDQYJKoZIhvcNAQELBQAD
2597+ggIBACR9nH4pRlcSIIF9DEExlJvLtkeFWHGIAYLBuauHmdzPdbq9Py9M5DOcc7yd
2598+OQYVYwW26hASb+3CYzhRQaWKOR+T/OwP+QMUl5Y6nc3HzLdYTSen2LLAYHySXK3G
2599+gTdOhmVQwdh+IzhpjLXC67/9gn/F1p73Ixv/0PBZzmC64DOp1ogso9RICu0xTAbo
2600+h8mdN4/Tbh9Ikd89lb91x1Xf86NyC7ZvSA9dUO07/3B6B0kkqCdP9Ytlsrt2wbt3
2601+2TVPp+ghjbPjdLrJUi3fbdC2CgjV2oLiYr1h7qn7SmYPNgOpDPKBI4Cei7UO+Wow
2602+yLCxBO0HgLZKcZorJFofekPjqtQYYj1sw3OEIcifMAmoHT7H57onfoQbRDpt57k2
2603+rHJKgzrRuT8Qbl3OHSkiWRE3u0S9kAg7QEq27e2fuvh23p+YHEiYIjAR9XLVh7/Q
2604+EG5QDfDq3MvtgD/khAd36il61T5h8F4u3MhONFMuwJ/TYtGR6QINrv4DqLBM1pRr
2605+LMApQYi0w/MCRj2wLeAro9NflE+PFDk+l44ojvnEUYAGUyIzWp80bjQrV7Up6sgQ
2606+HehcmxxTrOmiqrfw08c1aHhmGeplmPpQEET1wIjnyj49sfdSPYxg5Lh+f/l79fLb
2607+jFemE8otKfog84vNGbPFl/AHwxjKCeCA/MaNJz3y3RYVsZn6
2608+-----END CERTIFICATE-----
2609diff --git a/test/fixtures/x509-escaping/info-4-cert.pem b/test/fixtures/x509-escaping/info-4-cert.pem
2610new file mode 100644
2611index 0000000000..8f1e69afec
2612--- /dev/null
2613+++ b/test/fixtures/x509-escaping/info-4-cert.pem
2614@@ -0,0 +1,29 @@
2615+-----BEGIN CERTIFICATE-----
2616+MIIE9jCCAt6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
2617+LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
2618+MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
2619+ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
2620+WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
2621+qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
2622+aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
2623+DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
2624+BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
2625+icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
2626+UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
2627+nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
2628+iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
2629+R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
2630+RTBDMEEGCCsGAQUFBwEBBDUwMzAxBggrBgEFBQcwAaAlBggrBgEFBQcIBaAZDBdn
2631+b29kLmV4YW1wbGUuY29tAGFiYzEyMzANBgkqhkiG9w0BAQsFAAOCAgEAQERLvjQB
2632+E2fmTVgHbr4MVXPfse9Xxk9TK8/IhxDNnql4bor3xat5oP+tDHVRi2StajfIcJlX
2633+C9blYOWg4w6QH3pmD6M7eQGOw7ntOUid4R2vhX3XiK3QB1h8lWSPFmSwBHA47mMJ
2634+IkrKNIo9+M9b7M05YwbAENi3TPgT8h2Ej9V4DUjLIEhDcu8fSh3FkNpZ2HohZ2I3
2635+QPe23FB052jX7uPfeZ9gcjL/iGxuTuPbKWxzZ/Gy2RmS8xfLkJESvvQ8a0H4f7Ij
2636+yjn7qYUkY6FoHxyg5BU34YNaJCmfgzRIE53Kv2FMPwj2JaXmIguR+mSDAbc0xjw3
2637+G3dRoCqhZugn8C6I5FhuXHdu6zSuuHtwOGEf07y5Im2sBsPVoq+Txh/mv3Zy9Ydy
2638+0yCDuq87jKSZd7FKorHOEoQY94UMs33PYjS4h/hYWiysYUeR0mlbjr4gyv1KH6K8
2639+JERGpI/OE+vzfOtgj/Z46/+wn7jF0LBCin7Jn5Zw1a1TNsiHKAjqW/P4vJxxUW++
2640+FtYwJhI7XJehwNNFra9rSC5M4TkpaqAZnbPvWZWxWVJIEYFgNjnt+b/VOpRpv5bJ
2641+7BOlVvP+56KF+vlmCnzVBmlHcr45sZUZ3mw3Sb6dcF0V0VaNQKw/F5EteQyafIIl
2642+dvCwwV4OwLwPliPAvwYfVEI41Dv3mF4fN7k=
2643+-----END CERTIFICATE-----
2644diff --git a/test/fixtures/x509-escaping/package.json b/test/fixtures/x509-escaping/package.json
2645new file mode 100644
2646index 0000000000..37d9f2a938
2647--- /dev/null
2648+++ b/test/fixtures/x509-escaping/package.json
2649@@ -0,0 +1,12 @@
2650+{
2651+ "name": "x509-escaping",
2652+ "version": "1.0.0",
2653+ "description": "create certificates for x509-escaping test",
2654+ "main": "createCert.js",
2655+ "license": "SEE LICENSE IN ../../../LICENSE",
2656+ "private": true,
2657+ "dependencies": {
2658+ "asn1.js": "^5.4.1",
2659+ "asn1.js-rfc5280": "^3.0.0"
2660+ }
2661+}
2662diff --git a/test/fixtures/x509-escaping/server-key.pem b/test/fixtures/x509-escaping/server-key.pem
2663new file mode 100644
2664index 0000000000..db1d2652d0
2665--- /dev/null
2666+++ b/test/fixtures/x509-escaping/server-key.pem
2667@@ -0,0 +1,52 @@
2668+-----BEGIN PRIVATE KEY-----
2669+MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCxEWd00u9E9T/k
2670+o6WcCKjhZ7tjnfVylnA7M0EHOwvdivgD46eAb1omsonLagiVrZrG7EpYuMhtz+g3
2671+Yv1d0nvFvv8ge9UIdnN8EDTDzLpJ3KbNqHURraiXuBDqa3rdY4JBakCcuYHl1bj1
2672+OTew7xl1FWc1je04rBTQGTFIRdmJZYyc9bIw9WkY6msod0w1PDcLhZS3emh/eYaL
2673+4zAQWrVhQfWzf4rZzFaI/a5n0o75aUkTuvxDDQ51V2d6WkSU3KbOnf2JW+QJXfzs
2674+NOeiYA9AnfY59evr4GEeG8VZdGuUG39uDCIWmAUT8elhXXqVq+NdBqc6VUNLDJbq
2675+CmMx/Ecp48EHO6X5uXm0xViZIVPNIzqiiRhVt4nFfwPQZrTgaq2+tD7/zD1yED4O
2676+1FhlDl5twH2N7+oG06HsEluQdLPrj7IedpneGVKMs078Ddov7j6icYv/RZHVetDl
2677+rzDDHjLJWwxyAWzdGdkhtMGPd6B9i4TtF/PU3J3nbpLn5XfEBFu4jJ+w+5Wvk5a6
2678+0gF1ERy/OLBM/e8sro2sEBIpp1tN1wJVBZOtTIi4VVDhwDRQUiwb2d1Re7GQ7+mc
2679+z5D/01qxW6S+w0IKrpwJUjR3mpa0OU98KfKVJkeyeEBLkEhDdnGTDqZ9E/ickGos
2680+rW2gAAYKgzXk725dpxTdpLEosfDbpwIDAQABAoICAAwUElkTPHQZQKsBiL38jzyU
2681+/WDduQ0AexZmuCRcoEIUBTgKsvXdYqpqGmEwUfaX2YuBOc8Uh8OJ357Ll1nrjjre
2682+fPvDxrPllJodZuQGVpzMOuqjd5zlmi8DRNAg1cg9TfjVXSPzuYsqiYvcw9JDdRqa
2683+A6jRDiIEBwVs+oIiFaU8MpvQXL/fNbSX5QhlHuMwwNZ93beoV3F+ojFvpWswLNg+
2684+DhsY86lIuYxttZRqdgtIZc49PpD6VoalmC7t8mivJofImi9g/8ytxx97umNGpzOy
2685+ssWgY1/7NdS+czdXbDE1sPsaQ8cDxrDmGxPjswV7rK4/Um/1ufnoGXFMlRinS1lQ
2686+nns4VAFefVUCk81LRyFb+X97NXPGC1p4zNlC1ZoihMgWKJBzH0uk5K/hURS/wDNZ
2687+epm9ssnEQrFGJhEI+635srfn9SVRZ8xNh+oCguo5NaZm/BezC6iBQeoaBmVL2lY8
2688+KLztN/JQd6MMZi3CWhTn0ZAtVNMxGjU9/yrdWIkX9EV8Sw68fqLGoKQXI67AOynQ
2689+5AnUyEjhVu7M39gYL71l7BVpuG7qaX8l4brzBcgzFldvuhuNCx0SW4gU2/Nx4OwY
2690+BLOX1LOrpD+5M9YwcbtSxcxz97nP8efb3hUK3QD2iuZ9Fa6zKWsoreMb7Jku38i7
2691+e41lupAIkxxuxGBe1YrZAoIBAQDVF7Kru6tsaWtvJw5cbZpKxcuUHHQ0X3XRgA+H
2692+uWfT8EbxmDpgcG8polqiYuXPFWcrElmtWeBCYXazGZocHRV8y+ri/9c2rMTH6Bni
2693+TcYfsc4E8WY6adxfUqajgQ2zShdZbxZtBvSP50HheZ0a+L2qn2MWDUN/mbwYEmom
2694+SonVx3MSJWm/Vrh5i4b/L/+9u7uumIjWYFK6pKdLerTfbXO7ZsNR9KDIOBLDnUcf
2695++6K2vcclZN7aga1S7wTsrX+k9C/OQuj8ONMWQHCxryp5RAmgtArTBrJZq8el1lcG
2696+518Vo4QuOqsqTdAhqiImoPKe4NNCs1iTS9BdCqNYiF8sbmeJAoIBAQDUuL5ebQ68
2697+6vqTKYD47ZtCzeqziN3Y/0a1BsyZh0/snNmK5WIr4T0vX0Y/XG0EpkZdpW3odMBv
2698+CemKs6Zm+pfOUGu20PTJcdSOXRbFiVYSeQnfa0l3iXZvY9Ottz/IU/mWPuU3hc18
2699+hOZD9tKiwYDzZREg6L4XRizfT70UkD2eTz4lGBjR092TTj8WqSaI9GF6d9B6Aw9Y
2700+OCZdTqV7hPe0Rnvd1XiGsk68HN2Np47HHwwPsKMCYj8YNKmsUF8QSXmCkijlDeJW
2701+bC6TjAHlvnN6n1LjaLwULUs9Rb2fkNUOqsgR+T8YlqbclJbzC7gW53M/68c9eOQ1
2702+Y01JnzsB3S2vAoIBAQDT8DP2djtzIg6GiNPRvfj9cWifMQWqqV8nNTU9Cnxn4MzO
2703+sVcuX+VQBXgblj13D5SC1Ed5ELDplMJYM5iBabPbYX2GtGq6qG83XHOSD0SEdXWw
2704+mN/SLUPPUwcGC+8yaPh8LO6jFY3cKmft9+T31Hnf35LPdfWyTZc0YexNlUkt5Kdg
2705+XvGkKn5j9RAZcwXrEXMDnhZLEZZ2qBj0C2El71hyBS0ysBnRyWNwR1dcSgx1sJ8H
2706+ZCH6NYvLtoqxU4Zm6684eHf9lA7uTL1JHC0kWzUwLqGtbTWp1h5FpL790NVTUkS/
2707+Lf7bnnTpZqt8vAtTVc0IxBPOvFLKlzALd+cg69XxAoIBAQCv6Sbkh2NMrzUQRZ42
2708+PKfMkuSoG2L6dABQ65J+0/swPHVZ+1830kf6yNsawqAU3DwMbSV6ujH4oUXUQcQ2
2709+HL01DCRHRn1nqQ6RvEF8kZnwJNAZRmu2wqKCcxc17Ph9/ZPEv7ZmN+w6MN0LDy4Z
2710+EdRFcyq7AD1SmeG5ugMu4ilSpU1K96ZuvrnZezeI0dDgKNgDotlwTN9/oM95EfSf
2711+NNJy7ma4iDPnj8S0o1pELnBQEkizIOtsqTpsFgDKUpyKp3golh3jbZvixAuwUHOx
2712+PdHZca/mB1KhjONPhEDPl8HZIznYQzn+Z3cNqoM58lMF/di834ogN7zguYHMhDUT
2713+0YhZAoIBAHlYhuni+gyrn4tyZgep68VXW7wQxSvgSj8cpZAuT/w0UKAU53J5QTWZ
2714+aGHeICXvgvpalUL+2dGwASlOvPa52ekcOPd2+qKWyss0zA4ksI7mNE2vjFUcOr+S
2715+n9QSNvu3E8dYAjzSIsizcQbPTlk6A/TmytNJ4x67ZVGCmKXw1ZzzSrxSbAIdY254
2716+TxSGchrfcy0ofXIL2HXq16FRmesORTJFkkyQaldzn4y7S6HJ/vGppImTfeac1MwG
2717+jLYljIkIbt+nB1c8HeNvARmBa6M2pxB9f72oRMVqFdUUc5AxXuWP9v6xk227EuCq
2718+TBORAafu9WxKVwUsHa1rE1uGgNEfRJ8=
2719+-----END PRIVATE KEY-----
2720diff --git a/test/parallel/test-tls-0-dns-altname.js b/test/parallel/test-tls-0-dns-altname.js
2721index 4bc87e44cb..e5cb8e3d48 100644
2722--- a/test/parallel/test-tls-0-dns-altname.js
2723+++ b/test/parallel/test-tls-0-dns-altname.js
2724@@ -44,7 +44,7 @@ const server = tls.createServer({
2725 }, common.mustCall(() => {
2726 const cert = c.getPeerCertificate();
2727 assert.strictEqual(cert.subjectaltname,
2728- 'DNS:good.example.org\0.evil.example.com, ' +
2729+ 'DNS:"good.example.org\\u0000.evil.example.com", ' +
2730 'DNS:just-another.example.com, ' +
2731 'IP Address:8.8.8.8, ' +
2732 'IP Address:8.8.4.4, ' +
2733diff --git a/test/parallel/test-x509-escaping.js b/test/parallel/test-x509-escaping.js
2734new file mode 100644
2735index 0000000000..4e0f82767d
2736--- /dev/null
2737+++ b/test/parallel/test-x509-escaping.js
2738@@ -0,0 +1,349 @@
2739+'use strict';
2740+
2741+const common = require('../common');
2742+if (!common.hasCrypto)
2743+ common.skip('missing crypto');
2744+
2745+const assert = require('assert');
2746+const tls = require('tls');
2747+const fixtures = require('../common/fixtures');
2748+
2749+const { hasOpenSSL3 } = common;
2750+
2751+// Test that all certificate chains provided by the reporter are rejected.
2752+{
2753+ const rootPEM = fixtures.readSync('x509-escaping/google/root.pem');
2754+ const intermPEM = fixtures.readSync('x509-escaping/google/intermediate.pem');
2755+ const keyPEM = fixtures.readSync('x509-escaping/google/key.pem');
2756+
2757+ const numLeaves = 5;
2758+
2759+ for (let i = 0; i < numLeaves; i++) {
2760+ // TODO(tniessen): this test case requires proper handling of URI SANs,
2761+ // which node currently does not implement.
2762+ if (i === 3) continue;
2763+
2764+ const name = `x509-escaping/google/leaf${i}.pem`;
2765+ const leafPEM = fixtures.readSync(name, 'utf8');
2766+
2767+ const server = tls.createServer({
2768+ key: keyPEM,
2769+ cert: leafPEM + intermPEM,
2770+ }, common.mustNotCall()).listen(common.mustCall(() => {
2771+ const { port } = server.address();
2772+ const socket = tls.connect(port, {
2773+ ca: rootPEM,
2774+ servername: 'nodejs.org',
2775+ }, common.mustNotCall());
2776+ socket.on('error', common.mustCall());
2777+ })).unref();
2778+ }
2779+}
2780+
2781+// Test escaping rules for subject alternative names.
2782+{
2783+ const expectedSANs = [
2784+ 'DNS:"good.example.com\\u002c DNS:evil.example.com"',
2785+ // URIs should not require escaping.
2786+ 'URI:http://example.com/',
2787+ 'URI:http://example.com/?a=b&c=d',
2788+ // Unless they contain commas.
2789+ 'URI:"http://example.com/a\\u002cb"',
2790+ // Percent encoding should not require escaping.
2791+ 'URI:http://example.com/a%2Cb',
2792+ // Malicious attempts should be escaped.
2793+ 'URI:"http://example.com/a\\u002c DNS:good.example.com"',
2794+ // Non-ASCII characters in DNS names should be treated as Latin-1.
2795+ 'DNS:"ex\\u00e4mple.com"',
2796+ // It should not be possible to cause unescaping without escaping.
2797+ 'DNS:"\\"evil.example.com\\""',
2798+ // IPv4 addresses should be represented as usual.
2799+ 'IP Address:8.8.8.8',
2800+ 'IP Address:8.8.4.4',
2801+ // For backward-compatibility, include invalid IP address lengths.
2802+ hasOpenSSL3 ? 'IP Address:<invalid length=5>' : 'IP Address:<invalid>',
2803+ hasOpenSSL3 ? 'IP Address:<invalid length=6>' : 'IP Address:<invalid>',
2804+ // IPv6 addresses are represented as OpenSSL does.
2805+ 'IP Address:A0B:C0D:E0F:0:0:0:7A7B:7C7D',
2806+ // Regular email addresses don't require escaping.
2807+ 'email:foo@example.com',
2808+ // ... but should be escaped if they contain commas.
2809+ 'email:"foo@example.com\\u002c DNS:good.example.com"',
2810+ 'DirName:/C=DE/L=Hannover',
2811+ // TODO(tniessen): support UTF8 in DirName
2812+ 'DirName:"/C=DE/L=M\\\\xC3\\\\xBCnchen"',
2813+ 'DirName:"/C=DE/L=Berlin\\u002c DNS:good.example.com"',
2814+ 'DirName:"/C=DE/L=Berlin\\u002c DNS:good.example.com\\\\x00' +
2815+ 'evil.example.com"',
2816+ 'DirName:"/C=DE/L=Berlin\\u002c DNS:good.example.com\\\\\\\\x00' +
2817+ 'evil.example.com"',
2818+ // These next two tests might be surprising. OpenSSL applies its own rules
2819+ // first, which introduce backslashes, which activate node's escaping.
2820+ // Unfortunately, there are also differences between OpenSSL 1.1.1 and 3.0.
2821+ 'DirName:"/C=DE/L=Berlin\\\\x0D\\\\x0A"',
2822+ hasOpenSSL3 ?
2823+ 'DirName:"/C=DE/L=Berlin\\\\/CN=good.example.com"' :
2824+ 'DirName:/C=DE/L=Berlin/CN=good.example.com',
2825+ // TODO(tniessen): even OIDs that are well-known (such as the following,
2826+ // which is sha256WithRSAEncryption) should be represented numerically only.
2827+ 'Registered ID:sha256WithRSAEncryption',
2828+ // This is an OID that will likely never be assigned to anything, thus
2829+ // OpenSSL should not know it.
2830+ 'Registered ID:1.3.9999.12.34',
2831+ hasOpenSSL3 ?
2832+ 'othername: XmppAddr::abc123' :
2833+ 'othername:<unsupported>',
2834+ hasOpenSSL3 ?
2835+ 'othername:" XmppAddr::abc123\\u002c DNS:good.example.com"' :
2836+ 'othername:<unsupported>',
2837+ hasOpenSSL3 ?
2838+ 'othername:" XmppAddr::good.example.com\\u0000abc123"' :
2839+ 'othername:<unsupported>',
2840+ // This is unsupported because the OID is not recognized.
2841+ 'othername:<unsupported>',
2842+ hasOpenSSL3 ? 'othername: SRVName::abc123' : 'othername:<unsupported>',
2843+ // This is unsupported because it is an SRVName with a UTF8String value,
2844+ // which is not allowed for SRVName.
2845+ 'othername:<unsupported>',
2846+ hasOpenSSL3 ?
2847+ 'othername:" SRVName::abc\\u0000def"' :
2848+ 'othername:<unsupported>',
2849+ ];
2850+
2851+ const serverKey = fixtures.readSync('x509-escaping/server-key.pem', 'utf8');
2852+
2853+ for (let i = 0; i < expectedSANs.length; i++) {
2854+ const pem = fixtures.readSync(`x509-escaping/alt-${i}-cert.pem`, 'utf8');
2855+
2856+ // X509Certificate interface is not supported in v12.x & v14.x. Disable
2857+ // checks for subjectAltName with expectedSANs. The testcase is ported
2858+ // from v17.x
2859+ //
2860+ // Test the subjectAltName property of the X509Certificate API.
2861+ // const cert = new X509Certificate(pem);
2862+ // assert.strictEqual(cert.subjectAltName, expectedSANs[i]);
2863+
2864+ // Test that the certificate obtained by checkServerIdentity has the correct
2865+ // subjectaltname property.
2866+ const server = tls.createServer({
2867+ key: serverKey,
2868+ cert: pem,
2869+ }, common.mustCall((conn) => {
2870+ conn.destroy();
2871+ server.close();
2872+ })).listen(common.mustCall(() => {
2873+ const { port } = server.address();
2874+ tls.connect(port, {
2875+ ca: pem,
2876+ servername: 'example.com',
2877+ checkServerIdentity: (hostname, peerCert) => {
2878+ assert.strictEqual(hostname, 'example.com');
2879+ assert.strictEqual(peerCert.subjectaltname, expectedSANs[i]);
2880+ },
2881+ }, common.mustCall());
2882+ }));
2883+ }
2884+}
2885+
2886+// Test escaping rules for authority info access.
2887+{
2888+ const expectedInfoAccess = [
2889+ {
2890+ text: 'OCSP - URI:"http://good.example.com/\\u000a' +
2891+ 'OCSP - URI:http://evil.example.com/"',
2892+ legacy: {
2893+ 'OCSP - URI': [
2894+ 'http://good.example.com/\nOCSP - URI:http://evil.example.com/',
2895+ ],
2896+ },
2897+ },
2898+ {
2899+ text: 'CA Issuers - URI:"http://ca.example.com/\\u000a' +
2900+ 'OCSP - URI:http://evil.example.com"\n' +
2901+ 'OCSP - DNS:"good.example.com\\u000a' +
2902+ 'OCSP - URI:http://ca.nodejs.org/ca.cert"',
2903+ legacy: {
2904+ 'CA Issuers - URI': [
2905+ 'http://ca.example.com/\nOCSP - URI:http://evil.example.com',
2906+ ],
2907+ 'OCSP - DNS': [
2908+ 'good.example.com\nOCSP - URI:http://ca.nodejs.org/ca.cert',
2909+ ],
2910+ },
2911+ },
2912+ {
2913+ text: '1.3.9999.12.34 - URI:http://ca.example.com/',
2914+ legacy: {
2915+ '1.3.9999.12.34 - URI': [
2916+ 'http://ca.example.com/',
2917+ ],
2918+ },
2919+ },
2920+ hasOpenSSL3 ? {
2921+ text: 'OCSP - othername: XmppAddr::good.example.com\n' +
2922+ 'OCSP - othername:<unsupported>\n' +
2923+ 'OCSP - othername: SRVName::abc123',
2924+ legacy: {
2925+ 'OCSP - othername': [
2926+ ' XmppAddr::good.example.com',
2927+ '<unsupported>',
2928+ ' SRVName::abc123',
2929+ ],
2930+ },
2931+ } : {
2932+ text: 'OCSP - othername:<unsupported>\n' +
2933+ 'OCSP - othername:<unsupported>\n' +
2934+ 'OCSP - othername:<unsupported>',
2935+ legacy: {
2936+ 'OCSP - othername': [
2937+ '<unsupported>',
2938+ '<unsupported>',
2939+ '<unsupported>',
2940+ ],
2941+ },
2942+ },
2943+ hasOpenSSL3 ? {
2944+ text: 'OCSP - othername:" XmppAddr::good.example.com\\u0000abc123"',
2945+ legacy: {
2946+ 'OCSP - othername': [
2947+ ' XmppAddr::good.example.com\0abc123',
2948+ ],
2949+ },
2950+ } : {
2951+ text: 'OCSP - othername:<unsupported>',
2952+ legacy: {
2953+ 'OCSP - othername': [
2954+ '<unsupported>',
2955+ ],
2956+ },
2957+ },
2958+ ];
2959+
2960+ const serverKey = fixtures.readSync('x509-escaping/server-key.pem', 'utf8');
2961+
2962+ for (let i = 0; i < expectedInfoAccess.length; i++) {
2963+ const pem = fixtures.readSync(`x509-escaping/info-${i}-cert.pem`, 'utf8');
2964+ const expected = expectedInfoAccess[i];
2965+
2966+ // X509Certificate interface is not supported in v12.x & v14.x. Disable
2967+ // checks for cert.infoAccess with expected text. The testcase is ported
2968+ // from v17.x
2969+ // Test the subjectAltName property of the X509Certificate API.
2970+ // const cert = new X509Certificate(pem);
2971+ // assert.strictEqual(cert.infoAccess,
2972+ // `${expected.text}${hasOpenSSL3 ? '' : '\n'}`);
2973+
2974+ // Test that the certificate obtained by checkServerIdentity has the correct
2975+ // subjectaltname property.
2976+ const server = tls.createServer({
2977+ key: serverKey,
2978+ cert: pem,
2979+ }, common.mustCall((conn) => {
2980+ conn.destroy();
2981+ server.close();
2982+ })).listen(common.mustCall(() => {
2983+ const { port } = server.address();
2984+ tls.connect(port, {
2985+ ca: pem,
2986+ servername: 'example.com',
2987+ checkServerIdentity: (hostname, peerCert) => {
2988+ assert.strictEqual(hostname, 'example.com');
2989+ assert.deepStrictEqual(peerCert.infoAccess,
2990+ Object.assign(Object.create(null),
2991+ expected.legacy));
2992+ },
2993+ }, common.mustCall());
2994+ }));
2995+ }
2996+}
2997+
2998+// The internal parsing logic must match the JSON specification exactly.
2999+{
3000+ // This list is partially based on V8's own JSON tests.
3001+ const invalidJSON = [
3002+ '"\\a invalid escape"',
3003+ '"\\v invalid escape"',
3004+ '"\\\' invalid escape"',
3005+ '"\\x42 invalid escape"',
3006+ '"\\u202 invalid escape"',
3007+ '"\\012 invalid escape"',
3008+ '"Unterminated string',
3009+ '"Unterminated string\\"',
3010+ '"Unterminated string\\\\\\"',
3011+ '"\u0000 control character"',
3012+ '"\u001e control character"',
3013+ '"\u001f control character"',
3014+ ];
3015+
3016+ for (const invalidStringLiteral of invalidJSON) {
3017+ // Usually, checkServerIdentity returns an error upon verification failure.
3018+ // In this case, however, it should throw an error since this is not a
3019+ // verification error. Node.js itself will never produce invalid JSON string
3020+ // literals, so this can only happen when users construct invalid subject
3021+ // alternative name strings (that do not follow escaping rules).
3022+ assert.throws(() => {
3023+ tls.checkServerIdentity('example.com', {
3024+ subjectaltname: `DNS:${invalidStringLiteral}`,
3025+ });
3026+ }, {
3027+ code: 'ERR_TLS_CERT_ALTNAME_FORMAT',
3028+ message: 'Invalid subject alternative name string'
3029+ });
3030+ }
3031+}
3032+
3033+// While node does not produce commas within SAN entries, it should parse them
3034+// correctly (i.e., not simply split at commas).
3035+{
3036+ // Regardless of the quotes, splitting this SAN string at commas would
3037+ // cause checkServerIdentity to see 'DNS:b.example.com' and thus to accept
3038+ // the certificate for b.example.com.
3039+ const san = 'DNS:"a.example.com, DNS:b.example.com, DNS:c.example.com"';
3040+
3041+ // This is what node used to do, and which is not correct!
3042+ const hostname = 'b.example.com';
3043+ assert.strictEqual(san.split(', ')[1], `DNS:${hostname}`);
3044+
3045+ // The new implementation should parse the string correctly.
3046+ const err = tls.checkServerIdentity(hostname, { subjectaltname: san });
3047+ assert(err);
3048+ assert.strictEqual(err.code, 'ERR_TLS_CERT_ALTNAME_INVALID');
3049+ assert.strictEqual(err.message, 'Hostname/IP does not match certificate\'s ' +
3050+ 'altnames: Host: b.example.com. is not in ' +
3051+ 'the cert\'s altnames: DNS:"a.example.com, ' +
3052+ 'DNS:b.example.com, DNS:c.example.com"');
3053+}
3054+
3055+// The subject MUST be ignored if a dNSName subject alternative name exists.
3056+{
3057+ const key = fixtures.readKey('incorrect_san_correct_subject-key.pem');
3058+ const cert = fixtures.readKey('incorrect_san_correct_subject-cert.pem');
3059+
3060+ // The hostname is the CN, but not a SAN entry.
3061+ const servername = 'good.example.com';
3062+
3063+ // X509Certificate interface is not supported in v12.x & v14.x. Disable
3064+ // checks for certX509.subject and certX509.subjectAltName with expected
3065+ // value. The testcase is ported from v17.x
3066+ //
3067+ // const certX509 = new X509Certificate(cert);
3068+ // assert.strictEqual(certX509.subject, `CN=${servername}`);
3069+ // assert.strictEqual(certX509.subjectAltName, 'DNS:evil.example.com');
3070+
3071+ // Try connecting to a server that uses the self-signed certificate.
3072+ const server = tls.createServer({ key, cert }, common.mustNotCall());
3073+ server.listen(common.mustCall(() => {
3074+ const { port } = server.address();
3075+ const socket = tls.connect(port, {
3076+ ca: cert,
3077+ servername,
3078+ }, common.mustNotCall());
3079+ socket.on('error', common.mustCall((err) => {
3080+ assert.strictEqual(err.code, 'ERR_TLS_CERT_ALTNAME_INVALID');
3081+ assert.strictEqual(err.message, 'Hostname/IP does not match ' +
3082+ "certificate's altnames: Host: " +
3083+ "good.example.com. is not in the cert's" +
3084+ ' altnames: DNS:evil.example.com');
3085+ }));
3086+ })).unref();
3087+}
3088--
30892.17.1
3090
diff --git a/meta-oe/recipes-devtools/nodejs/nodejs_12.21.0.bb b/meta-oe/recipes-devtools/nodejs/nodejs_12.21.0.bb
index b9e3821776..00de29d9aa 100644
--- a/meta-oe/recipes-devtools/nodejs/nodejs_12.21.0.bb
+++ b/meta-oe/recipes-devtools/nodejs/nodejs_12.21.0.bb
@@ -22,6 +22,7 @@ SRC_URI = "http://nodejs.org/dist/v${PV}/node-v${PV}.tar.xz \
22 file://big-endian.patch \ 22 file://big-endian.patch \
23 file://mips-warnings.patch \ 23 file://mips-warnings.patch \
24 file://0001-Remove-use-of-register-r7-because-llvm-now-issues-an.patch \ 24 file://0001-Remove-use-of-register-r7-because-llvm-now-issues-an.patch \
25 file://CVE-2021-44532.patch \
25 " 26 "
26SRC_URI_append_class-target = " \ 27SRC_URI_append_class-target = " \
27 file://0002-Using-native-binaries.patch \ 28 file://0002-Using-native-binaries.patch \