Description
The Name.fromString() method incorrectly treats = characters inside an attribute value as a type/value separator.
According to RFC 4514 (Section 2.4), the equals sign (=) is not among the characters that must be escaped when it appears in the middle of a value string. Currently, the parser fails to treat these as literal characters, which leads to incorrect RDN splitting.
Steps to Reproduce
import { Name } from "@peculiar/x509";
// An RDN where the value contains an internal "=" character
// According to RFC 4514, this is a valid string representation.
const dn = "CN=Test=Value, OU=Test Department";
const name = new Name(dn);
console.log("Count of RDNs:", name.length);
console.log("String output:", name.toString());
// For deep inspection:
// name.forEach(rdn => console.log(rdn.toJSON()));
Expected Behavior
The parser should identify the first = as the separator and the subsequent = as part of the value.
RDN 1: Type: CN, Value: Test=Value
RDN 2: Type: OU, Value: Test Department
toString() Output: CN=Test=Value, OU=Test Department
Actual Behavior
The parser treats the internal = as the start of a new attribute, even though no separator (, or +) is present.
RDN 1: Type: CN, Value: Test
RDN 2: Type: Value, Value: `` (Empty)
RDN 3: Type: OU, Value: Test Department
toString() Output: CN=Test, Value=, OU=Test Department
Root Cause
In the fromString implementation, the global regex used for tokenization is:
(\d.[\d.]\d|[A-Za-z]+)=((?:"")|(?:".?[^\\]")|(?:^,+"\)|(?:[^,+].*?(?:[^\\][,+]))|(?:))([,+])?/g
The logic attempts to match the entire DN in one pass. Because the "Type" capture group ([A-Za-z]+)= looks for any alpha-string followed by an =, it captures Value= as a new key, truncating the previous value.
The parser should ideally split by RDN separators (, and +) first (accounting for escapes), and only then split each part by the first = encountered.
Environment
Node.js version: v18.20.8
@peculiar/x509 version: 1.14.0
Description
The Name.fromString() method incorrectly treats = characters inside an attribute value as a type/value separator.
According to RFC 4514 (Section 2.4), the equals sign (=) is not among the characters that must be escaped when it appears in the middle of a value string. Currently, the parser fails to treat these as literal characters, which leads to incorrect RDN splitting.
Steps to Reproduce
Expected Behavior
The parser should identify the first = as the separator and the subsequent = as part of the value.
RDN 1: Type: CN, Value: Test=Value
RDN 2: Type: OU, Value: Test Department
toString() Output: CN=Test=Value, OU=Test Department
Actual Behavior
The parser treats the internal = as the start of a new attribute, even though no separator (, or +) is present.
RDN 1: Type: CN, Value: Test
RDN 2: Type: Value, Value: `` (Empty)
RDN 3: Type: OU, Value: Test Department
toString() Output: CN=Test, Value=, OU=Test Department
Root Cause
In the fromString implementation, the global regex used for tokenization is:
(\d.[\d.]\d|[A-Za-z]+)=((?:"")|(?:".?[^\\]")|(?:^,+"\)|(?:[^,+].*?(?:[^\\][,+]))|(?:))([,+])?/g
The logic attempts to match the entire DN in one pass. Because the "Type" capture group ([A-Za-z]+)= looks for any alpha-string followed by an =, it captures Value= as a new key, truncating the previous value.
The parser should ideally split by RDN separators (, and +) first (accounting for escapes), and only then split each part by the first = encountered.
Environment
Node.js version: v18.20.8
@peculiar/x509 version: 1.14.0