aboutsummaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-devtools
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 /meta-oe/recipes-devtools
parent872e60a774b763b4fbebc2b902ea3570bf81939d (diff)
downloadmeta-openembedded-contrib-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>
Diffstat (limited to 'meta-oe/recipes-devtools')
-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 @@
+From 19873abfb24dce75ffff042efe76dc5633052677 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= <tniessen@tnie.de>
+Date: Wed, 29 Dec 2021 19:30:57 -0500
+Subject: [PATCH] crypto,tls: implement safe x509 GeneralName format
+
+This change introduces JSON-compatible escaping rules for strings that
+include X.509 GeneralName components (see RFC 5280). This non-standard
+format avoids ambiguities and prevents injection attacks that could
+previously lead to X.509 certificates being accepted even though they
+were not valid for the target hostname.
+
+These changes affect the format of subject alternative names and the
+format of authority information access. The checkServerIdentity function
+has been modified to safely handle the new format, eliminating the
+possibility of injecting subject alternative names into the verification
+logic.
+
+Because each subject alternative name is only encoded as a JSON string
+literal if necessary for security purposes, this change will only be
+visible in rare cases.
+
+This addresses CVE-2021-44532.
+
+Co-authored-by: Akshay K <iit.akshay@gmail.com>
+CVE-ID: CVE-2021-44532
+Backport-PR-URL: https://github.com/nodejs-private/node-private/pull/306
+PR-URL: https://github.com/nodejs-private/node-private/pull/300
+Reviewed-By: Michael Dawson <midawson@redhat.com>
+Reviewed-By: Rich Trott <rtrott@gmail.com>
+
+Upstream-Status: Backport [https://github.com/nodejs/node/commit/19873abfb24dce75ffff042efe76dc5633052677]
+
+CVE: CVE-2021-44532
+
+Signed-off-by: Virendra Thakur <virendra.thakur@kpit.com>
+
+---
+ doc/api/errors.md | 8 +
+ lib/_tls_common.js | 9 +
+ lib/internal/errors.js | 2 +
+ lib/tls.js | 52 +-
+ src/node_crypto_common.cc | 340 ++++++++++--
+ test/common/index.js | 7 +
+ test/fixtures/keys/Makefile | 14 +
+ .../incorrect_san_correct_subject-cert.pem | 11 +
+ .../incorrect_san_correct_subject-key.pem | 5 +
+ test/fixtures/x509-escaping/.gitignore | 2 +
+ test/fixtures/x509-escaping/alt-0-cert.pem | 29 +
+ test/fixtures/x509-escaping/alt-1-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-10-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-11-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-12-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-13-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-14-cert.pem | 29 +
+ test/fixtures/x509-escaping/alt-15-cert.pem | 29 +
+ test/fixtures/x509-escaping/alt-16-cert.pem | 29 +
+ test/fixtures/x509-escaping/alt-17-cert.pem | 29 +
+ test/fixtures/x509-escaping/alt-18-cert.pem | 29 +
+ test/fixtures/x509-escaping/alt-19-cert.pem | 29 +
+ test/fixtures/x509-escaping/alt-2-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-20-cert.pem | 29 +
+ test/fixtures/x509-escaping/alt-21-cert.pem | 29 +
+ test/fixtures/x509-escaping/alt-22-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-23-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-24-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-25-cert.pem | 29 +
+ test/fixtures/x509-escaping/alt-26-cert.pem | 29 +
+ test/fixtures/x509-escaping/alt-27-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-28-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-29-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-3-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-30-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-4-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-5-cert.pem | 29 +
+ test/fixtures/x509-escaping/alt-6-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-7-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-8-cert.pem | 28 +
+ test/fixtures/x509-escaping/alt-9-cert.pem | 28 +
+ test/fixtures/x509-escaping/create-certs.js | 502 ++++++++++++++++++
+ .../x509-escaping/google/intermediate.pem | 11 +
+ test/fixtures/x509-escaping/google/key.pem | 5 +
+ test/fixtures/x509-escaping/google/leaf0.pem | 10 +
+ test/fixtures/x509-escaping/google/leaf1.pem | 10 +
+ test/fixtures/x509-escaping/google/leaf2.pem | 10 +
+ test/fixtures/x509-escaping/google/leaf3.pem | 10 +
+ test/fixtures/x509-escaping/google/leaf4.pem | 10 +
+ test/fixtures/x509-escaping/google/root.pem | 9 +
+ test/fixtures/x509-escaping/info-0-cert.pem | 30 ++
+ test/fixtures/x509-escaping/info-1-cert.pem | 31 ++
+ test/fixtures/x509-escaping/info-2-cert.pem | 29 +
+ test/fixtures/x509-escaping/info-3-cert.pem | 30 ++
+ test/fixtures/x509-escaping/info-4-cert.pem | 29 +
+ test/fixtures/x509-escaping/package.json | 12 +
+ test/fixtures/x509-escaping/server-key.pem | 52 ++
+ test/parallel/test-tls-0-dns-altname.js | 2 +-
+ test/parallel/test-x509-escaping.js | 349 ++++++++++++
+ 59 files changed, 2429 insertions(+), 42 deletions(-)
+ create mode 100644 test/fixtures/keys/incorrect_san_correct_subject-cert.pem
+ create mode 100644 test/fixtures/keys/incorrect_san_correct_subject-key.pem
+ create mode 100644 test/fixtures/x509-escaping/.gitignore
+ create mode 100644 test/fixtures/x509-escaping/alt-0-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-1-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-10-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-11-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-12-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-13-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-14-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-15-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-16-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-17-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-18-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-19-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-2-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-20-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-21-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-22-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-23-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-24-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-25-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-26-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-27-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-28-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-29-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-3-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-30-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-4-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-5-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-6-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-7-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-8-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/alt-9-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/create-certs.js
+ create mode 100644 test/fixtures/x509-escaping/google/intermediate.pem
+ create mode 100644 test/fixtures/x509-escaping/google/key.pem
+ create mode 100644 test/fixtures/x509-escaping/google/leaf0.pem
+ create mode 100644 test/fixtures/x509-escaping/google/leaf1.pem
+ create mode 100644 test/fixtures/x509-escaping/google/leaf2.pem
+ create mode 100644 test/fixtures/x509-escaping/google/leaf3.pem
+ create mode 100644 test/fixtures/x509-escaping/google/leaf4.pem
+ create mode 100644 test/fixtures/x509-escaping/google/root.pem
+ create mode 100644 test/fixtures/x509-escaping/info-0-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/info-1-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/info-2-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/info-3-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/info-4-cert.pem
+ create mode 100644 test/fixtures/x509-escaping/package.json
+ create mode 100644 test/fixtures/x509-escaping/server-key.pem
+ create mode 100644 test/parallel/test-x509-escaping.js
+
+diff --git a/doc/api/errors.md b/doc/api/errors.md
+index d5d8e1efa7..9d176d9048 100644
+--- a/doc/api/errors.md
++++ b/doc/api/errors.md
+@@ -1869,6 +1869,14 @@ An unspecified or non-specific system error has occurred within the Node.js
+ process. The error object will have an `err.info` object property with
+ additional details.
+
++<a id="ERR_TLS_CERT_ALTNAME_FORMAT"></a>
++### `ERR_TLS_CERT_ALTNAME_FORMAT`
++
++This error is thrown by `checkServerIdentity` if a user-supplied
++`subjectaltname` property violates encoding rules. Certificate objects produced
++by Node.js itself always comply with encoding rules and will never cause
++this error.
++
+ <a id="ERR_TLS_CERT_ALTNAME_INVALID"></a>
+ ### `ERR_TLS_CERT_ALTNAME_INVALID`
+
+diff --git a/lib/_tls_common.js b/lib/_tls_common.js
+index b7a3b70a24..a2a74813f1 100644
+--- a/lib/_tls_common.js
++++ b/lib/_tls_common.js
+@@ -23,6 +23,7 @@
+
+ const {
+ ArrayIsArray,
++ JSONParse,
+ ObjectCreate,
+ } = primordials;
+
+@@ -323,6 +324,14 @@ exports.translatePeerCertificate = function translatePeerCertificate(c) {
+
+ // XXX: More key validation?
+ info.replace(/([^\n:]*):([^\n]*)(?:\n|$)/g, (all, key, val) => {
++ if (val.charCodeAt(0) === 0x22) {
++ // The translatePeerCertificate function is only
++ // used on internally created legacy certificate
++ // objects, and any value that contains a quote
++ // will always be a valid JSON string literal,
++ // so this should never throw.
++ val = JSONParse(val);
++ }
+ if (key in c.infoAccess)
+ c.infoAccess[key].push(val);
+ else
+diff --git a/lib/internal/errors.js b/lib/internal/errors.js
+index 2cf7df436b..cd7153ad1a 100644
+--- a/lib/internal/errors.js
++++ b/lib/internal/errors.js
+@@ -1345,6 +1345,8 @@ E('ERR_STREAM_WRAP', 'Stream has StringDecoder set or is in objectMode', Error);
+ E('ERR_STREAM_WRITE_AFTER_END', 'write after end', Error);
+ E('ERR_SYNTHETIC', 'JavaScript Callstack', Error);
+ E('ERR_SYSTEM_ERROR', 'A system error occurred', SystemError);
++E('ERR_TLS_CERT_ALTNAME_FORMAT', 'Invalid subject alternative name string',
++ SyntaxError);
+ E('ERR_TLS_CERT_ALTNAME_INVALID', function(reason, host, cert) {
+ this.reason = reason;
+ this.host = host;
+diff --git a/lib/tls.js b/lib/tls.js
+index 2ccbe409c9..cefb47d10f 100644
+--- a/lib/tls.js
++++ b/lib/tls.js
+@@ -24,11 +24,19 @@
+ const {
+ Array,
+ ArrayIsArray,
++ ArrayPrototypePush,
++ JSONParse,
+ ObjectDefineProperty,
+ ObjectFreeze,
++ RegExpPrototypeExec,
++ StringPrototypeIncludes,
++ StringPrototypeIndexOf,
++ StringPrototypeSplit,
++ StringPrototypeSubstring,
+ } = primordials;
+
+ const {
++ ERR_TLS_CERT_ALTNAME_FORMAT,
+ ERR_TLS_CERT_ALTNAME_INVALID,
+ ERR_OUT_OF_RANGE
+ } = require('internal/errors').codes;
+@@ -207,6 +215,45 @@ function check(hostParts, pattern, wildcards) {
+ return true;
+ }
+
++// This pattern is used to determine the length of escaped sequences within
++// the subject alt names string. It allows any valid JSON string literal.
++// This MUST match the JSON specification (ECMA-404 / RFC8259) exactly.
++const jsonStringPattern =
++ // eslint-disable-next-line no-control-regex
++ /^"(?:[^"\\\u0000-\u001f]|\\(?:["\\/bfnrt]|u[0-9a-fA-F]{4}))*"/;
++
++function splitEscapedAltNames(altNames) {
++ const result = [];
++ let currentToken = '';
++ let offset = 0;
++ while (offset !== altNames.length) {
++ const nextSep = StringPrototypeIndexOf(altNames, ', ', offset);
++ const nextQuote = StringPrototypeIndexOf(altNames, '"', offset);
++ if (nextQuote !== -1 && (nextSep === -1 || nextQuote < nextSep)) {
++ // There is a quote character and there is no separator before the quote.
++ currentToken += StringPrototypeSubstring(altNames, offset, nextQuote);
++ const match = RegExpPrototypeExec(
++ jsonStringPattern, StringPrototypeSubstring(altNames, nextQuote));
++ if (!match) {
++ throw new ERR_TLS_CERT_ALTNAME_FORMAT();
++ }
++ currentToken += JSONParse(match[0]);
++ offset = nextQuote + match[0].length;
++ } else if (nextSep !== -1) {
++ // There is a separator and no quote before it.
++ currentToken += StringPrototypeSubstring(altNames, offset, nextSep);
++ ArrayPrototypePush(result, currentToken);
++ currentToken = '';
++ offset = nextSep + 2;
++ } else {
++ currentToken += StringPrototypeSubstring(altNames, offset);
++ offset = altNames.length;
++ }
++ }
++ ArrayPrototypePush(result, currentToken);
++ return result;
++}
++
+ let urlWarningEmitted = false;
+ exports.checkServerIdentity = function checkServerIdentity(hostname, cert) {
+ const subject = cert.subject;
+@@ -218,7 +265,10 @@ exports.checkServerIdentity = function checkServerIdentity(hostname, cert) {
+ hostname = '' + hostname;
+
+ if (altNames) {
+- for (const name of altNames.split(', ')) {
++ const splitAltNames = StringPrototypeIncludes(altNames, '"') ?
++ splitEscapedAltNames(altNames) :
++ StringPrototypeSplit(altNames, ', ');
++ for (const name of splitAltNames) {
+ if (name.startsWith('DNS:')) {
+ dnsNames.push(name.slice(4));
+ } else if (name.startsWith('URI:')) {
+diff --git a/src/node_crypto_common.cc b/src/node_crypto_common.cc
+index 74bc0a9756..53fbc576ef 100644
+--- a/src/node_crypto_common.cc
++++ b/src/node_crypto_common.cc
+@@ -480,39 +480,320 @@ void AddFingerprintDigest(
+ }
+ }
+
+-bool SafeX509ExtPrint(const BIOPointer& out, X509_EXTENSION* ext) {
+- const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
++static inline bool IsSafeAltName(const char* name, size_t length, bool utf8) {
++ for (size_t i = 0; i < length; i++) {
++ char c = name[i];
++ switch (c) {
++ case '"':
++ case '\\':
++ // These mess with encoding rules.
++ // Fall through.
++ case ',':
++ // Commas make it impossible to split the list of subject alternative
++ // names unambiguously, which is why we have to escape.
++ // Fall through.
++ case '\'':
++ // Single quotes are unlikely to appear in any legitimate values, but they
++ // could be used to make a value look like it was escaped (i.e., enclosed
++ // in single/double quotes).
++ return false;
++ default:
++ if (utf8) {
++ // In UTF8 strings, we require escaping for any ASCII control character,
++ // but NOT for non-ASCII characters. Note that all bytes of any code
++ // point that consists of more than a single byte have their MSB set.
++ if (static_cast<unsigned char>(c) < ' ' || c == '\x7f') {
++ return false;
++ }
++ } else {
++ // Check if the char is a control character or non-ASCII character. Note
++ // that char may or may not be a signed type. Regardless, non-ASCII
++ // values will always be outside of this range.
++ if (c < ' ' || c > '~') {
++ return false;
++ }
++ }
++ }
++ }
++ return true;
++}
+
+- if (method != X509V3_EXT_get_nid(NID_subject_alt_name))
+- return false;
++static inline void PrintAltName(const BIOPointer& out, const char* name,
++ size_t length, bool utf8,
++ const char* safe_prefix) {
++ if (IsSafeAltName(name, length, utf8)) {
++ // For backward-compatibility, append "safe" names without any
++ // modifications.
++ if (safe_prefix != nullptr) {
++ BIO_printf(out.get(), "%s:", safe_prefix);
++ }
++ BIO_write(out.get(), name, length);
++ } else {
++ // If a name is not "safe", we cannot embed it without special
++ // encoding. This does not usually happen, but we don't want to hide
++ // it from the user either. We use JSON compatible escaping here.
++ BIO_write(out.get(), "\"", 1);
++ if (safe_prefix != nullptr) {
++ BIO_printf(out.get(), "%s:", safe_prefix);
++ }
++ for (size_t j = 0; j < length; j++) {
++ char c = static_cast<char>(name[j]);
++ if (c == '\\') {
++ BIO_write(out.get(), "\\\\", 2);
++ } else if (c == '"') {
++ BIO_write(out.get(), "\\\"", 2);
++ } else if ((c >= ' ' && c != ',' && c <= '~') || (utf8 && (c & 0x80))) {
++ // Note that the above condition explicitly excludes commas, which means
++ // that those are encoded as Unicode escape sequences in the "else"
++ // block. That is not strictly necessary, and Node.js itself would parse
++ // it correctly either way. We only do this to account for third-party
++ // code that might be splitting the string at commas (as Node.js itself
++ // used to do).
++ BIO_write(out.get(), &c, 1);
++ } else {
++ // Control character or non-ASCII character. We treat everything as
++ // Latin-1, which corresponds to the first 255 Unicode code points.
++ const char hex[] = "0123456789abcdef";
++ char u[] = { '\\', 'u', '0', '0', hex[(c & 0xf0) >> 4], hex[c & 0x0f] };
++ BIO_write(out.get(), u, sizeof(u));
++ }
++ }
++ BIO_write(out.get(), "\"", 1);
++ }
++}
++
++static inline void PrintLatin1AltName(const BIOPointer& out,
++ const ASN1_IA5STRING* name,
++ const char* safe_prefix = nullptr) {
++ PrintAltName(out, reinterpret_cast<const char*>(name->data), name->length,
++ false, safe_prefix);
++}
++
++static inline void PrintUtf8AltName(const BIOPointer& out,
++ const ASN1_UTF8STRING* name,
++ const char* safe_prefix = nullptr) {
++ PrintAltName(out, reinterpret_cast<const char*>(name->data), name->length,
++ true, safe_prefix);
++}
++
++// This function currently emulates the behavior of i2v_GENERAL_NAME in a safer
++// and less ambiguous way.
++// TODO(tniessen): gradually improve the format in the next major version(s)
++static bool PrintGeneralName(const BIOPointer& out, const GENERAL_NAME* gen) {
++ if (gen->type == GEN_DNS) {
++ ASN1_IA5STRING* name = gen->d.dNSName;
++ BIO_write(out.get(), "DNS:", 4);
++ // Note that the preferred name syntax (see RFCs 5280 and 1034) with
++ // wildcards is a subset of what we consider "safe", so spec-compliant DNS
++ // names will never need to be escaped.
++ PrintLatin1AltName(out, name);
++ } else if (gen->type == GEN_EMAIL) {
++ ASN1_IA5STRING* name = gen->d.rfc822Name;
++ BIO_write(out.get(), "email:", 6);
++ PrintLatin1AltName(out, name);
++ } else if (gen->type == GEN_URI) {
++ ASN1_IA5STRING* name = gen->d.uniformResourceIdentifier;
++ BIO_write(out.get(), "URI:", 4);
++ // The set of "safe" names was designed to include just about any URI,
++ // with a few exceptions, most notably URIs that contains commas (see
++ // RFC 2396). In other words, most legitimate URIs will not require
++ // escaping.
++ PrintLatin1AltName(out, name);
++ } else if (gen->type == GEN_DIRNAME) {
++ // For backward compatibility, use X509_NAME_oneline to print the
++ // X509_NAME object. The format is non standard and should be avoided
++ // elsewhere, but conveniently, the function produces ASCII and the output
++ // is unlikely to contains commas or other characters that would require
++ // escaping. With that in mind, note that it SHOULD NOT produce ASCII
++ // output since an RFC5280 AttributeValue may be a UTF8String.
++ // TODO(tniessen): switch to RFC2253 rules in a major release
++ BIO_printf(out.get(), "DirName:");
++ char oline[256];
++ if (X509_NAME_oneline(gen->d.dirn, oline, sizeof(oline)) != nullptr) {
++ PrintAltName(out, oline, strlen(oline), false, nullptr);
++ } else {
++ return false;
++ }
++ } else if (gen->type == GEN_IPADD) {
++ BIO_printf(out.get(), "IP Address:");
++ const ASN1_OCTET_STRING* ip = gen->d.ip;
++ const unsigned char* b = ip->data;
++ if (ip->length == 4) {
++ BIO_printf(out.get(), "%d.%d.%d.%d", b[0], b[1], b[2], b[3]);
++ } else if (ip->length == 16) {
++ for (unsigned int j = 0; j < 8; j++) {
++ uint16_t pair = (b[2 * j] << 8) | b[2 * j + 1];
++ BIO_printf(out.get(), (j == 0) ? "%X" : ":%X", pair);
++ }
++ } else {
++#if OPENSSL_VERSION_MAJOR >= 3
++ BIO_printf(out.get(), "<invalid length=%d>", ip->length);
++#else
++ BIO_printf(out.get(), "<invalid>");
++#endif
++ }
++ } else if (gen->type == GEN_RID) {
++ // TODO(tniessen): unlike OpenSSL's default implementation, never print the
++ // OID as text and instead always print its numeric representation, which is
++ // backward compatible in practice and more future proof (see OBJ_obj2txt).
++ char oline[256];
++ i2t_ASN1_OBJECT(oline, sizeof(oline), gen->d.rid);
++ BIO_printf(out.get(), "Registered ID:%s", oline);
++ } else if (gen->type == GEN_OTHERNAME) {
++ // TODO(tniessen): the format that is used here is based on OpenSSL's
++ // implementation of i2v_GENERAL_NAME (as of OpenSSL 3.0.1), mostly for
++ // backward compatibility. It is somewhat awkward, especially when passed to
++ // translatePeerCertificate, and should be changed in the future, probably
++ // to the format used by GENERAL_NAME_print (in a major release).
++ bool unicode = true;
++ const char* prefix = nullptr;
++ // OpenSSL 1.1.1 does not support othername in i2v_GENERAL_NAME and may not
++ // define these NIDs.
++#if OPENSSL_VERSION_MAJOR >= 3
++ int nid = OBJ_obj2nid(gen->d.otherName->type_id);
++ switch (nid) {
++ case NID_id_on_SmtpUTF8Mailbox:
++ prefix = " SmtpUTF8Mailbox:";
++ break;
++ case NID_XmppAddr:
++ prefix = " XmppAddr:";
++ break;
++ case NID_SRVName:
++ prefix = " SRVName:";
++ unicode = false;
++ break;
++ case NID_ms_upn:
++ prefix = " UPN:";
++ break;
++ case NID_NAIRealm:
++ prefix = " NAIRealm:";
++ break;
++ }
++#endif // OPENSSL_VERSION_MAJOR >= 3
++ int val_type = gen->d.otherName->value->type;
++ if (prefix == nullptr ||
++ (unicode && val_type != V_ASN1_UTF8STRING) ||
++ (!unicode && val_type != V_ASN1_IA5STRING)) {
++ BIO_printf(out.get(), "othername:<unsupported>");
++ } else {
++ BIO_printf(out.get(), "othername:");
++ if (unicode) {
++ PrintUtf8AltName(out, gen->d.otherName->value->value.utf8string,
++ prefix);
++ } else {
++ PrintLatin1AltName(out, gen->d.otherName->value->value.ia5string,
++ prefix);
++ }
++ }
++ } else if (gen->type == GEN_X400) {
++ // TODO(tniessen): this is what OpenSSL does, implement properly instead
++ BIO_printf(out.get(), "X400Name:<unsupported>");
++ } else if (gen->type == GEN_EDIPARTY) {
++ // TODO(tniessen): this is what OpenSSL does, implement properly instead
++ BIO_printf(out.get(), "EdiPartyName:<unsupported>");
++ } else {
++ // This is safe because X509V3_EXT_d2i would have returned nullptr in this
++ // case already.
++ UNREACHABLE();
++ }
++
++ return true;
++}
++
++bool SafeX509SubjectAltNamePrint(const BIOPointer& out, X509_EXTENSION* ext) {
++ const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
++ CHECK(method == X509V3_EXT_get_nid(NID_subject_alt_name));
+
+ GENERAL_NAMES* names = static_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(ext));
+ if (names == nullptr)
+ return false;
+
++ bool ok = true;
++
+ for (int i = 0; i < sk_GENERAL_NAME_num(names); i++) {
+ GENERAL_NAME* gen = sk_GENERAL_NAME_value(names, i);
+
+ if (i != 0)
+ BIO_write(out.get(), ", ", 2);
+
+- if (gen->type == GEN_DNS) {
+- ASN1_IA5STRING* name = gen->d.dNSName;
+-
+- BIO_write(out.get(), "DNS:", 4);
+- BIO_write(out.get(), name->data, name->length);
+- } else {
+- STACK_OF(CONF_VALUE)* nval = i2v_GENERAL_NAME(
+- const_cast<X509V3_EXT_METHOD*>(method), gen, nullptr);
+- if (nval == nullptr)
+- return false;
+- X509V3_EXT_val_prn(out.get(), nval, 0, 0);
+- sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
++ if (!(ok = PrintGeneralName(out, gen))) {
++ break;
+ }
+ }
+ sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
+
+- return true;
++ return ok;
++}
++
++bool SafeX509InfoAccessPrint(const BIOPointer& out, X509_EXTENSION* ext) {
++ const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
++ CHECK(method == X509V3_EXT_get_nid(NID_info_access));
++
++ AUTHORITY_INFO_ACCESS* descs =
++ static_cast<AUTHORITY_INFO_ACCESS*>(X509V3_EXT_d2i(ext));
++ if (descs == nullptr)
++ return false;
++
++ bool ok = true;
++
++ for (int i = 0; i < sk_ACCESS_DESCRIPTION_num(descs); i++) {
++ ACCESS_DESCRIPTION* desc = sk_ACCESS_DESCRIPTION_value(descs, i);
++
++ if (i != 0)
++ BIO_write(out.get(), "\n", 1);
++
++ char objtmp[80];
++ i2t_ASN1_OBJECT(objtmp, sizeof(objtmp), desc->method);
++ BIO_printf(out.get(), "%s - ", objtmp);
++ if (!(ok = PrintGeneralName(out, desc->location))) {
++ break;
++ }
++ }
++ sk_ACCESS_DESCRIPTION_pop_free(descs, ACCESS_DESCRIPTION_free);
++
++#if OPENSSL_VERSION_MAJOR < 3
++ BIO_write(out.get(), "\n", 1);
++#endif
++
++ return ok;
++}
++
++v8::MaybeLocal<v8::Value> GetSubjectAltNameString(
++ Environment* env,
++ const BIOPointer& bio,
++ X509* cert) {
++ int index = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
++ if (index < 0)
++ return Undefined(env->isolate());
++
++ X509_EXTENSION* ext = X509_get_ext(cert, index);
++ CHECK_NOT_NULL(ext);
++
++ if (!SafeX509SubjectAltNamePrint(bio, ext)) {
++ USE(BIO_reset(bio.get()));
++ return v8::Null(env->isolate());
++ }
++
++ return ToV8Value(env, bio);
++}
++
++v8::MaybeLocal<v8::Value> GetInfoAccessString(
++ Environment* env,
++ const BIOPointer& bio,
++ X509* cert) {
++ int index = X509_get_ext_by_NID(cert, NID_info_access, -1);
++ if (index < 0)
++ return Undefined(env->isolate());
++
++ X509_EXTENSION* ext = X509_get_ext(cert, index);
++ CHECK_NOT_NULL(ext);
++
++ if (!SafeX509InfoAccessPrint(bio, ext)) {
++ USE(BIO_reset(bio.get()));
++ return v8::Null(env->isolate());
++ }
++
++ return ToV8Value(env, bio);
+ }
+
+ MaybeLocal<Value> GetFingerprintDigest(
+@@ -628,27 +909,6 @@ MaybeLocal<Value> GetModulusString(
+ return ToV8Value(env, bio);
+ }
+
+-template <int nid>
+-MaybeLocal<Value> GetInfoString(
+- Environment* env,
+- const BIOPointer& bio,
+- X509* cert) {
+- int index = X509_get_ext_by_NID(cert, nid, -1);
+- if (index < 0)
+- return Undefined(env->isolate());
+-
+- X509_EXTENSION* ext = X509_get_ext(cert, index);
+- CHECK_NOT_NULL(ext);
+-
+- if (!SafeX509ExtPrint(bio, ext) &&
+- X509V3_EXT_print(bio.get(), ext, 0, 0) != 1) {
+- USE(BIO_reset(bio.get()));
+- return Null(env->isolate());
+- }
+-
+- return ToV8Value(env, bio);
+-}
+-
+ MaybeLocal<Value> GetIssuerString(
+ Environment* env,
+ const BIOPointer& bio,
+@@ -917,11 +1177,11 @@ MaybeLocal<Object> X509ToObject(Environment* env, X509* cert) {
+ !Set<Value>(context,
+ info,
+ env->subjectaltname_string(),
+- GetInfoString<NID_subject_alt_name>(env, bio, cert)) ||
++ GetSubjectAltNameString(env, bio, cert)) ||
+ !Set<Value>(context,
+ info,
+ env->infoaccess_string(),
+- GetInfoString<NID_info_access>(env, bio, cert))) {
++ GetInfoAccessString(env, bio, cert))) {
+ return MaybeLocal<Object>();
+ }
+
+diff --git a/test/common/index.js b/test/common/index.js
+index 8cd9841527..98b586cafd 100644
+--- a/test/common/index.js
++++ b/test/common/index.js
+@@ -51,6 +51,11 @@ const noop = () => {};
+ const hasCrypto = Boolean(process.versions.openssl) &&
+ !process.env.NODE_SKIP_CRYPTO;
+
++const hasOpenSSL3 = hasCrypto &&
++ require('crypto').constants.OPENSSL_VERSION_NUMBER >= 805306368;
++
++const hasQuic = hasCrypto && !!process.config.variables.openssl_quic;
++
+ // Check for flags. Skip this for workers (both, the `cluster` module and
+ // `worker_threads`) and child processes.
+ // If the binary was built without-ssl then the crypto flags are
+@@ -714,6 +719,8 @@ const common = {
+ getTTYfd,
+ hasIntl,
+ hasCrypto,
++ hasOpenSSL3,
++ hasQuic,
+ hasMultiLocalhost,
+ invalidArgTypeHelper,
+ isAIX,
+diff --git a/test/fixtures/keys/Makefile b/test/fixtures/keys/Makefile
+index 824704c724..49cc29ad1c 100644
+--- a/test/fixtures/keys/Makefile
++++ b/test/fixtures/keys/Makefile
+@@ -75,6 +75,8 @@ all: \
+ ed448_public.pem \
+ x448_private.pem \
+ x448_public.pem \
++ incorrect_san_correct_subject-cert.pem \
++ incorrect_san_correct_subject-key.pem \
+
+ #
+ # Create Certificate Authority: ca1
+@@ -733,6 +735,18 @@ x448_private.pem:
+ x448_public.pem: x448_private.pem
+ openssl pkey -in x448_private.pem -pubout -out x448_public.pem
+
++incorrect_san_correct_subject-cert.pem: incorrect_san_correct_subject-key.pem
++ openssl req -x509 \
++ -key incorrect_san_correct_subject-key.pem \
++ -out incorrect_san_correct_subject-cert.pem \
++ -sha256 \
++ -days 3650 \
++ -subj "/CN=good.example.com" \
++ -addext "subjectAltName = DNS:evil.example.com"
++
++incorrect_san_correct_subject-key.pem:
++ openssl ecparam -name prime256v1 -genkey -noout -out incorrect_san_correct_subject-key.pem
++
+ clean:
+ rm -f *.pfx *.pem *.srl ca2-database.txt ca2-serial fake-startcom-root-serial *.print *.old fake-startcom-root-issued-certs/*.pem
+ @> fake-startcom-root-database.txt
+diff --git a/test/fixtures/keys/incorrect_san_correct_subject-cert.pem b/test/fixtures/keys/incorrect_san_correct_subject-cert.pem
+new file mode 100644
+index 0000000000..787d9f1135
+--- /dev/null
++++ b/test/fixtures/keys/incorrect_san_correct_subject-cert.pem
+@@ -0,0 +1,11 @@
++-----BEGIN CERTIFICATE-----
++MIIBqDCCAU6gAwIBAgIUE3Kx4WUjkwuKy/fBOM+UJkb9aSAwCgYIKoZIzj0EAwIw
++GzEZMBcGA1UEAwwQZ29vZC5leGFtcGxlLmNvbTAeFw0yMTEyMTExNjUxNDVaFw0z
++MTEyMDkxNjUxNDVaMBsxGTAXBgNVBAMMEGdvb2QuZXhhbXBsZS5jb20wWTATBgcq
++hkjOPQIBBggqhkjOPQMBBwNCAASQ/CKa5uMZuLYssnNOm7DPdw3I5Doa0Qpyf3cS
++7aGatfK3tuY8qG7nJ5OGtl1WOL/gN0vRRN0/KA/iRJyjafzzo3AwbjAdBgNVHQ4E
++FgQUFkpgPzE1ePjK5UsPcR0gk5uLsTUwHwYDVR0jBBgwFoAUFkpgPzE1ePjK5UsP
++cR0gk5uLsTUwDwYDVR0TAQH/BAUwAwEB/zAbBgNVHREEFDASghBldmlsLmV4YW1w
++bGUuY29tMAoGCCqGSM49BAMCA0gAMEUCIQCMZAinQXkOEhfp+moxVnLbcUPAAqsl
++1KCq3NRG91TGCgIgC4grmOhCRqJMF1RPNWobGogX/yNrYNjiGzNVyJzMR0s=
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/keys/incorrect_san_correct_subject-key.pem b/test/fixtures/keys/incorrect_san_correct_subject-key.pem
+new file mode 100644
+index 0000000000..f7f51253a8
+--- /dev/null
++++ b/test/fixtures/keys/incorrect_san_correct_subject-key.pem
+@@ -0,0 +1,5 @@
++-----BEGIN EC PRIVATE KEY-----
++MHcCAQEEIOOVRgLS3H2T2fUhj4ASCFq60ySwO6yvSK6rvZHldAHuoAoGCCqGSM49
++AwEHoUQDQgAEkPwimubjGbi2LLJzTpuwz3cNyOQ6GtEKcn93Eu2hmrXyt7bmPKhu
++5yeThrZdVji/4DdL0UTdPygP4kSco2n88w==
++-----END EC PRIVATE KEY-----
+diff --git a/test/fixtures/x509-escaping/.gitignore b/test/fixtures/x509-escaping/.gitignore
+new file mode 100644
+index 0000000000..504afef81f
+--- /dev/null
++++ b/test/fixtures/x509-escaping/.gitignore
+@@ -0,0 +1,2 @@
++node_modules/
++package-lock.json
+diff --git a/test/fixtures/x509-escaping/alt-0-cert.pem b/test/fixtures/x509-escaping/alt-0-cert.pem
+new file mode 100644
+index 0000000000..30e6fa6c3f
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-0-cert.pem
+@@ -0,0 +1,29 @@
++-----BEGIN CERTIFICATE-----
++MIIE5jCCAs6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++NTAzMDEGA1UdEQQqMCiCJmdvb2QuZXhhbXBsZS5jb20sIEROUzpldmlsLmV4YW1w
++bGUuY29tMA0GCSqGSIb3DQEBCwUAA4ICAQAcsy+PIduM8NRrdqcTqufiajsAajQz
++eB5+5+lZLi9MliXqoS4HsdrDMDevMa2cC+wB+XZW9SJXjtqrwXAxTAHtEyhsCi25
++XV0sJPWmZM+OQkGTtp7Ain12htr/t/DJ13YJpT03W6kYogA1kKJ5OMYMTcGT+7UB
++zM4G2LUSrrSisxhfz9bF8Q9s1piG2gb5ACEQUiMLRrZXl8WLlaY59lloKyMa/9g6
++i3TgLxhp7XNS/bh/f2tDx+7ZgdtHUlkNhl1MycIVQRGK3BaZBEd+sDxS52kwym5I
++CWLXGLutU3OeaNgqyvZuMvy//2oER3PysizyjwNoFlUbIz3zMnXvBeEjeGtEHsCJ
++EBtX+xBWwMhUKE2QcMLxQaZNJCZFVFw8fDeEgFjTdEBcLsZ1PngT3jgXSHEWA+YL
++C3rQhFMjyjy2h8u1sjySFrTlbZPm8gC3q/+LaXxhf5i5xiZOOcVfeYiWFUa5gQal
++FaWj2SlQFaN2nidPaQO62vRIYn0Y/qbtUQAPkq4VVeycgxiuZaVVWCdct8UCYb9F
++b9QSMpK4r99MKy+s41RiJodDJy0XraOxy7hUDjyObL2fuuPUK6mQAFGwWtajv3qq
++vrRMvBEXdOPVmbETyzIosUHvOXT+v8WoCbC14mqMZTWVywRg7bD/NTHJDRIBrqvi
++O6Zqbod3EImVnQ==
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-1-cert.pem b/test/fixtures/x509-escaping/alt-1-cert.pem
+new file mode 100644
+index 0000000000..63883c2bbf
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-1-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIE0zCCArugAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++IjAgMB4GA1UdEQQXMBWGE2h0dHA6Ly9leGFtcGxlLmNvbS8wDQYJKoZIhvcNAQEL
++BQADggIBACFwNHWQ5w3UBbyq17emn7Z0BT0Zm5iFr8Qeik75WzbyzXd5QIeFWewB
++qmiuaoKGGZ674sGcuomnIwoZBCoqvzbBBqBHp+O3/6pq59THQxeE6vhjKAe8oaih
++emdigRmkX+Qi8UwUh76B51wHtkp6zAZnLDn8M67qmP7bjNrrMQeE81wRWYz9ssfd
++N63dzu2BdD3EGl4CepdszpfUYLkz6iiDwFkc1NaBcQbBDoGqn2ubNXTHAyGGeL5a
++ulDCND0FQtg+jhHHE3zXBqh1nPg/cXXRUG2zjxzUnaU2eMs5b4yqoLN/2n7fb7mV
++HRh0T6X1HZcYpf5BSsgmr3Ngd/9b3sYRvNXBkVmKAu8dH7zguksczsvbL9r/u2YX
++hgGjNT3xSphJbZTzqsACcoDo67EFkJ5p25f0N1i/rxk7O6uLMtrUqnzOXs6NXgEQ
++8lyfVEgLFrXzdKXuk2l/6bwym80Eqdpjv5yCckCl24cFVpc15MRP3MPwIHrtoOLw
++bdNZA5NUAnppLmG6zTdPPgBWEmf5+4ei9WjmpG1hq72/nJ1qM2dLIgV5nLggr1UH
++i+vih+ujceBLVumAu/naP440xO5HRvpPfDWI+eU/wuXjUyAqe6YlYS+Txu/5YnFh
++aMHO+PIgudWwGPhkABtrc/1jC+Yfy+GCtih10zBagoN9/DSugh0H
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-10-cert.pem b/test/fixtures/x509-escaping/alt-10-cert.pem
+new file mode 100644
+index 0000000000..14bec45d28
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-10-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIExTCCAq2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++FDASMBAGA1UdEQQJMAeHBQAICAQEMA0GCSqGSIb3DQEBCwUAA4ICAQA+jnyjJ/9X
++ENWXApq2g+GlWBM07KpsrxzwDXc6wsOnZCIiMoDqpcH96X8Q2Lahc4mZuz4yOZtv
++z8Q9YUDTnJY+RtKYNDbxlz7wI1ASxKdP0X1qdzkYtHH752tG/zwVU2FSvqJLw+nl
++rPJvQQ82/30BspejbW0JIfO7JnfN5BHPzzJp/V5tI1KQe+Wh0gEq6UvXjFrkCoeU
++gaedPaG2RYDi1LWawRque7pnYzrcJCtc+wb8wiL1dRv7fDDmI7fFm3Bj6Rnid4/6
++/CxK3WqLBQrXoGnPGwI4iR17Rx08hPCL2V8NvDuJlagJe/Vc6LzOEixofoHGx4rG
++Cm0AKubKbak/ML/rjyP2TiUmOhhm3Xdml3xexedErkgTLtlvmC0jesYuc4MeypNx
++Q0eKRnChRGZYT9kaNgXZG1Scq63vpxKhayVvwU4ahGQS+nmuZdbRMEMIH6YkGxo/
++i5qmNxQPLMLE6HclSdDtUxN4ywQAQ49CaTCxVYq7dLTzpII3ldQ+KuefenaXrYGE
++7TyqJBVdsTq0Bg2Ftf7GaoidJ/ZjjkB3Sj5uVQFMfU8uSATOolBOzh6fSiQJ60Zn
++CtAAkb9uOwTl67Qijo4qAe9JRNqR9H5d65D0Vx+gdhcZVEriqIVhXVcgsvYQ55Ju
++VGhc/foVd+vBuM3jXEdGR+DN/dEu+HZrhQ==
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-11-cert.pem b/test/fixtures/x509-escaping/alt-11-cert.pem
+new file mode 100644
+index 0000000000..694cb7e9d8
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-11-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIExjCCAq6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++FTATMBEGA1UdEQQKMAiHBgABAgMEBTANBgkqhkiG9w0BAQsFAAOCAgEAp2nxfYla
++giNJ9S2owtp/5DxB3jIhQJzmdSxuUKVwWBffmzxrTkOoK/IcGkq3hu27GIy+ICFc
++YkSsAE3DfboSTStxhkVZKMVv+e5tXPQ0i+Z+CSgHZbrnaA7nH0UPEgFFddhqogGw
++LGE54iZ3D7ZYebTw/ELCIHNu9KeOStF7j04WXG7qRrqza5NmKqlxTC5tGoWAljzN
++cdC2BdK7H2+6de3c4dBsYqcL2IgwNhA1uKIsDjJwwkOPmCEPl+7DjleI3IAKpROh
++vX66DLaAsLEkoHsN7XTienHF8o/avIMGUfb0rtNLbwW8tzfjeAaJ7iTSm7ibhBLP
++fK+n7Osh9QH+lG0K7M2zez7Kd3u+eNgTEG63gVR+zDZQwkA2Hy1o4zmZ+a3iCtdi
++w6JGq3TT8nfPNO4kSoq7EYs6daPnGi3sqNRC20t4FZw0jOpvI4Uw7rPcTTqmAeAw
++9H37WU3URD2EP8BpkoZiOShMHzNGqlC9qbqr5dd83Lkdz9gN4w3ipdbiiGFGPXhT
++YubUecjwXoBUUI+be/edVbg7RtSSuplDv5l4bBSy+BG8JEUL6CKAUEtt2Tpt2SVD
++AIaj0B19/DSYq1e4x8IBVBsI2RnEEpP70bdLiSYLhVhMdzp0PRqDVDE+zt4mm0lx
++NRDSdNS1/rJEH1gLQEh4SGMs9iY5Vv+kx28=
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-12-cert.pem b/test/fixtures/x509-escaping/alt-12-cert.pem
+new file mode 100644
+index 0000000000..7e48ebdf05
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-12-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIE0DCCArigAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++HzAdMBsGA1UdEQQUMBKHEAoLDA0ODwAAAAAAAHp7fH0wDQYJKoZIhvcNAQELBQAD
++ggIBAEMU6XcjSdQ+EG22BsyAYin2d3g9Fd0gljsuyEyw2qwFE1zeNqz2sFX7GdmP
++hEmUVdzQ0EQsHtKiO2BIhU5fkLoGIkJQT0MY/Tkc3xCLjVBG9ryHNjhv4aYfcvZ2
++K8LwWu5na5YtpmEHppFTmhQFHK9Yf2Jeh5Ms1VH2jwKR8iFM9dk0wcB74Y1WqyX0
++bhNUzv0ISvz/DK6rN0CM0OiZ7D1toMFJIslEcZD/MCZ0icFwRgGLzooDbm1xtixo
++NjgdswdiL0cS/wgSdzu9eIugUQZU2KvUWYXGqYMDpn7iukiZSKQuFhZGcuK17zyR
++y6TkDFe9rTxVtw9SAxjlo94rEqWN9Cns0n7tqAI/Wg6ILHUjUFwqSdrZQTEgH4O3
++tfhRkV4HCgP1Tzfz/20uMBqjCLbdt7xcSfLIiHgaxgwM0LGhH2Uk3oYinL2WIUDi
++bZPI+1bzeyZ/tHw4sDxkGn3W3Nr44Td/5DAFz1lRMxAliVwHNzFTiY7IjCqmB0DL
++z91agdgPMdh/huFvGJZHS/v7EXMSXyNLyIw+5JO12iwf4+pu8NLnOtMoHDB4yY0w
++MEerc4e8SmygBQGF0MrcmirdT+7yiKRktZZFuyQoj4fBSKeBaBKUrnnk4UYw9H8f
++j/EQwM87PmYjTwYPrJ0Kz5r4dmAUvq4z2ReLgM08Ve4SPa79
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-13-cert.pem b/test/fixtures/x509-escaping/alt-13-cert.pem
+new file mode 100644
+index 0000000000..574ad1ca8f
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-13-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIEzzCCAregAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++HjAcMBoGA1UdEQQTMBGBD2Zvb0BleGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOC
++AgEAkx9jG86PMjL+/UxlhX0B/gIKHyTVrEt8j+/fn74uMnd7CV7toK6f5DANIxYp
++3OJWAFYZ2lNS3MQMxpbjpd7D0BeNwhiJyBnRPhJ9KdsvdXnupF5ANNzr3oMioWwL
++3WxvmQDEz35sorae5nzuZu8EpuwgodR0NCEmoPdW9JOUiB7k3Ku5goZHqlrdzM8f
++YPbRDNOxSIpRqr5eqhEM9tEf+TF6qOM/NZJlXxtGDVdaDTbaULuCJGEW8TdVajnY
++FfWWtIHwF64G5qJTgENqJjR1kkJy5vg2lFoDXE8MG+LvTHfyY0rMilncD2YOBLcj
++gb3mBTxZGI2w2KZbchgEvA9+0heumAVJQPfdGs+pCUdvlhwWh8FCvu3aQb5X57OU
++3D97vwvEs8Mxm0KHf0o0ZnTvaBWN5htX2bbpvYxGGB0SsWM8r1LIXj8bwGNdViV8
++UWNrg37XyGCppL1jXJ1q+DDKOvi0JR384ocRmS8mWUf9qiAMOqveix38rHezWlEm
++4TCscq4tv135nM194D6uilzv4mUxLAMTX8Lvag1R3aKuOHio9lCGep4v776kALE6
++9/rekRGoMwNApoaC96x+V/dkbfnjWcxRXL5TvjDwVInl+RCcn6ijYZM0HYc+U1Dw
++MwqBCbP2Y9Ee7xcnAgPbqH2svWG7XadQHAcOEDc/DFsPRG8=
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-14-cert.pem b/test/fixtures/x509-escaping/alt-14-cert.pem
+new file mode 100644
+index 0000000000..0265b5992c
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-14-cert.pem
+@@ -0,0 +1,29 @@
++-----BEGIN CERTIFICATE-----
++MIIE5TCCAs2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++NDAyMDAGA1UdEQQpMCeBJWZvb0BleGFtcGxlLmNvbSwgRE5TOmdvb2QuZXhhbXBs
++ZS5jb20wDQYJKoZIhvcNAQELBQADggIBABf7bojDeoFEFyk/Xzo50sAL+5irJYzV
++n//5aEvUotYxQt5coi7UnkKUgdiUhIXD8WaxD9KP3nUH+C3cxAQ+I7iVjFhjqFQB
++X4c/ZjJA2QIX7VMWA3kpOFvR5N0HHest097Fi/HUEEXNkcUtCkRNtI2Msse9uz09
++DIv9P0IQ2TFgBRCTJwq2ZfVebHk/xoQ5fV9b0b39ts6ToiuMvGJVng2zz8fVNMah
++hycCn0WSb6dPi9k0ItSvRTYL6vp9X842+Q0Xkq0FxQPUcvzN7D1tSmHXDM7nYXp3
++FB6DKASp0+nn+J88RXVSpO0JedEyRDEluxHJcan+hqhWJ4DgamlVTEPN3q5yE4lt
++Jr/R5tnx0Lv0CxDTAfZLaFiKb2jz9nVhzbCh7t21mxyb2mOM+GAxRaIgxodeNJoY
++QA6Ezz4cbjjA72Rgi+tBxy2abXpbbJ/vX7FUhs0ICFKZJHvFoxazgtSGgHHYNxhc
++/+9o6Y9jhunwGn/MaoxWJsdSjZ8VX7HY0iOSU3z4d4PWvIz05n4sGoJET6s1JuKe
++dZAAeQy0V5/EzxIu4GPGrzVtk2SQhNHVJZKponZeCRruruGT5Z1T+gF5YSqVM6BA
++XA0ZVXwOEbZ5XRIzBBbaiX3Eeful50ILOiP/uxLlcZtTtOyT4wNBgijfJehRHbED
++ppJk42EFZKb2
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-15-cert.pem b/test/fixtures/x509-escaping/alt-15-cert.pem
+new file mode 100644
+index 0000000000..70a98fb90b
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-15-cert.pem
+@@ -0,0 +1,29 @@
++-----BEGIN CERTIFICATE-----
++MIIE4jCCAsqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++MTAvMC0GA1UdEQQmMCSkIjAgMQswCQYDVQQGEwJERTERMA8GA1UEBwwISGFubm92
++ZXIwDQYJKoZIhvcNAQELBQADggIBABIv7Wlg5F1gh0+0v/+LnushmLeypcXQGqkg
++E2IxXC2VnZxq8xTFCHy/m1qTBLPJK5VIg5qmtstL9zIk9rOUshQvusvNLplC0j3o
++GuQdQJNKV7rrzYYpUZO1en11q27AgDsO6lwSNg4U+mqzJxxIHc8IMeJpfaGTkUz/
++ZXXNz04JJalUff+W2436vSvu8Y82fD72/qNu6EMiOl0EHJFQ/7eCAlz6hSNleLT/
++N2GztApNzujbPgH7+PHOeVpwppDuXY1rkmPJMxCqkY8yOwyM5dMov0bjIN1f+QXv
++7voxVGMTefUajKADaNGMShH5rhgjIWBgujvdCyLPr6W2R4S1QPzjx4X26eTX1G8V
++/eTsJ6mMc+3cd6CEmEahUnc6LdEdwm+1SMRG2nejea4o8c+crwYX5KQVrqx92FqB
++SdkdCtS6qlnxJVvSz+HW6lEM0EShvjKEz/udsnttALQjhxfB7AHNWA073o/OiH25
++Y9QpUudmWJjOoqRokN0SV4rDQnfNcLKIoVFPu+rG2CpBDjUsoxG3/aC8Owcd8Ceh
++w+O/DqQXudXFS3RsePbz4rPfID9YtBHrihCE10B70DUutWPsbe5lKie3wJpQbqvl
++zp5kkI5RffVU7OFD6os3+wPomdIG21Cf/fru56nV3FmkINCabLQddes7OarQcZ5y
++xsumEzq+
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-16-cert.pem b/test/fixtures/x509-escaping/alt-16-cert.pem
+new file mode 100644
+index 0000000000..64f852ceeb
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-16-cert.pem
+@@ -0,0 +1,29 @@
++-----BEGIN CERTIFICATE-----
++MIIE4jCCAsqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++MTAvMC0GA1UdEQQmMCSkIjAgMQswCQYDVQQGEwJERTERMA8GA1UEBwwITcO8bmNo
++ZW4wDQYJKoZIhvcNAQELBQADggIBAEID22h5WK1YJrKUmmO0owley+tL519YwJbs
++FwbwPz7+SJKA+UQNqVXYOGLwDJ6A6OzsV1TnJuwGotTmvNwr7eOVyLf03qggIYEj
++5Twgk57gJmqE+Q8UXUq2ocALUcgReZhluhNoL1XYQMbDaHYwh9HSOP7udEszVQoE
++m1D74cSiW803XnqPJGj0i1s9mD6AEewPl2k0mQ0hTMM3rlE1jOCj4Jx81tWH5KNY
++LXn/LhFomeo/LAU4PCFTt65tAomKTNXq0GwuunU62fy8pwh9QUpD3Vfrkm4+08uz
++WXSk9PeaF8tOs5pRwVMRr0GIdnQHa9GKuBBSZEvkGTxLM+cxO7jp5qSs2IRVpI5s
++ztlJQcJpeTRNCEF7gM98nMqDqve/IySGle9s1RjpnBuSD9UKzbMGeBuZK8d0JfBt
++7XF3i6Tu74EbBL/mP/0xoHausW9Yo8HZhXjm5k9P7m9xxlq2JSSXeQCLbKFT/SN+
++Q3bS6rh0HaqLP8Gd3OyU+aOOy13Tr167LEFNK6DlfSadITuHwRMNvCk8UIDRDzAZ
++kXVXdT5UfUe4IJU6OPVsFfntTX6G8s2/K4WropnjD5NjBJ0ppvPgCBqEA03mCGVt
++IunRhQypiA0+SilM7BX6jD97IcmnbSyQ6fUkIdDBTMlX3MoYXkT00gDT3y8D/aKw
++KTd5SKbD
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-17-cert.pem b/test/fixtures/x509-escaping/alt-17-cert.pem
+new file mode 100644
+index 0000000000..f09f41b918
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-17-cert.pem
+@@ -0,0 +1,29 @@
++-----BEGIN CERTIFICATE-----
++MIIE9jCCAt6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++RTBDMEEGA1UdEQQ6MDikNjA0MQswCQYDVQQGEwJERTElMCMGA1UEBwwcQmVybGlu
++LCBETlM6Z29vZC5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAgEAchR9+hds
++zMK0NKgiX32XxJJ79tlo2sRMCZqij8Lqfyz7JDlTMSvIVqcrmimlAMX5u8BxKRXG
++99KzXhbJb6Hnj2i6fQobxpD6nKnPSUcoiiWccmp8jmcKQW7M6TuqOfEdEnKpf0BF
++vNFBjXGxs0KqOArX/1d0DqYS1LTnxaC6NimgvjAqKVRm9mqj62pc9//ixCgHkqLJ
++stuoSerbo/mO0ieY1wq9r9TZT1epacVrQpJFWeJWhow94WutMNesJSWLcxX63mH4
++j0LHEEkHLa1UkMzM2RkHTVhKrthCiuyrtqrglLsdPInU7ZYVONyUrR2D1tMy52mB
++b1HzzP43pomBJtp3OeEZtBDwmmGgD8RBdVK/T9hcK02cvB1w1yr4LHUeYLMqrZaP
++SJHQ7kv9AV5Os64SYW9+7cqjt1q4VmaEqcuCqvB6mORHWHnsa6PQ19myA7OdqNpT
++WAK3D94tpbGPTzfhUCHk0w0fPzJ4A1+S6g4eHX4iQQxxDg9sXV4ZRvAEKnJhs2S7
++OhtXdfyu/1+lfaunN13SyxMwyyxHzylEU707Sisxse2usX1Zy2zxqD+LO/9iIu1S
++76/rquhiOFRWxSpjb7ewpH97OGFmtzfH70vBBukn0alT4xjkje10NlBfzcFwHWQH
++59nxPd5sUEqq+DxTjoAgwO91woU7UTs98lw=
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-18-cert.pem b/test/fixtures/x509-escaping/alt-18-cert.pem
+new file mode 100644
+index 0000000000..341ac0b7ce
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-18-cert.pem
+@@ -0,0 +1,29 @@
++-----BEGIN CERTIFICATE-----
++MIIFBzCCAu+gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++VjBUMFIGA1UdEQRLMEmkRzBFMQswCQYDVQQGEwJERTE2MDQGA1UEBwwtQmVybGlu
++LCBETlM6Z29vZC5leGFtcGxlLmNvbQBldmlsLmV4YW1wbGUuY29tMA0GCSqGSIb3
++DQEBCwUAA4ICAQBFUk2Z1E5Q4mW7S8dLz5h78AmfNbwx9eNtECc8iLQq2Q0MuIzQ
++noURyNSHhH2hkohU4afXjolCr54DkJNYogrBwHaNDt3Y3wqGQXc+BKRnqblfr1+A
++1EoIaqRFjv/Mu2gB0H4U3vBRYriZu7BhQFXiQHAr6hWLG91B1eN1i+my9zOSoSZF
++7BuemB/9F4wjvwmDJieSwOgGk3FhNV64Ce9M95RwDKNSJBTBqOTLoyvOw2jgs22m
++MntqW9oRywGeHdJ5EucPBrZQKDNysNFj3We8H7PedGNlnG/QknE6pzpRgqbRCAax
++hcvGQIaMcUJ3oWhJuPNscjsJ/nfaitz58nH5raj4O8JhlS1h49NpbJO/pAWMHh0d
++ZruXspxdEwW17aMJJ365q0XyVysRHiwQuIQYCo8L7oVUsH5FUJ9xxPH22b+PG05r
++EABdID+aDV7X/MNwBxgeBOFVOgE5bfrH8NBjkx/F7ID/hjcQDLVWWoFnpIjekebC
++EeqTRl5TcnoN9Dc7zkfwmuYGoaYJrGhj7WRvfFgcw1Cr1xujiJtoKbEbMoeD45+H
++SQ8MwBb37Gm3aBNakpVmJlp/QZSJY403hA8QrZdjnqoS4THrC0+gN2q71aZ9ZCZY
++3+OPNg659ZcYvo1onBSA0p1WGKEAWdHKqZCVRdsl5LnRg4H5gEVW4gmhjA==
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-19-cert.pem b/test/fixtures/x509-escaping/alt-19-cert.pem
+new file mode 100644
+index 0000000000..f163184204
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-19-cert.pem
+@@ -0,0 +1,29 @@
++-----BEGIN CERTIFICATE-----
++MIIFCDCCAvCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++VzBVMFMGA1UdEQRMMEqkSDBGMQswCQYDVQQGEwJERTE3MDUGA1UEBwwuQmVybGlu
++LCBETlM6Z29vZC5leGFtcGxlLmNvbVwAZXZpbC5leGFtcGxlLmNvbTANBgkqhkiG
++9w0BAQsFAAOCAgEAWtSJOhwRpYdB/aq/AixRTIpwf5VR3MWaDNh7clpnpYhYoLDY
++7dJ8cv3AR5dOScFXLrCZ2UYVD+tTPyt18opnYDT4h6If/U9TTHVu5tRSX0wGIdPc
++j3zVVegty/HWMA5LfwygNTvZjgXhocckNND7hC42+BuXE2bqoqnkqMRer/R+9PmU
++FXpyLk0aDl2QmspDAz86FYpEuxpMfmDNmM1nWDz+n+uBbeuriTttsFqFWkfOGoNN
++/3tAmUjAt5IqkL+7rnDt6Lc9inY0z3uYGJEdqa0GJJFJ7U+8wcw8rUwvKETqAtW1
++mBOswkoCImPeNDpiqiotwl4cfrsb1+j9gNpYTP2oSurh/bF0mxGLoJa1iDeibwqg
+++f6oWcCdYQ94ItvS3d+lNXT0MWM6HU6sHXf3+5SqvsvsKjUBRyy1Nvnug1bha6Qv
++bdeErN0ZSGy12Vc90Y5fpl8kebmYiJc79OqvuTNDeRfgBm+U4ASAj/AEhtbN+wDd
++HrUHbk/9U9h0UFRZ5s7Pqoy5PEoLRoFeA/jQQa/fLC8nl7YTSwidVgj8cyAy36sV
++uaBNXrcgelqlR26SBynXM3APaFlv5IdSlF199swMCusQrGbiNajl21TUm+Iv+84g
++x7rnUPnQ1grkLpMOBtGaraKc93e2VfH5bAZvyaIq99qdA10ERCtE2grvjik=
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-2-cert.pem b/test/fixtures/x509-escaping/alt-2-cert.pem
+new file mode 100644
+index 0000000000..6ae58f5636
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-2-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIE2zCCAsOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++KjAoMCYGA1UdEQQfMB2GG2h0dHA6Ly9leGFtcGxlLmNvbS8/YT1iJmM9ZDANBgkq
++hkiG9w0BAQsFAAOCAgEANTZFCjNmspLkZaVYkcAXfT2poPPWAu7wS/wG4VEmKwPV
++A4dnFV2McXNW/iyABeoofeIjsjiYLpxTvz3teD2JJh+hidNED77PV7f4hj7vs4Dn
++DGB3HKJvTD63AVOiPJ4bbfUyiuvLO5TwdxAGm+q9lsf/fWFraTF2qlnFwyWf6Qul
+++NQo3bM8mErvntZMscq7wo0cOdAXA0bNqxKS+IDnc+HLxoEr2egbRJmEagMgV4/U
+++AGVQ1sY+HrEszOPUA6NZ/OzLuXUT3swm+4rqJZEQ3AVr2BdqSzoiGHqqzmfKO33
++sODcYXuED0sUkIhRZE1vW+wXR94WQsT5C4MtHabNjpPLSH7cVjGvEfTX8DJH/F7p
++OdMmXxvPey0wLGJwoZMMhG/XC8Nb1g+qCLLou9WuA7KHMibfiYdBnPcMDg3fwWwg
++pYzrvK/S6f5h6TS8y9zKxCJwTdfC7f4KT6EjxQFhgHCm8oFupOLSEZKF0UmLMeOA
++J504ZnGdhEG5p9AqQNBlyBsGGmSyQkSJg1BPB6U7wFBSwrXS+3b2ph4J5RivH68O
++CKjR7yWl7M75LOa1dt133GmhPUUGHLsjHTnuCDVB0eHcgboonKTjCSAmckNKm/uw
++tAUMkO3puty5JM38b8AwFRDXLnlWdSsNr9j243SHOfKyFWidjwglRpVGBhoECtA=
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-20-cert.pem b/test/fixtures/x509-escaping/alt-20-cert.pem
+new file mode 100644
+index 0000000000..eca176f2df
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-20-cert.pem
+@@ -0,0 +1,29 @@
++-----BEGIN CERTIFICATE-----
++MIIE4jCCAsqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++MTAvMC0GA1UdEQQmMCSkIjAgMQswCQYDVQQGEwJERTERMA8GA1UEBwwIQmVybGlu
++DQowDQYJKoZIhvcNAQELBQADggIBAKvkEHjR6lk0AlKiC7oltE+gp7SpVHdKs7I4
++zswnbZ1EcddA9D6hjemU+nIUriLkt8BxY+KxNtkwDm5mvXZn5E4XDXzRDsCdNZXE
++qx9og9LhkhfGbPJ1LPutQ0VmqPwY17mRUeaLhNIwOmD7g++oVHYmZWqA8tHVB9f+
++gP5Ni2x/PX772Vt/hIpI14VoYIsMFs4Ewjc0Gc02DvOdsDT9eUmAo6GNOAbxeRS/
++D2D0w6CQhwJ+cemcAo0lGw8KemCYfqzL+MQd8wUGPsiZgm5wQACOp+ImL4guy2gX
++h60W9Gtxu77jsjF7n0n4LlInylrZAgw09CkehUfF4+cP2kZDTcsuqOoCVYATAGxa
++49ZvuRHoo5Ine5PcfuARS09LmxgI0fdsjaRvRELYIRWHTvE+zCLlNkxkpwXULgZZ
++bpJ08L52P+jz+HJPeiHZnYKXgtXyGLpwG1danS600tqiMmDh0G9Ss+UzwhS+jhN5
++viIvpmns0zvI1Z1IWPw3y27pw7rmLVcFMbEZFK5mwHiT10iRrT4sxihWIT+sn6n5
++5baup/od4kSJABQy9LAuhhuZHyCfxC2yPYz70sP8qGVtY+rA3LNe0ns6pY1L77DR
++QIRD/Mm2hql91+U222mxikdT4WQEheh2cLwdg/T1uo/SQDruliNZncdNbTGDmnhc
++cg1mw5tk
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-21-cert.pem b/test/fixtures/x509-escaping/alt-21-cert.pem
+new file mode 100644
+index 0000000000..16d5e7265b
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-21-cert.pem
+@@ -0,0 +1,29 @@
++-----BEGIN CERTIFICATE-----
++MIIE9DCCAtygAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++QzBBMD8GA1UdEQQ4MDakNDAyMQswCQYDVQQGEwJERTEjMCEGA1UEBwwaQmVybGlu
++L0NOPWdvb2QuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggIBAHdccJEkqezS
++GSNNVIWv9XffNTrZnejms90h66UDC4O9shHMy0aNWgmGuu7uFi1BK4sTciXT+ZR5
++3+1ni3WKMhJ5Iu1aNlNeXULOlmuHKVJKrAj8BR7lflSFqj/MHnw22HU+BTmddZPj
++F/OCl2W+O+eUNBTTmYI2+pZgmyyU9v8qEwLZn57qlpAJa4gpnSRYQS1xfSaUgAcM
++xtZM/AE4F9mDFOdO86/RxXsYRyT0+sOGmaoJrlTWoKduoI7fhzQAIGHnhn9yBT60
++0K6LmCR2dXRyLxxVTy0Laiz487IXpQTJ8jo6c0wT6SeiQBlE0W3FTH3IM8Shzd7b
++5tbix0bCR1pUT2Q46oaB4xkEweKNGKS46kIps6mpTav3TMhNDVyalUfF4fOu4FQu
++RLB6B/I1TI1KHiTeD9xfNInBAdO9ewjWQ9spFei3EExZmvnnWKZIA82mjG/9Wcdh
++HFK/uEylzo1Nsxujv2V6ueMYc0pF4XH2U1Azjxb0+pWUZhoy537Nlf8b+PO/GSG8
++del0yPwf6JP5AZdXfiV8vNqwEGCC/BEIPrbZ6Zz1q6lT+7GZAGkzbMYlfkzA1lXh
++JteRIracA38WfQOHf3FOPYvTBOPlVHWB+tJbwlalYQqCPupMaaxxizCLPIsNvqdy
++TAtC5Jbx6N1DdeyHpRuKRUe1M926oKTp
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-22-cert.pem b/test/fixtures/x509-escaping/alt-22-cert.pem
+new file mode 100644
+index 0000000000..5f89b00dfd
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-22-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIEyTCCArGgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++GDAWMBQGA1UdEQQNMAuICSqGSIb3DQEBCzANBgkqhkiG9w0BAQsFAAOCAgEAE8vG
++nLYo/G+3Cuzir4toX726vLOkCEqZrkRE18dc3px/CgmEI/6+4lWjp3u/9MxER+kT
++t5o5Xin+vmg5F+hocR16mMeX6pjD6tXJ+uzDacTxDgRBFdbqX4x8Fjiig0FXsr3H
++jFBY2c4UcKszFlCTqjH1/RfwLYJPU6Q1WZM+1iJotSKnhK7y4A/3jho7sL0PPuMG
++WEoxbTBmpAf+jPT+LRe2MY++VnVJHjlPba+S4Y9PHOzizQuIJs7YnhNIqA9So7Iv
++eA7Lp8GID+w/eY4DEq4z6CIuCplKZTrrWH0kQbG1sV4J5+W+JL0DOXDk91JwkOPH
++rWf6aOb3akFRk5Z/PrrcTAlqtApPQF4uGycQBo8KgcatZyP/3HZZHyyxhEjF9sw/
++STHm93GlCIwocJ+SkwjBmdupv6Yk8fRmA7LinjVvi7EnQQ7qcRE3oUCPPReDD96G
++TuDsGkQbv5WQSh+0mBAiTFze3C6FSNcldQBrlWReqOj6pVWtUN49lpYOJ2XfLCQe
++RjS7IUYNn7Ku3xXi2etgNzmJXcSnNXZkh+3henpFqkwEFJ5b5RgOHXULTwoqo9KS
++YMs3eKHp62J6l0pQD+wTGUyVU8cJghJ0hR1WnNR7o32Bos2dfBmIQgET4ZH/P2+H
++A2gtbJO5mRsTvuD+kZut1jxJvUzuO0yZoNpuUVQ=
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-23-cert.pem b/test/fixtures/x509-escaping/alt-23-cert.pem
+new file mode 100644
+index 0000000000..5cd6795cde
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-23-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIExTCCAq2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++FDASMBAGA1UdEQQJMAeIBSvODwwiMA0GCSqGSIb3DQEBCwUAA4ICAQBps3VQshvW
++9HDR2oDXSldWNW2SWksa+9npI4IEMDusiDbLdR0VBphw2R3iUuJ4IAPDc1s/SMi0
++1t1o92lC5zVeTq9LvOOC1KxwbZXDubFDmdsuJ/DYPDkaRoDqoH7eFsJuIyD/TKqm
++HXPYmWmjUNv51SSLTTqPRz2TmLQVA1Iw7J7H3fz2LExsAtczx6gRZJPIZGdMx6do
++E67SUp/2RPYtkEmmCELOxCAh/Pzm6pBPncI86AMTNwppl+FpqaH0LPrqMre40tTt
++cQq/0XrMWRoWsS3VU8uor+aGTnNp5VT3ZLVmXZNyG7nISW7ERaGCeTZJRcqwjeH/
++yPxhQc7IpYCm5x+HN2sDuvVC7l/q1A7+CbO3jNR5Gb7aEEyGiKb5ZkElbsulfwom
++JOg1K8+SBDGrErEf0MDCenKY2g0lhpKGBwu6O+RVmKbhlHEjt2/31/NCSBMLopdU
++AmCNoBo3+KaRljo1lVf7tWbffNRCqsbPZPHtq9uXs0DliJTUroaJ584h92VrSLJB
++SdAUVLAwzmwu2Pa4bp0STv5tJy1hFNJdVFQ4rgAfaFudXy41K9zqrDCB7RbzX7Yi
++97TCDu/phzkoFpOZabqTrvcP13N0wfDeOx4Y9nx77aeqTAaQ0ooTG9IWrHmjuUKF
++wpEXQBfkuXug5+xq/hlCllkPj67cIaldDQ==
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-24-cert.pem b/test/fixtures/x509-escaping/alt-24-cert.pem
+new file mode 100644
+index 0000000000..2a858dd39a
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-24-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIE1DCCArygAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++IzAhMB8GA1UdEQQYMBagFAYIKwYBBQUHCAWgCAwGYWJjMTIzMA0GCSqGSIb3DQEB
++CwUAA4ICAQCKRaPaQO4+oztra70h3g1qwmJurQ1vGBdcXh27nf9epFAwhU1zL5v7
++7wN7iclY15BX3w3WrZ+ag74AvQLG6WQkDY1JCmidEjjt2bmVTxIus0H9Bb2AlUEw
++BtVYMJrr+fiWbfSwRxhMQa9BQ6ZcUA7EluYQFApo2m7GIcMc4x51L/bwzmsXYj4t
++2tjnkU7clL+7GR/w/+ZB7nIe80j7wYvIbOfMS3Yxh+uu0aQCNdoh9Tsdtu1jtmJv
++4lJ5aZIDABE/XIFVkWRyHv2ou14J/LXUKE3HPEhSKWu7GShrdTeS+gZpOixM+uPG
++ieHah1GfJMS69P82Z72Cr7XWpQY0NKwMB+ePhTzz1LMBHQ5ySXQCViQRClRMc5K+
++cXZm8cs6oe4IEhMcf3kc/9xblgRWqxX7vsb6Gcrn1eXsfxco17S1yNBzTt75ybt9
++kvPmrWqpg+sQ0r4473DjEASoSCPwlzCpd7AHOw+XxSwsOUNXkEnXMa2v2VHBjx06
++QnrLenB/n7EQ5Vo9JLDMLM6ie4gfehHxfdyoBg21jN9eUPpKGnjARVvyfDWV+7rI
++ZHU7wc2iMnqroAqm9FZ0YBqZ/eI8M4ZAYSvDKnGZQlUWfhdNDhI4FsHBPymMFtjW
++ln5eFUNLMoitMGs12Ib+omr9WSTxRj97GvRkRTNK5Gxmo9Mi/Pkxng==
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-25-cert.pem b/test/fixtures/x509-escaping/alt-25-cert.pem
+new file mode 100644
+index 0000000000..695b8ebba8
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-25-cert.pem
+@@ -0,0 +1,29 @@
++-----BEGIN CERTIFICATE-----
++MIIE6jCCAtKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++OTA3MDUGA1UdEQQuMCygKgYIKwYBBQUHCAWgHgwcYWJjMTIzLCBETlM6Z29vZC5l
++eGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAgEAIgp7IrYYdLCoUqg7E4igLD3u
++C68B896uoeenMmTKDfCzvB5svYKZlfIi3njJUZ2G6kgBNcSd/mwQ2ggex9AEUiGp
++uaT7Dpev3RpwtCz5zpOZxN+B0LJk4hPzzE4sjJFrmHRgJVzADL5RdcEF7+GV81nP
++X/cXviffkxSihAFALArAaOA6/hBoT6unvlDsY3cxgZWFl3ao76vTQFLs7ZNHYbHe
++WDkkNpheWmNlOrVTEz0vjNCQz5wYOM6HJ0O3cxzR/6+OnhPQagZRCWApPopYGuxc
++kXHAPbEkXpVzJTrNgHIvZ3l3JdJSHsh+DdGVz1NY4bogQNKCVa3xt+zLpUrr34XM
++61Z91MekMijfjOsy7LGLSBdCPCZ00enXPkflDEhv1kRlbo/ZdYGHynzl6Xzu1A5B
++nuwDbpsCzR6ij8fZDXGUS7F8Iemdfag4XTtrXnVXLgPpD/FMzJUx4kCIAjgh2MaP
++0nUvZDVYt+GKGohCNDrSt2ByFtbYGaX5GeMIp8zW+GT8KUW/K7pp9PjsmzG6vvQd
++kqxB45ddf87E8NoDWh/ptdj3pjfbDc5A1SeXKGXrt1TwgWHtUNW0zF8qOuG+PZ1P
++u10lUx4gayyF3unaSLZwYu8nYq5C7mC9DjjnbjLhsh0VOIEEh+Q8vJH8OvZFkyti
++l2ADXC+6evQTvqLwXi8=
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-26-cert.pem b/test/fixtures/x509-escaping/alt-26-cert.pem
+new file mode 100644
+index 0000000000..1204d95a8a
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-26-cert.pem
+@@ -0,0 +1,29 @@
++-----BEGIN CERTIFICATE-----
++MIIE5TCCAs2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++NDAyMDAGA1UdEQQpMCegJQYIKwYBBQUHCAWgGQwXZ29vZC5leGFtcGxlLmNvbQBh
++YmMxMjMwDQYJKoZIhvcNAQELBQADggIBAKmgEHc9b/bscpyO5mTKrITyoYtbhz/P
++0Uz2Uc4tKokUI9EBuuD/XX4EjtVzne9mssAAs9EhBSFmNhDjpAUYh9n2cFvAJQit
++4d9EbaNbB3SuzG5onu8ZBtfLsABr5L5tQspO3tinamSM2ZuRo4dvcQ2a38C38LAQ
++HBnvZ744Th3LckPMLTWNChe3E2jAt8Av0XA2yVJ/B+EeEaqSYDALKhI49CLeq96L
++m/Vq/mqADborW51pMNFn7CAF1jxizQNHy6K0E95ziq8q/OL7j4+j8Erh4x7bcjrQ
++X04Z+hrA9q5AjG++ieztKqGuGxHeSclqBhOdnU0UI528Vn0OXRxeMmbqMF+qhx17
++nHuxxs4z5CIdTwHA6LgMUpDxcOhdUctIj32gwZM3UHI8lmdRTWn13y/Ht6CpIXCL
++1ohSXne5y34z4AKeJQpdUfwQD552Ui8B+bhH1JBm5phjLn1fboXCYiCgnPQ+SJzx
++3hsIv7Fji7lfk1UPkr0s7Ze8b/seYS8nVB5rg4qXEwFDMo9zsjCEIyg0tKwj5Ani
++HlYzqjjsIK50TPjXYOA9J+NHcBDCDa3r8TBtRGtQqOXQGzvWTqAyT8Uwn7jimmh+
++EGDr4PJSTJxv43EYL+of0sRHkOhnfFfJYF9vQLT+wD6l+6T1xNPE/gjX8DyQS9a3
++zOgdOiTp0AKH
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-27-cert.pem b/test/fixtures/x509-escaping/alt-27-cert.pem
+new file mode 100644
+index 0000000000..268abdd300
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-27-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIE0TCCArmgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++IDAeMBwGA1UdEQQVMBOgEQYFK84PDCKgCAwGYWJjMTIzMA0GCSqGSIb3DQEBCwUA
++A4ICAQBtXT+t0fuBRClJdY6y01k1jqcsXEkmKOr4czznuiloGVEjpbjmxzxsgvzw
++nz3od6Sx56SHG1xYbKDCapX9Ld2IDsPvpF2wdH2wpIS5DI7tQdBpLm7vr3vTYKwm
++Wns+WKO5VBHDLCyuYvHNo37MJCAfBlr1ni7BCLOg3eycPiANJHPD2T9BnXlJm49K
++166VMviuiLBEyO9tadhvQHGqCX3D4pW31zwsKHvS4wau15N4yt053Iac6eaysdTp
++mspw5jX85tlQ9XxKNTftUVJU9Uzk2ll4A0Gvnq2FEjiqf6m3tye2nsqDI3C81Dwb
++Y/+AeO7ZsVyLpIstfUBFmpLGPUoZ5MNmgrboGf8K8dPPgVbmbS0msrsI4LWSQb8P
++R2hzj0F7bFvgbZad7rFXJW9FQOqTwvJrZBkkDpZpeNbhah14avV2Ftrc5+PtVfP0
++jB1L3nhc5KGpGL4xqE19K+GVR/KBREgiFD7B7NYUOPt9NjFTrbbC3XA8L0MC7PNh
++ySDN/NCiIF9K9MtpC8BYuNBlRt5C82L37qPY4Tw3z9sCyXK5oOQ4xdbdDEWdwzc5
++F2S4zfQiB7y+C9RigOyGPChxBqDK/bCExrG1S2b95oP4QMuaL55iXnaG9ME8sCoa
++cUd62cMPk7piQW29oFiQPYsStfo09u9JXbalKhol9oPrDtQfrQ==
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-28-cert.pem b/test/fixtures/x509-escaping/alt-28-cert.pem
+new file mode 100644
+index 0000000000..147fba3aff
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-28-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIE1DCCArygAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++IzAhMB8GA1UdEQQYMBagFAYIKwYBBQUHCAegCBYGYWJjMTIzMA0GCSqGSIb3DQEB
++CwUAA4ICAQA2KjgKCSLg/rDajrBTtVIu14rAP1pMwFZWrxcpTbN+fOs2dYQXZf7d
++/GaozSMSchjPAJ8lTFfEB20Mur/E284LlQPuQKqHHn3gIh92VkHHBHjj0ohnfigg
++eBHNMUisuGyNzKV7VI1+iwCoPBZC7ptbE4X08osVxxRESj+IT0TwtKDONTIIeogW
++6VhsKTQ1HM6AMbhVe0Led/ENxFFMquB25GG/hVB4ZzPmsJZzNdZYNNMa34kNcMN3
++5OFcxWV/4Hc77JYsqM9fE9gBaKC9pQE0XwIrOMQSaGYx+GO8Ty33YlM+oYBt6TMH
++/9oU8HVvEYW9GAyptNbXPOwyv/wikNBsJyDGfvuDoiTZ9iMFb/bEoWHSK/rYmAgk
++D272zxiPS3YgaZkvhlYZ+60w5CCgXoN5L0Zq9yAOTv92/VHFnMPrTP7zfD+4eUHY
++lg+A7pOCIUK4cIDUXQefn1dU5/8DHJ8aM+KQDBfkKOH3me3GzIKjtKQjhwYFiJ8L
++vD4V6+nq90GasShQDKUbMVbCxfyqlvrXOP0an+FxdknadnD5hRT3UsU9SRxAdkXi
++3er2sXpuULYqOst55Ahnj7D5uDN4KBoatZwFd1iw0CVPoox7ixZ2zOAkwVqzaEAq
++0yWyIlELm9/FdF78fu6LPrFKI1H4MH+0TQrF4MiyJWPvET7t8WKJsA==
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-29-cert.pem b/test/fixtures/x509-escaping/alt-29-cert.pem
+new file mode 100644
+index 0000000000..434bda3e8e
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-29-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIE1DCCArygAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++IzAhMB8GA1UdEQQYMBagFAYIKwYBBQUHCAegCAwGYWJjMTIzMA0GCSqGSIb3DQEB
++CwUAA4ICAQCIFfHE09aftJrS629ZBBRKjRiVcxN0/FjeEHWbnb+3Re/LoU/Y64BT
++LmjMBB6wik3JxxUtLs2UYExQKfz3zmB+O99lR94of3V3RXPCe9Dz8C12iohYBvVO
++q+WzXyg8g4zoIndn9+ByR+JJsuk+WVTZd50wRaRvssUB5yhpLaFdZpnLUBdV5J2d
++shmefZxr0NgMb9p75wvWgZ2BiZQDeTR93+PWaZTMdSxZh6ynfG//5sxxw5fLm3pv
++eVo3oQQ8px9j8G83ouiDZJn7XZgNfXYNq7wo3yaqXX0zlCE00K6tXGI6FkKJnVdQ
++si+JYfGjzTM39JqFU9YYOOc3Gfw20iKIEQ0jnE0Z+z9Pv2GAel0UNdovluttxu9R
++CJcPJOLS+TMd/sAwCAELvhPpeWsDLhfd+lG7ofE/nM6hzec6apWYyCqqlYIdE8WK
++rtHXBIMGk/5Eo+2KDGQHgpMs/P8fNUL6FBx/i1pjm5nSHveDQryepEmOJq9NJCBW
++1AJhE4jCXMv+43Fnr1OSATNiOd+1KfQ7KC5PFkpZLY4GDFZcbLBKYj1TWx4WzRnm
++EW7cC/00Z3Cd76L5i+y1Xr44nbQcAMw6TlT6vvZjFCbCO+ZDUJSZBZMpWwBI/gAf
++MNzYPltOGm+GZUuxib2MSF9Qy8c9NegENmsK+zyPT3N9mUHCl9nknA==
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-3-cert.pem b/test/fixtures/x509-escaping/alt-3-cert.pem
+new file mode 100644
+index 0000000000..59185b64a4
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-3-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIE1jCCAr6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++JTAjMCEGA1UdEQQaMBiGFmh0dHA6Ly9leGFtcGxlLmNvbS9hLGIwDQYJKoZIhvcN
++AQELBQADggIBAEKwv45Zp5xJEGENPrOIwrGmuBDMtBPmXtSKydKSNUgrv08u4dHL
++n295L7jIwQ3SnRjS8PrZWD8RQ46hgFRY9pqk1uTys4jB7lki0eAUBC7oPn7q0GUv
++ojdSwOEjp5bfXyuRv7Z+3y2gD8pcCZsqcCjF5Svim6Q3pXMLRKQFhzhzL9k/gsNF
++lJ8KcLBECJSm5nUrZIRHPdIGYmWJG+t8CfS3E6OIyHILK1xCc1MasEpmYVoY9uzT
++2W2z+3pvwQqfdXO+lEOsT9dnjM/WbnkQMTWAn+++YFtkvA4kON4b/cp9imnXok02
++vq7MCbN+b5CJXIhKMC5eNA36ez5hou0MUmnsNo9ai1gVJXRoL67YgUh1yMfcAaSM
++Sfy3UBF++Az/yQo4AWtqWk4KPePdcsrYo9Fke1inUl+M12gkdIz+efbElHMqehbt
++lunbyFI/7CY6/Tno+T1cDkQlTouHK8Ddb1cPhkJbE4euRuLGdtn2AcFSemYGtib0
++ffuhnEBF8M8enPVyLjYA/3sELkmmaHMtgDTm0+XYQJtjIbvGcY7+bftPZgbXPVGv
++7+tiYjwarIexXN5yzMasgFI5+7qLSQJHcmwrzOm8K+Bzx34f20vwR4M2FJ6cqUeN
++qzdN1HSNp8aYNilaFa3+hfGRG9CZnVP8up8BwYx736EMu0G3yAp6UqqJ
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-30-cert.pem b/test/fixtures/x509-escaping/alt-30-cert.pem
+new file mode 100644
+index 0000000000..1b67d1f782
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-30-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIE1TCCAr2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++JDAiMCAGA1UdEQQZMBegFQYIKwYBBQUHCAegCRYHYWJjAGRlZjANBgkqhkiG9w0B
++AQsFAAOCAgEAgG06c7GRpPohHa1X/YQVQGWa/J/f3qok3cu1nrD2H5Dkw1eAVPcQ
++lsng08lOxwSI0OgqJw0jl+ljLKuhHI3U68KbFmUO3Jw7uLDk1+UniRSNkfxVOrlc
++7YTlmsxiDgQdX6/TAHu6bERx147NqVzB4/I6qpX7ouLv4E7xdQgjKuvhWlJ+Fg/0
++pQ7EleQymRN6Y8qO6RwEWYao5pypg8/22cE3jgXleLM+5qWHqJs2ZewPQf7uo4Bf
++IwSUV5H0weftiSN+kOLYiNfUago108VHuk5sCIKr92q4WAJgA5C6ylcUWaJCKbCv
++HQYR/QG10Mrn4JCzzni90aBHrQoYQ8msEDH1QKyMJiNz6XXzwBP6bvgPlB2f7nPW
++ERpH45M2I4Z3dZYFw8bF7CcOIUuR0/Zu2WN22IhqhjVQSZPzdRWJt5Rr1mFUz+Nv
++Ymdi0w68KyRUiuOpKNLczDDnYpc9EqGBprnMOxALS4mQn1ySBXbZAXnTTdEzN5fM
++L4CXWUzIBVKv56Mn5YskhbCd+N8GV9Nj/A6dBwa004CQxbgAj+ndNWc7+h4iSNlz
++9VPHK2Kju6j4fVpe10jzSoEs0nnrsPy5Lxa6C4KhXBBJ3cPl6wWNe2mgbEqG9Pq2
++KrCizuFkIfZTAeSrR+prZXLw6cjmKPPEtNbK2JbteL2SEDT/3AjmmZE=
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-4-cert.pem b/test/fixtures/x509-escaping/alt-4-cert.pem
+new file mode 100644
+index 0000000000..086af8e02e
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-4-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIE2DCCAsCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++JzAlMCMGA1UdEQQcMBqGGGh0dHA6Ly9leGFtcGxlLmNvbS9hJTJDYjANBgkqhkiG
++9w0BAQsFAAOCAgEAPu7ubyZw1rOQJhFX6nBHyCYaBzaKxRZOHOFCjMrD/YQXPUNM
++Hs+8ChOeQ4M82jTyiP7XgF8EumDcckDIlIYvGXGrCB/6VcCVL1vPPtzjSaiF3PlG
++/dh0OlPvevr5Ajz7ZtFFwxeQ2EfsHiry8qnlDJSEjrh4Trcx9YzdkSZz8DaoODXz
++ctR/p1JEnQ6h/Axa6hdqTzbzTsINN7gD5Wi3ObfQbK6Ug/CuH6Zr8bdTsmeGcnD0
++fqHptuLVNcROykneYziXDzcqGwrZnYaOF54a4ibV/OfrBcgEKeDwsCrLs3nztSC4
++whV7DXZwaLl2KWl4/suBNI1cIKbxII1xTFLTog+UYz0zSZGPrtbt7zrlM4yG033t
++h9xIGUKebaNpQYkoxOc/+kKhbKCeL3klfxJoX+6Gf8DkTP7byX2HovfWV1rJbh57
++YZ04Bh69VmyxE4iyb1tAh5xh1bArCR9m96eXS/0KIZbykxltQGyHf1jpWw/4Wi3n
++oadkpMcyNX76M1xBJ5u03JL8+LWrXuzf/ScWdmPUWulAEhbo4fn4oRwP2C3l0vVQ
++iL482cIq1zF91lssRwQ17k38phulRdm+7W65/VI7hLoG6lXiSiHLH8e39hHO8Jey
++Z+BBvn8x+aFgIvpBK/MX35s0gSrl/UiIZPU9glnktSsX5D+aaQynbuvbOW8=
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-5-cert.pem b/test/fixtures/x509-escaping/alt-5-cert.pem
+new file mode 100644
+index 0000000000..04a918008c
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-5-cert.pem
+@@ -0,0 +1,29 @@
++-----BEGIN CERTIFICATE-----
++MIIE6jCCAtKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++OTA3MDUGA1UdEQQuMCyGKmh0dHA6Ly9leGFtcGxlLmNvbS9hLCBETlM6Z29vZC5l
++eGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAgEANAyZnL8f81Aax/0Rhw3CCdcQ
++SXF3dpAolObQB8rlirRZ7yOY1v3Poj411aV0x9zM6mjOJZwarUTL7kbO7odQxGhB
++x7O0DvUoG15VTvs0XLNHTPgnXtNjKOZ7XXVMzb46APfYSqdzMqhRWfy+Iaikp494
++urtqkVt05q2amzq7EXbXI8JQWhkJkhjBTowfZnpZUw4JeeqMNRZT9Ldv2XDZjaYS
++lkHOLzTmSmm2mf1oxhKGcRCgUCr/pzVUfDA3RBz25a6PWAQt4b2r8k5jydWyOeCZ
+++sjacoK5/E1PcdaOFJAjuAfbRMeK/gz2+yJwaB39Yh77t/9vQC0G6aiAmO0HxjJE
++L6Lb8BG/QNYBS7gGhzKFVXVVv5yXRioO9vMv0i8uxShqD2Lo/MbrNtRgi3eMFESd
++3NxUPXS1jMq2/SaXrENdKqNNi06LbnLaYpI3BLZ/Katq0V9ESlhcC2nT5uNBPiLr
++DNSekaIGobbTDkuV896L7jqsQpU+sgs4XqaISGgk2wAfnwbfpeiBCL8oH9yCYAO0
++1YlevrMGjBNvhysoABv7qaorqeL97ffRhjOZ72/fm2axD5l9MvWEFIf7L5uOah0f
++hF5vScQYgyWNuK8wjzT2tl0CuxvEyI7N4fkUEk+ZMkyI1Obx17p+d4SFyuq7wTXR
++05oWMsCMDyzxvFDv92w=
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-6-cert.pem b/test/fixtures/x509-escaping/alt-6-cert.pem
+new file mode 100644
+index 0000000000..6643519957
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-6-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIEyzCCArOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++GjAYMBYGA1UdEQQPMA2CC2V45G1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4ICAQBB
++lBfIjUH7/PbpC00TWTOSR6sAzyBr681lSxYAgFLduDdfR/bTkI1p7txIAgennoUq
+++9slIIMaR799BUtQDfAQRYdbsWiG/+5Lj3JXs33LPPTdW1C97LOPlnnbRJh1sjbi
++UfGdxvdPA6iuyWhfwPZd+4IrcN+kefkvEnRkvDMGwmfmKQDjbu2mSIAIe+ECyLLu
++wdSI2sPBSUKQEKk+dABYq9TcdxlA+OSPjgs5ZF3NK3s/or7ay2r/i8be5TswY4Up
++IwByEk+7AST6ijwi3P8EN0HAyyuOfpBelWZCQgdEGt40Mpa58AwBGqdrCZ5wDAz5
++nBx6GscZUsqG9sVM71Tgq7Bc1b69FXUYAhmFucnXizHv1Ys0oGQVza1tkKbaLEFQ
++WvXWc7zW/0hTzvmtogKn/oM6GoNcQiW8KCwaCJq1TTv7Tip9znfB496tDruOr+2w
++HoqZTJ7ERklz0mlZ38ISTuaz+Qkn1KjBYh4tgP/wZIjIyppAaAr+JdqXzBejfb4M
++6x0S1AG9QgvyR1xDv3Vljjkh3m55kktTWSOfjS6aSzomaAyVAgi/vhHkxhsoBhgQ
++41+ffkhM9ps9wkmguwqOXsByQAZUQEJQigO39qYuGuJEDV8Bu8i/T5BuuJWP4BRF
++X+now5ObP73ufyFwYGsSgblivHUX4z/zAt4kp4AMXw==
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-7-cert.pem b/test/fixtures/x509-escaping/alt-7-cert.pem
+new file mode 100644
+index 0000000000..6c0f287a1b
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-7-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIE0jCCArqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++ITAfMB0GA1UdEQQWMBSCEiJldmlsLmV4YW1wbGUuY29tIjANBgkqhkiG9w0BAQsF
++AAOCAgEAKmYr4QEnNq1Sy9lYePNRR60jufFXk44bczNT/wA6kvXKgv472V9wltVb
++yJVvYUWkTO8ahlELNLfqRcuih6myV64WJoewog8mwby0lBYr6bAz86DdeN/B9rFD
++OYnev1Ux4um45l42XP8acgJCoqn8+EE+H4AeMrz2xxHt+IDy4vUOowZna82f1Pcp
++O+vhod2uXlukfnhofVK4lMHl4++4kECkmUYl8U+L/zXwzOb4S3Yksffmadgo7ERk
++rJYLMLztvCk6TtP+p4NcvrE90dmss7R8hfw3asfjXsRbAMigdfSMKzGB2IHoHeV6
++fpmJy6kotfwulDrbr2QtrWOYdMrm1wT6ohT355KZQxcZr3VcK9gqEjcYafqIsXtA
++wYAaorKXaz7UkmFCDbk/24UuHgNgCl4KkGsFNwW6whTMpb9WnvPR7F798tiIbOL+
++FK6yA1q3Z2500lmloQWcUFBX48DViG3bsTJ9wmQ28aPqHVd5gTmTm/7W2iRGx36N
++PmbAk17J/bUzUSORgrPi2FLNNFg64x40pfdAyrF9ZBNcsVCFCUgOQHgMh4OjX/n7
++khmNbMYiOvJEoUbZ9flNr4AYY3ucpxQ2peTl4DNsVZZ8Xyh96h3URu63Ji9+xLrQ
++jSUtNHUCJaC3E9yTaIDc8jMli9s5/ElDZRkPxRP8o4VOt9KcLvU=
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-8-cert.pem b/test/fixtures/x509-escaping/alt-8-cert.pem
+new file mode 100644
+index 0000000000..201b520f8b
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-8-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIExDCCAqygAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++EzARMA8GA1UdEQQIMAaHBAgICAgwDQYJKoZIhvcNAQELBQADggIBAHfvavrzBLuS
++MMJwNkJGVt1W856zeZ6NZJ5vx2ZXziYxAkzw9N0pLHwgfzS8pXEPSZ6vMoeYMaH0
++zr/S5tHSMGEwOp/dIoxE4Hm1uMzugHFxNp34hvqsaDbwKMpQQzEPhN1QvAkD9IXL
++H2wOLqm+ZaTkT3OvOyJoml56wyUJ0nU746RuXgJHTFiWsUTPqT9bvofedC80MUyH
++MX2lA1oy8nzJa9h7JqsxOE4uccRhpCRf+PxeYvOdsUxyDWw8+rjwe4Ulr0yVjwnD
++x9ha/fTl96mYXyJGLtQvZmkllrctxcs0o82+wMZWBw4iPH/VnI7dj36b2uIHdrrf
++cVurEPcVE03zLwukjQPZh9otleTwmQI1wqg/Gm2OahXy/0f0fpBDQnPycczn8nFw
++nj6avmHubWVvzmEoKmOtavGEAbUn7ntQfsvM5JpiM+ck3MDMP9i9cMZvWKH8Eial
++ZnYcXkgAatWwp4Cbsv4H7LMNisKjrcY+r+MpaYYIpTRNp/s/P5bMCIVt07yosePg
++m9VWy03+hQJmD4/THeJsjuczPSBtsoJiKoTJ5TndmpFaG6J6lBVvpXJhoiW/QIgX
++u2QIb8Z6bRK/eQ8UVYm0/ZQLN+OOzYiQfm0AFbFpYhl46o6QNZ03P6GRLshv+N3E
++CX66ucPLd4QJitUy39LZjMlC0YxTZUry
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/alt-9-cert.pem b/test/fixtures/x509-escaping/alt-9-cert.pem
+new file mode 100644
+index 0000000000..660e65b8ed
+--- /dev/null
++++ b/test/fixtures/x509-escaping/alt-9-cert.pem
+@@ -0,0 +1,28 @@
++-----BEGIN CERTIFICATE-----
++MIIExDCCAqygAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++EzARMA8GA1UdEQQIMAaHBAgIBAQwDQYJKoZIhvcNAQELBQADggIBAIefUJjnOtt8
++viFkr3lupabUMwSgtBXVCp+M9xhKqcSnYReSgg/LcqVDaXmU4s23n0Bc0M51HQMG
++puTpfr34ZUSQiLup9huELm5L+lcpYANJsKrBo+vz1w+fkPlcxXvXHpLzgb393XSJ
++/Prn7lNBrrh9b74azUEhz1KPmFbbMs7IwlhE1+stQ107VeSGvKlAOmaYdnVG1PXl
++AG7KJynpE5Ex8XF1ONQLneTdvo8gXZueb07SY+my5wrCQhSlh4/6Y2MnE9h+9ugx
++BfdU72okDaYRH1MAfFeAsUE7Y52cQqm26b7nBz0+IeP+uk7oqDLF+PGHfjeUGXGW
++aGFfaLk8Dl2gMg1DsRE8zcT215Dl4rqOtwbhW8kX7XzYE0sA7cnyZ0daLrrtxwe6
++MhrAOjYklRZpwUvy6E2IyipKwWSuKHLUk3mVxPrxVqvye2enZWW1PJeHNdL//Ogx
++5Mm++BOTNR+61pg/UrATlO3GMK6ggAfkP8H1r3jp24hc/TkXRkoUuWZqtjC5+qwB
++KVIPlr+/0zIhzDjNbN0TMgqv/Yz4/wCUjsmCPJu21C3+BP2O5ZD2e4hYe/X9kuhC
++YGWTf8dpq0LgYgVHqwXo0gCU/Ich9KtaJmCgZRUrzMl1aIYhqpuR2EW8H1bs3a0P
++/7wXhGudHCwm6j2H5/tbsREeYInl3mv4
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/create-certs.js b/test/fixtures/x509-escaping/create-certs.js
+new file mode 100644
+index 0000000000..b84547e1d0
+--- /dev/null
++++ b/test/fixtures/x509-escaping/create-certs.js
+@@ -0,0 +1,502 @@
++'use strict';
++
++const asn1 = require('asn1.js');
++const crypto = require('crypto');
++const { writeFileSync } = require('fs');
++const rfc5280 = require('asn1.js-rfc5280');
++const BN = asn1.bignum;
++
++const oid = {
++ commonName: [2, 5, 4, 3],
++ countryName: [2, 5, 4, 6],
++ localityName: [2, 5, 4, 7],
++ rsaEncryption: [1, 2, 840, 113549, 1, 1, 1],
++ sha256WithRSAEncryption: [1, 2, 840, 113549, 1, 1, 11],
++ xmppAddr: [1, 3, 6, 1, 5, 5, 7, 8, 5],
++ srvName: [1, 3, 6, 1, 5, 5, 7, 8, 7],
++ ocsp: [1, 3, 6, 1, 5, 5, 7, 48, 1],
++ caIssuers: [1, 3, 6, 1, 5, 5, 7, 48, 2],
++ privateUnrecognized: [1, 3, 9999, 12, 34]
++};
++
++const digest = 'SHA256';
++
++const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {
++ modulusLength: 4096,
++ publicKeyEncoding: {
++ type: 'pkcs1',
++ format: 'der'
++ }
++});
++
++writeFileSync('server-key.pem', privateKey.export({
++ type: 'pkcs8',
++ format: 'pem'
++}));
++
++const now = Date.now();
++const days = 3650;
++
++function utilType(name, fn) {
++ return asn1.define(name, function() {
++ this[fn]();
++ });
++}
++
++const Null_ = utilType('Null_', 'null_');
++const null_ = Null_.encode('der');
++
++const IA5String = utilType('IA5String', 'ia5str');
++const PrintableString = utilType('PrintableString', 'printstr');
++const UTF8String = utilType('UTF8String', 'utf8str');
++
++const subjectCommonName = PrintableString.encode('evil.example.com', 'der');
++
++const sans = [
++ { type: 'dNSName', value: 'good.example.com, DNS:evil.example.com' },
++ { type: 'uniformResourceIdentifier', value: 'http://example.com/' },
++ { type: 'uniformResourceIdentifier', value: 'http://example.com/?a=b&c=d' },
++ { type: 'uniformResourceIdentifier', value: 'http://example.com/a,b' },
++ { type: 'uniformResourceIdentifier', value: 'http://example.com/a%2Cb' },
++ {
++ type: 'uniformResourceIdentifier',
++ value: 'http://example.com/a, DNS:good.example.com'
++ },
++ { type: 'dNSName', value: Buffer.from('exämple.com', 'latin1') },
++ { type: 'dNSName', value: '"evil.example.com"' },
++ { type: 'iPAddress', value: Buffer.from('08080808', 'hex') },
++ { type: 'iPAddress', value: Buffer.from('08080404', 'hex') },
++ { type: 'iPAddress', value: Buffer.from('0008080404', 'hex') },
++ { type: 'iPAddress', value: Buffer.from('000102030405', 'hex') },
++ {
++ type: 'iPAddress',
++ value: Buffer.from('0a0b0c0d0e0f0000000000007a7b7c7d', 'hex')
++ },
++ { type: 'rfc822Name', value: 'foo@example.com' },
++ { type: 'rfc822Name', value: 'foo@example.com, DNS:good.example.com' },
++ {
++ type: 'directoryName',
++ value: {
++ type: 'rdnSequence',
++ value: [
++ [
++ {
++ type: oid.countryName,
++ value: PrintableString.encode('DE', 'der')
++ }
++ ],
++ [
++ {
++ type: oid.localityName,
++ value: UTF8String.encode('Hannover', 'der')
++ }
++ ]
++ ]
++ }
++ },
++ {
++ type: 'directoryName',
++ value: {
++ type: 'rdnSequence',
++ value: [
++ [
++ {
++ type: oid.countryName,
++ value: PrintableString.encode('DE', 'der')
++ }
++ ],
++ [
++ {
++ type: oid.localityName,
++ value: UTF8String.encode('München', 'der')
++ }
++ ]
++ ]
++ }
++ },
++ {
++ type: 'directoryName',
++ value: {
++ type: 'rdnSequence',
++ value: [
++ [
++ {
++ type: oid.countryName,
++ value: PrintableString.encode('DE', 'der')
++ }
++ ],
++ [
++ {
++ type: oid.localityName,
++ value: UTF8String.encode('Berlin, DNS:good.example.com', 'der')
++ }
++ ]
++ ]
++ }
++ },
++ {
++ type: 'directoryName',
++ value: {
++ type: 'rdnSequence',
++ value: [
++ [
++ {
++ type: oid.countryName,
++ value: PrintableString.encode('DE', 'der')
++ }
++ ],
++ [
++ {
++ type: oid.localityName,
++ value: UTF8String.encode('Berlin, DNS:good.example.com\0evil.example.com', 'der')
++ }
++ ]
++ ]
++ }
++ },
++ {
++ type: 'directoryName',
++ value: {
++ type: 'rdnSequence',
++ value: [
++ [
++ {
++ type: oid.countryName,
++ value: PrintableString.encode('DE', 'der')
++ }
++ ],
++ [
++ {
++ type: oid.localityName,
++ value: UTF8String.encode(
++ 'Berlin, DNS:good.example.com\\\0evil.example.com', 'der')
++ }
++ ]
++ ]
++ }
++ },
++ {
++ type: 'directoryName',
++ value: {
++ type: 'rdnSequence',
++ value: [
++ [
++ {
++ type: oid.countryName,
++ value: PrintableString.encode('DE', 'der')
++ }
++ ],
++ [
++ {
++ type: oid.localityName,
++ value: UTF8String.encode('Berlin\r\n', 'der')
++ }
++ ]
++ ]
++ }
++ },
++ {
++ type: 'directoryName',
++ value: {
++ type: 'rdnSequence',
++ value: [
++ [
++ {
++ type: oid.countryName,
++ value: PrintableString.encode('DE', 'der')
++ }
++ ],
++ [
++ {
++ type: oid.localityName,
++ value: UTF8String.encode('Berlin/CN=good.example.com', 'der')
++ }
++ ]
++ ]
++ }
++ },
++ {
++ type: 'registeredID',
++ value: oid.sha256WithRSAEncryption
++ },
++ {
++ type: 'registeredID',
++ value: oid.privateUnrecognized
++ },
++ {
++ type: 'otherName',
++ value: {
++ 'type-id': oid.xmppAddr,
++ value: UTF8String.encode('abc123', 'der')
++ }
++ },
++ {
++ type: 'otherName',
++ value: {
++ 'type-id': oid.xmppAddr,
++ value: UTF8String.encode('abc123, DNS:good.example.com', 'der')
++ }
++ },
++ {
++ type: 'otherName',
++ value: {
++ 'type-id': oid.xmppAddr,
++ value: UTF8String.encode('good.example.com\0abc123', 'der')
++ }
++ },
++ {
++ type: 'otherName',
++ value: {
++ 'type-id': oid.privateUnrecognized,
++ value: UTF8String.encode('abc123', 'der')
++ }
++ },
++ {
++ type: 'otherName',
++ value: {
++ 'type-id': oid.srvName,
++ value: IA5String.encode('abc123', 'der')
++ }
++ },
++ {
++ type: 'otherName',
++ value: {
++ 'type-id': oid.srvName,
++ value: UTF8String.encode('abc123', 'der')
++ }
++ },
++ {
++ type: 'otherName',
++ value: {
++ 'type-id': oid.srvName,
++ value: IA5String.encode('abc\0def', 'der')
++ }
++ }
++];
++
++for (let i = 0; i < sans.length; i++) {
++ const san = sans[i];
++
++ const tbs = {
++ version: 'v3',
++ serialNumber: new BN('01', 16),
++ signature: {
++ algorithm: oid.sha256WithRSAEncryption,
++ parameters: null_
++ },
++ issuer: {
++ type: 'rdnSequence',
++ value: [
++ [
++ { type: oid.commonName, value: subjectCommonName }
++ ]
++ ]
++ },
++ validity: {
++ notBefore: { type: 'utcTime', value: now },
++ notAfter: { type: 'utcTime', value: now + days * 86400000 }
++ },
++ subject: {
++ type: 'rdnSequence',
++ value: [
++ [
++ { type: oid.commonName, value: subjectCommonName }
++ ]
++ ]
++ },
++ subjectPublicKeyInfo: {
++ algorithm: {
++ algorithm: oid.rsaEncryption,
++ parameters: null_
++ },
++ subjectPublicKey: {
++ unused: 0,
++ data: publicKey
++ }
++ },
++ extensions: [
++ {
++ extnID: 'subjectAlternativeName',
++ critical: false,
++ extnValue: [san]
++ }
++ ]
++ };
++
++ // Self-sign the certificate.
++ const tbsDer = rfc5280.TBSCertificate.encode(tbs, 'der');
++ const signature = crypto.createSign(digest).update(tbsDer).sign(privateKey);
++
++ // Construct the signed certificate.
++ const cert = {
++ tbsCertificate: tbs,
++ signatureAlgorithm: {
++ algorithm: oid.sha256WithRSAEncryption,
++ parameters: null_
++ },
++ signature: {
++ unused: 0,
++ data: signature
++ }
++ };
++
++ // Store the signed certificate.
++ const pem = rfc5280.Certificate.encode(cert, 'pem', {
++ label: 'CERTIFICATE'
++ });
++ writeFileSync(`./alt-${i}-cert.pem`, `${pem}\n`);
++}
++
++const infoAccessExtensions = [
++ [
++ {
++ accessMethod: oid.ocsp,
++ accessLocation: {
++ type: 'uniformResourceIdentifier',
++ value: 'http://good.example.com/\nOCSP - URI:http://evil.example.com/',
++ },
++ },
++ ],
++ [
++ {
++ accessMethod: oid.caIssuers,
++ accessLocation: {
++ type: 'uniformResourceIdentifier',
++ value: 'http://ca.example.com/\nOCSP - URI:http://evil.example.com',
++ },
++ },
++ {
++ accessMethod: oid.ocsp,
++ accessLocation: {
++ type: 'dNSName',
++ value: 'good.example.com\nOCSP - URI:http://ca.nodejs.org/ca.cert',
++ },
++ },
++ ],
++ [
++ {
++ accessMethod: oid.privateUnrecognized,
++ accessLocation: {
++ type: 'uniformResourceIdentifier',
++ value: 'http://ca.example.com/',
++ },
++ },
++ ],
++ [
++ {
++ accessMethod: oid.ocsp,
++ accessLocation: {
++ type: 'otherName',
++ value: {
++ 'type-id': oid.xmppAddr,
++ value: UTF8String.encode('good.example.com', 'der'),
++ },
++ },
++ },
++ {
++ accessMethod: oid.ocsp,
++ accessLocation: {
++ type: 'otherName',
++ value: {
++ 'type-id': oid.privateUnrecognized,
++ value: UTF8String.encode('abc123', 'der')
++ },
++ },
++ },
++ {
++ accessMethod: oid.ocsp,
++ accessLocation: {
++ type: 'otherName',
++ value: {
++ 'type-id': oid.srvName,
++ value: IA5String.encode('abc123', 'der')
++ }
++ }
++ },
++ ],
++ [
++ {
++ accessMethod: oid.ocsp,
++ accessLocation: {
++ type: 'otherName',
++ value: {
++ 'type-id': oid.xmppAddr,
++ value: UTF8String.encode('good.example.com\0abc123', 'der'),
++ },
++ },
++ },
++ ],
++];
++
++for (let i = 0; i < infoAccessExtensions.length; i++) {
++ const infoAccess = infoAccessExtensions[i];
++
++ const tbs = {
++ version: 'v3',
++ serialNumber: new BN('01', 16),
++ signature: {
++ algorithm: oid.sha256WithRSAEncryption,
++ parameters: null_
++ },
++ issuer: {
++ type: 'rdnSequence',
++ value: [
++ [
++ { type: oid.commonName, value: subjectCommonName }
++ ]
++ ]
++ },
++ validity: {
++ notBefore: { type: 'utcTime', value: now },
++ notAfter: { type: 'utcTime', value: now + days * 86400000 }
++ },
++ subject: {
++ type: 'rdnSequence',
++ value: [
++ [
++ { type: oid.commonName, value: subjectCommonName }
++ ]
++ ]
++ },
++ subjectPublicKeyInfo: {
++ algorithm: {
++ algorithm: oid.rsaEncryption,
++ parameters: null_
++ },
++ subjectPublicKey: {
++ unused: 0,
++ data: publicKey
++ }
++ },
++ extensions: [
++ {
++ extnID: 'authorityInformationAccess',
++ critical: false,
++ extnValue: infoAccess
++ }
++ ]
++ };
++
++ // Self-sign the certificate.
++ const tbsDer = rfc5280.TBSCertificate.encode(tbs, 'der');
++ const signature = crypto.createSign(digest).update(tbsDer).sign(privateKey);
++
++ // Construct the signed certificate.
++ const cert = {
++ tbsCertificate: tbs,
++ signatureAlgorithm: {
++ algorithm: oid.sha256WithRSAEncryption,
++ parameters: null_
++ },
++ signature: {
++ unused: 0,
++ data: signature
++ }
++ };
++
++ // Store the signed certificate.
++ const pem = rfc5280.Certificate.encode(cert, 'pem', {
++ label: 'CERTIFICATE'
++ });
++ writeFileSync(`./info-${i}-cert.pem`, `${pem}\n`);
++}
+diff --git a/test/fixtures/x509-escaping/google/intermediate.pem b/test/fixtures/x509-escaping/google/intermediate.pem
+new file mode 100644
+index 0000000000..9d2aeb32c4
+--- /dev/null
++++ b/test/fixtures/x509-escaping/google/intermediate.pem
+@@ -0,0 +1,11 @@
++-----BEGIN CERTIFICATE-----
++MIIBjjCCATSgAwIBAgIBAjAKBggqhkjOPQQDAjAPMQ0wCwYDVQQDEwRSb290MCAX
++DTAwMDEwMTAwMDAwMFoYDzIwOTkwMTAxMDAwMDAwWjAXMRUwEwYDVQQDEwxJbnRl
++cm1lZGlhdGUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR7DaOQvpvA47q2XxjM
++qxJVf/FvZm2ftiFRXNJMe/fhSlDh2CybdkFIw2mE5g4ShW5UBJe+sohqy5V9WRkY
++tM/Bo3cwdTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQlGcYbYohaK3S+XGeq
++CTi4LLHeLTAfBgNVHSMEGDAWgBQlGcYbYohaK3S+XGeqCTi4LLHeLTAiBgNVHR4B
++Af8EGDAWoBQwEoIQYXR0YWNrZXIuZXhhbXBsZTAKBggqhkjOPQQDAgNIADBFAiEA
++uZhmF3buUdhzHjXLZQSOyT41DqUUX/VKBEraDu+gj+wCIG/R1arbHFRFnEuoVgZI
++bihwUpUZjIZ5YwJcBu6yuXlZ
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/google/key.pem b/test/fixtures/x509-escaping/google/key.pem
+new file mode 100644
+index 0000000000..102a9d8816
+--- /dev/null
++++ b/test/fixtures/x509-escaping/google/key.pem
+@@ -0,0 +1,5 @@
++-----BEGIN PRIVATE KEY-----
++MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgaNbpDxJET5xVHxd/
++ig5x2u2KUIe0jaCVWqarpIN/582hRANCAAR7DaOQvpvA47q2XxjMqxJVf/FvZm2f
++tiFRXNJMe/fhSlDh2CybdkFIw2mE5g4ShW5UBJe+sohqy5V9WRkYtM/B
++-----END PRIVATE KEY-----
+diff --git a/test/fixtures/x509-escaping/google/leaf0.pem b/test/fixtures/x509-escaping/google/leaf0.pem
+new file mode 100644
+index 0000000000..ce19dc9699
+--- /dev/null
++++ b/test/fixtures/x509-escaping/google/leaf0.pem
+@@ -0,0 +1,10 @@
++-----BEGIN CERTIFICATE-----
++MIIBajCCARCgAwIBAgIBAzAKBggqhkjOPQQDAjAXMRUwEwYDVQQDEwxJbnRlcm1l
++ZGlhdGUwIBcNMDAwMTAxMDAwMDAwWhgPMjA5OTAxMDEwMDAwMDBaMA8xDTALBgNV
++BAMTBExlYWYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR7DaOQvpvA47q2XxjM
++qxJVf/FvZm2ftiFRXNJMe/fhSlDh2CybdkFIw2mE5g4ShW5UBJe+sohqy5V9WRkY
++tM/Bo1MwUTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFCUZxhtiiFordL5cZ6oJ
++OLgssd4tMCAGA1UdEQQZMBeCFWJsYWguYXR0YWNrZXIuZXhhbXBsZTAKBggqhkjO
++PQQDAgNIADBFAiEA4NgHDxVrBjNW+So4MrRZMwDknvjRaBsB4j2IwVRKl4sCIDpg
++Bhm4ZdHwlUYrALkXa3dFBy8kXBkVumY7UJpbB2mO
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/google/leaf1.pem b/test/fixtures/x509-escaping/google/leaf1.pem
+new file mode 100644
+index 0000000000..0b45056656
+--- /dev/null
++++ b/test/fixtures/x509-escaping/google/leaf1.pem
+@@ -0,0 +1,10 @@
++-----BEGIN CERTIFICATE-----
++MIIBdTCCARygAwIBAgIBBDAKBggqhkjOPQQDAjAXMRUwEwYDVQQDEwxJbnRlcm1l
++ZGlhdGUwIBcNMDAwMTAxMDAwMDAwWhgPMjA5OTAxMDEwMDAwMDBaMA8xDTALBgNV
++BAMTBExlYWYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR7DaOQvpvA47q2XxjM
++qxJVf/FvZm2ftiFRXNJMe/fhSlDh2CybdkFIw2mE5g4ShW5UBJe+sohqy5V9WRkY
++tM/Bo18wXTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFCUZxhtiiFordL5cZ6oJ
++OLgssd4tMCwGA1UdEQQlMCOCCm5vZGVqcy5vcmeCFWJsYWguYXR0YWNrZXIuZXhh
++bXBsZTAKBggqhkjOPQQDAgNHADBEAiAOFFOCfA6c/iZWxbDn5QMjNdtZbtJPBcRv
++uEgSqWrGTAIgK5RK0xGK8UZb2aM2VjGNTYozlcwKaLgQukA+UnKrrJg=
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/google/leaf2.pem b/test/fixtures/x509-escaping/google/leaf2.pem
+new file mode 100644
+index 0000000000..9cf03fae7d
+--- /dev/null
++++ b/test/fixtures/x509-escaping/google/leaf2.pem
+@@ -0,0 +1,10 @@
++-----BEGIN CERTIFICATE-----
++MIIBejCCASCgAwIBAgIBBTAKBggqhkjOPQQDAjAXMRUwEwYDVQQDEwxJbnRlcm1l
++ZGlhdGUwIBcNMDAwMTAxMDAwMDAwWhgPMjA5OTAxMDEwMDAwMDBaMA8xDTALBgNV
++BAMTBExlYWYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR7DaOQvpvA47q2XxjM
++qxJVf/FvZm2ftiFRXNJMe/fhSlDh2CybdkFIw2mE5g4ShW5UBJe+sohqy5V9WRkY
++tM/Bo2MwYTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFCUZxhtiiFordL5cZ6oJ
++OLgssd4tMDAGA1UdEQQpMCeCJW5vZGVqcy5vcmcsIEROUzpibGFoLmF0dGFja2Vy
++LmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIgWfT1VXQA79PxgM0DsfeoiwZCc2Be
++v3/RCRYoRky9DgICIQDUTjndnBQ0KeIWhuMjtSz1C5uPUYofKe7pV2qb/57kvA==
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/google/leaf3.pem b/test/fixtures/x509-escaping/google/leaf3.pem
+new file mode 100644
+index 0000000000..55a64fdc89
+--- /dev/null
++++ b/test/fixtures/x509-escaping/google/leaf3.pem
+@@ -0,0 +1,10 @@
++-----BEGIN CERTIFICATE-----
++MIIBZzCCAQ2gAwIBAgIBBjAKBggqhkjOPQQDAjAXMRUwEwYDVQQDEwxJbnRlcm1l
++ZGlhdGUwIBcNMDAwMTAxMDAwMDAwWhgPMjA5OTAxMDEwMDAwMDBaMA8xDTALBgNV
++BAMTBExlYWYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR7DaOQvpvA47q2XxjM
++qxJVf/FvZm2ftiFRXNJMe/fhSlDh2CybdkFIw2mE5g4ShW5UBJe+sohqy5V9WRkY
++tM/Bo1AwTjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFCUZxhtiiFordL5cZ6oJ
++OLgssd4tMB0GA1UdEQQWMBSGEmh0dHBzOi8vbm9kZWpzLm9yZzAKBggqhkjOPQQD
++AgNIADBFAiEArZgaxFBuPYFWCXeFTkXhV57MKxG/tIJ2Z3Wzts2Im7QCICoukuRf
++EsQN7g6h30fRuLOIdbfCCduc7YVpkkSlwe99
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/google/leaf4.pem b/test/fixtures/x509-escaping/google/leaf4.pem
+new file mode 100644
+index 0000000000..668a659f45
+--- /dev/null
++++ b/test/fixtures/x509-escaping/google/leaf4.pem
+@@ -0,0 +1,10 @@
++-----BEGIN CERTIFICATE-----
++MIIBdTCCARugAwIBAgIBBzAKBggqhkjOPQQDAjAXMRUwEwYDVQQDEwxJbnRlcm1l
++ZGlhdGUwIBcNMDAwMTAxMDAwMDAwWhgPMjA5OTAxMDEwMDAwMDBaMDwxHzAdBgNV
++BAsMFm9yZyB1bml0CkNOPW5vZGVqcy5vcmcxGTAXBgNVBAMTEGF0dGFja2VyLmV4
++YW1wbGUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR7DaOQvpvA47q2XxjMqxJV
++f/FvZm2ftiFRXNJMe/fhSlDh2CybdkFIw2mE5g4ShW5UBJe+sohqy5V9WRkYtM/B
++ozEwLzAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFCUZxhtiiFordL5cZ6oJOLgs
++sd4tMAoGCCqGSM49BAMCA0gAMEUCIQCpchwik2NT0v8ifDT8aMqOLv5YwqB7oeOu
++LincYQYMagIgZc2U7DBrdEAWNfuAJx4I+ZkluIcswcdnOhbriOrTSHg=
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/google/root.pem b/test/fixtures/x509-escaping/google/root.pem
+new file mode 100644
+index 0000000000..68eb00ae86
+--- /dev/null
++++ b/test/fixtures/x509-escaping/google/root.pem
+@@ -0,0 +1,9 @@
++-----BEGIN CERTIFICATE-----
++MIIBQTCB56ADAgECAgEBMAoGCCqGSM49BAMCMA8xDTALBgNVBAMTBFJvb3QwIBcN
++MDAwMTAxMDAwMDAwWhgPMjA5OTAxMDEwMDAwMDBaMA8xDTALBgNVBAMTBFJvb3Qw
++WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR7DaOQvpvA47q2XxjMqxJVf/FvZm2f
++tiFRXNJMe/fhSlDh2CybdkFIw2mE5g4ShW5UBJe+sohqy5V9WRkYtM/BozIwMDAP
++BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQlGcYbYohaK3S+XGeqCTi4LLHeLTAK
++BggqhkjOPQQDAgNJADBGAiEA+Y5oEpcG6aRK5qQFLYRi2FrOSSLF1/dI4HtBh0mk
++GFoCIQD1DpNg6m5ZaogRW1mY1wmR5HFIr3gG8PYDRimQogXUxg==
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/info-0-cert.pem b/test/fixtures/x509-escaping/info-0-cert.pem
+new file mode 100644
+index 0000000000..6872b9870a
+--- /dev/null
++++ b/test/fixtures/x509-escaping/info-0-cert.pem
+@@ -0,0 +1,30 @@
++-----BEGIN CERTIFICATE-----
++MIIFDTCCAvWgAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++XDBaMFgGCCsGAQUFBwEBBEwwSjBIBggrBgEFBQcwAYY8aHR0cDovL2dvb2QuZXhh
++bXBsZS5jb20vCk9DU1AgLSBVUkk6aHR0cDovL2V2aWwuZXhhbXBsZS5jb20vMA0G
++CSqGSIb3DQEBCwUAA4ICAQAAd/bIBmSIOJg+Rp96/BDpsZQYgYTyBNWrnBkuHQ0M
++bovgqEEI/5xiYGEzXhrzmWrUoG40PDeVrpCSsW5m+bsO4zDQeWW5mXejbr0Iwflf
++TYDxwGUUakAcZ1c5yJ/ABjKy0Tocb9bSzln+tc+HNStp86bbgrhb/wjddn6ca21V
++cuNFZbN+0SM0LxcWO8oGKXF0HFo0durGhamcH5B/D38FYkaVR5QXoOsWVqtPFjW2
++t67rmKS6XKaz2JhZDpWDZmDofCoFu/zlkPHXkq7yyrkJ/8qpJCznkZmLn+B1WA+y
++SrSOYMpQ6RnzMx7wK5UafX5J+lMv16+LTb/n1KAd4zElcqt5eRPLcEuknIEgC2X/
++AY1ooyN/Xb4QnqvtTmhzIDb7lzzMowi5QrG3rRYMldxG2Rdqwjc8qa5Tgh7EsiU8
++A/n5X/6cxA1zoyakSHFXzGtazIkPc+zFfOaV1+gpJtd2vD2T+FrmkL1fgazuHXNZ
++hAQq0RGZWPsCdxm7dG4w5bd3YgRKfD2ck+b9Imu0ta4pqMDHZYgncaeOuuHzHgXA
++MIvxIG5JfwYUJLUqBUz8hwDVcNMpnscyn2msdpiwXK0AahucBQjbyZ6sovoxmgk5
++xLdnq2GTtdghwdkF9DYK0ZekDlk1XWbP0tR5Cevo6WlMx+cbEBG+OSfNd8/dFrkd
++aw==
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/info-1-cert.pem b/test/fixtures/x509-escaping/info-1-cert.pem
+new file mode 100644
+index 0000000000..05247873d8
+--- /dev/null
++++ b/test/fixtures/x509-escaping/info-1-cert.pem
+@@ -0,0 +1,31 @@
++-----BEGIN CERTIFICATE-----
++MIIFVTCCAz2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++gaMwgaAwgZ0GCCsGAQUFBwEBBIGQMIGNMEUGCCsGAQUFBzAChjlodHRwOi8vY2Eu
++ZXhhbXBsZS5jb20vCk9DU1AgLSBVUkk6aHR0cDovL2V2aWwuZXhhbXBsZS5jb20w
++RAYIKwYBBQUHMAGCOGdvb2QuZXhhbXBsZS5jb20KT0NTUCAtIFVSSTpodHRwOi8v
++Y2Eubm9kZWpzLm9yZy9jYS5jZXJ0MA0GCSqGSIb3DQEBCwUAA4ICAQCbwqw8YKIt
++Ht9qegR076xpnxuiH0THPGsgazvhCmEr5YHJ68sR1LexjneQDhpNXcnpYpfk6J4d
++Tu0ApMSbVypFyHcd88g0qVYI9JF+CTNnzut/Zn6xgnUjVjrSz6SZPhkMcBX9ahtY
++tzswzcyTzso5Do5pxvCWDI+bshgIhC3CYNyAjyOyyhnQrwcOcoatlhDmX1fCk+dC
++fhmzurBFNIz2gwDC7aRjcaUdTIlYnd6qHk5xLs3neBm44gNk17GazPIPo04LTKXs
++ZYzvDEUAdJ2FJMiYqSvvEv4k9ozx5HtwtncZpu46El2PQRANgj1UhemYVmHfbdU+
++7Q+rCv+Loq2v76fddhc1cM3gCQ+6SW2QmRo2rShRGxpuSuZiTngwgdQEGrkQq7Sv
++r695V7NlHWJgvv1r49wGmqWkviH5l6A0QdzL6TNYhwqCRsjxgsvCZUpOlZPASiME
++jhwBIOMy1YUSdEMnBrbuemawvbfocSuUlHaodwLZvwMgqHvNz/8ebMyRyyZrnmCx
++TYh8d0JIcA57VvfaZvvsPPV7TO7WLoJgbmuqM02JzzkJMh0fbt2oi1cqJL65V5Sn
++z0sXh/A/BzB4QawI93f9m0hX7RtuT1SolTNVyhg7dm1MwfO8khpfz5LLgflVwgN8
++6egKc6L755SlqZRMT03txH2UCBizLz1gjA==
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/info-2-cert.pem b/test/fixtures/x509-escaping/info-2-cert.pem
+new file mode 100644
+index 0000000000..06212d4e12
+--- /dev/null
++++ b/test/fixtures/x509-escaping/info-2-cert.pem
+@@ -0,0 +1,29 @@
++-----BEGIN CERTIFICATE-----
++MIIE5DCCAsygAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++MzAxMC8GCCsGAQUFBwEBBCMwITAfBgUrzg8MIoYWaHR0cDovL2NhLmV4YW1wbGUu
++Y29tLzANBgkqhkiG9w0BAQsFAAOCAgEABR5VyTZEQ0AQvdqlk+IDQT85qyf891eN
++BREiSg5KCei9Kmubv3ZJGoNVwZgybr5sCi5GqWOtG7S0GXvzS6c2Qy+cW0R4DDYs
++s6IIUn+ex1XygGrRHTDHu6tEUwSJMmOMKBh+iLjhtamD+YHjgOLG3MfadO5/9mvp
++r412MPhU1VvQ3FC3dZmBUW2gIKNEU4mzwISgPkLJXmBsnxu8F9YqHPgppqsfJ9AF
++KIc2nX7N3s8w9fCc03FrihdkE2C802jy71px5aPqa1xrIT/YBq/1fKTcYRAWF/pd
++iy2G1v0pz0kYu2/yPIC/xlFcUgeFqR/biwxAD9T9rp7rq+dpIJA5BUCpXVULqhY1
++SVZ22WKS0NR5rbu4BPDMShTOiwaDSwFQtI0OxM0g5zVFVjFOc6YbFu7ZyfLQ582S
++vgVU5/vaHANnEsCSUegXyLofqxTMPbM1rqibFmv2A4pm1Mp18ZFmqwh8cm6C0f7F
++qjdzBuSkcktTCq/dLX5yTm9aocyzye9cfNBjiGUregJEF7sD3nzsokEGj+S320w2
++5yUl95xgrHr+5bdDUEox+trTeBnddC4VxrieeH+Wv45try0Go48yK7b1Aqfu9G4B
++B/as+upQ+YjMG8mAe6JJ9JibpTvTmatYAsssEKT1vDZ5trqo4C5/utfbuyaf7qtx
++O+jFfYToPtE=
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/info-3-cert.pem b/test/fixtures/x509-escaping/info-3-cert.pem
+new file mode 100644
+index 0000000000..1825949bd3
+--- /dev/null
++++ b/test/fixtures/x509-escaping/info-3-cert.pem
+@@ -0,0 +1,30 @@
++-----BEGIN CERTIFICATE-----
++MIIFMDCCAxigAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++fzB9MHsGCCsGAQUFBwEBBG8wbTAqBggrBgEFBQcwAaAeBggrBgEFBQcIBaASDBBn
++b29kLmV4YW1wbGUuY29tMB0GCCsGAQUFBzABoBEGBSvODwwioAgMBmFiYzEyMzAg
++BggrBgEFBQcwAaAUBggrBgEFBQcIB6AIFgZhYmMxMjMwDQYJKoZIhvcNAQELBQAD
++ggIBACR9nH4pRlcSIIF9DEExlJvLtkeFWHGIAYLBuauHmdzPdbq9Py9M5DOcc7yd
++OQYVYwW26hASb+3CYzhRQaWKOR+T/OwP+QMUl5Y6nc3HzLdYTSen2LLAYHySXK3G
++gTdOhmVQwdh+IzhpjLXC67/9gn/F1p73Ixv/0PBZzmC64DOp1ogso9RICu0xTAbo
++h8mdN4/Tbh9Ikd89lb91x1Xf86NyC7ZvSA9dUO07/3B6B0kkqCdP9Ytlsrt2wbt3
++2TVPp+ghjbPjdLrJUi3fbdC2CgjV2oLiYr1h7qn7SmYPNgOpDPKBI4Cei7UO+Wow
++yLCxBO0HgLZKcZorJFofekPjqtQYYj1sw3OEIcifMAmoHT7H57onfoQbRDpt57k2
++rHJKgzrRuT8Qbl3OHSkiWRE3u0S9kAg7QEq27e2fuvh23p+YHEiYIjAR9XLVh7/Q
++EG5QDfDq3MvtgD/khAd36il61T5h8F4u3MhONFMuwJ/TYtGR6QINrv4DqLBM1pRr
++LMApQYi0w/MCRj2wLeAro9NflE+PFDk+l44ojvnEUYAGUyIzWp80bjQrV7Up6sgQ
++HehcmxxTrOmiqrfw08c1aHhmGeplmPpQEET1wIjnyj49sfdSPYxg5Lh+f/l79fLb
++jFemE8otKfog84vNGbPFl/AHwxjKCeCA/MaNJz3y3RYVsZn6
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/info-4-cert.pem b/test/fixtures/x509-escaping/info-4-cert.pem
+new file mode 100644
+index 0000000000..8f1e69afec
+--- /dev/null
++++ b/test/fixtures/x509-escaping/info-4-cert.pem
+@@ -0,0 +1,29 @@
++-----BEGIN CERTIFICATE-----
++MIIE9jCCAt6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBldmls
++LmV4YW1wbGUuY29tMB4XDTIxMTIyMDE0NTczNVoXDTMxMTIxODE0NTczNVowGzEZ
++MBcGA1UEAxMQZXZpbC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
++ADCCAgoCggIBALERZ3TS70T1P+SjpZwIqOFnu2Od9XKWcDszQQc7C92K+APjp4Bv
++WiayictqCJWtmsbsSli4yG3P6Ddi/V3Se8W+/yB71Qh2c3wQNMPMukncps2odRGt
++qJe4EOpret1jgkFqQJy5geXVuPU5N7DvGXUVZzWN7TisFNAZMUhF2YlljJz1sjD1
++aRjqayh3TDU8NwuFlLd6aH95hovjMBBatWFB9bN/itnMVoj9rmfSjvlpSRO6/EMN
++DnVXZ3paRJTcps6d/Ylb5Ald/Ow056JgD0Cd9jn16+vgYR4bxVl0a5Qbf24MIhaY
++BRPx6WFdepWr410GpzpVQ0sMluoKYzH8RynjwQc7pfm5ebTFWJkhU80jOqKJGFW3
++icV/A9BmtOBqrb60Pv/MPXIQPg7UWGUOXm3AfY3v6gbToewSW5B0s+uPsh52md4Z
++UoyzTvwN2i/uPqJxi/9FkdV60OWvMMMeMslbDHIBbN0Z2SG0wY93oH2LhO0X89Tc
++nedukufld8QEW7iMn7D7la+TlrrSAXURHL84sEz97yyujawQEimnW03XAlUFk61M
++iLhVUOHANFBSLBvZ3VF7sZDv6ZzPkP/TWrFbpL7DQgqunAlSNHealrQ5T3wp8pUm
++R7J4QEuQSEN2cZMOpn0T+JyQaiytbaAABgqDNeTvbl2nFN2ksSix8NunAgMBAAGj
++RTBDMEEGCCsGAQUFBwEBBDUwMzAxBggrBgEFBQcwAaAlBggrBgEFBQcIBaAZDBdn
++b29kLmV4YW1wbGUuY29tAGFiYzEyMzANBgkqhkiG9w0BAQsFAAOCAgEAQERLvjQB
++E2fmTVgHbr4MVXPfse9Xxk9TK8/IhxDNnql4bor3xat5oP+tDHVRi2StajfIcJlX
++C9blYOWg4w6QH3pmD6M7eQGOw7ntOUid4R2vhX3XiK3QB1h8lWSPFmSwBHA47mMJ
++IkrKNIo9+M9b7M05YwbAENi3TPgT8h2Ej9V4DUjLIEhDcu8fSh3FkNpZ2HohZ2I3
++QPe23FB052jX7uPfeZ9gcjL/iGxuTuPbKWxzZ/Gy2RmS8xfLkJESvvQ8a0H4f7Ij
++yjn7qYUkY6FoHxyg5BU34YNaJCmfgzRIE53Kv2FMPwj2JaXmIguR+mSDAbc0xjw3
++G3dRoCqhZugn8C6I5FhuXHdu6zSuuHtwOGEf07y5Im2sBsPVoq+Txh/mv3Zy9Ydy
++0yCDuq87jKSZd7FKorHOEoQY94UMs33PYjS4h/hYWiysYUeR0mlbjr4gyv1KH6K8
++JERGpI/OE+vzfOtgj/Z46/+wn7jF0LBCin7Jn5Zw1a1TNsiHKAjqW/P4vJxxUW++
++FtYwJhI7XJehwNNFra9rSC5M4TkpaqAZnbPvWZWxWVJIEYFgNjnt+b/VOpRpv5bJ
++7BOlVvP+56KF+vlmCnzVBmlHcr45sZUZ3mw3Sb6dcF0V0VaNQKw/F5EteQyafIIl
++dvCwwV4OwLwPliPAvwYfVEI41Dv3mF4fN7k=
++-----END CERTIFICATE-----
+diff --git a/test/fixtures/x509-escaping/package.json b/test/fixtures/x509-escaping/package.json
+new file mode 100644
+index 0000000000..37d9f2a938
+--- /dev/null
++++ b/test/fixtures/x509-escaping/package.json
+@@ -0,0 +1,12 @@
++{
++ "name": "x509-escaping",
++ "version": "1.0.0",
++ "description": "create certificates for x509-escaping test",
++ "main": "createCert.js",
++ "license": "SEE LICENSE IN ../../../LICENSE",
++ "private": true,
++ "dependencies": {
++ "asn1.js": "^5.4.1",
++ "asn1.js-rfc5280": "^3.0.0"
++ }
++}
+diff --git a/test/fixtures/x509-escaping/server-key.pem b/test/fixtures/x509-escaping/server-key.pem
+new file mode 100644
+index 0000000000..db1d2652d0
+--- /dev/null
++++ b/test/fixtures/x509-escaping/server-key.pem
+@@ -0,0 +1,52 @@
++-----BEGIN PRIVATE KEY-----
++MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCxEWd00u9E9T/k
++o6WcCKjhZ7tjnfVylnA7M0EHOwvdivgD46eAb1omsonLagiVrZrG7EpYuMhtz+g3
++Yv1d0nvFvv8ge9UIdnN8EDTDzLpJ3KbNqHURraiXuBDqa3rdY4JBakCcuYHl1bj1
++OTew7xl1FWc1je04rBTQGTFIRdmJZYyc9bIw9WkY6msod0w1PDcLhZS3emh/eYaL
++4zAQWrVhQfWzf4rZzFaI/a5n0o75aUkTuvxDDQ51V2d6WkSU3KbOnf2JW+QJXfzs
++NOeiYA9AnfY59evr4GEeG8VZdGuUG39uDCIWmAUT8elhXXqVq+NdBqc6VUNLDJbq
++CmMx/Ecp48EHO6X5uXm0xViZIVPNIzqiiRhVt4nFfwPQZrTgaq2+tD7/zD1yED4O
++1FhlDl5twH2N7+oG06HsEluQdLPrj7IedpneGVKMs078Ddov7j6icYv/RZHVetDl
++rzDDHjLJWwxyAWzdGdkhtMGPd6B9i4TtF/PU3J3nbpLn5XfEBFu4jJ+w+5Wvk5a6
++0gF1ERy/OLBM/e8sro2sEBIpp1tN1wJVBZOtTIi4VVDhwDRQUiwb2d1Re7GQ7+mc
++z5D/01qxW6S+w0IKrpwJUjR3mpa0OU98KfKVJkeyeEBLkEhDdnGTDqZ9E/ickGos
++rW2gAAYKgzXk725dpxTdpLEosfDbpwIDAQABAoICAAwUElkTPHQZQKsBiL38jzyU
++/WDduQ0AexZmuCRcoEIUBTgKsvXdYqpqGmEwUfaX2YuBOc8Uh8OJ357Ll1nrjjre
++fPvDxrPllJodZuQGVpzMOuqjd5zlmi8DRNAg1cg9TfjVXSPzuYsqiYvcw9JDdRqa
++A6jRDiIEBwVs+oIiFaU8MpvQXL/fNbSX5QhlHuMwwNZ93beoV3F+ojFvpWswLNg+
++DhsY86lIuYxttZRqdgtIZc49PpD6VoalmC7t8mivJofImi9g/8ytxx97umNGpzOy
++ssWgY1/7NdS+czdXbDE1sPsaQ8cDxrDmGxPjswV7rK4/Um/1ufnoGXFMlRinS1lQ
++nns4VAFefVUCk81LRyFb+X97NXPGC1p4zNlC1ZoihMgWKJBzH0uk5K/hURS/wDNZ
++epm9ssnEQrFGJhEI+635srfn9SVRZ8xNh+oCguo5NaZm/BezC6iBQeoaBmVL2lY8
++KLztN/JQd6MMZi3CWhTn0ZAtVNMxGjU9/yrdWIkX9EV8Sw68fqLGoKQXI67AOynQ
++5AnUyEjhVu7M39gYL71l7BVpuG7qaX8l4brzBcgzFldvuhuNCx0SW4gU2/Nx4OwY
++BLOX1LOrpD+5M9YwcbtSxcxz97nP8efb3hUK3QD2iuZ9Fa6zKWsoreMb7Jku38i7
++e41lupAIkxxuxGBe1YrZAoIBAQDVF7Kru6tsaWtvJw5cbZpKxcuUHHQ0X3XRgA+H
++uWfT8EbxmDpgcG8polqiYuXPFWcrElmtWeBCYXazGZocHRV8y+ri/9c2rMTH6Bni
++TcYfsc4E8WY6adxfUqajgQ2zShdZbxZtBvSP50HheZ0a+L2qn2MWDUN/mbwYEmom
++SonVx3MSJWm/Vrh5i4b/L/+9u7uumIjWYFK6pKdLerTfbXO7ZsNR9KDIOBLDnUcf
+++6K2vcclZN7aga1S7wTsrX+k9C/OQuj8ONMWQHCxryp5RAmgtArTBrJZq8el1lcG
++518Vo4QuOqsqTdAhqiImoPKe4NNCs1iTS9BdCqNYiF8sbmeJAoIBAQDUuL5ebQ68
++6vqTKYD47ZtCzeqziN3Y/0a1BsyZh0/snNmK5WIr4T0vX0Y/XG0EpkZdpW3odMBv
++CemKs6Zm+pfOUGu20PTJcdSOXRbFiVYSeQnfa0l3iXZvY9Ottz/IU/mWPuU3hc18
++hOZD9tKiwYDzZREg6L4XRizfT70UkD2eTz4lGBjR092TTj8WqSaI9GF6d9B6Aw9Y
++OCZdTqV7hPe0Rnvd1XiGsk68HN2Np47HHwwPsKMCYj8YNKmsUF8QSXmCkijlDeJW
++bC6TjAHlvnN6n1LjaLwULUs9Rb2fkNUOqsgR+T8YlqbclJbzC7gW53M/68c9eOQ1
++Y01JnzsB3S2vAoIBAQDT8DP2djtzIg6GiNPRvfj9cWifMQWqqV8nNTU9Cnxn4MzO
++sVcuX+VQBXgblj13D5SC1Ed5ELDplMJYM5iBabPbYX2GtGq6qG83XHOSD0SEdXWw
++mN/SLUPPUwcGC+8yaPh8LO6jFY3cKmft9+T31Hnf35LPdfWyTZc0YexNlUkt5Kdg
++XvGkKn5j9RAZcwXrEXMDnhZLEZZ2qBj0C2El71hyBS0ysBnRyWNwR1dcSgx1sJ8H
++ZCH6NYvLtoqxU4Zm6684eHf9lA7uTL1JHC0kWzUwLqGtbTWp1h5FpL790NVTUkS/
++Lf7bnnTpZqt8vAtTVc0IxBPOvFLKlzALd+cg69XxAoIBAQCv6Sbkh2NMrzUQRZ42
++PKfMkuSoG2L6dABQ65J+0/swPHVZ+1830kf6yNsawqAU3DwMbSV6ujH4oUXUQcQ2
++HL01DCRHRn1nqQ6RvEF8kZnwJNAZRmu2wqKCcxc17Ph9/ZPEv7ZmN+w6MN0LDy4Z
++EdRFcyq7AD1SmeG5ugMu4ilSpU1K96ZuvrnZezeI0dDgKNgDotlwTN9/oM95EfSf
++NNJy7ma4iDPnj8S0o1pELnBQEkizIOtsqTpsFgDKUpyKp3golh3jbZvixAuwUHOx
++PdHZca/mB1KhjONPhEDPl8HZIznYQzn+Z3cNqoM58lMF/di834ogN7zguYHMhDUT
++0YhZAoIBAHlYhuni+gyrn4tyZgep68VXW7wQxSvgSj8cpZAuT/w0UKAU53J5QTWZ
++aGHeICXvgvpalUL+2dGwASlOvPa52ekcOPd2+qKWyss0zA4ksI7mNE2vjFUcOr+S
++n9QSNvu3E8dYAjzSIsizcQbPTlk6A/TmytNJ4x67ZVGCmKXw1ZzzSrxSbAIdY254
++TxSGchrfcy0ofXIL2HXq16FRmesORTJFkkyQaldzn4y7S6HJ/vGppImTfeac1MwG
++jLYljIkIbt+nB1c8HeNvARmBa6M2pxB9f72oRMVqFdUUc5AxXuWP9v6xk227EuCq
++TBORAafu9WxKVwUsHa1rE1uGgNEfRJ8=
++-----END PRIVATE KEY-----
+diff --git a/test/parallel/test-tls-0-dns-altname.js b/test/parallel/test-tls-0-dns-altname.js
+index 4bc87e44cb..e5cb8e3d48 100644
+--- a/test/parallel/test-tls-0-dns-altname.js
++++ b/test/parallel/test-tls-0-dns-altname.js
+@@ -44,7 +44,7 @@ const server = tls.createServer({
+ }, common.mustCall(() => {
+ const cert = c.getPeerCertificate();
+ assert.strictEqual(cert.subjectaltname,
+- 'DNS:good.example.org\0.evil.example.com, ' +
++ 'DNS:"good.example.org\\u0000.evil.example.com", ' +
+ 'DNS:just-another.example.com, ' +
+ 'IP Address:8.8.8.8, ' +
+ 'IP Address:8.8.4.4, ' +
+diff --git a/test/parallel/test-x509-escaping.js b/test/parallel/test-x509-escaping.js
+new file mode 100644
+index 0000000000..4e0f82767d
+--- /dev/null
++++ b/test/parallel/test-x509-escaping.js
+@@ -0,0 +1,349 @@
++'use strict';
++
++const common = require('../common');
++if (!common.hasCrypto)
++ common.skip('missing crypto');
++
++const assert = require('assert');
++const tls = require('tls');
++const fixtures = require('../common/fixtures');
++
++const { hasOpenSSL3 } = common;
++
++// Test that all certificate chains provided by the reporter are rejected.
++{
++ const rootPEM = fixtures.readSync('x509-escaping/google/root.pem');
++ const intermPEM = fixtures.readSync('x509-escaping/google/intermediate.pem');
++ const keyPEM = fixtures.readSync('x509-escaping/google/key.pem');
++
++ const numLeaves = 5;
++
++ for (let i = 0; i < numLeaves; i++) {
++ // TODO(tniessen): this test case requires proper handling of URI SANs,
++ // which node currently does not implement.
++ if (i === 3) continue;
++
++ const name = `x509-escaping/google/leaf${i}.pem`;
++ const leafPEM = fixtures.readSync(name, 'utf8');
++
++ const server = tls.createServer({
++ key: keyPEM,
++ cert: leafPEM + intermPEM,
++ }, common.mustNotCall()).listen(common.mustCall(() => {
++ const { port } = server.address();
++ const socket = tls.connect(port, {
++ ca: rootPEM,
++ servername: 'nodejs.org',
++ }, common.mustNotCall());
++ socket.on('error', common.mustCall());
++ })).unref();
++ }
++}
++
++// Test escaping rules for subject alternative names.
++{
++ const expectedSANs = [
++ 'DNS:"good.example.com\\u002c DNS:evil.example.com"',
++ // URIs should not require escaping.
++ 'URI:http://example.com/',
++ 'URI:http://example.com/?a=b&c=d',
++ // Unless they contain commas.
++ 'URI:"http://example.com/a\\u002cb"',
++ // Percent encoding should not require escaping.
++ 'URI:http://example.com/a%2Cb',
++ // Malicious attempts should be escaped.
++ 'URI:"http://example.com/a\\u002c DNS:good.example.com"',
++ // Non-ASCII characters in DNS names should be treated as Latin-1.
++ 'DNS:"ex\\u00e4mple.com"',
++ // It should not be possible to cause unescaping without escaping.
++ 'DNS:"\\"evil.example.com\\""',
++ // IPv4 addresses should be represented as usual.
++ 'IP Address:8.8.8.8',
++ 'IP Address:8.8.4.4',
++ // For backward-compatibility, include invalid IP address lengths.
++ hasOpenSSL3 ? 'IP Address:<invalid length=5>' : 'IP Address:<invalid>',
++ hasOpenSSL3 ? 'IP Address:<invalid length=6>' : 'IP Address:<invalid>',
++ // IPv6 addresses are represented as OpenSSL does.
++ 'IP Address:A0B:C0D:E0F:0:0:0:7A7B:7C7D',
++ // Regular email addresses don't require escaping.
++ 'email:foo@example.com',
++ // ... but should be escaped if they contain commas.
++ 'email:"foo@example.com\\u002c DNS:good.example.com"',
++ 'DirName:/C=DE/L=Hannover',
++ // TODO(tniessen): support UTF8 in DirName
++ 'DirName:"/C=DE/L=M\\\\xC3\\\\xBCnchen"',
++ 'DirName:"/C=DE/L=Berlin\\u002c DNS:good.example.com"',
++ 'DirName:"/C=DE/L=Berlin\\u002c DNS:good.example.com\\\\x00' +
++ 'evil.example.com"',
++ 'DirName:"/C=DE/L=Berlin\\u002c DNS:good.example.com\\\\\\\\x00' +
++ 'evil.example.com"',
++ // These next two tests might be surprising. OpenSSL applies its own rules
++ // first, which introduce backslashes, which activate node's escaping.
++ // Unfortunately, there are also differences between OpenSSL 1.1.1 and 3.0.
++ 'DirName:"/C=DE/L=Berlin\\\\x0D\\\\x0A"',
++ hasOpenSSL3 ?
++ 'DirName:"/C=DE/L=Berlin\\\\/CN=good.example.com"' :
++ 'DirName:/C=DE/L=Berlin/CN=good.example.com',
++ // TODO(tniessen): even OIDs that are well-known (such as the following,
++ // which is sha256WithRSAEncryption) should be represented numerically only.
++ 'Registered ID:sha256WithRSAEncryption',
++ // This is an OID that will likely never be assigned to anything, thus
++ // OpenSSL should not know it.
++ 'Registered ID:1.3.9999.12.34',
++ hasOpenSSL3 ?
++ 'othername: XmppAddr::abc123' :
++ 'othername:<unsupported>',
++ hasOpenSSL3 ?
++ 'othername:" XmppAddr::abc123\\u002c DNS:good.example.com"' :
++ 'othername:<unsupported>',
++ hasOpenSSL3 ?
++ 'othername:" XmppAddr::good.example.com\\u0000abc123"' :
++ 'othername:<unsupported>',
++ // This is unsupported because the OID is not recognized.
++ 'othername:<unsupported>',
++ hasOpenSSL3 ? 'othername: SRVName::abc123' : 'othername:<unsupported>',
++ // This is unsupported because it is an SRVName with a UTF8String value,
++ // which is not allowed for SRVName.
++ 'othername:<unsupported>',
++ hasOpenSSL3 ?
++ 'othername:" SRVName::abc\\u0000def"' :
++ 'othername:<unsupported>',
++ ];
++
++ const serverKey = fixtures.readSync('x509-escaping/server-key.pem', 'utf8');
++
++ for (let i = 0; i < expectedSANs.length; i++) {
++ const pem = fixtures.readSync(`x509-escaping/alt-${i}-cert.pem`, 'utf8');
++
++ // X509Certificate interface is not supported in v12.x & v14.x. Disable
++ // checks for subjectAltName with expectedSANs. The testcase is ported
++ // from v17.x
++ //
++ // Test the subjectAltName property of the X509Certificate API.
++ // const cert = new X509Certificate(pem);
++ // assert.strictEqual(cert.subjectAltName, expectedSANs[i]);
++
++ // Test that the certificate obtained by checkServerIdentity has the correct
++ // subjectaltname property.
++ const server = tls.createServer({
++ key: serverKey,
++ cert: pem,
++ }, common.mustCall((conn) => {
++ conn.destroy();
++ server.close();
++ })).listen(common.mustCall(() => {
++ const { port } = server.address();
++ tls.connect(port, {
++ ca: pem,
++ servername: 'example.com',
++ checkServerIdentity: (hostname, peerCert) => {
++ assert.strictEqual(hostname, 'example.com');
++ assert.strictEqual(peerCert.subjectaltname, expectedSANs[i]);
++ },
++ }, common.mustCall());
++ }));
++ }
++}
++
++// Test escaping rules for authority info access.
++{
++ const expectedInfoAccess = [
++ {
++ text: 'OCSP - URI:"http://good.example.com/\\u000a' +
++ 'OCSP - URI:http://evil.example.com/"',
++ legacy: {
++ 'OCSP - URI': [
++ 'http://good.example.com/\nOCSP - URI:http://evil.example.com/',
++ ],
++ },
++ },
++ {
++ text: 'CA Issuers - URI:"http://ca.example.com/\\u000a' +
++ 'OCSP - URI:http://evil.example.com"\n' +
++ 'OCSP - DNS:"good.example.com\\u000a' +
++ 'OCSP - URI:http://ca.nodejs.org/ca.cert"',
++ legacy: {
++ 'CA Issuers - URI': [
++ 'http://ca.example.com/\nOCSP - URI:http://evil.example.com',
++ ],
++ 'OCSP - DNS': [
++ 'good.example.com\nOCSP - URI:http://ca.nodejs.org/ca.cert',
++ ],
++ },
++ },
++ {
++ text: '1.3.9999.12.34 - URI:http://ca.example.com/',
++ legacy: {
++ '1.3.9999.12.34 - URI': [
++ 'http://ca.example.com/',
++ ],
++ },
++ },
++ hasOpenSSL3 ? {
++ text: 'OCSP - othername: XmppAddr::good.example.com\n' +
++ 'OCSP - othername:<unsupported>\n' +
++ 'OCSP - othername: SRVName::abc123',
++ legacy: {
++ 'OCSP - othername': [
++ ' XmppAddr::good.example.com',
++ '<unsupported>',
++ ' SRVName::abc123',
++ ],
++ },
++ } : {
++ text: 'OCSP - othername:<unsupported>\n' +
++ 'OCSP - othername:<unsupported>\n' +
++ 'OCSP - othername:<unsupported>',
++ legacy: {
++ 'OCSP - othername': [
++ '<unsupported>',
++ '<unsupported>',
++ '<unsupported>',
++ ],
++ },
++ },
++ hasOpenSSL3 ? {
++ text: 'OCSP - othername:" XmppAddr::good.example.com\\u0000abc123"',
++ legacy: {
++ 'OCSP - othername': [
++ ' XmppAddr::good.example.com\0abc123',
++ ],
++ },
++ } : {
++ text: 'OCSP - othername:<unsupported>',
++ legacy: {
++ 'OCSP - othername': [
++ '<unsupported>',
++ ],
++ },
++ },
++ ];
++
++ const serverKey = fixtures.readSync('x509-escaping/server-key.pem', 'utf8');
++
++ for (let i = 0; i < expectedInfoAccess.length; i++) {
++ const pem = fixtures.readSync(`x509-escaping/info-${i}-cert.pem`, 'utf8');
++ const expected = expectedInfoAccess[i];
++
++ // X509Certificate interface is not supported in v12.x & v14.x. Disable
++ // checks for cert.infoAccess with expected text. The testcase is ported
++ // from v17.x
++ // Test the subjectAltName property of the X509Certificate API.
++ // const cert = new X509Certificate(pem);
++ // assert.strictEqual(cert.infoAccess,
++ // `${expected.text}${hasOpenSSL3 ? '' : '\n'}`);
++
++ // Test that the certificate obtained by checkServerIdentity has the correct
++ // subjectaltname property.
++ const server = tls.createServer({
++ key: serverKey,
++ cert: pem,
++ }, common.mustCall((conn) => {
++ conn.destroy();
++ server.close();
++ })).listen(common.mustCall(() => {
++ const { port } = server.address();
++ tls.connect(port, {
++ ca: pem,
++ servername: 'example.com',
++ checkServerIdentity: (hostname, peerCert) => {
++ assert.strictEqual(hostname, 'example.com');
++ assert.deepStrictEqual(peerCert.infoAccess,
++ Object.assign(Object.create(null),
++ expected.legacy));
++ },
++ }, common.mustCall());
++ }));
++ }
++}
++
++// The internal parsing logic must match the JSON specification exactly.
++{
++ // This list is partially based on V8's own JSON tests.
++ const invalidJSON = [
++ '"\\a invalid escape"',
++ '"\\v invalid escape"',
++ '"\\\' invalid escape"',
++ '"\\x42 invalid escape"',
++ '"\\u202 invalid escape"',
++ '"\\012 invalid escape"',
++ '"Unterminated string',
++ '"Unterminated string\\"',
++ '"Unterminated string\\\\\\"',
++ '"\u0000 control character"',
++ '"\u001e control character"',
++ '"\u001f control character"',
++ ];
++
++ for (const invalidStringLiteral of invalidJSON) {
++ // Usually, checkServerIdentity returns an error upon verification failure.
++ // In this case, however, it should throw an error since this is not a
++ // verification error. Node.js itself will never produce invalid JSON string
++ // literals, so this can only happen when users construct invalid subject
++ // alternative name strings (that do not follow escaping rules).
++ assert.throws(() => {
++ tls.checkServerIdentity('example.com', {
++ subjectaltname: `DNS:${invalidStringLiteral}`,
++ });
++ }, {
++ code: 'ERR_TLS_CERT_ALTNAME_FORMAT',
++ message: 'Invalid subject alternative name string'
++ });
++ }
++}
++
++// While node does not produce commas within SAN entries, it should parse them
++// correctly (i.e., not simply split at commas).
++{
++ // Regardless of the quotes, splitting this SAN string at commas would
++ // cause checkServerIdentity to see 'DNS:b.example.com' and thus to accept
++ // the certificate for b.example.com.
++ const san = 'DNS:"a.example.com, DNS:b.example.com, DNS:c.example.com"';
++
++ // This is what node used to do, and which is not correct!
++ const hostname = 'b.example.com';
++ assert.strictEqual(san.split(', ')[1], `DNS:${hostname}`);
++
++ // The new implementation should parse the string correctly.
++ const err = tls.checkServerIdentity(hostname, { subjectaltname: san });
++ assert(err);
++ assert.strictEqual(err.code, 'ERR_TLS_CERT_ALTNAME_INVALID');
++ assert.strictEqual(err.message, 'Hostname/IP does not match certificate\'s ' +
++ 'altnames: Host: b.example.com. is not in ' +
++ 'the cert\'s altnames: DNS:"a.example.com, ' +
++ 'DNS:b.example.com, DNS:c.example.com"');
++}
++
++// The subject MUST be ignored if a dNSName subject alternative name exists.
++{
++ const key = fixtures.readKey('incorrect_san_correct_subject-key.pem');
++ const cert = fixtures.readKey('incorrect_san_correct_subject-cert.pem');
++
++ // The hostname is the CN, but not a SAN entry.
++ const servername = 'good.example.com';
++
++ // X509Certificate interface is not supported in v12.x & v14.x. Disable
++ // checks for certX509.subject and certX509.subjectAltName with expected
++ // value. The testcase is ported from v17.x
++ //
++ // const certX509 = new X509Certificate(cert);
++ // assert.strictEqual(certX509.subject, `CN=${servername}`);
++ // assert.strictEqual(certX509.subjectAltName, 'DNS:evil.example.com');
++
++ // Try connecting to a server that uses the self-signed certificate.
++ const server = tls.createServer({ key, cert }, common.mustNotCall());
++ server.listen(common.mustCall(() => {
++ const { port } = server.address();
++ const socket = tls.connect(port, {
++ ca: cert,
++ servername,
++ }, common.mustNotCall());
++ socket.on('error', common.mustCall((err) => {
++ assert.strictEqual(err.code, 'ERR_TLS_CERT_ALTNAME_INVALID');
++ assert.strictEqual(err.message, 'Hostname/IP does not match ' +
++ "certificate's altnames: Host: " +
++ "good.example.com. is not in the cert's" +
++ ' altnames: DNS:evil.example.com');
++ }));
++ })).unref();
++}
+--
+2.17.1
+
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 \
file://big-endian.patch \
file://mips-warnings.patch \
file://0001-Remove-use-of-register-r7-because-llvm-now-issues-an.patch \
+ file://CVE-2021-44532.patch \
"
SRC_URI_append_class-target = " \
file://0002-Using-native-binaries.patch \