Decoding a CSR: Reading SAN & Subject Fields

How a PKCS#10 Certificate Signing Request is actually structured at the ASN.1 level, how to read openssl req -text output line by line, and why the SAN extension — not the Common Name — is the field that actually governs which hostnames a certificate protects.

🛠️ Related tool: Open CSR Decoder →

What a CSR Actually Contains, Structurally

A PKCS#10 CSR — formally defined in RFC 2986 — is a single ASN.1 SEQUENCE built from exactly three parts, in a fixed order that never changes regardless of which fields you filled in when it was generated. The first and largest part is certificationRequestInfo, itself a nested SEQUENCE holding a version number, the subject distinguished name, the public key, and an optional attributes field. The second part, signatureAlgorithm, names the exact algorithm and hash used to sign everything in the first part. The third, signature, is the raw signature bytes computed over the DER encoding of certificationRequestInfo specifically — not over the whole CSR, which matters because it means the signature can be checked before you even look at what algorithm signed it. Understanding this three-part shape is the key to reading any decoded output sensibly: everything you'll see printed by a decoder maps onto one of these three buckets, and knowing which bucket a field belongs to tells you whether it was something the requester chose (inside CertificationRequestInfo) or something imposed by the signing process itself.

⭐
ToolsNovaHub Pro Tip
When comparing two CSRs to see if they're "the same request," compare the decoded subject and SAN fields, not the raw PEM text byte-for-byte — the same logical CSR re-encoded by a different tool can have different DER byte lengths (different string type choices, different attribute ordering) while representing identical information.
⚠️
Common Beginner Mistake
Reading only the Subject line and assuming that's the complete list of domains the certificate will cover. The Subject's Common Name is one name; the actual list a browser will trust lives in the SAN extension inside Attributes, and it's frequently a different, longer list.

Reading Real Output: openssl req -text, Field by Field

Running openssl req -in file.csr -noout -text against any CSR prints a human-readable rendering of the exact ASN.1 structure above. The first line, Version: 1 (0x0), looks like it should mean something configurable, but it's fixed — PKCS#10's only defined version integer value is 0, which OpenSSL confusingly labels "Version: 1" in its display (a historical off-by-one in the tool's own text, not in the standard). Next comes Subject:, listing whichever of C, ST, L, O, OU, CN, and emailAddress were populated, in the order they appear in the underlying RDN sequence. Below that, Subject Public Key Info shows the key algorithm and either the RSA modulus/exponent or the ECDSA curve name and point. If any extensions were requested, an Attributes: block follows, almost always containing Requested Extensions: with the SAN list nested inside. Finally, Signature Algorithm: and the raw signature bytes close out the printout, corresponding directly to the second and third top-level ASN.1 fields described above.

The Subject Field's X.500 Origins

The C, ST, L, O, OU, and CN abbreviations predate SSL/TLS entirely — they come from X.500, an ITU-T directory service standard from the 1980s designed to organize entries in a hierarchical, postal-address-like naming system for large institutional directories. Country, State/Province, Locality, Organization, and Organizational Unit map directly onto X.500's idea of narrowing down through a physical and organizational hierarchy before finally naming a specific entity with a Common Name. When SSL certificates borrowed X.509 (X.500's certificate format) in the 1990s, they inherited this entire naming scheme wholesale, which is why a field designed to identify an entry in a corporate directory ended up being reused to name a website's domain. This history explains a few things that otherwise look arbitrary: why Country is capped at exactly two characters (it's an ISO 3166-1 code, a convention layered on top of X.500 rather than part of it), and why Organizational Unit exists as a separate field from Organization at all (X.500 directories commonly nested departments under a parent company entry).

PrintableString vs UTF8String vs teletexString

Every string-valued field in the subject is DER-encoded with an explicit ASN.1 type tag, and that tag choice is visible if you look at the raw bytes rather than OpenSSL's already-decoded text. PrintableString (ASN.1 tag 0x13) is restricted to uppercase and lowercase Latin letters, digits, spaces, and a small fixed set of punctuation marks — no accented characters, no non-Latin scripts. UTF8String (tag 0x0C) allows the entire Unicode range and is what essentially all current tooling uses for Organization, Organizational Unit, and Common Name, since real company names frequently need characters PrintableString can't represent. Country is the one field convention still typically encodes as PrintableString, since two-letter ISO codes never need anything outside its character set anyway. A third, older type, teletexString (tag 0x14), shows up occasionally in CSRs generated by legacy X.500-lineage software from the 1990s and early 2000s; most current CA parsers reject it outright, which is why a CSR decoded and found to contain a teletexString-tagged field is worth flagging as a likely source of validation failure regardless of what the actual text content says.

SAN's GeneralName Choice: More Than Just Domains

The Subject Alternative Name extension, defined in RFC 5280, is a SEQUENCE OF GeneralName, and GeneralName is itself an ASN.1 CHOICE type supporting several distinct kinds of identifier, each with its own context-specific tag number: dNSName [2] for hostnames, iPAddress [7] for a raw IP address, rfc822Name [1] for an email address, and uniformResourceIdentifier [6] for a URI, among a few less common choices like otherName and directoryName. Public web server certificates use dNSName almost exclusively, which is why every decoder you'll encounter shows SAN output as a simple list of domain strings — but the underlying extension format is genuinely more general than that narrow usage suggests, and other certificate use cases (S/MIME email certificates, IPsec/IKE peer certificates) lean on the other GeneralName choices routinely.

Why Browsers Read SAN and Ignore CN for Hostname Matching

This wasn't always true. Early implementations of hostname verification fell back to Common Name when no SAN extension was present at all, and for years CAs issued certificates where CN alone was considered sufficient. That changed formally with the CA/Browser Forum's baseline requirements, and the practical enforcement deadline that mattered most was Chrome's 2017 rollout of strict SAN-only matching (Chrome 58), which every other major browser followed shortly after. The result: a certificate whose only name lives in CN, with no matching SAN entry, now fails hostname verification in every current browser — not a warning, an outright connection failure. This is precisely why the CSR generation and decoding tools on this site treat SAN as the authoritative name list and CN as effectively a legacy label kept for backward compatibility and CA record-keeping, not a security-relevant field.

Reading the Public Key Section Correctly

For an RSA key, the decoded output shows the full modulus in hex (a number whose bit length directly determines the "2048-bit" or "4096-bit" figure you see quoted elsewhere) and the public exponent, which is essentially always 65537 (0x10001) in any modern-generated key — a value chosen for computational efficiency during signature verification, not for any security property specific to that number. For ECDSA, there's no modulus at all; instead you'll see a named curve identifier (P-256, P-384, or occasionally P-521) and an encoded elliptic curve point representing the public key. A useful sanity check when decoding a CSR you didn't generate yourself: the stated key size or curve should match whatever policy the destination CA publishes as a minimum, since a CSR carrying a key below policy will be rejected regardless of how clean every other field looks.

The Attributes Field and the extensionRequest OID

SAN doesn't live directly inside CertificationRequestInfo as its own top-level field — PKCS#10's original 1990s design predates X.509v3 extensions and has no dedicated slot for them. Instead, extensions are smuggled in through the generic attributes field using a specific, well-known attribute type: extensionRequest, identified by OID 1.2.840.113549.1.9.14, whose value is a standard X.509 Extensions SEQUENCE — the exact same structure a finished certificate uses to carry SAN, key usage, and other extensions. This is why decoded output labels the section "Requested Extensions" rather than simply "Extensions": it's a CSR politely asking the CA to carry these extensions forward into the issued certificate, not a guarantee that it will, since the CA independently decides what actually ends up in the final cert regardless of what was requested.

A Byte-Level Walkthrough of DER Tag-Length-Value

Every ASN.1 DER element follows the same Tag-Length-Value pattern, and seeing one concretely demystifies the rest. Take a Common Name of "example.com" encoded as UTF8String: the bytes are 0C 0B 65 78 61 6D 70 6C 65 2E 63 6F 6D. 0C is the tag for UTF8String. 0B is the length — 11 bytes, matching "example.com"'s 11 characters. The remaining 11 bytes are the ASCII value itself. That single element then sits nested inside a SEQUENCE (tag 30) pairing it with the Common Name's OID 2.5.4.3, which itself sits inside a SET (tag 31, since X.500 technically allows multiple values per RDN even though CSRs virtually never use that), which sits inside the outer subject SEQUENCE alongside every other RDN. Every field in a decoded CSR, no matter how deeply nested it looks in a text printout, unpacks to this same tag-length-value pattern at the byte level — there's no separate parsing logic for "special" fields, just consistent recursive application of the same rule.

Comparing Ways to Decode a CSR

MethodShows Raw ASN.1 Tags?Verifies Signature?Setup Needed
openssl req -textNo (pre-decoded, human-readable)No (use -verify separately)OpenSSL installed locally
openssl asn1parseYes, full tag/length breakdownNoOpenSSL installed locally
Browser-based CSR decoderNo (pre-decoded, human-readable)Not typicallyNone — runs in-browser
Manual hex/byte inspectionYes, full controlNo, manual onlyHex editor, ASN.1 reference

For everyday work — confirming a CSR's SAN list and subject before submitting it — a human-readable decoder is almost always the right tool, since raw tag/length output is genuinely useful only when debugging a malformed or unusually-encoded CSR that a normal decoder is choking on.

Encoding Mistakes That Cause Silent CA Rejections

A handful of specific encoding choices, all invisible if you only glance at a decoded field's text value, account for most CSR rejections that aren't about the actual content of the names requested. A subject field encoded as teletexString instead of UTF8String, as covered earlier, is one. Another is a CSR whose SAN extension was built correctly in terms of content but placed as a standalone X.509v3 extension rather than wrapped inside the proper extensionRequest attribute — some older or nonstandard generator libraries have gotten this wrong, producing a CSR that decodes and "looks right" in casual inspection but that standards-compliant CA parsers don't recognize as carrying any extensions at all. A third is inconsistent line-wrapping or missing header/footer lines in the PEM encoding itself, which isn't an ASN.1 issue but a Base64 transport issue — covered in more depth in our companion guide on verifying and troubleshooting CSR errors.

When You'd Actually Need to Decode a CSR by Hand

Most people decoding a CSR fall into one of a few concrete situations. Someone inherited a legacy CSR-generation script from a departed team member and needs to confirm exactly what subject fields and SAN list it's producing before trusting it in a renewal pipeline. A security review flagged a certificate request as containing unexpected fields, and someone needs to trace precisely what's encoded rather than trusting a summary. A CA support ticket references a specific ASN.1 field by name ("your CSR's attributes field is malformed") and resolving it requires actually looking at that structure rather than guessing. Or, less dramatically, someone simply wants to confirm a CSR their hosting control panel generated automatically actually requests the domains they expect, before submitting it somewhere that charges per certificate and doesn't offer free reissuance.

Related Reading

For the actual cryptographic verification step this article doesn't cover, see our companion guide Verifying & Troubleshooting CSR Errors. For generating a fresh CSR from scratch with a compliant SAN list, use the CSR Generator. For background on certificate validation levels these subject fields feed into, read SSL Certificate Validation Levels: EV vs OV vs DV. For the broader TLS/certificate landscape, see TLS/SSL Protocol & Certificate Types Guide.

📅 Last updated: September 2026📜 Sourced from: RFC 2986 & RFC 5280

ToolsNovaHub guides are researched against primary sources (RFCs, vendor docs) and kept up to date as standards change. Spotted an error? Let us know.

📋 Related Tools & Guides Comparison

ResourceTypeLink
CSR DecoderToolOpen Tool →
Certificate DecoderToolOpen Tool →
CSR GeneratorToolOpen Tool →
Verifying & Troubleshooting CSR ErrorsGuideRead Guide →
X.509 Certificate Structure: Fields & SAN ExtensionGuideRead Guide →
SSL Certificate Validation Levels: EV vs OV vs DVGuideRead Guide →
SSL Certificate CheckerToolOpen Tool →
Try it yourself — 100% free
🚀 Open CSR Decoder

🔗 More Guides

FAQ

CertificationRequestInfo (the subject, public key, and any requested extensions), signatureAlgorithm (which algorithm and hash signed it), and signature (the actual signature bytes over the first part). All three sit inside one outer ASN.1 SEQUENCE.
The CSR format itself defines a fixed structure with required fields — version is always present and is always 0 for the current PKCS#10 syntax, regardless of what you filled into a generator's form. It's part of the ASN.1 schema, not something you configure.
It's still required by CAs and still displayed, but browsers stopped trusting it for hostname matching once the CA/Browser Forum baseline requirements mandated SAN-based validation, later fully enforced by major browsers from 2017 onward. Treat it as a label, not a security-relevant field.
They're different ASN.1 string encodings with different allowed character sets — PrintableString is restricted to a small set of Latin characters, digits, and punctuation, while UTF8String allows the full Unicode range. Most modern tools use UTF8String for O/OU/CN and reserve PrintableString for the two-letter Country field by convention.
Yes — the GeneralName type SAN uses supports several choices including dNSName (the common case), iPAddress, rfc822Name (an email address), and uniformResourceIdentifier, though public web certificates almost always use dNSName exclusively.
Inside the attributes field of CertificationRequestInfo, as an extensionRequest attribute (OID 1.2.840.113549.1.9.14) whose value is a standard X.509 Extensions sequence — the same Extensions structure a real certificate uses, just requested rather than final.
teletexString was a legacy ASN.1 string type from early X.500 tooling that some old certificate software still emits for non-ASCII subject fields. Most current CAs' parsers no longer accept it, expecting UTF8String instead, so CSRs generated by very old software can fail validation purely on this encoding choice.
For parsing purposes, no CA cares whether Country comes before Organization or after — the subject is a set of RDNs, not a strictly ordered list, though tools conventionally emit them in a consistent C, ST, L, O, OU, CN order for readability.
Yes — any tool implementing an ASN.1 DER parser can do it, including browser-based decoders that run entirely client-side. OpenSSL's req -text is simply the most universally available and trusted reference implementation for a quick manual check.
For RSA, the exact modulus in hex and the public exponent (almost always 65537), from which the bit length is derived. For ECDSA, the named curve (P-256, P-384, etc.) and the encoded public point rather than a modulus.
No — decoding shows you what fields are structurally present; verifying additionally checks that the embedded signature is cryptographically valid for the embedded public key. A CSR can decode cleanly and still fail signature verification if it was tampered with.