RFC 2459

Internet X.509 Public Key Infrastructure Certificate and CRL Profile

๐Ÿ“… published January 1999, from ietf

RFC 2459: Internet X.509 Public Key Infrastructure Certificate and CRL Profile ๐ŸŽ€

okay bestie, this is the big one. it's the spec that says how X.509 certificates and CRLs should look and behave on the Internet. ๐ŸŒธ

  • Number and title: RFC 2459, Internet X.509 Public Key Infrastructure Certificate and CRL Profile
  • Authors: R. Housley (SPYRUS), W. Ford (VeriSign), W. Polk (NIST), D. Solo (Citicorp)
  • Category: Standards Track โœจ
  • Date: January 1999
  • Obsoletes / Updates: the header doesn't list anything it obsoletes or updates ๐Ÿฆ‹

It came from the Network Working Group, so it's very much a team project. ๐Ÿซถ


Status of this Memo ๐Ÿ’…

this one is an Internet standards track protocol for the Internet community, and it's literally asking everyone to discuss it and suggest improvements. ๐Ÿ’– if you want to know where it stands officially, check the current edition of the "Internet Official Protocol Standards" (STD 1). and yep, distribution is unlimited, so share away ๐ŸŒˆ

Copyright (C) The Internet Society (1999). All Rights Reserved. ๐Ÿ’œ

Abstract โœจ

okay so the main vibe here is that this memo profiles X.509 v3 certificates and X.509 v2 CRLs so they work for the Internet. ๐Ÿงš it starts with an overview of the approach and the model, then goes deep on the X.509 v3 certificate format, including extra info on how Internet name forms (like IP addresses) get formatted and what they mean. ๐Ÿ“

it describes the standard certificate extensions, defines one brand-new Internet-specific extension, and specifies a required set of certificate extensions. ๐Ÿ‘‘ the X.509 v2 CRL format gets the same treatment, with its own required extension set. then there's an algorithm for certificate path validation, plus supplemental info on how public keys and digital signatures should be formatted for RSA, DSA, and Diffie-Hellman. ๐Ÿฆ‹ the ASN.1 modules and examples live in the appendices. iconic, honestly. ๐Ÿ˜ญ

here's the keyword bit, so you know how to read the requirement words: "The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119." ๐Ÿ™ˆ those capitalised words carry the real weight, so read them carefully.

and if you have feedback, send it to the ietf-pkix@imc.org mail list. ๐Ÿ’Œ


Table of Contents ๐Ÿงพ

TTTTaaaabbbblllleeee ooooffff CCCCoooonnnntttteeeennnnttttssss



   1  Introduction ................................................    5
   2  Requirements and Assumptions ................................    6
   2.1  Communication and Topology ................................    6
   2.2  Acceptability Criteria ....................................    7
   2.3  User Expectations .........................................    7
   2.4  Administrator Expectations ................................    7
   3  Overview of Approach ........................................    7
   3.1  X.509 Version 3 Certificate ...............................    9
   3.2  Certification Paths and Trust .............................   10
   3.3  Revocation ................................................   12
   3.4  Operational Protocols .....................................   13
   3.5  Management Protocols ......................................   13
   4  Certificate and Certificate Extensions Profile ..............   15
   4.1  Basic Certificate Fields ..................................   15
   4.1.1  Certificate Fields ......................................   16
   4.1.1.1  tbsCertificate ........................................   16
   4.1.1.2  signatureAlgorithm ....................................   16
   4.1.1.3  signatureValue ........................................   17
   4.1.2  TBSCertificate ..........................................   17
   4.1.2.1  Version ...............................................   17
   4.1.2.2  Serial number .........................................   18
   4.1.2.3  Signature .............................................   18
   4.1.2.4  Issuer ................................................   18
   4.1.2.5  Validity ..............................................   21
   4.1.2.5.1  UTCTime .............................................   22
   4.1.2.5.2  GeneralizedTime .....................................   22
   4.1.2.6  Subject ...............................................   22
   4.1.2.7  Subject Public Key Info ...............................   23
   4.1.2.8  Unique Identifiers ....................................   24
   4.1.2.9 Extensions .............................................   24
   4.2  Certificate Extensions ....................................   24
   4.2.1  Standard Extensions .....................................   25
   4.2.1.1  Authority Key Identifier ..............................   25
   4.2.1.2  Subject Key Identifier ................................   26
   4.2.1.3  Key Usage .............................................   27
   4.2.1.4  Private Key Usage Period ..............................   29
   4.2.1.5  Certificate Policies ..................................   29
   4.2.1.6  Policy Mappings .......................................   31
   4.2.1.7  Subject Alternative Name ..............................   32
   4.2.1.8  Issuer Alternative Name ...............................   34
   4.2.1.9  Subject Directory Attributes ..........................   34
   4.2.1.10  Basic Constraints ....................................   35
   4.2.1.11  Name Constraints .....................................   35
   4.2.1.12  Policy Constraints ...................................   37
   4.2.1.13  Extended key usage field .............................   38
   4.2.1.14  CRL Distribution Points ..............................   39
   4.2.2  Private Internet Extensions .............................   40
   4.2.2.1  Authority Information Access ..........................   41
   5  CRL and CRL Extensions Profile ..............................   42
   5.1  CRL Fields ................................................   43
   5.1.1  CertificateList Fields ..................................   43
   5.1.1.1  tbsCertList ...........................................   44
   5.1.1.2  signatureAlgorithm ....................................   44
   5.1.1.3  signatureValue ........................................   44
   5.1.2  Certificate List "To Be Signed" .........................   44
   5.1.2.1  Version ...............................................   45
   5.1.2.2  Signature .............................................   45
   5.1.2.3  Issuer Name ...........................................   45
   5.1.2.4  This Update ...........................................   45
   5.1.2.5  Next Update ...........................................   45
   5.1.2.6  Revoked Certificates ..................................   46
   5.1.2.7  Extensions ............................................   46
   5.2  CRL Extensions ............................................   46
   5.2.1  Authority Key Identifier ................................   47
   5.2.2  Issuer Alternative Name .................................   47
   5.2.3  CRL Number ..............................................   47
   5.2.4  Delta CRL Indicator .....................................   48
   5.2.5  Issuing Distribution Point ..............................   48
   5.3  CRL Entry Extensions ......................................   49
   5.3.1  Reason Code .............................................   50
   5.3.2  Hold Instruction Code ...................................   50
   5.3.3  Invalidity Date .........................................   51
   5.3.4  Certificate Issuer ......................................   51
   6  Certificate Path Validation .................................   52
   6.1  Basic Path Validation .....................................   52
   6.2  Extending Path Validation .................................   56
   7  Algorithm Support ...........................................   57
   7.1  One-way Hash Functions ....................................   57
   7.1.1  MD2 One-way Hash Function ...............................   57
   7.1.2  MD5 One-way Hash Function ...............................   58
   7.1.3  SHA-1 One-way Hash Function .............................   58
   7.2  Signature Algorithms ......................................   58
   7.2.1  RSA Signature Algorithm .................................   59
   7.2.2  DSA Signature Algorithm .................................   60
   7.3  Subject Public Key Algorithms .............................   60
   7.3.1  RSA Keys ................................................   61
   7.3.2  Diffie-Hellman Key Exchange Key .........................   61
   7.3.3  DSA Signature Keys ......................................   63
   8  References ..................................................   64
   9  Intellectual Property Rights ................................   66
   10  Security Considerations ....................................   67
   Appendix A.  ASN.1 Structures and OIDs .........................   70
   A.1 Explicitly Tagged Module, 1988 Syntax ......................   70
   A.2 Implicitly Tagged Module, 1988 Syntax ......................   84
   Appendix B.  1993 ASN.1 Structures and OIDs ....................   91
   B.1 Explicitly Tagged Module, 1993 Syntax ......................   91
   B.2 Implicitly Tagged Module, 1993 Syntax ......................  108
   Appendix C.  ASN.1 Notes .......................................  116
   Appendix D.  Examples ..........................................  117
   D.1  Certificate ...............................................  117
   D.2  Certificate ...............................................  120
   D.3  End-Entity Certificate Using RSA ..........................  123
   D.4  Certificate Revocation List ...............................  126
   Appendix E.  Authors' Addresses ................................  128
   Appendix F.  Full Copyright Statement ..........................  129

1. Introduction โœจ

Okay bestie, so this spec is just one piece of a whole family of standards for the X.509 Public Key Infrastructure (PKI) for the Internet ๐Ÿ”. It's a standalone doc though, so implementations can proceed independent from the other parts ๐Ÿ’….

This one profiles the format and semantics of certificates and certificate revocation lists for the Internet PKI ๐ŸŽ€. It also describes procedures for processing certification paths in the Internet environment, gives encoding rules for popular cryptographic algorithms ๐Ÿฆ‹, and has ASN.1 modules in the appendices for all data structures defined or referenced ๐Ÿ’œ.

Section 2 lays out the requirements that inspired this doc and the assumptions that shape its scope ๐ŸŒธ. Section 3 shows the architectural model and how it connects to earlier IETF and ISO/IEC/ITU standards, especially how this doc relates to the IETF PEM specifications and the ISO/IEC/ITU X.509 docs ๐Ÿ‘‘.

Section 4 profiles the X.509 version 3 certificate, and Section 5 does the X.509 version 2 certificate revocation list (CRL) ๐Ÿงš. The profiles also call out ISO/IEC/ITU and ANSI extensions that might be useful in the Internet PKI โœจ. They're written in the 1988 Abstract Syntax Notation One (ASN.1) instead of the 1994 syntax used in the ISO/IEC/ITU standards ๐Ÿ™ˆ.

Section 6 is where the path validation procedures live ๐Ÿ“. They're based on the ISO/IEC/ITU definition, but the presentation assumes one or more self-signed trusted CA certificates. Implementations are required to derive the same results but are not required to use the specified procedures, so you do you as long as your answers match ๐Ÿ’–.

Section 7 describes how to identify and encode public key materials and digital signatures ๐Ÿ”ฅ. Implementations are not required to use any particular cryptographic algorithms. But conforming implementations that do use the identified algorithms are required to identify and encode the public key materials and digital signatures as described ๐Ÿ’….

Finally, there are four appendices to help implementers ๐Ÿซถ. Appendix A has all the ASN.1 structures defined or referenced in this spec, again in the 1988 notation. Appendix B has the same info in the 1994 ASN.1 notation for folks with updated toolsets ๐Ÿ› ๏ธ. Appendix C has notes on the less familiar features of the ASN.1 notation used here ๐ŸŒˆ. Appendix D has examples of a conforming certificate and a conforming CRL ๐Ÿ“œ.

Heads up: if Appendix A and Appendix B ever disagree, Appendix A takes precedence ๐Ÿ’€.

2. Requirements and Assumptions ๐Ÿ’œ

The goal here is to develop a profile that makes X.509 certificates easier to use in Internet applications for communities that want to use X.509 tech ๐Ÿฆ‹. Those apps might include WWW, electronic mail, user authentication, and IPsec ๐Ÿ“ง. To clear some of the obstacles to using X.509 certificates, this doc defines a profile that promotes the development of certificate management systems, application tools, and interoperability determined by policy ๐Ÿ”ง.

Some communities will need to supplement, or maybe even replace, this profile to meet the needs of specialized application domains or environments with extra authorization, assurance, or operational requirements ๐Ÿ™ƒ. But for basic applications, common representations of frequently used attributes are defined, so app devs can get the info they need without caring which issuer made a particular certificate or certificate revocation list (CRL) ๐Ÿ’….

A certificate user should review the certificate policy generated by the certification authority (CA) before relying on the authentication or non-repudiation services tied to the public key in a particular certificate ๐Ÿ‘€. To that end, this standard does not prescribe legally binding rules or duties, so don't go thinking of it as a legal contract ๐Ÿ“œ.

As supplemental authorization and attribute management tools emerge, like attribute certificates, it may be appropriate to limit the authenticated attributes included in a certificate ๐ŸŒฑ. These other management tools may offer better ways to convey many authenticated attributes ๐Ÿงฉ.

2.1. Communication and Topology ๐ŸŒ

The users of certificates will be operating in all kinds of communication topologies, especially users of secure electronic mail ๐Ÿ“ฎ. This profile supports users without high bandwidth, real-time IP connectivity, or high connection availability ๐Ÿ“ถ. It also allows for the presence of firewall or other filtered communication ๐Ÿงฑ.

This profile does not assume that an X.500 Directory system is deployed ๐Ÿ—‚๏ธ. It doesn't prohibit the use of an X.500 Directory, but other means of distributing certificates and certificate revocation lists (CRLs) may be used too ๐Ÿฆ„.

2.2. Acceptability Criteria ๐ŸŽฏ

The goal of the Internet Public Key Infrastructure (PKI) is to meet the needs of deterministic, automated identification, authentication, access control, and authorization functions ๐Ÿค–. The services it supports decide which attributes end up in the certificate, along with the ancillary control info like policy data and certification path constraints ๐Ÿ“‹.

2.3. User Expectations ๐Ÿ™‹

Users of the Internet PKI are people and processes who use client software and are the subjects named in certificates ๐Ÿง‘โ€๐Ÿ’ป. That covers readers and writers of electronic mail, clients for WWW browsers, WWW servers, and the key manager for IPsec within a router ๐Ÿ–ฅ๏ธ. This profile recognizes the limits of the platforms these users run on, and the limits in sophistication and attentiveness of the users themselves ๐Ÿ˜…. So it keeps user configuration responsibility minimal (think trusted CA keys and rules), sets explicit platform usage constraints within the certificate, uses certification path constraints that shield users from many malicious actions ๐Ÿ›ก๏ธ, and has applications sensibly automate validation functions ๐Ÿค–โœจ.

2.4. Administrator Expectations ๐Ÿง‘โ€๐Ÿซ

Same energy as the users: the Internet PKI profile is structured to support the individuals who generally operate CAs ๐Ÿฐ. Giving admins unbounded choices raises the chances that a subtle CA administrator mistake will lead to broad compromise ๐Ÿ’€. Unbounded choices also greatly complicate the software that has to process and validate the certificates the CA creates ๐Ÿ˜ญ.


3. Overview of Approach ๐Ÿ—บ๏ธ

Here's a simplified view of the architectural model assumed by the PKIX specifications ๐Ÿง :

       +---+
       | C |                       +------------+
       | e | <-------------------->| End entity |
       | r |       Operational     +------------+
       | t |       transactions          ^
       |   |      and management         |  Management
       | / |       transactions          |  transactions
       |   |                             |                PKI users
       | C |                             v
       | R |       -------------------+--+-----------+----------------
       | L |                          ^              ^
       |   |                          |              |  PKI management
       |   |                          v              |      entities
       | R |                       +------+          |
       | e | <---------------------| RA   | <---+    |
       | p |  Publish certificate  +------+     |    |
       | o |                                    |    |
       | s |                                    |    |
       | I |                                    v    v
       | t |                                +------------+
       | o | <------------------------------|     CA     |
       | r |   Publish certificate          +------------+
       | y |   Publish CRL                         ^
       |   |                                       |
       +---+                        Management     |
                                    transactions   |
                                                   v
                                               +------+
                                               |  CA  |
                                               +------+

                          Figure 1 - PKI Entities

Here's the cast of characters in this model ๐ŸŽญ:

  • end entity ๐Ÿ™‹: a user of PKI certificates and/or an end user system that is the subject of a certificate;
  • CA ๐Ÿ›๏ธ: the certification authority;
  • RA ๐Ÿ“‹: the registration authority, which is an optional system that a CA hands certain management functions off to;
  • repository ๐Ÿ—„๏ธ: a system or collection of distributed systems that stores certificates and CRLs and acts as the way these certificates and CRLs get distributed to end entities.

3.1. X.509 Version 3 Certificate โœจ

Okay bestie, so anyone using a public key SHALL feel totally sure that the private key really belongs to the correct remote subject (a person or a system) they're about to encrypt for or verify a signature from ๐Ÿ”. That confidence comes from public key certificates, which are data structures that tie public key values to subjects ๐Ÿ’–. A trusted CA digitally signs each certificate to vouch for that binding. The CA MAY base that vouching on technical means (aka proof of possession through a challenge-response protocol), on seeing the private key itself, or on the subject's own assertion ๐Ÿฆ‹. Every certificate has a limited valid lifetime, and that's written right into its signed contents โณ. The iconic part is that a certificate-using client can check the signature and the timeliness on its own, so certs can travel over untrusted communications and server systems and even sit in unsecured storage ๐Ÿ’….

ITU-T X.509 (formerly CCITT X.509), aka ISO/IEC/ITU 9594-8, first dropped in 1988 as part of the X.500 Directory recommendations and defines a standard certificate format [X.509] ๐Ÿ“œ. That original format is the version 1 (v1) format. When X.500 got revised in 1993, two more fields were added, which gave us the version 2 (v2) format. These two fields MAY be used to support directory access control ๐Ÿ”‘.

The Internet Privacy Enhanced Mail (PEM) RFCs, published in 1993, include specs for a public key infrastructure built on X.509 v1 certificates [RFC 1422] ๐ŸŒธ. Trying to actually deploy RFC 1422 made it painfully clear that the v1 and v2 formats are deficient in several respects ๐Ÿ˜ญ. The biggest issue was that more fields were needed to carry information that PEM design and implementation experience had proven necessary. So ISO/IEC/ITU and ANSI X9 developed the X.509 version 3 (v3) certificate format to fix that ๐Ÿ”ฅ. The v3 format extends v2 by adding provision for additional extension fields. Particular extension field types MAY be specified in standards or MAY be defined and registered by any organization or community ๐ŸŒˆ. In June 1996, standardization of the basic v3 format was completed [X.509] ๐ŸŽ‰.

ISO/IEC/ITU and ANSI X9 have also developed standard extensions for use in the v3 extensions field [X.509][X9.55] โœจ. These extensions can convey things like additional subject identification information, key attribute information, policy information, and certification path constraints ๐Ÿงš.

Here's the catch, though: the ISO/IEC/ITU and ANSI X9 standard extensions are very broad in their applicability ๐Ÿ™ˆ. To build interoperable X.509 v3 implementations for Internet use, you need to specify a profile for using those extensions that's tailored for the Internet ๐Ÿ‘‘. That's one of the main goals of this document: to specify a profile for Internet WWW, electronic mail, and IPsec applications ๐Ÿ’œ. Environments with extra requirements MAY build on this profile or MAY replace it entirely ๐Ÿซถ.

3.2. Certification Paths and Trust ๐Ÿ›ค๏ธ

A user of a security service who needs to know a public key usually has to obtain and validate a certificate that contains the required public key ๐Ÿ’…. If that public key user doesn't already hold an assured copy of the signing CA's public key, the CA's name, and related info (like the validity period or name constraints), then they might need an extra certificate to get that public key ๐Ÿ”. In general, you may need a chain of multiple certificates: the end entity's certificate, signed by one CA, plus zero or more certificates of CAs signed by other CAs ๐Ÿ”—. These chains are called certification paths, and they're needed because a public key user is only initialized with a limited number of assured CA public keys ๐Ÿ’–.

There are different ways CAs might be configured so public key users can find certification paths ๐Ÿ—บ๏ธ. For PEM, RFC 1422 defined a rigid hierarchical structure of CAs. There are three types of PEM certification authority:

  • (a) Internet Policy Registration Authority (IPRA): This authority, operated under the auspices of the Internet Society, acts as the root of the PEM certification hierarchy at level 1. It issues certificates only for the next level of authorities, PCAs. All certification paths start with the IPRA ๐Ÿ‘‘.
  • (b) Policy Certification Authorities (PCAs): PCAs sit at level 2 of the hierarchy, and each PCA is certified by the IPRA. A PCA SHALL establish and publish a statement of its policy regarding certifying users or subordinate certification authorities ๐Ÿ“‹. Distinct PCAs aim to satisfy different user needs. For example, one PCA (an organizational PCA) might support the general electronic mail needs of commercial organizations, while another PCA (a high-assurance PCA) might have a stricter policy built for legally binding digital signature requirements โœ๏ธ.
  • (c) Certification Authorities (CAs): CAs are at level 3 of the hierarchy and can also be at lower levels. The ones at level 3 are certified by PCAs. CAs represent things like particular organizations, particular organizational units (e.g., departments, groups, sections), or particular geographical areas ๐ŸŒ.

RFC 1422 also has a name subordination rule, which says a CA can only issue certificates for entities whose names are subordinate (in the X.500 naming tree) to the CA's own name ๐ŸŒณ. The trust associated with a PEM certification path is implied by the PCA name ๐Ÿฆ‹. The name subordination rule keeps CAs below the PCA sensibly constrained as to which subordinate entities they can certify. For instance, a CA for an organization can only certify entities in that organization's name tree ๐Ÿข. Certificate user systems can mechanically check that the name subordination rule was followed ๐Ÿค–.

RFC 1422 uses the X.509 v1 certificate formats, and v1's limitations meant it needed several structural restrictions to clearly associate policy information or restrict how certificates could be used ๐Ÿ™ƒ. Those restrictions were:

  • (a) a pure top-down hierarchy, with all certification paths starting from IPRA;
  • (b) a naming subordination rule restricting the names of a CA's subjects; and
  • (c) use of the PCA concept, which requires knowledge of individual PCAs to be built into certificate chain verification logic. Knowing about individual PCAs was required to decide whether a chain could be accepted ๐Ÿ˜ตโ€๐Ÿ’ซ.

With X.509 v3, most of the requirements RFC 1422 addressed can be handled using certificate extensions, without having to restrict the CA structures used ๐Ÿ™Œ. Specifically, the certificate extensions for certificate policies make PCAs unnecessary, and the constraint extensions make the name subordination rule unnecessary ๐ŸŽ‰. So this document supports a more flexible architecture, including:

  • (a) Certification paths MAY start with the public key of a CA in a user's own domain, or with the public key of the top of a hierarchy. Starting with a CA in your own domain has real advantages, because in some environments the local domain is the most trusted ๐Ÿ .
  • (b) Name constraints MAY be imposed through explicit inclusion of a name constraints extension in a certificate, but they are not required ๐Ÿงฉ.
  • (c) Policy extensions and policy mappings replace the PCA concept, which allows a greater degree of automation. The application can decide whether a certification path is acceptable based on the contents of the certificates, instead of needing a priori knowledge of PCAs. That's what makes automating certificate chain processing possible ๐Ÿค–โœจ.

3.3. Revocation ๐Ÿšซ

When a certificate is issued, it's expected to be in use for its entire validity period ๐Ÿ“…. But various circumstances can make a certificate invalid before that period ends, like a change of name, a change in the association between subject and CA (e.g., an employee leaves an organization), or a compromise or suspected compromise of the corresponding private key ๐Ÿ˜ฑ. When that happens, the CA needs to revoke the certificate ๐Ÿ›‘.

X.509 defines one method of certificate revocation ๐Ÿ”. It works like this: each CA periodically issues a signed data structure called a certificate revocation list (CRL) ๐Ÿ“ƒ. A CRL is a time-stamped list identifying revoked certificates, signed by a CA and made freely available in a public repository ๐ŸŒ. Each revoked certificate is identified in a CRL by its certificate serial number ๐Ÿ”ข. When a certificate-using system uses a certificate (e.g., to verify a remote user's digital signature), it doesn't just check the certificate's signature and validity. It also acquires a suitably recent CRL and checks that the certificate's serial number isn't on that CRL โœ…. What counts as "suitably recent" may vary with local policy, but it usually means the most recently issued CRL ๐Ÿ—“๏ธ. A CA issues a new CRL on a regular periodic basis (e.g., hourly, daily, or weekly) โฐ. A new revocation gets added to the CRL as part of the next update after notification of the revocation. An entry MAY be removed from the CRL after it has appeared on one regularly scheduled CRL issued beyond the revoked certificate's validity period ๐Ÿงน.

A big perk of this revocation method is that CRLs can be distributed by exactly the same means as certificates themselves, namely via untrusted communications and server systems ๐Ÿฅณ.

The catch with the CRL method, when using untrusted communications and servers, is that the time granularity of revocation is limited to the CRL issue period ๐Ÿ˜ฌ. Say a revocation is reported right now: it won't be reliably notified to certificate-using systems until the next periodic CRL is issued. That could be up to one hour, one day, or one week, depending on how often the CA issues CRLs ๐Ÿข.

Just like with the X.509 v3 certificate format, the X.509 v2 CRL format needs to be profiled for Internet use so implementations from different vendors work together ๐Ÿค. That's another goal of this document: to specify that profile. However, this profile does NOT require CAs to issue CRLs (wait, keep it lowercase, see below). Message formats and protocols that support on-line revocation notification MAY be defined in other PKIX specifications ๐Ÿ“ก. On-line methods of revocation notification MAY be applicable in some environments as an alternative to the X.509 CRL ๐Ÿ’ป. On-line revocation checking may significantly reduce the latency between a revocation report and the distribution of that information to relying parties โšก. Once the CA accepts the report as authentic and valid, any query to the on-line service will correctly reflect the certificate validation impacts of the revocation ๐ŸŽฏ. But these methods come with new security requirements: the certificate validator SHALL trust the on-line validation service, while the repository does not need to be trusted ๐Ÿ”๐Ÿ’€.

3.4 Operational Protocols

Okay so, operational protocols are the delivery squad ๐Ÿššโœจ They get certificates and CRLs (or status info) to the client systems that need them. There are a bunch of ways to deliver them, including LDAP, HTTP, FTP, and X.500, and the other PKIX specs define the protocols that make each of those work. Those specs can also define message formats and procedures for all of these environments, plus the MIME content types that go with them ๐ŸŽ€

3.5 Management Protocols

Management protocols are how PKI users and management entities chat with each other online ๐Ÿ’ฌ Picture a CA talking to a client system that holds a key pair, or two CAs cross-certifying each other ๐Ÿฆ‹ These are the functions management protocols could need to support:

  • (a) registration: a user first introduces itself to a CA, either directly or through an RA, before that CA issues any certificate for that user ๐Ÿซถ
  • (b) initialization: before a client system can operate securely, it needs key materials that have the right relationship with keys stored elsewhere in the infrastructure ๐Ÿ” For example, the client has to be securely set up with the public key and other assured information of the trusted CA(s), so it can validate certificate paths. A client also usually needs its own key pair(s) to get started.
  • (c) certification: a CA issues a certificate for a user's public key, then hands that certificate back to the user's client system and/or posts it in a repository ๐Ÿ“ฎ
  • (d) key pair recovery: optionally, a user's client key materials (for example, a private key used for encryption) can be backed up by a CA or a key backup system. If the user needs those backed-up materials again (say they forgot a password or lost a key chain file), an online protocol exchange may be needed to make that recovery happen ๐Ÿ™ˆ
  • (e) key pair update: every key pair needs to be refreshed regularly, meaning it gets replaced with a new key pair and new certificates are issued ๐Ÿ”„
  • (f) revocation request: an authorized person tells a CA about an abnormal situation that calls for certificate revocation ๐Ÿšจ
  • (g) cross-certification: two CAs swap the information they need to set up a cross-certificate. A cross-certificate is a certificate that one CA issues to another CA, and it contains a CA signature key used for issuing certificates ๐Ÿ‘‘

Here's the tea โ˜• online protocols aren't the only way to do any of this. Every one of these functions has an offline method that gets the same result, and this spec does not mandate online protocols. With hardware tokens, for example, a lot of these functions can happen during the physical token delivery ๐Ÿ“ฆ Some functions can also be merged into one protocol exchange, and two or more of registration, initialization, and certification can be combined into a single exchange ๐Ÿ’…

The PKIX series may define a set of standard message formats for these functions in future specs. If that happens, those specs will also describe how the messages get carried in different environments, such as online, file transfer, e-mail, and WWW ๐ŸŒˆ


4 Certificate and Certificate Extensions Profile ๐ŸŽ€

This section is a profile for public key certificates that's meant to keep things interoperable and make a PKI reusable โ™ป๏ธ It's built on the X.509 v3 certificate format and the standard certificate extensions defined in [X.509]. The ISO/IEC/ITU docs use the 1993 version of ASN.1, while this document uses the 1988 ASN.1 syntax. The encoded certificate and standard extensions still come out equivalent ๐Ÿค“ This section also defines private extensions needed to support a PKI for the Internet community ๐ŸŒธ

Certificates can show up in a wild range of applications and environments, with all kinds of interoperability goals and even more operational and assurance requirements ๐Ÿงš The aim here is a common baseline for generic applications that need broad interoperability and only a few special-purpose requirements. The main focus is supporting X.509 v3 certificates for informal Internet electronic mail, IPsec, and WWW applications ๐Ÿ’–

4.1 Basic Certificate Fields

Here's the basic syntax for an X.509 v3 certificate ๐Ÿ’… When the signature gets calculated, the certificate is encoded using the ASN.1 distinguished encoding rules (DER) [X.208]. ASN.1 DER is a tag, length, value encoding system applied to each element โœจ

   Certificate  ::=  SEQUENCE  {
        tbsCertificate       TBSCertificate,
        signatureAlgorithm   AlgorithmIdentifier,
        signatureValue       BIT STRING  }

   TBSCertificate  ::=  SEQUENCE  {
        version         [0]  EXPLICIT Version DEFAULT v1,
        serialNumber         CertificateSerialNumber,
        signature            AlgorithmIdentifier,
        issuer               Name,
        validity             Validity,
        subject              Name,
        subjectPublicKeyInfo SubjectPublicKeyInfo,
        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
                             -- If present, version shall be v2 or v3
        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
                             -- If present, version shall be v2 or v3
        extensions      [3]  EXPLICIT Extensions OPTIONAL
                             -- If present, version shall be v3
        }

   Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }

   CertificateSerialNumber  ::=  INTEGER

   Validity ::= SEQUENCE {
        notBefore      Time,
        notAfter       Time }

   Time ::= CHOICE {
        utcTime        UTCTime,
        generalTime    GeneralizedTime }

   UniqueIdentifier  ::=  BIT STRING

   SubjectPublicKeyInfo  ::=  SEQUENCE  {
        algorithm            AlgorithmIdentifier,
        subjectPublicKey     BIT STRING  }

   Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension

   Extension  ::=  SEQUENCE  {
        extnID      OBJECT IDENTIFIER,
        critical    BOOLEAN DEFAULT FALSE,
        extnValue   OCTET STRING  }

Here's what the rest of this section covers for the X.509 v3 certificate on the Internet ๐Ÿ‘€

4.1.1 Certificate Fields

A Certificate is a SEQUENCE with three required fields ๐Ÿซง Each one gets its own detailed subsection below.

4.1.1.1 tbsCertificate

This field holds the names of the subject and issuer, a public key tied to the subject, a validity period, and other associated info ๐Ÿ—‚๏ธ The details are in section 4.1.2. The tbscertificate can also include extensions, which are described in section 4.2 ๐ŸŒท

4.1.1.2 signatureAlgorithm

This is where the identifier for the cryptographic algorithm the CA used to sign this certificate lives ๐Ÿ” Section 7.2 lists the supported signature algorithms.

An algorithm identifier is defined by this ASN.1 structure:

   AlgorithmIdentifier  ::=  SEQUENCE  {
        algorithm               OBJECT IDENTIFIER,
        parameters              ANY DEFINED BY algorithm OPTIONAL  }

The algorithm identifier is what names a cryptographic algorithm. The OBJECT IDENTIFIER part identifies the algorithm (DSA with SHA-1 is an example). The optional parameters field changes depending on which algorithm it's pointing at ๐Ÿงฉ Section 7.2 lists the supported algorithms for this spec.

This field MUST contain the same algorithm identifier as the signature field in the sequence tbsCertificate (see sec. 4.1.2.3) ๐Ÿ’œ

4.1.1.3 signatureValue

This field holds a digital signature computed over the ASN.1 DER encoded tbsCertificate. That encoded tbsCertificate is what gets fed into the signature function ๐Ÿ–Š๏ธ The signature value is then ASN.1 encoded as a BIT STRING and placed in the Certificate's signature field. Section 7.2 has the details for each supported algorithm.

By generating this signature, a CA vouches for the information in the tbsCertificate field ๐Ÿซถ Most importantly, the CA certifies the binding between the public key material and the subject of the certificate.

4.1.2 TBSCertificate

The TBSCertificate sequence holds info about the certificate's subject and the CA that issued it ๐ŸŒŸ Every TBSCertificate includes the names of the subject and issuer, a public key for the subject, a validity period, a version number, and a serial number. Some may also have optional unique identifier fields. The rest of this section explains the syntax and semantics of those fields. A TBSCertificate can also include extensions, and the ones for the Internet PKI are described in Section 4.2 ๐Ÿฆ‹

4.1.2.1 Version

This field says which version of the encoded certificate you're looking at ๐Ÿ”ข When extensions are used, which this profile expects, use X.509 version 3 (value is 2). If there are no extensions but a UniqueIdentifier is present, use version 2 (value is 1). If only basic fields are present, use version 1. In that case the value is left out of the certificate because it's the default value ๐Ÿ™ˆ

Implementations SHOULD be prepared to accept any version certificate. At a minimum, conforming implementations MUST recognize version 3 certificates ๐Ÿซง

Implementations based on this profile aren't expected to generate version 2 certificates ๐Ÿšซ

4.1.2.2 Serial number

The serial number is an integer the CA assigns to each certificate ๐Ÿ”ข It MUST be unique for each certificate a given CA issues, because the issuer name and serial number together identify one unique certificate ๐Ÿชช

4.1.2.3 Signature

This field holds the algorithm identifier for the algorithm the CA used to sign the certificate โœ๏ธ

This field MUST contain the same algorithm identifier as the signatureAlgorithm field in the sequence Certificate (see sec. 4.1.1.2). The optional parameters field changes depending on the algorithm identified. Section 7.2 lists the supported signature algorithms ๐Ÿ’…

4.1.2.4. Issuer ๐ŸŽ€

okay bestie, the issuer field tells you who signed and issued the certificate ๐Ÿ’… It MUST contain a non-empty distinguished name (DN), and it's defined as the X.501 type Name [X.501]. The Name is described by these ASN.1 structures:

Name ::= CHOICE {
  RDNSequence }

RDNSequence ::= SEQUENCE OF RelativeDistinguishedName

RelativeDistinguishedName ::=
  SET OF AttributeTypeAndValue

AttributeTypeAndValue ::= SEQUENCE {
  type     AttributeType,
  value    AttributeValue }

AttributeType ::= OBJECT IDENTIFIER

AttributeValue ::= ANY DEFINED BY AttributeType
DirectoryString ::= CHOICE {
      teletexString           TeletexString (SIZE (1..MAX)),
      printableString         PrintableString (SIZE (1..MAX)),
      universalString         UniversalString (SIZE (1..MAX)),
      utf8String              UTF8String (SIZE (1.. MAX)),
      bmpString               BMPString (SIZE (1..MAX)) }

So a Name is a hierarchical name made of attributes, like country name โžก๏ธ US. The type of each AttributeValue depends on its AttributeType, and it's usually a DirectoryString ๐ŸŒธ

DirectoryString is a choice of PrintableString, TeletexString, BMPString, UTF8String, and UniversalString. UTF8String is the preferred encoding ๐Ÿ‘‘ All certificates issued after December 31, 2003 MUST use the UTF8String encoding of DirectoryString (except as noted below). Until that date, conforming CAs MUST choose from these options when creating a distinguished name, including their own:

  • (a) if the character set is sufficient, the string MAY be represented as a PrintableString;
  • (b) failing (a), if the BMPString character set is sufficient the string MAY be represented as a BMPString; and
  • (c) failing (a) and (b), the string MUST be represented as a UTF8String. If (a) or (b) is satisfied, the CA MAY still choose to represent the string as a UTF8String.

There are exceptions to the December 31, 2003 UTF8 rule ๐Ÿฆ‹

  • (a) CAs MAY issue "name rollover" certificates to support an orderly migration to UTF8String encoding. Such certificates would include the CA's UTF8String encoded name as issuer and and the old name encoding as subject, or vice-versa.
  • (b) As stated in section 4.1.2.6, the subject field MUST be populated with a non-empty distinguished name matching the contents of the issuer field in all certificates issued by the subject CA regardless of encoding.

TeletexString and UniversalString are only there for backward compatibility, so they should not be used for certificates for new subjects. They're still fine in certificates where the name was already established, though, and certificate users SHOULD be prepared to receive certificates with these types ๐Ÿงš

Also, a lot of legacy implementations store names in the ISO 8859-1 character set (Latin1String) but tag them as TeletexString ๐Ÿ™ˆ Latin1String has characters used in Western European countries that aren't part of the TeletexString character set. Implementations that process TeletexString SHOULD be prepared to handle the entire ISO 8859-1 character set [ISO 8859-1].

As mentioned, distinguished names are made of attributes. This specification doesn't restrict which attribute types can appear in names ๐Ÿ’œ But conforming implementations MUST be prepared to receive certificates with issuer names containing the set of attribute types defined below. This specification also recommends support for additional attribute types.

Standard attribute sets are defined in the X.500 series of specifications [X.520]. Implementations of this specification MUST be prepared to receive these standard attribute types in issuer names: country, organization, organizational-unit, distinguished name qualifier, state or province name, and common name (e.g., "Susan Housley"). Implementations of this specification SHOULD also be prepared to receive these standard attribute types in issuer names: locality, title, surname, given name, initials, and generation qualifier (e.g., "Jr.", "3rd", or "IV"). The syntax and associated object identifiers (OIDs) for these attribute types are in the ASN.1 modules in Appendices A and B โœจ

Implementations of this specification MUST also be prepared to receive the domainComponent attribute, as defined in [RFC 2247]. DNS (the Domain (Nameserver) System) is a hierarchical resource labeling system. This attribute is a convenient way for organizations that want DNs that parallel their DNS names. It is not a replacement for the dNSName component of the alternative name field. Implementations are not required to convert such names into DNS names. The syntax and associated OID for this attribute type are in the ASN.1 modules in Appendices A and B.

Certificate users MUST be prepared to process the issuer distinguished name and subject distinguished name (see sec. 4.1.2.6) fields so they can do name chaining for certification path validation (see section 6). Name chaining works by matching the issuer distinguished name in one certificate with the subject name in a CA certificate. ๐Ÿ”ฅ

This specification only requires a subset of the name comparison functionality from the X.500 series. Conforming implementations follow these requirements:

  • (a) attribute values encoded in different types (e.g., PrintableString and BMPString) may be assumed to represent different strings;
  • (b) attribute values in types other than PrintableString are case sensitive (this permits matching of attribute values as binary objects);
  • (c) attribute values in PrintableString are not case sensitive (e.g., "Marianne Swanson" is the same as "MARIANNE SWANSON"); and
  • (d) attribute values in PrintableString are compared after removing leading and trailing white space and converting internal substrings of one or more consecutive white space characters to a single space.

These name comparison rules let a certificate user validate certificates issued using languages or encodings they don't recognize ๐ŸŒˆ

Implementations of this specification MAY also use these comparison rules to process unfamiliar attribute types for name chaining. This lets implementations handle certificates with unfamiliar attributes in the issuer name ๐Ÿซถ

Heads up: the X.500 comparison rules say the character sets used to encode data in distinguished names don't matter. The characters themselves are compared without regard to encoding. Implementations of the profile are allowed to use the X.500 comparison algorithm. Such an implementation will recognize a superset of the name matches recognized by the algorithm specified above ๐Ÿ’–


4.1.2.5. Validity โณ

The certificate validity period is the time interval during which the CA promises that it will maintain information about the certificate's status. The field is a SEQUENCE of two dates: the date the validity period begins (notBefore) and the date it ends (notAfter). Both notBefore and notAfter may be encoded as UTCTime or GeneralizedTime ๐Ÿฆ‹

CAs conforming to this profile MUST always encode certificate validity dates through the year 2049 as UTCTime. Certificate validity dates in 2050 or later MUST be encoded as GeneralizedTime ๐Ÿ˜ญ

4.1.2.5.1. UTCTime ๐Ÿ•ฐ๏ธ

UTCTime is a standard ASN.1 type meant for international applications where local time alone isn't enough. It specifies the year using the two low order digits, and time is given to the precision of one minute or one second. UTCTime includes either Z (for Zulu, or Greenwich Mean Time) or a time differential.

For this profile, UTCTime values MUST be expressed in Greenwich Mean Time (Zulu) and MUST include seconds (i.e., times are YYMMDDHHMMSSZ), even when the number of seconds is zero. Conforming systems MUST interpret the year field (YY) as follows:

  • Where YY is greater than or equal to 50, the year shall be interpreted as 19YY; and
  • Where YY is less than 50, the year shall be interpreted as 20YY.

4.1.2.5.2. GeneralizedTime ๐ŸŒธ

GeneralizedTime is a standard ASN.1 type for variable precision representation of time. Optionally, the GeneralizedTime field can include a representation of the time differential between local time and Greenwich Mean Time.

For this profile, GeneralizedTime values MUST be expressed in Greenwich Mean Time (Zulu) and MUST include seconds (i.e., times are YYYYMMDDHHMMSSZ), even when the number of seconds is zero. GeneralizedTime values MUST NOT include fractional seconds โœจ

4.1.2.6. Subject ๐Ÿซถ

Okay bestie, the subject field tells you who owns the public key sitting in the subject public key field ๐Ÿ”‘. The name can live in the subject field, in the subjectAltName extension, or in both ๐Ÿ’–. If the subject is a CA (like when the basic constraints extension from sec. 4.2.1.10 is there and cA is TRUE ๐Ÿ‘‘), then the subject field MUST be filled with a non-empty distinguished name that matches the issuer field (sec. 4.1.2.4) on every certificate that CA issues ๐ŸŽ€. And if the only naming info is in subjectAltName (think a key tied to just an email or URI ๐Ÿ“ง), then the subject name MUST be an empty sequence and the subjectAltName extension MUST be critical ๐Ÿ’….

When it isn't empty, the subject field MUST contain an X.500 distinguished name (DN) ๐ŸŒธ. That DN MUST be unique for each subject entity certified by one CA, and the issuer name field is what defines the "one CA" part โœจ. A CA can still issue more than one certificate with the same DN to the same subject entity, no cap ๐Ÿงš.

The subject name field is the X.501 type Name ๐Ÿง . The implementation rules are the same ones defined for the issuer field (see sec. 4.1.2.4). When encoding DirectoryString attribute values, the issuer field's encoding rules MUST be implemented ๐Ÿ’œ. Implementations MUST be prepared to receive subject names with the attribute types required for the issuer field, and SHOULD be prepared for the recommended ones too ๐Ÿฆ‹. The syntax and OIDs for these attribute types live in the ASN.1 modules in Appendices A and B ๐Ÿ“š. Implementations MAY use these comparison rules to process unfamiliar attribute types (for name chaining), which means they can handle certificates with weird attributes in the subject name ๐Ÿ™ˆ.

Legacy alert! Some older implementations stuff an RFC 822 name into the subject DN as an EmailAddress attribute ๐Ÿ“ฎ. That value is an IA5String so it can include the '@' character, which isn't in PrintableString. EmailAddress values are not case sensitive, so "fanfeedback@redsox.com" is the same as "FANFEEDBACK@REDSOX.COM" ๐Ÿ˜ญ.

Conforming implementations making new certificates with email addresses MUST use the rfc822Name in the subject alternative name field (see sec. 4.2.1.7) to describe those identities ๐Ÿ“ฌ. Putting the EmailAddress attribute in the subject DN too, to support legacy implementations, is deprecated but still permitted ๐Ÿฅ€.

4.1.2.7. Subject Public Key Info ๐Ÿ”‘

This field carries the public key and tells you which algorithm it's used with ๐ŸŽฏ. The algorithm is identified with the AlgorithmIdentifier structure from section 4.1.1.2. The OIDs for the supported algorithms, plus the methods for encoding the public key material (public key and parameters), are in section 7.3 ๐Ÿ“–.

4.1.2.8. Unique Identifiers ๐Ÿชช

These fields can only show up if the version is 2 or 3 (see sec. 4.1.2.1) ๐Ÿ“. The subject and issuer unique identifiers exist to handle the possibility that subject and/or issuer names get reused over time ๐Ÿ”. This profile recommends that names not be reused for different entities, and that Internet certificates not use unique identifiers at all ๐Ÿ™…โ€โ™€๏ธ. CAs conforming to this profile SHOULD NOT generate certificates with unique identifiers. Applications conforming to this profile SHOULD be capable of parsing unique identifiers and making comparisons with them ๐Ÿซง.

4.1.2.9. Extensions ๐ŸŽ

This field can only show up if the version is 3 (see sec. 4.1.2.1) ๐ŸŒˆ. When it's there, it's a SEQUENCE of one or more certificate extensions. The format and content of those extensions in the Internet PKI are defined in section 4.2 โœจ.

4.2. Standard Certificate Extensions ๐Ÿ‘‘

Extensions are the secret sauce of X.509 v3 ๐Ÿง. They let you attach extra attributes to users or public keys and manage the certification hierarchy ๐ŸŒณ. Communities are also allowed to define private extensions for their own special info ๐Ÿฆ‹. Every extension in a certificate can be marked critical or non-critical ๐Ÿšฆ. A certificate-using system MUST reject the certificate if it runs into a critical extension it doesn't recognize ๐Ÿ™…โ€โ™€๏ธ. A non-critical extension, though, may be ignored if it's not recognized ๐Ÿซถ.

The sections that follow list the recommended extensions for Internet certificates, plus the standard places to put info ๐Ÿ“. Communities can use extra extensions if they want, but be careful adopting any critical ones, because they might stop the cert from working in a general context ๐Ÿ˜ฌ.

Each extension has an OID and an ASN.1 structure ๐Ÿงฉ. When an extension shows up in a certificate, the OID is the field extnID, and the ASN.1 encoded structure is the value of the octet string extnValue ๐Ÿ’œ. Only one instance of a particular extension can appear in a given certificate. For example, a certificate can only have one authority key identifier extension (see sec. 4.2.1.1) ๐Ÿ™ƒ. An extension also has a boolean critical with a default value of FALSE, and each extension's text spells out which values are acceptable for that field ๐Ÿ“.

Conforming CAs MUST support the key identifier (see sec. 4.2.1.1 and 4.2.1.2), basic constraints (see sec. 4.2.1.10), key usage (see sec. 4.2.1.3), and certificate policies (see sec. 4.2.1.5) extensions ๐Ÿ”. If a CA issues certificates with an empty sequence for the subject field, that CA MUST support the subject alternative name extension (see sec. 4.2.1.7) ๐Ÿ“ง. Support for the remaining extensions is OPTIONAL ๐ŸŒท. Conforming CAs may support extensions that aren't identified in this specification, but certificate issuers should know that marking those as critical may hurt interoperability ๐Ÿšง.

At a minimum, applications conforming to this profile MUST recognize the extensions that must or may be critical in this specification ๐Ÿง. Those are: key usage (see sec. 4.2.1.3), certificate policies (see sec. 4.2.1.5), the subject alternative name (see sec. 4.2.1.7), basic constraints (see sec. 4.2.1.10), name constraints (see sec. 4.2.1.11), policy constraints (see sec. 4.2.1.12), and extended key usage (see sec. 4.2.1.13) ๐ŸŽ€.

On top of that, this profile RECOMMENDS that applications support the authority and subject key identifier extensions (see sec. 4.2.1.1 and 4.2.1.2) ๐Ÿ’–.

4.2.1. Standard Extensions โญ

This section names the standard certificate extensions defined in [X.509] for use in the Internet PKI ๐Ÿ“œ. Each extension has an OID defined in [X.509]. These OIDs belong to the id-ce arc, which is defined like this ๐ŸŒธ:

id-ce   OBJECT IDENTIFIER ::=  {joint-iso-ccitt(2) ds(5) 29}

4.2.1.1. Authority Key Identifier ๐Ÿ”‘

The authority key identifier extension tells you which public key matches the private key that signed a certificate ๐Ÿ–Š๏ธ. It's used when an issuer has multiple signing keys, whether from several concurrent key pairs or from a changeover ๐Ÿ”„. The identification can be based on either the key identifier (the subject key identifier in the issuer's certificate), or on the issuer name and serial number ๐Ÿชช.

The keyIdentifier field of the authorityKeyIdentifier extension MUST be included in all certificates generated by conforming CAs so chain building works smoothly ๐Ÿงฉ. There's one exception: when a CA hands out its public key in a "self-signed" certificate, the authority key identifier can be left out. In that case, the subject and authority key identifiers would be identical ๐Ÿชž.

The value of the keyIdentifier field SHOULD be derived from the public key used to verify the certificate's signature, or from a method that makes unique values ๐Ÿ”. Two common methods for making key identifiers from the public key are described in (sec. 4.2.1.2). One common method for making unique values is also described in (sec. 4.2.1.2). If there's no key identifier established yet, this specification recommends using one of these methods to generate keyIdentifier values ๐Ÿ’….

This profile recommends that all certificate users support the key identifier method ๐Ÿซถ.

This extension MUST NOT be marked critical ๐Ÿšซ.

id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 }

AuthorityKeyIdentifier ::= SEQUENCE {
      keyIdentifier             [0] KeyIdentifier           OPTIONAL,
      authorityCertIssuer       [1] GeneralNames            OPTIONAL,
      authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL  }

KeyIdentifier ::= OCTET STRING

4.2.1.2. Subject Key Identifier ๐Ÿฆ‹

The subject key identifier extension is how you identify certificates that contain a particular public key ๐Ÿ†”.

To help with chain building, this extension MUST appear in all conforming CA certificates. That means every certificate that includes the basic constraints extension (see sec. 4.2.1.10) where cA is TRUE ๐Ÿ‘‘. The value of the subject key identifier MUST be the value placed in the key identifier field of the Authority Key Identifier extension (see sec. 4.2.1.1) of certificates issued by the subject of this certificate ๐Ÿ”—.

For CA certificates, subject key identifiers SHOULD be derived from the public key, or from a method that makes unique values ๐Ÿง . Two common methods for making key identifiers from the public key are:

  1. The keyIdentifier is made of the 160-bit SHA-1 hash of the value of the BIT STRING subjectPublicKey (not counting the tag, the length, or the number of unused bits) ๐Ÿฐ.
  2. The keyIdentifier is made of a four bit type field with the value 0100, followed by the least significant 60 bits of the SHA-1 hash of the value of the BIT STRING subjectPublicKey โœจ.

One common method for making unique values is a monotonically increasing sequence of integers ๐Ÿ”ข.

For end entity certificates, the subject key identifier extension helps identify certificates containing the particular public key an application uses ๐Ÿ“ฑ. If an end entity has gotten multiple certificates, especially from multiple CAs, the subject key identifier lets you quickly find the set of certificates holding that public key ๐Ÿ”Ž. To help applications identify the right end entity certificate, this extension SHOULD be included in all end entity certificates ๐ŸŽฏ.

For end entity certificates, subject key identifiers SHOULD be derived from the public key. Two common methods for making key identifiers from the public key are identified above ๐Ÿ™Œ.

If there's no key identifier established yet, this specification recommends using one of these methods to generate keyIdentifier values ๐Ÿ’œ.

This extension MUST NOT be marked critical ๐Ÿšซ.

id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 14 }

SubjectKeyIdentifier ::= KeyIdentifier

4.2.1.3 Key Usage โœจ

okay so the key usage extension tells everyone what a key is actually allowed to do ๐Ÿ’… like encipherment, signing, or signing certificates. ๐ŸŽ€ It's super useful when a key could do a bunch of stuff but you want to lock it down to just one job. For example, if an RSA key should only be used for signing, you'd set the digitalSignature and/or nonRepudiation bits. ๐Ÿฆ‹ And if that RSA key is only for key management, the keyEncipherment bit gets asserted instead. When this extension is used, it SHOULD be marked critical ๐Ÿ”ฅ

   id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }

   KeyUsage ::= BIT STRING {
        digitalSignature        (0),
        nonRepudiation          (1),
        keyEncipherment         (2),
        dataEncipherment        (3),
        keyAgreement            (4),
        keyCertSign             (5),
        cRLSign                 (6),
        encipherOnly            (7),
        decipherOnly            (8) }

okay now let's talk about what each bit actually means ๐Ÿงš

The digitalSignature bit is asserted when the subject public key is used with a digital signature mechanism for security services other than non-repudiation (bit 1), certificate signing (bit 5), or revocation information signing (bit 6). ๐ŸŒธ These are often used for entity authentication and data origin authentication with integrity. iykyk ๐Ÿ™ˆ

The nonRepudiation bit is asserted when the subject public key verifies digital signatures that give a non-repudiation service, which protects against the signing entity falsely denying some action, excluding certificate or CRL signing. ๐Ÿ’œ

The keyEncipherment bit is asserted when the subject public key is used for key transport. For example, when an RSA key is to be used for key management, then this bit shall asserted. ๐Ÿ”‘

The dataEncipherment bit is asserted when the subject public key is used for enciphering user data, other than cryptographic keys. ๐Ÿ“

The keyAgreement bit is asserted when the subject public key is used for key agreement. For example, when a Diffie-Hellman key is to be used for key management, then this bit shall asserted. โœจ

The keyCertSign bit is asserted when the subject public key is used for verifying a signature on certificates. This bit may only be asserted in CA certificates. ๐Ÿ‘‘

The cRLSign bit is asserted when the subject public key is used for verifying a signature on revocation information (e.g., a CRL). ๐Ÿซถ

The meaning of the encipherOnly bit is undefined in the absence of the keyAgreement bit. When encipherOnly is asserted and keyAgreement is also set, the subject public key may be used only for enciphering data while performing key agreement. ๐ŸŒˆ

The meaning of the decipherOnly bit is undefined in the absence of the keyAgreement bit. When decipherOnly is asserted and keyAgreement is also set, the subject public key may be used only for deciphering data while performing key agreement. ๐Ÿฆ‹

This profile does not restrict the combinations of bits that may be set in an instantiation of the keyUsage extension. ๐Ÿ’… However, appropriate values for keyUsage extensions for particular algorithms are specified in section 7.3. โœจ

4.2.1.4 Private Key Usage Period ๐ŸŒธ

ngl this one is a little bit of a "please don't" situation ๐Ÿ™ˆ This profile RECOMMENDS against using this extension. CAs conforming to this profile MUST NOT generate certificates with critical private key usage period extensions. ๐Ÿ’€

The private key usage period extension lets the certificate issuer give the private key a different validity period than the certificate itself. ๐ŸŽ€ It's meant for digital signature keys. It has two optional components, notBefore and notAfter. The private key associated with the certificate should not be used to sign objects before or after the times those two components specify, respectively. CAs conforming to this profile MUST NOT generate certificates with private key usage period extensions unless at least one of the two components is present. ๐Ÿ”ฅ

When used, notBefore and notAfter are represented as GeneralizedTime and MUST be specified and interpreted as defined in section 4.1.2.5.2. ๐Ÿงš

   id-ce-privateKeyUsagePeriod OBJECT IDENTIFIER ::=  { id-ce 16 }

   PrivateKeyUsagePeriod ::= SEQUENCE {
        notBefore       [0]     GeneralizedTime OPTIONAL,
        notAfter        [1]     GeneralizedTime OPTIONAL }

4.2.1.5 Certificate Policies ๐Ÿ‘‘

the certificate policies extension holds a sequence of one or more policy information terms, and each one has an object identifier (OID) plus optional qualifiers. ๐Ÿ’– These terms say which policy the certificate was issued under and what it can be used for. Optional qualifiers can be there, but they aren't expected to change what the policy means. โœจ

Apps with specific policy needs are expected to keep a list of the policies they'll accept, then compare the policy OIDs in the certificate against that list. ๐Ÿฆ‹ If this extension is critical, the path validation software MUST be able to interpret it (including the optional qualifier), or MUST reject the certificate. ๐Ÿ˜ญ

To keep things interoperable, this profile RECOMMENDS that policy information terms consist of only an OID. ๐Ÿซถ If an OID alone isn't enough, this profile strongly recommends limiting qualifiers to the ones identified in this section. ๐ŸŒธ

This spec defines two policy qualifier types for certificate policy writers and certificate issuers: the CPS Pointer and User Notice qualifiers. ๐Ÿ’œ

The CPS Pointer qualifier contains a pointer to a Certification Practice Statement (CPS) published by the CA. The pointer is a URI. ๐Ÿ“

User notice is meant to be displayed to a relying party when a certificate is used. The application software SHOULD display all user notices in all certificates of the certification path used, except that if a notice is duplicated, only one copy needs to be displayed. To prevent duplication, this qualifier SHOULD only be present in end-entity certificates and CA certificates issued to other organizations. ๐Ÿ”ฅ

The user notice has two optional fields: the noticeRef field and the explicitText field. ๐ŸŒˆ

The noticeRef field, if used, names an organization and identifies, by number, a particular textual statement that organization prepared. For example, it might identify the organization "CertsRUs" and notice number 1. ๐Ÿงš In a typical setup, the application will have a notice file with the current set of notices for CertsRUs, pull the notice text out of that file, and display it. Messages can be multilingual, so the software can pick the language that fits its environment. ๐Ÿ’…

The explicitText field includes the textual statement directly in the certificate. It's a string with a maximum size of 200 characters. ๐ŸŽ€

If both noticeRef and explicitText are included in the one qualifier, and the application software can locate the notice text indicated by noticeRef, then that text should be displayed. Otherwise, the explicitText string should be displayed. ๐Ÿฆ‹

   id-ce-certificatePolicies OBJECT IDENTIFIER ::=  { id-ce 32 }

   certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
   PolicyInformation ::= SEQUENCE {
        policyIdentifier   CertPolicyId,
        policyQualifiers   SEQUENCE SIZE (1..MAX) OF
                                PolicyQualifierInfo OPTIONAL }

   CertPolicyId ::= OBJECT IDENTIFIER

   PolicyQualifierInfo ::= SEQUENCE {
        policyQualifierId  PolicyQualifierId,
        qualifier          ANY DEFINED BY policyQualifierId }

   -- policyQualifierIds for Internet policy qualifiers

   id-qt          OBJECT IDENTIFIER ::=  { id-pkix 2 }
   id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }
   id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }

   PolicyQualifierId ::=
        OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )

   Qualifier ::= CHOICE {
        cPSuri           CPSuri,
        userNotice       UserNotice }

   CPSuri ::= IA5String

   UserNotice ::= SEQUENCE {
        noticeRef        NoticeReference OPTIONAL,
        explicitText     DisplayText OPTIONAL}

   NoticeReference ::= SEQUENCE {
        organization     DisplayText,
        noticeNumbers    SEQUENCE OF INTEGER }

   DisplayText ::= CHOICE {
        visibleString    VisibleString  (SIZE (1..200)),
        bmpString        BMPString      (SIZE (1..200)),
        utf8String       UTF8String     (SIZE (1..200)) }

4.2.1.6 Policy Mappings ๐Ÿงš

this extension shows up in CA certificates ๐Ÿ’… It lists one or more pairs of OIDs, and each pair has an issuerDomainPolicy and a subjectDomainPolicy. The pairing says the issuing CA considers its issuerDomainPolicy equivalent to the subject CA's subjectDomainPolicy. ๐ŸŒˆ

The issuing CA's users may accept an issuerDomainPolicy for certain applications. The policy mapping tells those users which policies tied to the subject CA are comparable to the policy they accept. ๐Ÿซถ

This extension may be supported by CAs and/or applications, and it MUST be non-critical. ๐Ÿ’–

   id-ce-policyMappings OBJECT IDENTIFIER ::=  { id-ce 33 }

   PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
        issuerDomainPolicy      CertPolicyId,
        subjectDomainPolicy     CertPolicyId }

4.2.1.7 Subject Alternative Name โœจ

okay so the subject alternative names extension is how you attach extra identities to the subject of a certificate ๐Ÿฆ‹ the options include an Internet email address, a DNS name, an IP address, and a URI. there are other options too, even completely local ones ๐Ÿ’… you can include multiple name forms, and multiple instances of each form, which is so iconic. whenever you're binding identities like this into a certificate, the subject alternative name (or issuer alternative name) extension MUST be used ๐Ÿซถ

because the subject alternative name is considered to be definitively bound to the public key, the CA MUST verify all parts of it ๐Ÿ” no skipping the checks, bestie ๐Ÿ˜ญ

now, if the only subject identity in the certificate is an alternative name form (like an email address), then the subject distinguished name MUST be empty (an empty sequence), and the subjectAltName extension MUST be present ๐ŸŒธ and if the subject field is an empty sequence, the subjectAltName extension MUST be marked critical ๐Ÿ’œ

when the subjectAltName extension holds an Internet mail address, that address MUST be included as an rfc822Name ๐Ÿ“ง the format is an "addr-spec" as defined in RFC 822 [RFC 822], which looks like local-part@domain. here's the tea: an addr-spec has no phrase (like a common name) in front of it, no comment (text in parentheses) after it, and it's not wrapped in "<" and ">" ๐Ÿ™ˆ also, upper and lower case letters are allowed in an RFC 822 addr-spec, but no significance is attached to the case, so Wpolk@nist.gov and wpolk@nist.gov aren't treated differently ๐Ÿ“

when the subjectAltName extension holds an iPAddress, the address MUST be stored in the octet string in "network byte order," as specified in RFC 791 [RFC 791] โœจ the least significant bit (LSB) of each octet is the LSB of the corresponding byte in the network address. for IP Version 4, as specified in RFC 791, the octet string MUST contain exactly four octets ๐Ÿงš for IP Version 6, as specified in RFC 1883, the octet string MUST contain exactly sixteen octets [RFC 1883] ๐Ÿ‘‘

when the subjectAltName extension holds a domain name service label, the domain name MUST be stored in the dNSName (an IA5String) ๐ŸŒˆ the name MUST be in the "preferred name syntax," as specified by RFC 1034 [RFC 1034]. upper and lower case letters are allowed in domain names, but no significance is attached to the case, which is giving very relaxed energy ๐Ÿ’– also, the string " " is technically a legal domain name, BUT subjectAltName extensions with a dNSName of " " are not permitted ๐Ÿšซ and the DNS representation for Internet mail addresses (wpolk.nist.gov instead of wpolk@nist.gov) is not permitted either. those identities have to be encoded as rfc822Name instead ๐Ÿ“ฌ

when the subjectAltName extension holds a URI, the name MUST be stored in the uniformResourceIdentifier (an IA5String) ๐Ÿฆ‹ the name MUST be a non-relative URL, and it MUST follow the URL syntax and encoding rules specified in [RFC 1738]. the name must include both a scheme (like "http" or "ftp") and a scheme-specific-part, and the scheme-specific-part must include a fully qualified domain name or IP address as the host ๐ŸŒ

as specified in [RFC 1738], the scheme name is not case-sensitive (so "http" is equivalent to "HTTP") ๐Ÿ’… the host part is also not case-sensitive, but other components of the scheme-specific-part may be case-sensitive, so be careful there ๐Ÿ‘€ when comparing URIs, conforming implementations MUST compare the scheme and host without regard to case, but they assume the rest of the scheme-specific-part is case sensitive. that's a whole vibe check ๐Ÿ’œ

subject alternative names may be constrained in the same way as subject distinguished names, using the name constraints extension as described in section 4.2.1.11 ๐Ÿ”—

if the subjectAltName extension is present, the sequence MUST contain at least one entry ๐Ÿซถ unlike the subject field, conforming CAs MUST NOT issue certificates with subjectAltNames containing empty GeneralName fields. for example, an rfc822Name is represented as an IA5String, and while an empty string is a valid IA5String, an empty rfc822Name is not permitted by this profile ๐Ÿ™… what clients do when they meet such a certificate while processing a certification path is not defined by this profile, so that's a mystery for another day ๐ŸŒซ๏ธ

finally, the semantics of subject alternative names that include wildcard characters (like a placeholder for a set of names) are not addressed by this specification ๐ŸŽ€ applications with specific requirements may use such names, but they shall define the semantics themselves ๐Ÿ› ๏ธ

   id-ce-subjectAltName OBJECT IDENTIFIER ::=  { id-ce 17 }

   SubjectAltName ::= GeneralNames

   GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName

   GeneralName ::= CHOICE {
        otherName                       [0]     OtherName,
        rfc822Name                      [1]     IA5String,
        dNSName                         [2]     IA5String,
        x400Address                     [3]     ORAddress,
        directoryName                   [4]     Name,
        ediPartyName                    [5]     EDIPartyName,
        uniformResourceIdentifier       [6]     IA5String,
        iPAddress                       [7]     OCTET STRING,
        registeredID                    [8]     OBJECT IDENTIFIER}

   OtherName ::= SEQUENCE {
        type-id    OBJECT IDENTIFIER,
        value      [0] EXPLICIT ANY DEFINED BY type-id }

   EDIPartyName ::= SEQUENCE {
        nameAssigner            [0]     DirectoryString OPTIONAL,
        partyName               [1]     DirectoryString }

4.2.1.8 Issuer Alternative Names ๐Ÿชž

as with 4.2.1.7, this extension is used to associate Internet style identities with the certificate issuer ๐Ÿ›๏ธ issuer alternative names MUST be encoded as in 4.2.1.7.

where present, this extension SHOULD NOT be marked critical ๐Ÿ™ƒ

   id-ce-issuerAltName OBJECT IDENTIFIER ::=  { id-ce 18 }

   IssuerAltName ::= GeneralNames

4.2.1.9 Subject Directory Attributes ๐Ÿ“‡

the subject directory attributes extension is not recommended as an essential part of this profile, but it may be used in local environments ๐Ÿก this extension MUST be non-critical ๐Ÿ’•

   id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::=  { id-ce 9 }

   SubjectDirectoryAttributes ::= SEQUENCE SIZE (1..MAX) OF Attribute

4.2.1.10 Basic Constraints ๐Ÿงฑ

the basic constraints extension tells you whether the subject of the certificate is a CA, and how deep a certification path may go through that CA ๐Ÿ›ค๏ธ

the pathLenConstraint field only means something if cA is set to TRUE ๐Ÿ‘€ in that case, it gives the maximum number of CA certificates that may follow this certificate in a certification path. a value of zero means only an end-entity certificate may follow in the path ๐ŸŒฑ where it appears, the pathLenConstraint field MUST be greater than or equal to zero. where pathLenConstraint doesn't appear, there is no limit to the allowed length of the certification path ๐ŸŒˆ

this extension MUST appear as a critical extension in all CA certificates ๐Ÿ”’ this extension SHOULD NOT appear in end entity certificates ๐Ÿ™…โ€โ™€๏ธ

   id-ce-basicConstraints OBJECT IDENTIFIER ::=  { id-ce 19 }

   BasicConstraints ::= SEQUENCE {
        cA                      BOOLEAN DEFAULT FALSE,
        pathLenConstraint       INTEGER (0..MAX) OPTIONAL }

4.2.1.11. Name Constraints โœจ

okay so the name constraints extension is basically a VIP guest list for names ๐ŸŽ€. It MUST be used only in a CA certificate, and it says which name space every subject name in the later certificates of a certification path has to live inside ๐Ÿฆ‹. The restrictions can hit the subject distinguished name or the subject alternative names, but they only kick in when that name form is actually in the certificate. If there's no name of that type in the cert, the cert is totally acceptable ๐Ÿซถ

Restrictions are built out of permitted and excluded name subtrees ๐ŸŒธ. Any name that matches something in excludedSubtrees is invalid, no matter what permittedSubtrees says ๐Ÿ’€. This extension MUST be critical ๐Ÿ˜ญ

In this profile, minimum and maximum aren't used with any name forms, so minimum is always zero and maximum is always absent ๐Ÿงš

For URIs, the constraint applies to the host part of the name. It can name a host, like "foo.bar.com", or a domain, like ".xyz.com" ๐Ÿ“. When the constraint starts with a period, subdomains get in too: ".xyz.com" is satisfied by both abc.xyz.com and abc.def.xyz.com. But ".xyz.com" is NOT satisfied by "xyz.com" itself, which is lowkey wild ๐Ÿ™ˆ. If the constraint doesn't start with a period, it's just one host.

For Internet mail addresses, a constraint can be a specific mailbox, all addresses on a particular host, or all mailboxes in a domain ๐Ÿ“ฌ. A particular mailbox is the full address, like "root@xyz.com" (the root mailbox on the host "xyz.com"). All mail addresses on one host is just the host name, so "xyz.com" covers any mail address at the host "xyz.com". To cover a whole domain, you add a leading period, so ".xyz.com" means all the Internet mail addresses in the domain "xyz.com", but not the addresses on the host "xyz.com" ๐Ÿ’Œ

DNS name restrictions are written as foo.bar.com, and any subdomain satisfies them. www.foo.bar.com passes, but bigfoo.bar.com doesn't, because it isn't actually a subdomain ๐Ÿ˜ค

Heads up: there are legacy implementations where an RFC 822 name is tucked inside the subject distinguished name, in an attribute of type EmailAddress (see sec. 4.1.2.6). If rfc822 names are constrained but the certificate has no subject alternative name, the rfc822 name constraint MUST be applied to that EmailAddress attribute in the subject distinguished name. The ASN.1 syntax for EmailAddress and its OID are in Appendix A and B ๐Ÿ“Ž

Restrictions of the form directoryName MUST be applied to the subject field in the certificate and to subjectAltName extensions of type directoryName. Restrictions of the form x400Address MUST be applied to subjectAltName extensions of type x400Address ๐ŸŒˆ

When applying directoryName restrictions, an implementation MUST compare DN attributes. At a minimum, implementations MUST perform the DN comparison rules in Section 4.1.2.4 ๐Ÿซถ. CAs issuing certificates with a directoryName restriction SHOULD NOT rely on implementations doing the full ISO DN name comparison algorithm. That means the name restrictions shall be written exactly the same way as they're encoded in the subject field or subjectAltName extension ๐Ÿ”ฅ

The iPAddress syntax MUST be as described in section 4.2.1.7, with the extra stuff for Name Constraints added on top โœจ. For IPv4 addresses, the ipAddress field of generalName MUST contain eight (8) octets, encoded in the CIDR style of RFC 1519 to represent an address range [RFC 1519]. For IPv6 addresses, the ipAddress field MUST contain 32 octets, encoded the same way. For example, a name constraint for the "class C" subnet 10.9.8.0 is represented as the octets 0A 09 08 00 FF FF FF 00, which is the CIDR notation 10.9.8.0/255.255.255.0 ๐Ÿ‘‘

The syntax and semantics for name constraints on otherName, ediPartyName, and registeredID are not defined by this specification ๐Ÿ™…โ€โ™€๏ธ

id-ce-nameConstraints OBJECT IDENTIFIER ::=  { id-ce 30 }

NameConstraints ::= SEQUENCE {
     permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
     excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }

GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree

GeneralSubtree ::= SEQUENCE {
     base                    GeneralName,
     minimum         [0]     BaseDistance DEFAULT 0,
     maximum         [1]     BaseDistance OPTIONAL }

BaseDistance ::= INTEGER (0..MAX)

4.2.1.12. Policy Constraints ๐ŸŽ€

okay the policy constraints extension can show up in certificates issued to CAs, and it controls path validation in two ways ๐Ÿ’…. It can stop policy mapping, or it can require that every certificate in a path has an acceptable policy identifier ๐Ÿฆ‹

If inhibitPolicyMapping is there, its value is how many more certificates can show up in the path before policy mapping isn't allowed anymore ๐ŸŒธ. Like, a value of one means policy mapping can happen in certificates issued by the subject of this certificate, but not in any additional certificates after that ๐Ÿ’œ

If requireExplicitPolicy is there, the later certificates shall include an acceptable policy identifier ๐Ÿซถ. Its value is how many more certificates can appear before an explicit policy is required. An acceptable policy identifier is either one the user of the certification path asked for, or one that's been declared equivalent through policy mapping โœจ

Conforming CAs MUST NOT issue certificates where the policy constraints is a null sequence ๐Ÿ™…โ€โ™€๏ธ. In other words, at least one of inhibitPolicyMapping or requireExplicitPolicy MUST be present. How clients handle a null policy constraints field isn't addressed in this profile, so that's a mystery for another day ๐Ÿ”ฎ

This extension may be critical or non-critical ๐ŸŒˆ

id-ce-policyConstraints OBJECT IDENTIFIER ::=  { id-ce 36 }

PolicyConstraints ::= SEQUENCE {
     requireExplicitPolicy           [0] SkipCerts OPTIONAL,
     inhibitPolicyMapping            [1] SkipCerts OPTIONAL }

SkipCerts ::= INTEGER (0..MAX)

4.2.1.13. Extended key usage field ๐Ÿ”‘

this field lists one or more purposes the certified public key can be used for, either on top of or instead of the basic purposes in the key usage extension field ๐Ÿ’–. Here's how it's defined:

id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37}

ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId

KeyPurposeId ::= OBJECT IDENTIFIER

Any organization with a need can define key purposes ๐ŸŒ. The object identifiers used for key purposes shall be assigned in accordance with IANA or ITU-T Rec. X.660 | ISO/IEC/ITU 9834-1 ๐Ÿ“‹

This extension may, at the option of the certificate issuer, be either critical or non-critical ๐Ÿงš

If the extension is flagged critical, the certificate MUST be used only for one of the purposes indicated. Strict mode, no cap ๐Ÿšซ

If the extension is flagged non-critical, it indicates the intended purpose or purposes of the key. It can help find the right key/certificate when an entity has multiple keys/certificates ๐Ÿ”. It's advisory though, so it doesn't mean the certification authority is restricting the key to only that purpose. Certificate-using applications can still require a particular purpose to be indicated before they accept the certificate ๐Ÿ’…

If a certificate has both a critical key usage field and a critical extended key usage field, then both fields MUST be processed independently, and the certificate MUST only be used for a purpose consistent with both fields. If there's no purpose consistent with both fields, then the certificate MUST NOT be used for any purpose ๐Ÿ˜ญ (the cert is basically benched)

The following key usage purposes are defined by this profile ๐Ÿ“œ

id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }

id-kp-serverAuth              OBJECT IDENTIFIER ::=   {id-kp 1}
-- TLS Web server authentication
-- Key usage bits that may be consistent: digitalSignature,
--                         keyEncipherment or keyAgreement
--
id-kp-clientAuth              OBJECT IDENTIFIER ::=   {id-kp 2}
-- TLS Web client authentication
-- Key usage bits that may be consistent: digitalSignature and/or
--                            keyAgreement
--
id-kp-codeSigning             OBJECT IDENTIFIER ::=   {id-kp 3}
-- Signing of downloadable executable code
-- Key usage bits that may be consistent: digitalSignature
--
id-kp-emailProtection         OBJECT IDENTIFIER ::=   {id-kp 4}
-- E-mail protection
-- Key usage bits that may be consistent: digitalSignature,
--                         nonRepudiation, and/or (keyEncipherment
--                         or keyAgreement)
--
id-kp-timeStamping    OBJECT IDENTIFIER ::= { id-kp 8 }
-- Binding the hash of an object to a time from an agreed-upon time
-- source. Key usage bits that may be consistent: digitalSignature,
--                         nonRepudiation

4.2.1.14. CRL Distribution Points ๐Ÿฆ‹

the CRL distribution points extension tells you how to get CRL information ๐Ÿ“ฅ. It SHOULD be non-critical, but this profile recommends that CAs and applications support it. More on CRL management is in section 5 ๐Ÿ’œ

If the cRLDistributionPoints extension has a DistributionPointName of type URI, the following semantics MUST be assumed: the URI points to the current CRL for the associated reasons, and it will be issued by the associated cRLIssuer. The expected values for the URI are the ones defined in 4.2.1.7. Processing rules for other values aren't defined by this specification ๐Ÿ™ˆ. If the distributionPoint omits reasons, the CRL MUST include revocations for all reasons. If the distributionPoint omits cRLIssuer, the CRL MUST be issued by the CA that issued the certificate ๐Ÿซถ

id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::=  { id-ce 31 }

cRLDistributionPoints ::= {
     CRLDistPointsSyntax }

CRLDistPointsSyntax ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint

DistributionPoint ::= SEQUENCE {
     distributionPoint       [0]     DistributionPointName OPTIONAL,
     reasons                 [1]     ReasonFlags OPTIONAL,
     cRLIssuer               [2]     GeneralNames OPTIONAL }

DistributionPointName ::= CHOICE {
     fullName                [0]     GeneralNames,
     nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }

ReasonFlags ::= BIT STRING {
     unused                  (0),
     keyCompromise           (1),
     cACompromise            (2),
     affiliationChanged      (3),
     superseded              (4),
     cessationOfOperation    (5),
     certificateHold         (6) }

4.2.2. Private Internet Extensions ๐ŸŽ€

okay so this section defines one new extension for the Internet Public Key Infrastructure ๐ŸŒธ this extension can be used to point applications at an on-line validation service that backs up the issuing CA. the info might live in a bunch of different forms, so each extension is a sequence of IA5String values, and every one of those represents a URI. the URI itself tells you where the info lives, what format it's in, and how to get it. it's giving self-describing ๐Ÿงš

an object identifier gets defined for this private extension. it sits under the arc id-pe inside the id-pkix name space, and any future extensions for the Internet PKI will live under id-pe too. the whole family tree is a vibe ๐Ÿ’œ

   id-pkix  OBJECT IDENTIFIER  ::=
            { iso(1) identified-organization(3) dod(6) internet(1)
                    security(5) mechanisms(5) pkix(7) }

   id-pe  OBJECT IDENTIFIER  ::=  { id-pkix 1 }

4.2.2.1. Authority Information Access ๐Ÿฆ‹

the authority information access extension shows you how to reach the CA info and services for the issuer of the certificate it's sitting in. that can include on-line validation services and CA policy data โœจ (quick aside: where the CRLs live is NOT in this extension, that job belongs to the cRLDistributionPoints extension ๐Ÿ™ˆ). this extension may be included in subject or CA certificates, and it MUST be non-critical. no drama, just info ๐Ÿ’…

   id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }

   AuthorityInfoAccessSyntax  ::=
           SEQUENCE SIZE (1..MAX) OF AccessDescription

   AccessDescription  ::=  SEQUENCE {
           accessMethod          OBJECT IDENTIFIER,
           accessLocation        GeneralName  }

   id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }

   id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }

so each entry in the AuthorityInfoAccessSyntax sequence describes the format and location of extra info about the CA that issued the certificate with this extension in it. the accessMethod field tells you the type and format of the info, and the accessLocation field tells you where it's stored. the retrieval mechanism can be implied by the accessMethod, or it can be spelled out in accessLocation ๐Ÿซถ

this profile defines one OID for accessMethod, and that's id-ad-caIssuers. it's used when the extra info lists CAs that have issued certificates superior to the CA that issued this certificate. the CA Issuers description is there to help certificate users pick a certification path that ends at a point they actually trust. main character energy for path selection ๐Ÿ‘‘

when id-ad-caIssuers shows up as accessInfoType, the accessLocation field describes the referenced description server and the access protocol needed to grab that description. accessLocation is a GeneralName, which can take a bunch of forms. if the info is available via http, ftp, or ldap, accessLocation MUST be a uniformResourceIdentifier. if it's available via the directory access protocol (dap), accessLocation MUST be a directoryName. if it's available via electronic mail, accessLocation MUST be an rfc822Name. the semantics of any other name forms of accessLocation (when accessMethod is id-ad-caIssuers) are not defined by this specification, so that's a no-go zone for now ๐Ÿ™…โ€โ™€๏ธ

additional access descriptors can be defined in other PKIX specifications, so this list isn't the final word ๐ŸŒˆ


5. CRL and CRL Extensions Profile ๐Ÿ’…

okay so as we said earlier, one big goal of this X.509 v2 CRL profile is to encourage an interoperable and reusable Internet PKI ๐Ÿซถ to get there, the profile gives guidelines for using extensions and makes some assumptions about what info goes in the CRL.

CRLs can show up in a huge range of applications and environments, with all kinds of interoperability goals and even wilder operational and assurance requirements ๐Ÿ˜ญ this profile sets a common baseline for generic applications that need broad interoperability. it defines a baseline set of info you can expect in every CRL, and it also defines common spots in the CRL for frequently used attributes, plus common ways to represent those attributes ๐ŸŽ€

this profile does not define any private Internet CRL extensions or CRL entry extensions, so don't go looking for those here ๐Ÿ™ˆ

environments with extra or special purpose needs can build on this profile or replace it entirely. totally their call โœจ

conforming CAs are not required to issue CRLs if other revocation or certificate status mechanisms are provided. conforming CAs that do issue CRLs MUST issue version 2 CRLs, and CAs MUST include the date by which the next CRL will be issued in the nextUpdate field (see sec. 5.1.2.5), the CRL number extension (see sec. 5.2.3) and the authority key identifier extension (see sec. 5.2.1). conforming applications are required to process version 1 and 2 CRLs ๐Ÿ”ฅ

5.1. CRL Fields ๐ŸŒธ

the X.509 v2 CRL syntax looks like this. for signature calculation, the data being signed is ASN.1 DER encoded, and ASN.1 DER encoding is a tag, length, value encoding system for each element ๐Ÿง 

   CertificateList  ::=  SEQUENCE  {
        tbsCertList          TBSCertList,
        signatureAlgorithm   AlgorithmIdentifier,
        signatureValue       BIT STRING  }

   TBSCertList  ::=  SEQUENCE  {
        version                 Version OPTIONAL,
                                     -- if present, shall be v2
        signature               AlgorithmIdentifier,
        issuer                  Name,
        thisUpdate              Time,
        nextUpdate              Time OPTIONAL,
        revokedCertificates     SEQUENCE OF SEQUENCE  {
             userCertificate         CertificateSerialNumber,
             revocationDate          Time,
             crlEntryExtensions      Extensions OPTIONAL
                                           -- if present, shall be v2
                                  }  OPTIONAL,
        crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
                                           -- if present, shall be v2
                                  }

   -- Version, Time, CertificateSerialNumber, and Extensions
   -- are all defined in the ASN.1 in section 4.1

   -- AlgorithmIdentifier is defined in section 4.1.1.2

the next bit describes how the X.509 v2 CRL gets used in the Internet PKI ๐Ÿฆ‹

5.1.1. CertificateList Fields ๐Ÿ’–

the CertificateList is a SEQUENCE of three required fields. each one is described in more detail in the subsections below โœจ

5.1.1.1. tbsCertList ๐Ÿ“

the first field in the sequence is the tbsCertList. it's its own sequence, holding the issuer's name, the issue date, the issue date of the next list, the list of revoked certificates, and optional CRL extensions. each entry on the revoked certificate list is a sequence of user certificate serial number, revocation date, and optional CRL entry extensions ๐ŸŒˆ

5.1.1.2. signatureAlgorithm ๐Ÿ”

the signatureAlgorithm field holds the algorithm identifier for the algorithm the CA used to sign the CertificateList. it's an AlgorithmIdentifier, which is defined in section 4.1.1.2, and section 7.2 lists the supported algorithms for this spec ๐ŸŽ€

conforming CAs MUST use the algorithm identifiers presented in section 7.2 when signing with a supported signature algorithm.

this field MUST contain the same algorithm identifier as the signature field in the sequence tbsCertList (see sec. 5.1.2.2). twins only, no mismatches ๐Ÿ‘ฏ

5.1.1.3. signatureValue โœ๏ธ

the signatureValue field holds a digital signature computed over the ASN.1 DER encoded tbsCertList. that encoded tbsCertList is the input to the signature function. the signature value then gets ASN.1 encoded as a BIT STRING and goes into the CRL's signatureValue field. the details for each supported algorithm are spelled out in section 7.2 ๐Ÿ’œ

5.1.2. Certificate List "To Be Signed" ๐ŸŒŸ

the certificate list to be signed (aka TBSCertList) is a SEQUENCE of required and optional fields. the required ones identify the CRL issuer, the algorithm used to sign the CRL, the date and time the CRL was issued, and the date and time by which the CA will issue the next CRL ๐Ÿ“…

the optional fields include lists of revoked certificates and CRL extensions. the revoked certificate list is optional so it can cover the case where a CA hasn't revoked any unexpired certificates it issued. the profile requires conforming CAs to use the CRL extension cRLNumber in all CRLs they issue ๐Ÿ”ข

5.1.2.1. Version ๐ŸŒธ

this optional field describes the version of the encoded CRL. when extensions are used, as this profile requires, this field MUST be present and MUST specify version 2 (the integer value is 1). no version drama here ๐Ÿ’…

5.1.2.2. Signature ๐Ÿ–‹๏ธ

this field holds the algorithm identifier for the algorithm used to sign the CRL. section 7.2 lists OIDs for the most popular signature algorithms used in the Internet PKI โœจ

this field MUST contain the same algorithm identifier as the signatureAlgorithm field in the sequence CertificateList (see section 5.1.1.2). matching is non-negotiable ๐Ÿซถ

5.1.2.3. Issuer Name ๐Ÿ›๏ธ

the issuer name identifies the entity who signed and issued the CRL. the issuer identity is carried in the issuer name field. alternative name forms may also show up in the issuerAltName extension (see sec. 5.2.2) ๐ŸŒˆ the issuer name field MUST contain an X.500 distinguished name (DN). it's defined as the X.501 type Name, and it MUST follow the encoding rules for the issuer name field in the certificate (see sec. 4.1.2.4). rules are rules, bestie ๐Ÿ“œ

5.1.2.4. This Update ๐Ÿ•ฐ๏ธ

this field indicates the issue date of this CRL. thisUpdate may be encoded as UTCTime or GeneralizedTime ๐ŸŒท

CAs conforming to this profile that issue CRLs MUST encode thisUpdate as UTCTime for dates through the year 2049. CAs conforming to this profile that issue CRLs MUST encode thisUpdate as GeneralizedTime for dates in the year 2050 or later. y2050 is the glow-up era ๐ŸŒ™

where thisUpdate is encoded as UTCTime, it MUST be specified and interpreted as defined in section 4.1.2.5.1. where it's encoded as GeneralizedTime, thisUpdate MUST be specified and interpreted as defined in section 4.1.2.5.2 โฐ

5.1.2.5. Next Update โญ๏ธ

this field indicates the date by which the next CRL will be issued. the next CRL could be issued before that date, but it won't be issued any later than that date. CAs SHOULD issue CRLs with a nextUpdate time equal to or later than all previous CRLs ๐Ÿ“ˆ

this profile requires nextUpdate to be included in all CRLs issued by conforming CAs. heads up: the ASN.1 syntax of TBSCertList lists this field as OPTIONAL, which lines up with the ASN.1 structure defined in [X.509]. how clients handle CRLs that leave out nextUpdate is not specified by this profile, so that one's a mystery ๐Ÿ™ˆ

CAs conforming to this profile that issue CRLs MUST encode nextUpdate as UTCTime for dates through the year 2049. CAs conforming to this profile that issue CRLs MUST encode nextUpdate as GeneralizedTime for dates in the year 2050 or later ๐Ÿ’–

where nextUpdate is encoded as UTCTime, it MUST be specified and interpreted as defined in section 4.1.2.5.1. where it's encoded as GeneralizedTime, nextUpdate MUST be specified and interpreted as defined in section 4.1.2.5.2 ๐ŸŽ€

5.1.2.6 Revoked Certificates ๐Ÿฆ‹

okay so this part is the list of revoked certs ๐Ÿ“œ each one gets named by its serial number, because that's what uniquely identifies a cert the CA revoked ๐Ÿ”‘ the date the revocation happened is specified too. the time for revocationDate MUST be expressed as described in section 5.1.2.4, no freelancing the time format bestie ๐Ÿ’… extra info can ride along in CRL entry extensions, which we cover in section 5.3 ๐ŸŽ€

5.1.2.7 Extensions โœจ

this field is only allowed to show up if the version is 2 (check section 5.1.2.1 ๐Ÿค“). when it's there, it's a SEQUENCE of one or more CRL extensions. more on those in section 5.2 ๐Ÿซถ

5.2 CRL Extensions ๐ŸŒˆ

the extensions defined by ANSI X9 and ISO/IEC/ITU for X.509 v2 CRLs [X.509] [X9.55] are how you attach extra attributes to CRLs ๐Ÿงš the X.509 v2 CRL format also lets communities define private extensions for info that only they care about ๐Ÿ’œ

every extension in a CRL can be marked critical or non-critical. a CRL validation MUST fail if it runs into a critical extension it doesn't know how to process ๐Ÿ’€ but an unrecognized non-critical extension is allowed to be ignored, so it's chill ๐ŸŒธ communities can add extensions that aren't defined in this spec too, but be careful about putting critical extensions in CRLs that might be used in a general context ๐Ÿ‘€

conforming CAs that issue CRLs are required to include the authority key identifier (see sec. 5.2.1) and the CRL number (see sec. 5.2.3) extensions in all CRLs issued ๐Ÿ‘‘

5.2.1 Authority Key Identifier ๐Ÿ”

this extension tells you which public key matches the private key that signed a CRL ๐Ÿ—๏ธ the identification can be based on either the key identifier (the subject key identifier in the CRL signer's certificate) or on the issuer name and serial number. it's especially useful when an issuer has more than one signing key, whether that's because of multiple concurrent key pairs or a changeover ๐Ÿ”„

conforming CAs MUST use the key identifier method, and MUST include this extension in all CRLs issued. no skipping!! ๐Ÿ˜ค

the syntax for this CRL extension is defined in section 4.2.1.1 ๐Ÿ“–

5.2.2 Issuer Alternative Name ๐ŸŒ

the issuer alternative names extension lets you attach extra identities to the CRL's issuer. the options are an rfc822 name (electronic mail address), a DNS name, an IP address, and a URI ๐Ÿ’Œ you can include multiple instances of a name and multiple name forms too. whenever these identities are used, the issuer alternative name extension MUST be used ๐Ÿ™Œ

the issuerAltName extension SHOULD NOT be marked critical ๐Ÿ™ˆ

the OID and syntax for this CRL extension are defined in section 4.2.1.8 ๐Ÿฆ‹

5.2.3 CRL Number ๐Ÿ”ข

the CRL number is a non-critical CRL extension that carries a monotonically increasing sequence number for each CRL a CA issues ๐Ÿ“ˆ this is how users can easily tell when one CRL supersedes another, which is so useful ๐Ÿ˜ญ CAs conforming to this profile MUST include this extension in all CRLs.

id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 }

cRLNumber ::= INTEGER (0..MAX)

5.2.4 Delta CRL Indicator ๐Ÿ“

the delta CRL indicator is a critical CRL extension that identifies a delta-CRL โœจ delta-CRLs can seriously speed things up for apps that store revocation info in a format other than the CRL structure ๐Ÿš€ changes get added to the local database while the unchanged stuff that's already in there gets ignored. iconic efficiency ๐Ÿ’…

when a delta-CRL is issued, the CAs MUST also issue a complete CRL ๐Ÿ“‹

the value of BaseCRLNumber tells you the CRL number of the base CRL that was used as the starting point for this delta-CRL. the delta-CRL holds the changes between that base CRL and the current CRL issued alongside it. whether to provide delta-CRLs is up to the CA ๐Ÿคทโ€โ™€๏ธ but again, a delta-CRL MUST NOT be issued without a corresponding complete CRL. the value of CRLnumber for both the delta-CRL and the corresponding complete CRL MUST be identical ๐Ÿ‘ฏโ€โ™€๏ธ

a CRL user building a locally held CRL out of delta-CRLs MUST consider the constructed CRL incomplete and unusable if the CRLNumber of the received delta-CRL is more than one greater than the CRLnumber of the delta-CRL last processed. gaps = nope ๐Ÿšซ

id-ce-deltaCRLIndicator OBJECT IDENTIFIER ::= { id-ce 27 }

deltaCRLIndicator ::= BaseCRLNumber

BaseCRLNumber ::= CRLNumber

5.2.5 Issuing Distribution Point ๐Ÿ“

the issuing distribution point is a critical CRL extension that identifies the CRL distribution point for a particular CRL ๐Ÿ—บ๏ธ it also says whether the CRL covers revocation for end entity certificates only, CA certificates only, or a limited set of reason codes. even though the extension is critical, conforming implementations are not required to support it ๐Ÿซ 

the CRL is signed using the CA's private key. CRL Distribution Points don't get their own key pairs, so no separate keys here ๐Ÿ”‘ if the CRL is stored in the X.500 Directory, it lives in the Directory entry for the CRL distribution point, which might be different from the CA's Directory entry ๐Ÿ“‚

the reason codes tied to a distribution point SHALL be specified in onlySomeReasons. wait, lowercase, so: the reason codes associated with a distribution point shall be specified in onlySomeReasons. if onlySomeReasons doesn't show up, the distribution point shall contain revocations for all reason codes ๐ŸŒˆ CAs can also use distribution points to split the CRL by compromise and routine revocation. in that setup, the revocations with reason code keyCompromise (1) and cACompromise (2) go in one distribution point, and the ones with other reason codes go in another ๐Ÿ’œ

where the issuingDistributionPoint extension contains a URL, the following semantics MUST be assumed: the object is a pointer to the most current CRL issued by this CA ๐Ÿ‘‘ the URI schemes ftp, http, mailto [RFC1738] and ldap [RFC1778] are defined for this purpose. the URI MUST be an absolute, not relative, pathname and MUST specify the host ๐ŸŒ

id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 }

issuingDistributionPoint ::= SEQUENCE {
     distributionPoint       [0] DistributionPointName OPTIONAL,
     onlyContainsUserCerts   [1] BOOLEAN DEFAULT FALSE,
     onlyContainsCACerts     [2] BOOLEAN DEFAULT FALSE,
     onlySomeReasons         [3] ReasonFlags OPTIONAL,
     indirectCRL             [4] BOOLEAN DEFAULT FALSE }

5.3 CRL Entry Extensions ๐Ÿงพ

the CRL entry extensions already defined by ANSI X9 and ISO/IEC/ITU for X.509 v2 CRLs let you attach extra attributes to CRL entries [X.509] [X9.55] ๐Ÿ’– the X.509 v2 CRL format also lets communities define private CRL entry extensions for their own info ๐ŸŒธ each extension in a CRL entry can be critical or non-critical. a CRL validation MUST fail if it hits a critical CRL entry extension it can't process, but an unrecognized non-critical one can be ignored ๐Ÿซถ the subsections below cover recommended extensions for Internet CRL entries and where to find certain info. communities can use more CRL entry extensions too, but be careful about critical ones in general contexts โš ๏ธ

all CRL entry extensions used in this specification are non-critical. support for them is optional for conforming CAs and applications. BUT CAs that issue CRLs SHOULD include reason codes (see sec. 5.3.1) and invalidity dates (see sec. 5.3.3) whenever that info is available ๐Ÿฅน

5.3.1 Reason Code ๐Ÿ’ฌ

the reasonCode is a non-critical CRL entry extension that identifies why a certificate got revoked. CAs are strongly encouraged to include meaningful reason codes in CRL entries ๐Ÿ“ however, the reason code CRL entry extension SHOULD be absent instead of using the unspecified (0) reasonCode value. so no lazy "unspecified" vibes ๐Ÿ™…โ€โ™€๏ธ

id-ce-cRLReason OBJECT IDENTIFIER ::= { id-ce 21 }

-- reasonCode ::= { CRLReason }

CRLReason ::= ENUMERATED {
     unspecified             (0),
     keyCompromise           (1),
     cACompromise            (2),
     affiliationChanged      (3),
     superseded              (4),
     cessationOfOperation    (5),
     certificateHold         (6),
     removeFromCRL           (8) }

5.3.2 Hold Instruction Code ๐ŸŽซ

the hold instruction code is a non-critical CRL entry extension that gives a registered instruction identifier telling you what to do after you run into a certificate that's been placed on hold โธ๏ธ

id-ce-holdInstructionCode OBJECT IDENTIFIER ::= { id-ce 23 }

holdInstructionCode ::= OBJECT IDENTIFIER

these instruction codes have been defined, and conforming applications that process this extension MUST recognize them ๐Ÿง 

holdInstruction    OBJECT IDENTIFIER ::=
                 { iso(1) member-body(2) us(840) x9-57(10040) 2 }

id-holdinstruction-none   OBJECT IDENTIFIER ::= {holdInstruction 1}
id-holdinstruction-callissuer
                          OBJECT IDENTIFIER ::= {holdInstruction 2}
id-holdinstruction-reject OBJECT IDENTIFIER ::= {holdInstruction 3}

the vibe rules are: conforming applications that encounter id-holdinstruction-callissuer MUST call the certificate issuer or reject the certificate ๐Ÿ“ž conforming applications that encounter id-holdinstruction-reject MUST reject the certificate ๐Ÿšซ and id-holdinstruction-none is semantically equivalent to not having a holdInstructionCode at all, and its use is strongly deprecated for the Internet PKI ๐Ÿฅ€

5.3.3 Invalidity Date ๐Ÿ—“๏ธ

the invalidity date is a non-critical CRL entry extension that gives the date when it's known or suspected that the private key got compromised, or the cert otherwise became invalid ๐Ÿ•ต๏ธโ€โ™€๏ธ this date can be earlier than the revocation date in the CRL entry, which is the date the CA actually processed the revocation ๐Ÿ•ฐ๏ธ when a revocation first gets posted in a CRL, the invalidity date may come before the issue date of earlier CRLs, but the revocation date SHOULD NOT precede the issue date of earlier CRLs. and whenever this info is available, CAs are strongly encouraged to share it with CRL users ๐Ÿซถ

the GeneralizedTime values in this field MUST be expressed in Greenwich Mean Time (Zulu), and MUST be specified and interpreted as defined in section 4.1.2.5.2 ๐ŸŒโฐ

id-ce-invalidityDate OBJECT IDENTIFIER ::= { id-ce 24 }

invalidityDate ::=  GeneralizedTime

5.3.4 Certificate Issuer ๐Ÿฆ‹

okay so this CRL entry extension tells you which certificate issuer goes with an entry in an indirect CRL ๐Ÿงš (an indirect CRL is one with the indirectCRL indicator set in its issuing distribution point extension). it's giving "who's the real owner of this entry" energy ๐Ÿ’… If this extension isn't on the first entry in an indirect CRL, the certificate issuer defaults to the CRL issuer. On later entries, if it's missing, the certificate issuer is the same as the one on the entry right before it. the field is defined like this:

id-ce-certificateIssuer   OBJECT IDENTIFIER ::= { id-ce 29 }

certificateIssuer ::=     GeneralNames

if conforming CAs that issue CRLs use it, it is always critical ๐Ÿ”ฅ and that makes sense, because if an implementation ignored it, it couldn't correctly attribute CRL entries to certificates ๐Ÿ’€ This specification RECOMMENDS that implementations recognize this extension ๐Ÿซถ


6 Certification Path Validation โœจ

okay this is the part where the certificate chain gets checked ๐ŸŽ€ Certification path validation for the Internet PKI is based on section 12.4.3 of [X.509]. Basically, path processing verifies the binding between the subject distinguished name and/or subject alternative name and the subject public key ๐Ÿ”‘ That binding is limited by constraints written into the certificates that make up the path. The basic constraints and policy constraints extensions let the path processing logic automate the decision making ๐Ÿค–

This section describes an algorithm for validating certification paths. Conforming implementations of this specification are not required to implement this algorithm, but they MUST be functionally equivalent to the external behavior that this procedure produces ๐Ÿง Any algorithm can be used by a particular implementation, as long as it derives the correct result โœจ

section 6.2 covers extensions to the basic path validation algorithm ๐ŸŒˆ It discusses two cases: paths that may begin with one of several trusted CAs, and compatibility with the PEM architecture.

6.1 Basic Path Validation ๐ŸŒธ

so the basic version assumes all valid paths begin with certificates issued by a single "most-trusted CA" ๐Ÿ‘‘ The algorithm needs the public key of that CA, the CA's name, the validity period of the public key, and any constraints on which paths can be validated with this key.

The "most-trusted CA" is a matter of policy. It could be a root CA in a hierarchical PKI, the CA that issued the verifier's own certificate(s), or any other CA in a network PKI. The path validation procedure is the same no matter which "most-trusted CA" you pick ๐Ÿ’…

This text assumes the trusted public key (and related information) lives in a "self-signed" certificate, which keeps the description of path processing simple ๐Ÿฆ‹ The signature on that self-signed certificate doesn't provide any security services. the trusted public key (and related information) can be obtained in other formats too, because it's trusted due to other procedures used to obtain and protect it.

The goal of path validation is to verify the binding between a subject distinguished name or subject alternative name and a subject public key, as shown in the "end entity" certificate, based on the public key of the "most-trusted CA" โœจ To do that, you need a sequence of certificates that support the binding. the procedures for obtaining that sequence are outside the scope of this section.

This text also assumes that certificates don't use subject or unique identifier fields, or private critical extensions, as recommended within this profile. However, if these components do appear in certificates, they MUST be processed. Policy qualifiers are also ignored here, just for clarity ๐Ÿ™ˆ

A certification path is a sequence of n certificates where:

  • for all x in {1,(n-1)}, the subject of certificate x is the issuer of certificate x+1.
  • certificate x=1 is the self-signed certificate, and
  • certificate x=n is the end entity certificate.

This section assumes the following inputs are given to the path processing logic:

  • (a) a certification path of length n;
  • (b) a set of initial policy identifiers (each comprising a sequence of policy element identifiers), which identifies one or more certificate policies, any one of which would be acceptable for the purposes of certification path processing, or the special value "any-policy";
  • (c) the current date/time (if not available internally to the certification path processing module); and
  • (d) the time, T, for which the validity of the path should be determined. (This may be the current date/time, or some point in the past.)

From those inputs, the procedure initializes five state variables ๐Ÿง 

  • (a) acceptable policy set: A set of certificate policy identifiers comprising the policy or policies recognized by the public key user, together with policies deemed equivalent through policy mapping. The initial value of the acceptable policy set is the special value "any-policy".
  • (b) constrained subtrees: A set of root names defining a set of subtrees within which all subject names in subsequent certificates in the certification path shall fall. The initial value is "unbounded".
  • (c) excluded subtrees: A set of root names defining a set of subtrees within which no subject name in subsequent certificates in the certification path may fall. The initial value is "empty".
  • (d) explicit policy: an integer which indicates whether an explicit policy identifier is required. The integer indicates the first certificate in the path where this requirement is imposed. Once set, this variable may be decreased, but may not be increased. (So if a certificate in the path requires explicit policy identifiers, a later certificate can't remove that requirement ๐Ÿ™…โ€โ™€๏ธ) The initial value is n+1.
  • (e) policy mapping: an integer which indicates whether policy mapping is permitted. The integer indicates the last certificate on which policy mapping may be applied. Once set, this variable may be decreased, but may not be increased. (So if a certificate in the path says policy mapping is not permitted, a later certificate can't override it.) The initial value is n+1.

The path processing software performs the actions below for each certificate i=1 through n. The self-signed certificate is certificate i=1, and the end entity certificate is i=n. Processing is sequential, so processing certificate i affects the state variables for processing certificate (i+1). Note that actions (h) through (m) are not applied to the end entity certificate (certificate n) ๐Ÿ’–

The path processing actions are:

  • (a) Verify the basic certificate information, including:
    • (1) the certificate was signed using the subject public key from certificate i-1 (in the special case i=1, this step may be omitted; if not, use the subject public key from the same certificate),
    • (2) the certificate validity period includes time T,
    • (3) the certificate had not been revoked at time T and is not currently on hold status that commenced before time T (this may be determined by obtaining the appropriate CRL or status information, or by out-of-band mechanisms), and
    • (4) the subject and issuer names chain correctly (that is, the issuer of this certificate was the subject of the previous certificate).
  • (b) Verify that the subject name and subjectAltName extension (critical or noncritical) is consistent with the constrained subtrees state variables.
  • (c) Verify that the subject name and subjectAltName extension (critical or noncritical) is consistent with the excluded subtrees state variables.
  • (d) Verify that policy information is consistent with the initial policy set:
    • (1) if the explicit policy state variable is less than or equal to i, a policy identifier in the certificate shall be in the initial policy set; and
    • (2) if the policy mapping variable is less than or equal to i, the policy identifier may not be mapped.
  • (e) Verify that policy information is consistent with the acceptable policy set:
    • (1) if the certificate policies extension is marked critical, the intersection of the policies extension and the acceptable policy set shall be non-null;
    • (2) the acceptable policy set is assigned the resulting intersection as its new value.
  • (g) Verify that the intersection of the acceptable policy set and the initial policy set is non-null.
  • (h) Recognize and process any other critical extension present in the certificate.
  • (i) Verify that the certificate is a CA certificate (as specified in a basicConstraints extension or as verified out-of-band).
  • (j) If permittedSubtrees is present in the certificate, set the constrained subtrees state variable to the intersection of its previous value and the value indicated in the extension field.
  • (k) If excludedSubtrees is present in the certificate, set the excluded subtrees state variable to the union of its previous value and the value indicated in the extension field.
  • (l) If a policy constraints extension is included in the certificate, modify the explicit policy and policy mapping state variables as follows:
    • (1) If requireExplicitPolicy is present and has value r, the explicit policy state variable is set to the minimum of its current value and the sum of r and i (the current certificate in the sequence).
    • (2) If inhibitPolicyMapping is present and has value q, the policy mapping state variable is set to the minimum of its current value and the sum of q and i (the current certificate in the sequence).
  • (m) If a key usage extension is marked critical, ensure the keyCertSign bit is set.

If any one of the above checks fails, the procedure terminates, returning a failure indication and an appropriate reason ๐Ÿšซ If none of the above checks fail on the end-entity certificate, the procedure terminates, returning a success indication together with the set of all policy qualifier values encountered in the set of certificates ๐ŸŽ‰

6.2 Extending Path Validation โœจ

okay so the path validation algorithm in 6.1 is built on a few simplifying assumptions ๐ŸŽ€ like, there's one trusted CA that starts every valid path. but it can be extended for the cases where those assumptions don't hold ๐Ÿ’…

for multiple trusted CAs, you give the validation module a set of self-signed certificates. then a valid path can begin with any one of those self-signed certificates ๐Ÿฆ‹ limits on the trust paths for a particular key can be built right into that self-signed certificate's extensions. so the path validation module can automatically pick up local security policy and requirements. literally iconic ๐Ÿ‘‘

it's also possible to specify an extended version of the certification path processing procedure that gives default behavior identical to the rules of PEM [RFC 1422]. in this version, the extra inputs are a list of one or more Policy Certification Authorities (PCAs) names and an indicator of the position in the certification path where the PCA is expected. at the nominated PCA position, the CA name gets compared against that list. if a recognized PCA name is found, then a constraint of SubordinateToCA is implicitly assumed for the rest of the certification path and processing keeps going. if no valid PCA name is found, and if the certification path can't be validated on the basis of identified policies, then the certification path is considered invalid ๐Ÿ™ˆ


7 Algorithm Support ๐Ÿงš

this section describes the cryptographic algorithms that may be used with this profile ๐Ÿ”ฅ it covers the one-way hash functions and digital signature algorithms that can sign certificates and CRLs, and it identifies the OIDs for public keys contained in a certificate.

conforming CAs and applications are not required to support the algorithms or algorithm identifiers described in this section. but if conforming CAs and applications use the algorithms identified here, they MUST support them as specified ๐Ÿ’œ

7.1 One-way Hash Functions ๐ŸŒธ

this section identifies the one-way hash functions for use in the Internet PKI. one-way hash functions are also called message digest algorithms. SHA-1 is the preferred one-way hash function for the Internet PKI ๐Ÿ“ however, PEM uses MD2 for certificates [RFC 1422] [RFC 1423], and MD5 is still used in other legacy applications. that's why MD2 and MD5 are included in this profile ๐Ÿซถ

7.1.1 MD2 One-way Hash Function ๐Ÿฆ‹

MD2 was developed by Ron Rivest for RSA Data Security. RSA Data Security has not placed the MD2 algorithm in the public domain. instead, it granted a license to use MD2 for non-commercial Internet Privacy-Enhanced Mail ๐Ÿ™ˆ so MD2 may continue to be used with PEM certificates, but SHA-1 is preferred. MD2 produces a 128-bit "hash" of the input. MD2 is fully described in RFC 1319 [RFC 1319].

at the Selected Areas in Cryptography '95 conference in May 1995, Rogier and Chauvaud presented an attack on MD2 that can nearly find collisions [RC95]. collisions happen when you can find two different messages that generate the same message digest. a checksum operation in MD2 is the only remaining obstacle to that attack succeeding ๐Ÿ˜ญ for this reason, the use of MD2 for new applications is discouraged. it's still reasonable to use MD2 to verify existing signatures, because being able to find collisions in MD2 doesn't let an attacker find new messages that have a previously computed hash value ๐Ÿ’…

7.1.2 MD5 One-way Hash Function ๐ŸŒˆ

MD5 was developed by Ron Rivest for RSA Data Security. RSA Data Security has placed the MD5 algorithm in the public domain โœจ MD5 produces a 128-bit "hash" of the input. MD5 is fully described in RFC 1321 [RFC 1321].

Den Boer and Bosselaers [DB94] have found pseudo-collisions for MD5, but there are no other known cryptanalytic results ๐Ÿ‘€ the use of MD5 for new applications is discouraged. it's still reasonable to use MD5 to verify existing signatures ๐Ÿซถ

7.1.3 SHA-1 One-way Hash Function ๐Ÿ‘‘

SHA-1 was developed by the U.S. Government. it produces a 160-bit "hash" of the input ๐Ÿ’– SHA-1 is fully described in FIPS 180-1 [FIPS 180-1].

SHA-1 is the one-way hash function of choice for use with both the RSA and DSA signature algorithms (see sec. 7.2) ๐Ÿ”ฅ

7.2 Signature Algorithms ๐Ÿ’…

certificates and CRLs described by this standard may be signed with any public key signature algorithm ๐ŸŒธ the certificate or CRL shows which algorithm it used through an algorithm identifier, which appears in the signatureAlgorithm field in a Certificate or CertificateList. that algorithm identifier is an OID and it can optionally have associated parameters. this section identifies the algorithm identifiers and parameters that shall be used in the signatureAlgorithm field in a Certificate or CertificateList ๐ŸŽ€

RSA and DSA are the most popular signature algorithms on the Internet ๐Ÿฆ‹ signature algorithms are always used together with a one-way hash function identified in section 7.1.

the signature algorithm and the one-way hash function used to sign a certificate or CRL get indicated by an algorithm identifier. an algorithm identifier is an OID, and it may include associated parameters. this section identifies OIDs for RSA and DSA. the contents of the parameters component vary for each algorithm, and details are provided for each one ๐Ÿงš

the data to be signed (for example, the one-way hash function output value) gets formatted for the signature algorithm being used. then a private key operation (for example, RSA encryption) is performed to generate the signature value. that signature value is then ASN.1 encoded as a BIT STRING and included in the Certificate or CertificateList in the signature field ๐ŸŒˆ

7.2.1 RSA Signature Algorithm ๐Ÿ’–

there's a patent statement about the RSA algorithm at the end of this profile ๐Ÿ‘€

the RSA algorithm is named after its inventors: Rivest, Shamir, and Adleman ๐Ÿ“ this profile includes three signature algorithms based on the RSA asymmetric encryption algorithm. they combine RSA with either the MD2, MD5, or SHA-1 one-way hash functions โœจ

the signature algorithm with MD2 and the RSA encryption algorithm is defined in PKCS #1 [RFC 2313]. as RFC 2313 defines it, the ASN.1 OID used to identify this signature algorithm is:

     md2WithRSAEncryption OBJECT IDENTIFIER  ::=  {
         iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
         pkcs-1(1) 2  }

the signature algorithm with MD5 and the RSA encryption algorithm is also defined in PKCS #1 [RFC 2313]. as RFC 2313 defines it, the ASN.1 OID used to identify this signature algorithm is:

     md5WithRSAEncryption OBJECT IDENTIFIER  ::=  {
         iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
         pkcs-1(1) 4  }

the signature algorithm with SHA-1 and the RSA encryption algorithm is implemented using the padding and encoding conventions described in PKCS #1 [RFC 2313]. the message digest is computed using the SHA-1 hash algorithm ๐Ÿ”ฅ the ASN.1 object identifier used to identify this signature algorithm is:

     sha-1WithRSAEncryption OBJECT IDENTIFIER  ::=  {
         iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
         pkcs-1(1) 5  }

when any of these three OIDs appears within the ASN.1 type AlgorithmIdentifier, the parameters component of that type shall be the ASN.1 type NULL ๐Ÿ’…

the RSA signature generation process, and how the result is encoded, is described in detail in RFC 2313 ๐Ÿซถ

7.2.2 DSA Signature Algorithm ๐ŸŽ€

there's a patent statement about the DSA at the end of this profile too ๐Ÿ™ˆ

the Digital Signature Algorithm (DSA) is also called the Digital Signature Standard (DSS) ๐Ÿฆ‹ DSA was developed by the U.S. Government, and it's used together with the SHA-1 one-way hash function. DSA is fully described in FIPS 186 [FIPS 186]. the ASN.1 OIDs used to identify this signature algorithm are:

        id-dsa-with-sha1 ID  ::=  {
                iso(1) member-body(2) us(840) x9-57 (10040)
                x9cm(4) 3 }

where the id-dsa-with-sha1 algorithm identifier appears as the algorithm field in an AlgorithmIdentifier, the encoding shall omit the parameters field. that means the AlgorithmIdentifier shall be a SEQUENCE of one component, the OBJECT IDENTIFIER id-dsa-with-sha1 ๐Ÿงš

the DSA parameters in the subjectPublicKeyInfo field of the issuer's certificate shall apply to verifying the signature โœจ

when signing, the DSA algorithm generates two values. these are commonly referred to as r and s ๐Ÿ’– to transfer these two values easily as one signature, they shall be ASN.1 encoded using the following ASN.1 structure:

        Dss-Sig-Value  ::=  SEQUENCE  {
                r       INTEGER,
                s       INTEGER  }

7.3 Subject Public Key Algorithms ๐ŸŒˆ

certificates described by this profile may convey a public key for any public key algorithm ๐Ÿ’œ the certificate shows which algorithm it uses through an algorithm identifier. this algorithm identifier is an OID with optionally associated parameters ๐Ÿ“

this section identifies the preferred OIDs and parameters for the RSA, DSA, and Diffie-Hellman algorithms ๐Ÿ”ฅ conforming CAs shall use the identified OIDs when issuing certificates that contain public keys for these algorithms. conforming applications that support any of these algorithms shall, at a minimum, recognize the OID identified in this section ๐Ÿ‘‘

7.3.1 RSA Keys ๐Ÿซถ

the OID rsaEncryption identifies RSA public keys ๐Ÿฆ‹

     pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
                    rsadsi(113549) pkcs(1) 1 }

     rsaEncryption OBJECT IDENTIFIER ::=  { pkcs-1 1}

the rsaEncryption OID is meant to be used in the algorithm field of an AlgorithmIdentifier value. for this algorithm identifier, the parameters field shall have ASN.1 type NULL โœจ

the RSA public key shall be encoded using the ASN.1 type RSAPublicKey:

   RSAPublicKey ::= SEQUENCE {
      modulus            INTEGER, -- n
      publicExponent     INTEGER  -- e -- }

where modulus is the modulus n, and publicExponent is the public exponent e. the DER encoded RSAPublicKey is the value of the BIT STRING subjectPublicKey ๐ŸŽ€

this OID is used in public key certificates for both RSA signature keys and RSA encryption keys. the intended application for the key may be indicated in the key usage field (see sec. 4.2.1.3). using a single key for both signature and encryption purposes is not recommended, but it's not forbidden ๐ŸŒธ

if the keyUsage extension is present in an end entity certificate that conveys an RSA public key, any combination of the following values may be present: digitalSignature; nonRepudiation; keyEncipherment; and dataEncipherment. if the keyUsage extension is present in a CA certificate that conveys an RSA public key, any combination of the following values may be present: digitalSignature; nonRepudiation; keyEncipherment; dataEncipherment; keyCertSign; and cRLSign. however, this specification RECOMMENDS that if keyCertSign or cRLSign is present, both keyEncipherment and dataEncipherment should not be present ๐Ÿšจ๐Ÿ’…

7.3.2 Diffie-Hellman Key Exchange Key โœจ

okay so the Diffie-Hellman OID this profile supports comes from ANSI X9.42 [X9.42] ๐Ÿ’…

dhpublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
          us(840) ansi-x942(10046) number-type(2) 1 }

the dhpublicnumber OID goes in the algorithm field of an AlgorithmIdentifier value ๐Ÿฆ‹ its parameters field is algorithm-specific (ANY DEFINED BY algorithm), and for this algorithm that field has the ASN.1 type DomainParameters ๐ŸŽ€

DomainParameters ::= SEQUENCE {
      p       INTEGER, -- odd prime, p=jq +1
      g       INTEGER, -- generator, g
      q       INTEGER, -- factor of p-1
      j       INTEGER OPTIONAL, -- subgroup factor
      validationParms  ValidationParms OPTIONAL }

ValidationParms ::= SEQUENCE {
      seed             BIT STRING,
      pgenCounter      INTEGER }

here's what each DomainParameters field means ๐ŸŒธ

  • p identifies the prime p that defines the Galois field
  • g specifies the generator of the multiplicative subgroup of order g
  • q specifies the prime factor of p-1
  • j optionally specifies the value that satisfies the equation p=jq+1, to support the optional verification of group parameters
  • seed optionally specifies the bit string parameter used as the seed for the system parameter generation process
  • pgenCounter optionally specifies the integer value output as part of the system parameter prime generation process
โš ๏ธ bestie, if either of the parameter generation components (pgencounter or seed) shows up, the other shall be present as well. no skipping!

the Diffie-Hellman public key gets ASN.1 encoded as an INTEGER ๐Ÿงš that encoding is the contents (the value) of the subjectPublicKey component (a BIT STRING) inside the subjectPublicKeyInfo data element ๐Ÿ’œ

DHPublicKey ::= INTEGER -- public key, y = g^x mod p

and if a certificate that carries a DH public key has the keyUsage extension, these values may be there: keyAgreement; encipherOnly; and decipherOnly ๐Ÿซถ at most one of encipherOnly and decipherOnly shall be asserted in the keyUsage extension, so don't go turning on both ๐Ÿ™ˆ


7.3.3 DSA Signature Keys ๐Ÿ”ฅ

the Digital Signature Algorithm (DSA) is also known as the Digital Signature Standard (DSS) ๐ŸŒˆ the DSA OID this profile supports is:

id-dsa ID ::= { iso(1) member-body(2) us(840) x9-57(10040)
          x9cm(4) 1 }

the id-dsa algorithm syntax has optional parameters, usually called p, q, and g โœจ if they're left out, the parameters component shall be omitted entirely. so the AlgorithmIdentifier shall be a SEQUENCE with just one component, the OBJECT IDENTIFIER id-dsa ๐Ÿ“

if the DSA parameters are present in the subjectPublicKeyInfo AlgorithmIdentifier, they're included using this ASN.1 structure:

Dss-Parms  ::=  SEQUENCE  {
    p             INTEGER,
    q             INTEGER,
    g             INTEGER  }

now the tricky bit ๐Ÿ‘€ if the DSA parameters are absent from the subjectPublicKeyInfo AlgorithmIdentifier and the CA signed the subject certificate using DSA, then the certificate issuer's DSA parameters apply to the subject's DSA key ๐Ÿฆ‹ if the parameters are absent and the CA signed the subject certificate with something other than DSA, then the subject's DSA parameters are distributed by other means ๐ŸŒธ and if the subjectPublicKeyInfo AlgorithmIdentifier leaves out the parameters component and the CA signed the subject with a signature algorithm other than DSA, then clients shall reject the certificate ๐Ÿšซ no exceptions, bestie ๐Ÿ˜ญ

when DSA signs something, it generates two values, usually called r and s ๐Ÿ’– to pass those two values around as one signature, they get ASN.1 encoded with this structure:

Dss-Sig-Value  ::=  SEQUENCE  {
    r             INTEGER,
    s             INTEGER  }

the encoded signature is the value of the BIT STRING signature in a Certificate or CertificateList ๐ŸŽ€

the DSA public key shall be ASN.1 DER encoded as an INTEGER ๐Ÿงš that encoding shall be used as the contents (the value) of the subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo data element ๐Ÿ’œ

DSAPublicKey ::= INTEGER -- public key, Y

if an end entity certificate has the keyUsage extension and carries a DSA public key, any combination of these values may be present: digitalSignature; and nonRepudiation ๐ŸŒŸ

if a CA certificate has the keyUsage extension and carries a DSA public key, any combination of these values may be present: digitalSignature; nonRepudiation; keyCertSign; and cRLSign ๐Ÿ‘‘


8 References ๐Ÿ“š

[FIPS 180-1]  Federal Information Processing Standards Publication
              (FIPS PUB) 180-1, Secure Hash Standard, 17 April 1995.
              [Supersedes FIPS PUB 180 dated 11 May 1993.]

[FIPS 186]    Federal Information Processing Standards Publication
              (FIPS PUB) 186, Digital Signature Standard, 18 May
              1994.

[RC95]        Rogier, N. and Chauvaud, P., "The compression function
              of MD2 is not collision free," Presented at Selected
              Areas in Cryptography '95, May 1995.

[RFC 791]     Postel, J., "Internet Protocol", STD 5, RFC 791,
              September 1981.

[RFC 822]     Crocker, D., "Standard for the format of ARPA Internet
              text messages", STD 11, RFC 822, August 1982.

[RFC 1034]    Mockapetris, P., "Domain names - concepts and
              facilities", STD 13, RFC 1034, November 1987.

[RFC 1319]    Kaliski, B., "The MD2 Message-Digest Algorithm," RFC
              1319, April 1992.

[RFC 1321]    Rivest, R., "The MD5 Message-Digest Algorithm," RFC
              1321, April 1992.

[RFC 1422]    Kent, S.,  "Privacy Enhancement for Internet Electronic
              Mail: Part II: Certificate-Based Key Management," RFC
              1422, February 1993.

[RFC 1423]    Balenson, D., "Privacy Enhancement for Internet
              Electronic Mail: Part III: Algorithms, Modes, and
              Identifiers," RFC 1423, February 1993.

[RFC 1519]    Fuller, V., Li, T., Yu, J. and K. Varadhan. "Classless
              Inter-Domain Routing (CIDR): an Address Assignment and
              Aggregation Strategy", RFC 1519, September 1993.

[RFC 1738]    Berners-Lee, T., Masinter L., and M. McCahill.
              "Uniform Resource Locators (URL)", RFC 1738, December
              1994.

[RFC 1778]    Howes, T., Kille S., Yeong, W. and C. Robbins. "The
              String Representation of Standard Attribute Syntaxes,"
              RFC 1778, March 1995.

[RFC 1883]    Deering, S. and R. Hinden. "Internet Protocol, Version
              6 (IPv6) Specification", RFC 1883, December 1995.

[RFC 2119]    Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119, March 1997.

[RFC 2247]    Kille, S., Wahl, M., Grimstad, A., Huber, R. and S.
              Sataluri. "Using Domains in LDAP/X.500 Distinguished
              Names", RFC 2247, January 1998.

[RFC 2277]    Alvestrand, H., "IETF Policy on Character Sets and
              Languages", RFC 2277, January 1998.

[RFC 2279]    Yergeau, F., "UTF-8, a transformation format of ISO
              10646", RFC 2279, January 1998.

[RFC 2313]    Kaliski, B., "PKCS #1: RSA Encryption Version 1.5", RFC
              2313, March 1998.

[SDN.701]     SDN.701, "Message Security Protocol 4.0", Revision A
              1997-02-06.

[X.208]       CCITT Recommendation X.208: Specification of Abstract
              Syntax Notation One (ASN.1), 1988.

[X.501]       ITU-T Recommendation X.501: Information Technology -
              Open Systems Interconnection - The Directory: Models,
              1993.

[X.509]       ITU-T Recommendation X.509 (1997 E): Information
              Technology - Open Systems Interconnection - The
              Directory: Authentication Framework, June 1997.

[X.520]       ITU-T Recommendation X.520: Information Technology -
              Open Systems Interconnection - The Directory: Selected
              Attribute Types, 1993.

[X9.42]       ANSI X9.42-199x, Public Key Cryptography for The
              Financial Services Industry: Agreement of Symmetric
              Algorithm Keys Using Diffie-Hellman (Working Draft),
              December 1997.

[X9.55]       ANSI X9.55-1995, Public Key Cryptography For The
              Financial Services Industry: Extensions To Public Key
              Certificates And Certificate Revocation Lists, 8
              December, 1995.

[X9.57]       ANSI X9.57-199x, Public Key Cryptography For The
              Financial Services Industry: Certificate Management
              (Working Draft), 21 June, 1996.

9 Intellectual Property Rights ๐ŸŒˆ

okay so the IETF has been told about intellectual property rights that someone claims apply to some or all of the specification in this document ๐Ÿซถ if you want the details, you can check the online list of claimed rights.

the IETF doesn't take a position on whether any of those rights are valid or how far they reach, and it doesn't claim it has tried to find every right out there ๐Ÿ™ˆ whether a license is available for them is also up in the air. info about the IETF's rules for rights in standards-track and standards-related docs lives in BCP-11 ๐Ÿ“– and if you want copies of claimed rights, any assurances about licenses, or the outcome of any attempt to get a general license or permission to use those proprietary rights, you can ask the IETF Secretariat ๐Ÿ’…

10. Security Considerations ๐Ÿ”โœจ

okay bestie, this section is where we talk about what can go wrong ๐Ÿ˜ญ most of this spec is about the format and content of certificates and CRLs. since they're digitally signed, you don't need an extra integrity service on top ๐Ÿ’… nobody has to keep them secret either, and unrestricted, anonymous access to certs and CRLs has no security implications ๐Ÿ™ˆ

BUT, and this is lowkey important, security factors outside this spec still affect how much trust a certificate gets ๐Ÿซถ so this section is the highlight reel for implementers, admins, and users.

The procedures CAs and RAs use to check that the subject's identity really matches their public key hugely affect how much trust a cert deserves ๐ŸŽ€ relying parties might wanna look over the CA's certificate practice statement. this is especially important when the CA is issuing certs to other CAs ๐Ÿ‘‘

Using a single key pair for both signatures and other purposes is strongly discouraged ๐Ÿ’€ splitting things into separate signature and key management pairs gives users real perks. losing or leaking a signature key is a different situation than losing or leaking a key management key, and separate pairs let you respond in a balanced, flexible way ๐Ÿฆ‹ validity periods or key lengths can also differ for each pair depending on the app environment ๐ŸŒธ sadly, some legacy apps (e.g., SSL) use one pair for both, which is the tea ๐Ÿต

Protecting private keys is everything ๐Ÿ”ฅ on a small scale, if users don't protect theirs, an attacker can pretend to be them or decrypt their personal info. on a larger scale, compromising a CA's private signing key can be catastrophic ๐Ÿ˜ฑ if an attacker grabs it unnoticed, they can issue bogus certs and CRLs, and bogus certs and CRLs wreck confidence in the whole system. if the compromise gets detected, all certs issued to the CA shall be revoked, which cuts off services between its users and users of other CAs ๐Ÿ’” rebuilding after that is a nightmare, so CAs are advised to combine strong technical measures (e.g., tamper-resistant cryptographic modules) with solid management procedures (e.g., separation of duties) to avoid this ๐Ÿ›ก๏ธ

losing a CA's private signing key is a whole other problem too ๐Ÿ™ƒ

Losing a CA's private signing key is also problematic ๐Ÿ™ƒ the CA wouldn't be able to produce CRLs or do normal key rollover. CAs are advised to keep secure backups of their signing keys, and how secure those backup procedures are is a critical factor in avoiding key compromise ๐Ÿ”

Revocation info is a big deal ๐Ÿฆ‹ how available and fresh it is affects how much assurance a cert deserves. certs expire naturally, but events can happen during their lifetime that break the binding between the subject and the public key. if revocation info is untimely or unavailable, the assurance attached to that binding is clearly reduced. similarly, Path Validation implementations (see section 6) that skip revocation checking give less assurance than the ones that support it ๐Ÿ™…

Path validation depends on certain knowledge of the public keys (and other info) for one or more trusted CAs ๐Ÿ‘‘ deciding to trust a CA is an important choice, since it ultimately decides how much trust a certificate gets. getting trusted CA public keys (usually as a "self-signed" cert) through an authenticated distribution is a security-critical out-of-band process, and it's beyond the scope of this spec ๐Ÿงš

If a trusted CA has a key compromise or a failure, the user will need to update the info given to the path validation routine ๐Ÿ˜ค trusting too many CAs makes that info hard to maintain, but trusting only one might trap users in a closed community until a global PKI emerges ๐ŸŒ

Implementation quality matters too โœจ path validation relies on the integrity of the trusted CA info, especially the integrity of the public keys tied to those trusted CAs. if an attacker swaps in public keys they hold the private key for, they could trick the user into accepting false certs ๐Ÿ˜ˆ

The binding between a key and a cert subject can't be stronger than the crypto module implementation and the algorithms used to generate the signature ๐Ÿ’… short key lengths or weak hash algorithms limit how useful a cert is. CAs are encouraged to keep up with advances in cryptology so they can use strong techniques ๐ŸŒˆ and CAs should decline to issue certs to CAs or end entities that generate weak signatures ๐Ÿšซ

Name comparison is another trap ๐Ÿคฏ inconsistent application of the rules can get you accepting invalid X.509 certification paths, or rejecting valid ones. the X.500 series defines rules for comparing distinguished names that require comparing strings without regard to case, character set, multi-character white space substring, or leading and trailing white space. this specification relaxes those requirements and only requires binary comparison as a minimum ๐ŸŽ€

CAs shall encode the distinguished name in the subject field of a CA cert identically to the distinguished name in the issuer field of certs issued by that latter CA ๐Ÿ’– if CAs use different encodings, implementations of this spec may fail to recognize name chains for paths that include that cert. as a result, valid paths could get rejected ๐Ÿ˜ญ

Name constraints for distinguished names shall be stated identically to the encoding used in the subject field or subjectAltName extension ๐Ÿ“ if they aren't:

  • (1) name constraints stated as excludedSubTrees won't match, and invalid paths will be accepted
  • (2) name constraints expressed as permittedSubtrees won't match, and valid paths will be rejected

to avoid accepting invalid paths, CAs should state name constraints for distinguished names as permittedSubtrees wherever possible ๐Ÿ’œ


Appendix A. Psuedo-ASN.1 Structures and OIDs ๐Ÿงธ

This section describes the data objects used by conforming PKI components in an "ASN.1-like" syntax ๐Ÿ“ the syntax is a hybrid of the 1988 and 1993 ASN.1 syntaxes. the 1988 ASN.1 syntax gets augmented with the 1993 UNIVERSAL Types UniversalString, BMPString and UTF8String.

ngl, this is where the nerdy stuff gets real ๐Ÿค“ the ASN.1 syntax doesn't allow type statements in the ASN.1 module, and the 1993 ASN.1 standard doesn't allow the new UNIVERSAL types in modules that use the 1988 syntax. so this module doesn't conform to either version of the ASN.1 standard ๐Ÿ™ˆ

This appendix may be converted into 1988 ASN.1 by replacing the defintions for the UNIVERSAL Types with the 1988 catch-all "ANY" ๐Ÿฆ‹

A.1. Explicitly Tagged Module, 1988 Syntax

PKIX1Explicit88 {iso(1) identified-organization(3) dod(6) internet(1)
  security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-explicit-88(1)}


DEFINITIONS EXPLICIT TAGS ::=

BEGIN

-- EXPORTS ALL --

-- IMPORTS NONE --

-- UNIVERSAL Types defined in '93 and '98 ASN.1
-- but required by this specification

UniversalString ::= [UNIVERSAL 28] IMPLICIT OCTET STRING
        -- UniversalString is defined in ASN.1:1993

BMPString ::= [UNIVERSAL 30] IMPLICIT OCTET STRING
      -- BMPString is the subtype of UniversalString and models
       -- the Basic Multilingual Plane of ISO/IEC/ITU 10646-1

UTF8String ::= [UNIVERSAL 12] IMPLICIT OCTET STRING
        -- The content of this type conforms to RFC 2279.

--
-- PKIX specific OIDs

id-pkix  OBJECT IDENTIFIER  ::=
         { iso(1) identified-organization(3) dod(6) internet(1)

                    security(5) mechanisms(5) pkix(7) }
-- PKIX arcs

id-pe OBJECT IDENTIFIER  ::=  { id-pkix 1 }
        -- arc for private certificate extensions
id-qt OBJECT IDENTIFIER ::= { id-pkix 2 }
        -- arc for policy qualifier types
id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
        -- arc for extended key purpose OIDS
id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
        -- arc for access descriptors

-- policyQualifierIds for Internet policy qualifiers

id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }
        -- OID for CPS qualifier
id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }
        -- OID for user notice qualifier

-- access descriptor definitions

id-ad-ocsp      OBJECT IDENTIFIER ::= { id-ad 1 }
id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }

-- attribute data types --

Attribute       ::=     SEQUENCE {
        type            AttributeType,
        values  SET OF AttributeValue
                -- at least one value is required -- }

AttributeType           ::=   OBJECT IDENTIFIER

AttributeValue          ::=   ANY

AttributeTypeAndValue           ::=     SEQUENCE {
        type    AttributeType,
        value   AttributeValue }

-- suggested naming attributes: Definition of the following
--  information object set may be augmented to meet local
--  requirements.  Note that deleting members of the set may
--  prevent interoperability with conforming implementations.
--  presented in pairs: the AttributeType followed by the
--  type definition for the corresponding AttributeValue

--Arc for standard naming attributes
id-at           OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4}
-- Attributes of type NameDirectoryString
id-at-name              AttributeType   ::=     {id-at 41}
id-at-surname           AttributeType   ::=     {id-at 4}
id-at-givenName         AttributeType   ::=     {id-at 42}
id-at-initials          AttributeType   ::=     {id-at 43}
id-at-generationQualifier       AttributeType   ::=     {id-at 44}

X520name        ::= CHOICE {
      teletexString         TeletexString (SIZE (1..ub-name)),
      printableString       PrintableString (SIZE (1..ub-name)),
      universalString       UniversalString (SIZE (1..ub-name)),
      utf8String            UTF8String (SIZE (1..ub-name)),
      bmpString             BMPString (SIZE(1..ub-name))   }

--

id-at-commonName        AttributeType   ::=     {id-at 3}

X520CommonName  ::=      CHOICE {
      teletexString         TeletexString (SIZE (1..ub-common-name)),
      printableString       PrintableString (SIZE (1..ub-common-name)),
      universalString       UniversalString (SIZE (1..ub-common-name)),
      utf8String            UTF8String (SIZE (1..ub-common-name)),
      bmpString             BMPString (SIZE(1..ub-common-name))   }

--

id-at-localityName      AttributeType   ::=     {id-at 7}

X520LocalityName ::= CHOICE {
      teletexString       TeletexString (SIZE (1..ub-locality-name)),
      printableString     PrintableString (SIZE (1..ub-locality-name)),
      universalString     UniversalString (SIZE (1..ub-locality-name)),
      utf8String          UTF8String (SIZE (1..ub-locality-name)),
      bmpString           BMPString (SIZE(1..ub-locality-name))   }

Okay, the X520 attribute types are up next, and they're giving layers ๐Ÿ’…

id-at-stateOrProvinceName       AttributeType   ::=     {id-at 8}

X520StateOrProvinceName         ::= CHOICE {
      teletexString       TeletexString (SIZE (1..ub-state-name)),
      printableString     PrintableString (SIZE (1..ub-state-name)),
      universalString     UniversalString (SIZE (1..ub-state-name)),
      utf8String          UTF8String (SIZE (1..ub-state-name)),
      bmpString           BMPString (SIZE(1..ub-state-name))   }

--
id-at-organizationName          AttributeType   ::=     {id-at 10}

X520OrganizationName ::= CHOICE {
  teletexString     TeletexString (SIZE (1..ub-organization-name)),
  printableString   PrintableString (SIZE (1..ub-organization-name)),
  universalString   UniversalString (SIZE (1..ub-organization-name)),
  utf8String        UTF8String (SIZE (1..ub-organization-name)),
  bmpString         BMPString (SIZE(1..ub-organization-name))   }

--

id-at-organizationalUnitName    AttributeType   ::=     {id-at 11}

X520OrganizationalUnitName ::= CHOICE {
 teletexString    TeletexString (SIZE (1..ub-organizational-unit-name)),
 printableString        PrintableString
                      (SIZE (1..ub-organizational-unit-name)),
 universalString        UniversalString
                      (SIZE (1..ub-organizational-unit-name)),
 utf8String       UTF8String (SIZE (1..ub-organizational-unit-name)),
 bmpString        BMPString (SIZE(1..ub-organizational-unit-name))   }

--

id-at-title     AttributeType   ::=     {id-at 12}

X520Title ::=   CHOICE {
      teletexString         TeletexString (SIZE (1..ub-title)),
      printableString       PrintableString (SIZE (1..ub-title)),
      universalString       UniversalString (SIZE (1..ub-title)),
      utf8String            UTF8String (SIZE (1..ub-title)),
      bmpString             BMPString (SIZE(1..ub-title))   }

--

id-at-dnQualifier       AttributeType   ::=     {id-at 46}
X520dnQualifier ::=     PrintableString

id-at-countryName       AttributeType   ::=     {id-at 6}
X520countryName ::=     PrintableString (SIZE (2)) -- IS 3166 codes


 -- Legacy attributes

pkcs-9 OBJECT IDENTIFIER ::=
       { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 }

emailAddress AttributeType      ::= { pkcs-9 1 }
Pkcs9email ::= IA5String (SIZE (1..ub-emailaddress-length))

-- naming data types --

Name            ::=   CHOICE { -- only one possibility for now --
                                 rdnSequence  RDNSequence }

RDNSequence     ::=   SEQUENCE OF RelativeDistinguishedName

DistinguishedName       ::=   RDNSequence

RelativeDistinguishedName  ::=
                    SET SIZE (1 .. MAX) OF AttributeTypeAndValue

-- Directory string type --

DirectoryString ::= CHOICE {
      teletexString             TeletexString (SIZE (1..MAX)),
      printableString           PrintableString (SIZE (1..MAX)),
      universalString           UniversalString (SIZE (1..MAX)),
      utf8String              UTF8String (SIZE (1..MAX)),
      bmpString               BMPString (SIZE(1..MAX))   }

-- certificate and CRL specific structures begin here

Certificate  ::=  SEQUENCE  {
     tbsCertificate       TBSCertificate,
     signatureAlgorithm   AlgorithmIdentifier,
     signature            BIT STRING  }

TBSCertificate  ::=  SEQUENCE  {
     version         [0]  Version DEFAULT v1,
     serialNumber         CertificateSerialNumber,
     signature            AlgorithmIdentifier,
     issuer               Name,
     validity             Validity,
     subject              Name,
     subjectPublicKeyInfo SubjectPublicKeyInfo,
     issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
                          -- If present, version shall be v2 or v3
     subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
                          -- If present, version shall be v2 or v3
     extensions      [3]  Extensions OPTIONAL
                          -- If present, version shall be v3 --  }

Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }

CertificateSerialNumber  ::=  INTEGER
Validity ::= SEQUENCE {
     notBefore      Time,
     notAfter       Time }

Time ::= CHOICE {
     utcTime        UTCTime,
     generalTime    GeneralizedTime }

UniqueIdentifier  ::=  BIT STRING

SubjectPublicKeyInfo  ::=  SEQUENCE  {
     algorithm            AlgorithmIdentifier,
     subjectPublicKey     BIT STRING  }

Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension

Extension  ::=  SEQUENCE  {
     extnID      OBJECT IDENTIFIER,
     critical    BOOLEAN DEFAULT FALSE,
     extnValue   OCTET STRING  }

-- CRL structures

CertificateList  ::=  SEQUENCE  {
     tbsCertList          TBSCertList,
     signatureAlgorithm   AlgorithmIdentifier,
     signature            BIT STRING  }

TBSCertList  ::=  SEQUENCE  {
     version                 Version OPTIONAL,
                                  -- if present, shall be v2
     signature               AlgorithmIdentifier,
     issuer                  Name,
     thisUpdate              Time,
     nextUpdate              Time OPTIONAL,
     revokedCertificates     SEQUENCE OF SEQUENCE  {
          userCertificate         CertificateSerialNumber,
          revocationDate          Time,
          crlEntryExtensions      Extensions OPTIONAL
                                         -- if present, shall be v2
                               }  OPTIONAL,
     crlExtensions           [0] Extensions OPTIONAL
                                         -- if present, shall be v2 -- }

-- Version, Time, CertificateSerialNumber, and Extensions were
-- defined earlier for use in the certificate structure

AlgorithmIdentifier  ::=  SEQUENCE  {

     algorithm               OBJECT IDENTIFIER,
     parameters              ANY DEFINED BY algorithm OPTIONAL  }
                                -- contains a value of the type
                                -- registered for use with the
                                -- algorithm object identifier value

-- Algorithm OIDs and parameter structures

pkcs-1 OBJECT IDENTIFIER ::= {
     iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }

rsaEncryption OBJECT IDENTIFIER ::=  { pkcs-1 1 }

md2WithRSAEncryption OBJECT IDENTIFIER  ::=  { pkcs-1 2 }

md5WithRSAEncryption OBJECT IDENTIFIER  ::=  { pkcs-1 4 }

sha1WithRSAEncryption OBJECT IDENTIFIER  ::=  { pkcs-1 5 }

id-dsa-with-sha1 OBJECT IDENTIFIER ::=  {
     iso(1) member-body(2) us(840) x9-57 (10040) x9algorithm(4) 3 }

Dss-Sig-Value  ::=  SEQUENCE  {
     r       INTEGER,
     s       INTEGER  }

dhpublicnumber OBJECT IDENTIFIER ::= {
     iso(1) member-body(2) us(840) ansi-x942(10046) number-type(2) 1 }

DomainParameters ::= SEQUENCE {
     p       INTEGER, -- odd prime, p=jq +1
     g       INTEGER, -- generator, g
     q       INTEGER, -- factor of p-1
     j       INTEGER OPTIONAL, -- subgroup factor, j>= 2
     validationParms  ValidationParms OPTIONAL }

ValidationParms ::= SEQUENCE {
     seed             BIT STRING,
     pgenCounter      INTEGER }

id-dsa OBJECT IDENTIFIER ::= {
     iso(1) member-body(2) us(840) x9-57(10040) x9algorithm(4) 1 }

Dss-Parms  ::=  SEQUENCE  {
     p             INTEGER,
     q             INTEGER,
     g             INTEGER  }

-- x400 address syntax starts here
--      OR Names

ORAddress ::= SEQUENCE {
   built-in-standard-attributes BuiltInStandardAttributes,
   built-in-domain-defined-attributes
                        BuiltInDomainDefinedAttributes OPTIONAL,
   -- see also teletex-domain-defined-attributes
   extension-attributes ExtensionAttributes OPTIONAL }
--      The OR-address is semantically absent from the OR-name if the
--      built-in-standard-attribute sequence is empty and the
--      built-in-domain-defined-attributes and extension-attributes are
--      both omitted.

--      Built-in Standard Attributes

BuiltInStandardAttributes ::= SEQUENCE {
   country-name CountryName OPTIONAL,
   administration-domain-name AdministrationDomainName OPTIONAL,
   network-address      [0] NetworkAddress OPTIONAL,
   -- see also extended-network-address
   terminal-identifier  [1] TerminalIdentifier OPTIONAL,
   private-domain-name  [2] PrivateDomainName OPTIONAL,
   organization-name    [3] OrganizationName OPTIONAL,
   -- see also teletex-organization-name
   numeric-user-identifier      [4] NumericUserIdentifier OPTIONAL,
   personal-name        [5] PersonalName OPTIONAL,
   -- see also teletex-personal-name
   organizational-unit-names    [6] OrganizationalUnitNames OPTIONAL
   -- see also teletex-organizational-unit-names -- }

CountryName ::= [APPLICATION 1] CHOICE {
   x121-dcc-code NumericString
                (SIZE (ub-country-name-numeric-length)),
   iso-3166-alpha2-code PrintableString
                (SIZE (ub-country-name-alpha-length)) }

AdministrationDomainName ::= [APPLICATION 2] CHOICE {
   numeric NumericString (SIZE (0..ub-domain-name-length)),
   printable PrintableString (SIZE (0..ub-domain-name-length)) }

NetworkAddress ::= X121Address  -- see also extended-network-address

X121Address ::= NumericString (SIZE (1..ub-x121-address-length))

TerminalIdentifier ::= PrintableString (SIZE (1..ub-terminal-id-length))

PrivateDomainName ::= CHOICE {

   numeric NumericString (SIZE (1..ub-domain-name-length)),
   printable PrintableString (SIZE (1..ub-domain-name-length)) }

OrganizationName ::= PrintableString
                            (SIZE (1..ub-organization-name-length))
-- see also teletex-organization-name

NumericUserIdentifier ::= NumericString
                            (SIZE (1..ub-numeric-user-id-length))

PersonalName ::= SET {
   surname [0] PrintableString (SIZE (1..ub-surname-length)),
   given-name [1] PrintableString
                        (SIZE (1..ub-given-name-length)) OPTIONAL,
   initials [2] PrintableString (SIZE (1..ub-initials-length)) OPTIONAL,
   generation-qualifier [3] PrintableString
                (SIZE (1..ub-generation-qualifier-length)) OPTIONAL }
-- see also teletex-personal-name

OrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units)
                                        OF OrganizationalUnitName
-- see also teletex-organizational-unit-names

OrganizationalUnitName ::= PrintableString (SIZE
                        (1..ub-organizational-unit-name-length))

--      Built-in Domain-defined Attributes

BuiltInDomainDefinedAttributes ::= SEQUENCE SIZE
                                (1..ub-domain-defined-attributes) OF
                                BuiltInDomainDefinedAttribute

BuiltInDomainDefinedAttribute ::= SEQUENCE {
   type PrintableString (SIZE
                        (1..ub-domain-defined-attribute-type-length)),
   value PrintableString (SIZE
                        (1..ub-domain-defined-attribute-value-length))}

--      Extension Attributes

ExtensionAttributes ::= SET SIZE (1..ub-extension-attributes) OF
                        ExtensionAttribute

ExtensionAttribute ::=  SEQUENCE {
   extension-attribute-type [0] INTEGER (0..ub-extension-attributes),
   extension-attribute-value [1]
                        ANY DEFINED BY extension-attribute-type }

-- Extension types and attribute values
--

common-name INTEGER ::= 1

CommonName ::= PrintableString (SIZE (1..ub-common-name-length))

teletex-common-name INTEGER ::= 2

TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-length))

teletex-organization-name INTEGER ::= 3

TeletexOrganizationName ::=
                TeletexString (SIZE (1..ub-organization-name-length))

teletex-personal-name INTEGER ::= 4

TeletexPersonalName ::= SET {
   surname [0] TeletexString (SIZE (1..ub-surname-length)),
   given-name [1] TeletexString
                (SIZE (1..ub-given-name-length)) OPTIONAL,
   initials [2] TeletexString (SIZE (1..ub-initials-length)) OPTIONAL,
   generation-qualifier [3] TeletexString (SIZE
                (1..ub-generation-qualifier-length)) OPTIONAL }

teletex-organizational-unit-names INTEGER ::= 5

That's the whole certificate and CRL skeleton, plus the X.400 address bits, all laid out in one place ๐Ÿงš

Next up, the TeletexOrganizationalUnitNames definition. Stay tuned, bestie ๐ŸŽ€

TeletexOrganizationalUnitNames ::= SEQUENCE SIZE
        (1..ub-organizational-units) OF TeletexOrganizationalUnitName

TeletexOrganizationalUnitName ::= TeletexString
                        (SIZE (1..ub-organizational-unit-name-length))

pds-name INTEGER ::= 7

PDSName ::= PrintableString (SIZE (1..ub-pds-name-length))

physical-delivery-country-name INTEGER ::= 8

PhysicalDeliveryCountryName ::= CHOICE {
   x121-dcc-code NumericString (SIZE (ub-country-name-numeric-length)),
   iso-3166-alpha2-code PrintableString
                        (SIZE (ub-country-name-alpha-length)) }

postal-code INTEGER ::= 9

PostalCode ::= CHOICE {

   numeric-code NumericString (SIZE (1..ub-postal-code-length)),
   printable-code PrintableString (SIZE (1..ub-postal-code-length)) }

physical-delivery-office-name INTEGER ::= 10

PhysicalDeliveryOfficeName ::= PDSParameter

physical-delivery-office-number INTEGER ::= 11

PhysicalDeliveryOfficeNumber ::= PDSParameter

extension-OR-address-components INTEGER ::= 12

ExtensionORAddressComponents ::= PDSParameter

physical-delivery-personal-name INTEGER ::= 13

PhysicalDeliveryPersonalName ::= PDSParameter

physical-delivery-organization-name INTEGER ::= 14

PhysicalDeliveryOrganizationName ::= PDSParameter

extension-physical-delivery-address-components INTEGER ::= 15

ExtensionPhysicalDeliveryAddressComponents ::= PDSParameter

unformatted-postal-address INTEGER ::= 16

UnformattedPostalAddress ::= SET {
   printable-address SEQUENCE SIZE (1..ub-pds-physical-address-lines) OF
           PrintableString (SIZE (1..ub-pds-parameter-length)) OPTIONAL,
   teletex-string TeletexString
         (SIZE (1..ub-unformatted-address-length)) OPTIONAL }

street-address INTEGER ::= 17

StreetAddress ::= PDSParameter

post-office-box-address INTEGER ::= 18

PostOfficeBoxAddress ::= PDSParameter

poste-restante-address INTEGER ::= 19

PosteRestanteAddress ::= PDSParameter

unique-postal-name INTEGER ::= 20
UniquePostalName ::= PDSParameter

local-postal-attributes INTEGER ::= 21

LocalPostalAttributes ::= PDSParameter

PDSParameter ::= SET {
   printable-string PrintableString
                (SIZE(1..ub-pds-parameter-length)) OPTIONAL,
   teletex-string TeletexString
                (SIZE(1..ub-pds-parameter-length)) OPTIONAL }

extended-network-address INTEGER ::= 22

ExtendedNetworkAddress ::= CHOICE {
   e163-4-address SEQUENCE {
        number [0] NumericString (SIZE (1..ub-e163-4-number-length)),
        sub-address [1] NumericString
                (SIZE (1..ub-e163-4-sub-address-length)) OPTIONAL },
   psap-address [0] PresentationAddress }

PresentationAddress ::= SEQUENCE {
        pSelector       [0] EXPLICIT OCTET STRING OPTIONAL,
        sSelector       [1] EXPLICIT OCTET STRING OPTIONAL,
        tSelector       [2] EXPLICIT OCTET STRING OPTIONAL,
        nAddresses      [3] EXPLICIT SET SIZE (1..MAX) OF OCTET STRING }

terminal-type  INTEGER ::= 23

TerminalType ::= INTEGER {
   telex (3),
   teletex (4),
   g3-facsimile (5),
   g4-facsimile (6),
   ia5-terminal (7),
   videotex (8) } (0..ub-integer-options)

--      Extension Domain-defined Attributes

teletex-domain-defined-attributes INTEGER ::= 6

TeletexDomainDefinedAttributes ::= SEQUENCE SIZE
   (1..ub-domain-defined-attributes) OF TeletexDomainDefinedAttribute

TeletexDomainDefinedAttribute ::= SEQUENCE {
        type TeletexString
               (SIZE (1..ub-domain-defined-attribute-type-length)),
        value TeletexString

               (SIZE (1..ub-domain-defined-attribute-value-length)) }

--  specifications of Upper Bounds shall be regarded as mandatory
--  from Annex B of ITU-T X.411 Reference Definition of MTS Parameter
--  Upper Bounds

--      Upper Bounds
ub-name INTEGER ::=     32768
ub-common-name  INTEGER ::=     64
ub-locality-name        INTEGER ::=     128
ub-state-name   INTEGER ::=     128
ub-organization-name    INTEGER ::=     64
ub-organizational-unit-name     INTEGER ::=     64
ub-title        INTEGER ::=     64
ub-match        INTEGER ::=     128

ub-emailaddress-length INTEGER ::= 128

ub-common-name-length INTEGER ::= 64
ub-country-name-alpha-length INTEGER ::= 2
ub-country-name-numeric-length INTEGER ::= 3
ub-domain-defined-attributes INTEGER ::= 4
ub-domain-defined-attribute-type-length INTEGER ::= 8
ub-domain-defined-attribute-value-length INTEGER ::= 128
ub-domain-name-length INTEGER ::= 16
ub-extension-attributes INTEGER ::= 256
ub-e163-4-number-length INTEGER ::= 15
ub-e163-4-sub-address-length INTEGER ::= 40
ub-generation-qualifier-length INTEGER ::= 3
ub-given-name-length INTEGER ::= 16
ub-initials-length INTEGER ::= 5
ub-integer-options INTEGER ::= 256
ub-numeric-user-id-length INTEGER ::= 32
ub-organization-name-length INTEGER ::= 64
ub-organizational-unit-name-length INTEGER ::= 32
ub-organizational-units INTEGER ::= 4
ub-pds-name-length INTEGER ::= 16
ub-pds-parameter-length INTEGER ::= 30
ub-pds-physical-address-lines INTEGER ::= 6
ub-postal-code-length INTEGER ::= 16
ub-surname-length INTEGER ::= 40
ub-terminal-id-length INTEGER ::= 24
ub-unformatted-address-length INTEGER ::= 180
ub-x121-address-length INTEGER ::= 16

-- Note - upper bounds on string types, such as TeletexString, are
-- measured in characters.  Excepting PrintableString or IA5String, a
-- significantly greater number of octets will be required to hold
-- such a value.  As a minimum, 16 octets, or twice the specified upper
-- bound, whichever is the larger, should be allowed for TeletexString.
-- For UTF8String or UniversalString at least four times the upper
-- bound should be allowed.

END

A.2 Implicitly Tagged Module, 1988 Syntax ๐ŸŽ€

okay bestie, now we swap into the IMPLICIT TAGS version ๐Ÿ’… same cast of characters, just a different tagging vibe, so pay attention to the header ๐Ÿ‘€

PKIX1Implicit88 {iso(1) identified-organization(3) dod(6) internet(1)
  security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-implicit-88(2)}

DEFINITIONS IMPLICIT TAGS ::=

BEGIN

-- EXPORTS ALL --

IMPORTS
        id-pkix, id-pe, id-qt, id-kp, id-qt-unotice, id-qt-cps,
            id-ad, id-ad-ocsp, id-ad-caIssuers,
            -- delete following line if "new" types are supported --
            BMPString, UniversalString, UTF8String, -- end "new" types
                ORAddress, Name, RelativeDistinguishedName,
                CertificateSerialNumber,
                CertificateList, AlgorithmIdentifier, ub-name,
                Attribute, DirectoryString
                FROM PKIX1Explicit88 {iso(1) identified-organization(3)
                dod(6) internet(1) security(5) mechanisms(5) pkix(7)
                id-mod(0) id-pkix1-explicit(1)};


-- ISO arc for standard certificate and CRL extensions

id-ce OBJECT IDENTIFIER  ::=  {joint-iso-ccitt(2) ds(5) 29}

-- authority key identifier OID and syntax

id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 }

AuthorityKeyIdentifier ::= SEQUENCE {
      keyIdentifier             [0] KeyIdentifier            OPTIONAL,
      authorityCertIssuer       [1] GeneralNames             OPTIONAL,
      authorityCertSerialNumber [2] CertificateSerialNumber  OPTIONAL }
    -- authorityCertIssuer and authorityCertSerialNumber shall both
    -- be present or both be absent

KeyIdentifier ::= OCTET STRING

-- subject key identifier OID and syntax

id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 14 }

SubjectKeyIdentifier ::= KeyIdentifier
-- key usage extension OID and syntax

id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }

KeyUsage ::= BIT STRING {
     digitalSignature        (0),
     nonRepudiation          (1),
     keyEncipherment         (2),
     dataEncipherment        (3),
     keyAgreement            (4),
     keyCertSign             (5),
     cRLSign                 (6),
     encipherOnly            (7),
     decipherOnly            (8) }

-- private key usage period extension OID and syntax

id-ce-privateKeyUsagePeriod OBJECT IDENTIFIER ::=  { id-ce 16 }

PrivateKeyUsagePeriod ::= SEQUENCE {
     notBefore       [0]     GeneralizedTime OPTIONAL,
     notAfter        [1]     GeneralizedTime OPTIONAL }
     -- either notBefore or notAfter shall be present

-- certificate policies extension OID and syntax

id-ce-certificatePolicies OBJECT IDENTIFIER ::=  { id-ce 32 }

CertificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation

PolicyInformation ::= SEQUENCE {
     policyIdentifier   CertPolicyId,
     policyQualifiers   SEQUENCE SIZE (1..MAX) OF
             PolicyQualifierInfo OPTIONAL }

CertPolicyId ::= OBJECT IDENTIFIER

PolicyQualifierInfo ::= SEQUENCE {
       policyQualifierId  PolicyQualifierId,
       qualifier        ANY DEFINED BY policyQualifierId }

-- Implementations that recognize additional policy qualifiers shall
-- augment the following definition for PolicyQualifierId

PolicyQualifierId ::=
    OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )

-- CPS pointer qualifier
CPSuri ::= IA5String

-- user notice qualifier

UserNotice ::= SEQUENCE {
     noticeRef        NoticeReference OPTIONAL,
     explicitText     DisplayText OPTIONAL}

NoticeReference ::= SEQUENCE {
     organization     DisplayText,
     noticeNumbers    SEQUENCE OF INTEGER }

DisplayText ::= CHOICE {
     visibleString    VisibleString  (SIZE (1..200)),
     bmpString        BMPString      (SIZE (1..200)),
     utf8String       UTF8String     (SIZE (1..200)) }

-- policy mapping extension OID and syntax

id-ce-policyMappings OBJECT IDENTIFIER ::=  { id-ce 33 }

PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
     issuerDomainPolicy      CertPolicyId,
     subjectDomainPolicy     CertPolicyId }

-- subject alternative name extension OID and syntax

id-ce-subjectAltName OBJECT IDENTIFIER ::=  { id-ce 17 }

SubjectAltName ::= GeneralNames

GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName

GeneralName ::= CHOICE {
     otherName                       [0]     AnotherName,
     rfc822Name                      [1]     IA5String,
     dNSName                         [2]     IA5String,
     x400Address                     [3]     ORAddress,
     directoryName                   [4]     Name,
     ediPartyName                    [5]     EDIPartyName,
     uniformResourceIdentifier       [6]     IA5String,
     iPAddress                       [7]     OCTET STRING,
     registeredID                    [8]     OBJECT IDENTIFIER }

-- AnotherName replaces OTHER-NAME ::= TYPE-IDENTIFIER, as
-- TYPE-IDENTIFIER is not supported in the '88 ASN.1 syntax

AnotherName ::= SEQUENCE {

     type-id    OBJECT IDENTIFIER,
     value      [0] EXPLICIT ANY DEFINED BY type-id }

EDIPartyName ::= SEQUENCE {
     nameAssigner            [0]     DirectoryString OPTIONAL,
     partyName               [1]     DirectoryString }

-- issuer alternative name extension OID and syntax

id-ce-issuerAltName OBJECT IDENTIFIER ::=  { id-ce 18 }

IssuerAltName ::= GeneralNames

id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::=  { id-ce 9 }

SubjectDirectoryAttributes ::= SEQUENCE SIZE (1..MAX) OF Attribute

-- basic constraints extension OID and syntax

id-ce-basicConstraints OBJECT IDENTIFIER ::=  { id-ce 19 }

BasicConstraints ::= SEQUENCE {
     cA                      BOOLEAN DEFAULT FALSE,
     pathLenConstraint       INTEGER (0..MAX) OPTIONAL }

-- name constraints extension OID and syntax

id-ce-nameConstraints OBJECT IDENTIFIER ::=  { id-ce 30 }

NameConstraints ::= SEQUENCE {
     permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
     excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }

GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree

GeneralSubtree ::= SEQUENCE {
     base                    GeneralName,
     minimum         [0]     BaseDistance DEFAULT 0,
     maximum         [1]     BaseDistance OPTIONAL }

BaseDistance ::= INTEGER (0..MAX)

-- policy constraints extension OID and syntax

id-ce-policyConstraints OBJECT IDENTIFIER ::=  { id-ce 36 }

PolicyConstraints ::= SEQUENCE {
     requireExplicitPolicy           [0] SkipCerts OPTIONAL,
     inhibitPolicyMapping            [1] SkipCerts OPTIONAL }

SkipCerts ::= INTEGER (0..MAX)

okay so the next bit is all about where to find your CRL and why it matters ๐Ÿฆ‹ it's giving "distribution," but make it spicy ๐ŸŒธ

-- CRL distribution points extension OID and syntax

id-ce-cRLDistributionPoints     OBJECT IDENTIFIER  ::=  {id-ce 31}

CRLDistPointsSyntax ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint

DistributionPoint ::= SEQUENCE {
     distributionPoint       [0]     DistributionPointName OPTIONAL,
     reasons                 [1]     ReasonFlags OPTIONAL,
     cRLIssuer               [2]     GeneralNames OPTIONAL }

DistributionPointName ::= CHOICE {
     fullName                [0]     GeneralNames,
     nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }

ReasonFlags ::= BIT STRING {
     unused                  (0),
     keyCompromise           (1),
     cACompromise            (2),
     affiliationChanged      (3),
     superseded              (4),
     cessationOfOperation    (5),
     certificateHold         (6) }

okay the extended key usage extension is so iconic ๐Ÿ‘‘ it's basically the "what is this cert allowed to do" tag ๐Ÿ’…

-- extended key usage extension OID and syntax

id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37}

ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId

KeyPurposeId ::= OBJECT IDENTIFIER

-- extended key purpose OIDs
id-kp-serverAuth      OBJECT IDENTIFIER ::= { id-kp 1 }
id-kp-clientAuth      OBJECT IDENTIFIER ::= { id-kp 2 }
id-kp-codeSigning     OBJECT IDENTIFIER ::= { id-kp 3 }
id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 }
id-kp-ipsecEndSystem  OBJECT IDENTIFIER ::= { id-kp 5 }
id-kp-ipsecTunnel     OBJECT IDENTIFIER ::= { id-kp 6 }
id-kp-ipsecUser       OBJECT IDENTIFIER ::= { id-kp 7 }
id-kp-timeStamping    OBJECT IDENTIFIER ::= { id-kp 8 }

-- authority info access
id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }

AuthorityInfoAccessSyntax  ::=
        SEQUENCE SIZE (1..MAX) OF AccessDescription

AccessDescription  ::=  SEQUENCE {
        accessMethod          OBJECT IDENTIFIER,
        accessLocation        GeneralName  }

-- CRL number extension OID and syntax

id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 }

CRLNumber ::= INTEGER (0..MAX)

-- issuing distribution point extension OID and syntax

id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 }

IssuingDistributionPoint ::= SEQUENCE {
     distributionPoint       [0] DistributionPointName OPTIONAL,
     onlyContainsUserCerts   [1] BOOLEAN DEFAULT FALSE,
     onlyContainsCACerts     [2] BOOLEAN DEFAULT FALSE,
     onlySomeReasons         [3] ReasonFlags OPTIONAL,
     indirectCRL             [4] BOOLEAN DEFAULT FALSE }


id-ce-deltaCRLIndicator OBJECT IDENTIFIER ::= { id-ce 27 }

-- deltaCRLIndicator ::= BaseCRLNumber

BaseCRLNumber ::= CRLNumber

-- CRL reasons extension OID and syntax

id-ce-cRLReasons OBJECT IDENTIFIER ::= { id-ce 21 }

CRLReason ::= ENUMERATED {
     unspecified             (0),
     keyCompromise           (1),
     cACompromise            (2),
     affiliationChanged      (3),
     superseded              (4),
     cessationOfOperation    (5),
     certificateHold         (6),
     removeFromCRL           (8) }

-- certificate issuer CRL entry extension OID and syntax
id-ce-certificateIssuer OBJECT IDENTIFIER ::= { id-ce 29 }

CertificateIssuer ::= GeneralNames

-- hold instruction extension OID and syntax

id-ce-holdInstructionCode OBJECT IDENTIFIER ::= { id-ce 23 }

HoldInstructionCode ::= OBJECT IDENTIFIER

-- ANSI x9 holdinstructions

-- ANSI x9 arc holdinstruction arc
holdInstruction OBJECT IDENTIFIER ::=
          {joint-iso-itu-t(2) member-body(2) us(840) x9cm(10040) 2}

-- ANSI X9 holdinstructions referenced by this standard
id-holdinstruction-none OBJECT IDENTIFIER  ::=
                {holdInstruction 1} -- deprecated
id-holdinstruction-callissuer OBJECT IDENTIFIER ::=
                {holdInstruction 2}
id-holdinstruction-reject OBJECT IDENTIFIER ::=
                {holdInstruction 3}

-- invalidity date CRL entry extension OID and syntax

id-ce-invalidityDate OBJECT IDENTIFIER ::= { id-ce 24 }

InvalidityDate ::=  GeneralizedTime

END

Appendix B. 1993 ASN.1 Structures and OIDs โœจ

B.1 Explicitly Tagged Module, 1993 Syntax ๐ŸŽ€

this appendix is the full module, so grab a snack ๐Ÿ“ it starts by naming the module and importing the implicit one, then it sets up the PKIX arcs, the certificate and CRL structures, and the signing wrapper

PKIX1Explicit93 {iso(1) identified-organization(3) dod(6) internet(1)
   security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-explicit-93(3)}


DEFINITIONS EXPLICIT TAGS ::=

BEGIN

-- EXPORTS ALL --

IMPORTS
        authorityKeyIdentifier, subjectKeyIdentifier, keyUsage,
           extendedKeyUsage, privateKeyUsagePeriod, certificatePolicies,
           policyMappings, subjectAltName, issuerAltName,
           basicConstraints, nameConstraints, policyConstraints,
           cRLDistributionPoints, subjectDirectoryAttributes,
           cRLNumber, reasonCode, instructionCode, invalidityDate,
           issuingDistributionPoint, certificateIssuer,
           deltaCRLIndicator, authorityInfoAccess, id-ce
           FROM PKIX1Implicit93 {iso(1) identified-organization(3)
           dod(6) internet(1) security(5) mechanisms(5) pkix(7)
           id-mod(0) id-pkix1-implicit-93(4)} ;

--
                   --  Locally defined OIDs  --

id-pkix  OBJECT IDENTIFIER  ::=
         { iso(1) identified-organization(3) dod(6) internet(1)
                    security(5) mechanisms(5) pkix(7) }

-- PKIX arcs
-- arc for private certificate extensions
id-pe OBJECT IDENTIFIER  ::=  { id-pkix 1 }
 -- arc for policy qualifier types
id-qt OBJECT IDENTIFIER ::= { id-pkix 2 }
-- arc for extended key purpose OIDS
id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
-- arc for access descriptors
id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }

-- policyQualifierIds for Internet policy qualifiers
id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }
        -- OID for CPS qualifier

id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }
        -- OID for user notice qualifier

-- based on excerpts from AuthenticationFramework
--    {joint-iso-ccitt ds(5) modules(1) authenticationFramework(7) 2}

               -- Public Key Certificate --

Certificate            ::=   SIGNED { SEQUENCE {
   version                 [0]   Version DEFAULT v1,
   serialNumber                  CertificateSerialNumber,
   signature                     AlgorithmIdentifier,
   issuer                        Name,
   validity                      Validity,
   subject                       Name,
   subjectPublicKeyInfo          SubjectPublicKeyInfo,
   issuerUniqueIdentifier  [1]   IMPLICIT UniqueIdentifier OPTIONAL,
                              ---if present, version shall be v2 or v3--
   subjectUniqueIdentifier [2]   IMPLICIT UniqueIdentifier OPTIONAL,
                              ---if present, version shall be v2 or v3--
   extensions              [3]   Extensions OPTIONAL
                              --if present, version shall be v3--}  }

UniqueIdentifier        ::=  BIT STRING

Version                 ::=  INTEGER { v1(0), v2(1), v3(2) }

CertificateSerialNumber ::=  INTEGER

Validity                        ::=     SEQUENCE {
   notBefore            Time,
   notAfter             Time }

Time ::= CHOICE {
        utcTime         UTCTime,
        generalTime             GeneralizedTime }

SubjectPublicKeyInfo    ::=     SEQUENCE{
   algorithm            AlgorithmIdentifier,
   subjectPublicKey     BIT STRING}

Extensions        ::=   SEQUENCE SIZE (1..MAX) OF Extension

Extension         ::=   SEQUENCE {
   extnId            EXTENSION.&id ({ExtensionSet}),
   critical          BOOLEAN DEFAULT FALSE,
   extnValue         OCTET STRING }
                -- contains a DER encoding of a value of type
                -- &ExtnType for the
                -- extension object identified by extnId --

-- The following information object set is defined to constrain the
-- set of legal certificate extensions.

ExtensionSet    EXTENSION       ::=     { authorityKeyIdentifier |
                                        subjectKeyIdentifier |
                                        keyUsage |
                                        extendedKeyUsage |
                                        privateKeyUsagePeriod |
                                        certificatePolicies |
                                        policyMappings |
                                        subjectAltName |
                                        issuerAltName |
                                        basicConstraints |
                                        nameConstraints |
                                        policyConstraints |
                                        cRLDistributionPoints |
                                        subjectDirectoryAttributes |
                                        authorityInfoAccess }

EXTENSION       ::=     CLASS {
   &id          OBJECT IDENTIFIER UNIQUE,
   &ExtnType }
WITH SYNTAX  {
   SYNTAX               &ExtnType
   IDENTIFIED BY        &id }

                  -- Certificate Revocation List --

CertificateList ::=    SIGNED { SEQUENCE {
   version                Version  OPTIONAL, -- if present, shall be v2
   signature              AlgorithmIdentifier,
   issuer                 Name,
   thisUpdate             Time,
   nextUpdate             Time OPTIONAL,
   revokedCertificates    SEQUENCE OF SEQUENCE {
   userCertificate        CertificateSerialNumber,
   revocationDate         Time,
   crlEntryExtensions     EntryExtensions OPTIONAL } OPTIONAL,
   crlExtensions          [0]   CRLExtensions OPTIONAL }}

CRLExtensions        ::=        SEQUENCE SIZE (1..MAX) OF CRLExtension

CRLExtension         ::=        SEQUENCE {
   extnId            EXTENSION.&id ({CRLExtensionSet}),
   critical          BOOLEAN DEFAULT FALSE,
   extnValue         OCTET STRING }
                -- contains a DER encoding of a value of type
                -- &ExtnType for the
                -- extension object identified by extnId --

-- The following information object set is defined to constrain the
-- set of legal CRL extensions.

CRLExtensionSet EXTENSION       ::=     { authorityKeyIdentifier |
                                        issuerAltName |
                                        cRLNumber |
                                        deltaCRLIndicator |
                                        issuingDistributionPoint }

-- EXTENSION defined above for certificates

EntryExtensions        ::=      SEQUENCE SIZE (1..MAX) OF EntryExtension

EntryExtension         ::=      SEQUENCE {
   extnId            EXTENSION.&id ({EntryExtensionSet}),
   critical          BOOLEAN DEFAULT FALSE,
   extnValue         OCTET STRING }
                -- contains a DER encoding of a value of type
                -- &ExtnType for the
                -- extension object identified by extnId --

-- The following information object set is defined to constrain the
-- set of legal CRL entry extensions.

EntryExtensionSet       EXTENSION       ::=     { reasonCode |
                                                instructionCode |
                                                invalidityDate |
                                                certificateIssuer }

         -- information object classes used in the defintion --
                    -- of certificates and CRLs --

-- Parameterized Type SIGNED --

  SIGNED { ToBeSigned } ::= SEQUENCE {
     toBeSigned  ToBeSigned,
     algorithm   AlgorithmIdentifier,
     signature   BIT STRING
  }

-- Definition of AlgorithmIdentifier
-- ISO definition was:
--
-- AlgorithmIdentifier     ::=  SEQUENCE {
--   algorithm          ALGORITHM.&id({SupportedAlgorithms}),
--   parameters         ALGORITHM.&Type({SupportedAlgorithms}
--                                         { @algorithm}) OPTIONAL }
-- Definition of ALGORITHM
-- ALGORITHM    ::=     TYPE-IDENTIFIER

-- The following PKIX definition replaces the X.509 definition
--

AlgorithmIdentifier     ::=  SEQUENCE {
   algorithm            ALGORITHM-ID.&id({SupportedAlgorithms}),
   parameters           ALGORITHM-ID.&Type({SupportedAlgorithms}
                                           { @algorithm}) OPTIONAL }

-- Definition of ALGORITHM-ID

 ALGORITHM-ID ::= CLASS {
     &id    OBJECT IDENTIFIER UNIQUE,
     &Type  OPTIONAL
  }
     WITH SYNTAX { OID &id [PARMS &Type] }

okay bestie, this part is all ASN.1 ๐Ÿ’… the code stays exactly as written because it's a spec and implementers rely on every character ๐ŸŽ€

-- The definition of SupportedAlgorithms may be modified as this
-- document does not specify a mandatory algorithm set.  In addition,
-- the set is specified as extensible, since additional algorithms
-- may be supported

SupportedAlgorithms     ALGORITHM-ID  ::=       { ..., -- extensible
                                            rsaPublicKey |
                                            rsaSHA-1  |
                                            rsaMD5 |
                                            rsaMD2 |
                                            dssPublicKey |
                                            dsaSHA-1 |
                                            dhPublicKey }

-- OIDs and parameter structures for ALGORITHM-IDs used
-- in this specification

rsaPublicKey ALGORITHM-ID ::= { OID rsaEncryption PARMS NULL }

rsaSHA-1 ALGORITHM-ID ::= { OID sha1WithRSAEncryption PARMS NULL }

rsaMD5 ALGORITHM-ID ::= { OID md5WithRSAEncryption PARMS NULL  }

rsaMD2 ALGORITHM-ID ::= { OID md2WithRSAEncryption PARMS NULL  }
dssPublicKey ALGORITHM-ID ::= { OID id-dsa PARMS Dss-Parms }

dsaSHA-1 ALGORITHM-ID ::= { OID id-dsa-with-sha1 }

dhPublicKey ALGORITHM-ID ::= {OID dhpublicnumber PARMS DomainParameters}

-- algorithm identifiers and parameter structures

pkcs-1 OBJECT IDENTIFIER ::= {
     iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }

rsaEncryption OBJECT IDENTIFIER ::=  { pkcs-1 1 }

md2WithRSAEncryption OBJECT IDENTIFIER  ::=  { pkcs-1 2 }

md5WithRSAEncryption OBJECT IDENTIFIER  ::=  { pkcs-1 4 }

sha1WithRSAEncryption OBJECT IDENTIFIER  ::=  { pkcs-1 5 }

id-dsa-with-sha1 OBJECT IDENTIFIER ::=  {
     iso(1) member-body(2) us(840) x9-57 (10040) x9algorithm(4) 3 }

Dss-Sig-Value  ::=  SEQUENCE  {
     r       INTEGER,
     s       INTEGER  }

dhpublicnumber OBJECT IDENTIFIER ::= {
     iso(1) member-body(2) us(840) ansi-x942(10046) number-type(2) 1 }

DomainParameters ::= SEQUENCE {
     p       INTEGER, -- odd prime, p=jq +1
     g       INTEGER, -- generator, g
     q       INTEGER, -- factor of p-1
     j       INTEGER OPTIONAL, -- subgroup factor, j>= 2
     validationParms  ValidationParms OPTIONAL }

ValidationParms ::= SEQUENCE {
     seed             BIT STRING,
     pgenCounter      INTEGER }

id-dsa OBJECT IDENTIFIER ::= {
     iso(1) member-body(2) us(840) x9-57(10040) x9algorithm(4) 1 }

Dss-Parms  ::=  SEQUENCE  {
     p             INTEGER,
     q             INTEGER,
     g             INTEGER  }
     -- The ASN.1 in this section supports the Name type
     -- and the directoryAttribute extension

-- attribute data types --

Attribute       ::=     SEQUENCE {
        type            ATTRIBUTE.&id ({SupportedAttributes}),
        values  SET SIZE (1 .. MAX) OF ATTRIBUTE.&Type
                        ({SupportedAttributes}{@type})}

AttributeTypeAndValue           ::=     SEQUENCE {
        type            ATTRIBUTE.&id ({SupportedAttributes}),
        value   ATTRIBUTE.&Type ({SupportedAttributes}{@type})}

-- naming data types --

Name            ::=     CHOICE { -- only one possibility for now --
                                        rdnSequence  RDNSequence }

RDNSequence ::= SEQUENCE OF RelativeDistinguishedName

RelativeDistinguishedName       ::=
                SET SIZE (1 .. MAX) OF AttributeTypeAndValue

ID     ::=    OBJECT IDENTIFIER

-- ATTRIBUTE information object class specification
--  Note: This has been greatly simplified for PKIX !!

ATTRIBUTE               ::=     CLASS {
        &Type,
        &id                     OBJECT IDENTIFIER UNIQUE }
WITH SYNTAX {
        WITH SYNTAX &Type ID &id }

-- suggested naming attributes
--      Definition of the following information object set may be
--    augmented to meet local requirements.  Note that deleting
--    members of the set may prevent interoperability with
--    conforming implementations.

SupportedAttributes     ATTRIBUTE       ::=     {
                name | commonName | surname | givenName | initials |
                generationQualifier | dnQualifier | countryName |
                localityName | stateOrProvinceName | organizationName |
                        organizationalUnitName | title | pkcs9email }

name ATTRIBUTE  ::=     {

        WITH SYNTAX                     DirectoryString { ub-name }
        ID                              id-at-name }

commonName ATTRIBUTE    ::=     {
        WITH SYNTAX                     DirectoryString {ub-common-name}
        ID                              id-at-commonName }

surname ATTRIBUTE       ::=             {
        WITH SYNTAX                     DirectoryString {ub-name}
        ID                              id-at-surname }

givenName ATTRIBUTE     ::=             {
        WITH SYNTAX                     DirectoryString {ub-name}
        ID                              id-at-givenName }

initials ATTRIBUTE      ::=             {
        WITH SYNTAX                     DirectoryString {ub-name}
        ID                              id-at-initials }

generationQualifier ATTRIBUTE   ::=             {
        WITH SYNTAX                     DirectoryString {ub-name}
        ID                              id-at-generationQualifier}

dnQualifier ATTRIBUTE   ::=     {
        WITH SYNTAX                     PrintableString
        ID                              id-at-dnQualifier }


countryName ATTRIBUTE   ::=     {
        WITH SYNTAX                     PrintableString (SIZE (2))
                                                -- IS 3166 codes only
        ID                              id-at-countryName }

localityName ATTRIBUTE  ::=     {
        WITH SYNTAX             DirectoryString {ub-locality-name}
        ID                      id-at-localityName }

stateOrProvinceName ATTRIBUTE   ::=     {
        WITH SYNTAX             DirectoryString {ub-state-name}
        ID                      id-at-stateOrProvinceName }

organizationName ATTRIBUTE      ::=     {
        WITH SYNTAX             DirectoryString {ub-organization-name}
        ID                      id-at-organizationName }

organizationalUnitName ATTRIBUTE        ::=     {
        WITH SYNTAX  DirectoryString {ub-organizational-unit-name}
        ID                      id-at-organizationalUnitName }

title ATTRIBUTE ::=                     {
        WITH SYNTAX             DirectoryString {ub-title}
        ID                      id-at-title }

 -- Legacy attributes

pkcs9email ATTRIBUTE ::= {
        WITH SYNTAX                     PHGString,
        ID                              emailAddress }

PHGString ::= IA5String (SIZE(1..ub-emailaddress-length))

pkcs-9 OBJECT IDENTIFIER ::=
       { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 }

emailAddress OBJECT IDENTIFIER ::= { pkcs-9 1 }

    -- object identifiers for Name type and directory attribute support

-- Object identifier assignments --

id-at   OBJECT IDENTIFIER       ::=     {joint-iso-ccitt(2) ds(5) 4}

-- Attributes --

id-at-commonName        OBJECT IDENTIFIER       ::=     {id-at 3}
id-at-surname           OBJECT IDENTIFIER       ::=     {id-at 4}
id-at-countryName       OBJECT IDENTIFIER       ::=     {id-at 6}
id-at-localityName      OBJECT IDENTIFIER       ::=     {id-at 7}
id-at-stateOrProvinceName     OBJECT IDENTIFIER ::= {id-at 8}
id-at-organizationName        OBJECT IDENTIFIER ::= {id-at 10}
id-at-organizationalUnitName  OBJECT IDENTIFIER ::= {id-at 11}
id-at-title             OBJECT IDENTIFIER       ::=     {id-at 12}
id-at-name              OBJECT IDENTIFIER       ::=     {id-at 41}
id-at-givenName         OBJECT IDENTIFIER       ::=     {id-at 42}
id-at-initials          OBJECT IDENTIFIER       ::=     {id-at 43}
id-at-generationQualifier   OBJECT IDENTIFIER   ::=     {id-at 44}
id-at-dnQualifier       OBJECT IDENTIFIER       ::=     {id-at 46}

-- Directory string type, used extensively in Name types --

DirectoryString { INTEGER:maxSize } ::= CHOICE {
        teletexString           TeletexString (SIZE (1..maxSize)),
        printableString         PrintableString (SIZE (1..maxSize)),
        universalString         UniversalString (SIZE (1..maxSize)),
        bmpString               BMPString (SIZE(1..maxSize)),
        utf8String              UTF8String (SIZE(1..maxSize))
                            }

     -- End of ASN.1 for Name type and directory attribute support --

     -- The ASN.1 in this section supports X.400 style names   --
     -- for implementations that use the x400Address component --
     -- of GeneralName.                                        --

ORAddress ::= SEQUENCE {
   built-in-standard-attributes BuiltInStandardAttributes,
   built-in-domain-defined-attributes
                        BuiltInDomainDefinedAttributes OPTIONAL,
   -- see also teletex-domain-defined-attributes
   extension-attributes ExtensionAttributes OPTIONAL }

--  The OR-address is semantically absent from the OR-name if the
--  built-in-standard-attribute sequence is empty and the
--  built-in-domain-defined-attributes and extension-attributes are
--  both omitted.

--      Built-in Standard Attributes

BuiltInStandardAttributes ::= SEQUENCE {
   country-name CountryName OPTIONAL,
   administration-domain-name AdministrationDomainName OPTIONAL,
   network-address      [0] NetworkAddress OPTIONAL,
   -- see also extended-network-address
   terminal-identifier  [1] TerminalIdentifier OPTIONAL,
   private-domain-name  [2] PrivateDomainName OPTIONAL,
   organization-name    [3] OrganizationName OPTIONAL,
   -- see also teletex-organization-name
   numeric-user-identifier      [4] NumericUserIdentifier OPTIONAL,
   personal-name        [5] PersonalName OPTIONAL,
   -- see also teletex-personal-name
   organizational-unit-names    [6] OrganizationalUnitNames OPTIONAL
   -- see also teletex-organizational-unit-names -- }

CountryName ::= [APPLICATION 1] CHOICE {
   x121-dcc-code NumericString
                (SIZE (ub-country-name-numeric-length)),
   iso-3166-alpha2-code PrintableString
                (SIZE (ub-country-name-alpha-length)) }

AdministrationDomainName ::= [APPLICATION 2] CHOICE {
   numeric NumericString (SIZE (0..ub-domain-name-length)),
   printable PrintableString (SIZE (0..ub-domain-name-length)) }

NetworkAddress ::= X121Address
-- see also extended-network-address
X121Address ::= NumericString (SIZE (1..ub-x121-address-length))

TerminalIdentifier ::= PrintableString (SIZE (1..ub-terminal-id-length))

PrivateDomainName ::= CHOICE {
   numeric NumericString (SIZE (1..ub-domain-name-length)),
   printable PrintableString (SIZE (1..ub-domain-name-length)) }

OrganizationName ::= PrintableString
                           (SIZE (1..ub-organization-name-length))
-- see also teletex-organization-name

NumericUserIdentifier ::= NumericString
                             (SIZE (1..ub-numeric-user-id-length))

PersonalName ::= SET {
   surname    [0] PrintableString (SIZE (1..ub-surname-length)),
   given-name [1] PrintableString
                        (SIZE (1..ub-given-name-length)) OPTIONAL,
   initials   [2] PrintableString
                        (SIZE (1..ub-initials-length)) OPTIONAL,
   generation-qualifier [3] PrintableString
                (SIZE (1..ub-generation-qualifier-length)) OPTIONAL}
-- see also teletex-personal-name

OrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units)
                                        OF OrganizationalUnitName
-- see also teletex-organizational-unit-names

OrganizationalUnitName ::= PrintableString (SIZE
                        (1..ub-organizational-unit-name-length))

--      Built-in Domain-defined Attributes
BuiltInDomainDefinedAttributes ::= SEQUENCE SIZE
                                (1..ub-domain-defined-attributes) OF
                                BuiltInDomainDefinedAttribute

BuiltInDomainDefinedAttribute ::= SEQUENCE { type PrintableString (SIZE (1..ub-domain-defined-attribute-type-length)), value PrintableString (SIZE (1..ub-domain-defined-attribute-value-length)) }

-- Extension Attributes

ExtensionAttributes ::= SET SIZE (1..ub-extension-attributes) OF ExtensionAttribute ExtensionAttribute ::= SEQUENCE {

extension-attribute-type [0] EXTENSION-ATTRIBUTE.&id ({ExtensionAttributeTable}), extension-attribute-value [1] EXTENSION-ATTRIBUTE.&Type ({ExtensionAttributeTable} {@extension-attribute-type}) }

EXTENSION-ATTRIBUTE ::= CLASS { &id INTEGER (0..ub-extension-attributes) UNIQUE, &Type } WITH SYNTAX {&Type IDENTIFIED BY &id}

ExtensionAttributeTable EXTENSION-ATTRIBUTE ::= { common-name | teletex-common-name | teletex-organization-name | teletex-personal-name | teletex-organizational-unit-names | teletex-domain-defined-attributes | pds-name | physical-delivery-country-name | postal-code | physical-delivery-office-name | physical-delivery-office-number | extension-OR-address-components | physical-delivery-personal-name | physical-delivery-organization-name | extension-physical-delivery-address-components | unformatted-postal-address | street-address | post-office-box-address | poste-restante-address | unique-postal-name | local-postal-attributes | extended-network-address | terminal-type }

okay the extension attributes are giving main character energy ๐ŸŽ€ next up are the standard ones ๐Ÿ’…

-- Extension Standard Attributes

common-name EXTENSION-ATTRIBUTE ::= {CommonName IDENTIFIED BY 1}

CommonName ::= PrintableString (SIZE (1..ub-common-name-length))

teletex-common-name EXTENSION-ATTRIBUTE ::= {TeletexCommonName IDENTIFIED BY 2}

TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-length))

teletex-organization-name EXTENSION-ATTRIBUTE ::= {TeletexOrganizationName IDENTIFIED BY 3}

TeletexOrganizationName ::= TeletexString (SIZE (1..ub-organization-name-length))

teletex-personal-name EXTENSION-ATTRIBUTE ::= {TeletexPersonalName IDENTIFIED BY 4}

TeletexPersonalName ::= SET { surname [0] TeletexString (SIZE (1..ub-surname-length)), given-name [1] TeletexString (SIZE (1..ub-given-name-length)) OPTIONAL, initials [2] TeletexString (SIZE (1..ub-initials-length)) OPTIONAL, generation-qualifier [3] TeletexString (SIZE (1..ub-generation-qualifier-length)) OPTIONAL }

teletex-organizational-unit-names EXTENSION-ATTRIBUTE ::= {TeletexOrganizationalUnitNames IDENTIFIED BY 5}

TeletexOrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units) OF TeletexOrganizationalUnitName

TeletexOrganizationalUnitName ::= TeletexString (SIZE (1..ub-organizational-unit-name-length))

pds-name EXTENSION-ATTRIBUTE ::= {PDSName IDENTIFIED BY 7}

PDSName ::= PrintableString (SIZE (1..ub-pds-name-length))

physical-delivery-country-name EXTENSION-ATTRIBUTE ::= {PhysicalDeliveryCountryName IDENTIFIED BY 8}

PhysicalDeliveryCountryName ::= CHOICE { x121-dcc-code NumericString (SIZE (ub-country-name-numeric-length)), iso-3166-alpha2-code PrintableString (SIZE (ub-country-name-alpha-length)) }

postal-code EXTENSION-ATTRIBUTE ::= {PostalCode IDENTIFIED BY 9}

PostalCode ::= CHOICE { numeric-code NumericString (SIZE (1..ub-postal-code-length)), printable-code PrintableString (SIZE (1..ub-postal-code-length)) }

physical-delivery-office-name EXTENSION-ATTRIBUTE ::= {PhysicalDeliveryOfficeName IDENTIFIED BY 10}

PhysicalDeliveryOfficeName ::= PDSParameter

physical-delivery-office-number EXTENSION-ATTRIBUTE ::= {PhysicalDeliveryOfficeNumber IDENTIFIED BY 11}

PhysicalDeliveryOfficeNumber ::= PDSParameter

extension-OR-address-components EXTENSION-ATTRIBUTE ::= {ExtensionORAddressComponents IDENTIFIED BY 12}

ExtensionORAddressComponents ::= PDSParameter

physical-delivery-personal-name EXTENSION-ATTRIBUTE ::= {PhysicalDeliveryPersonalName IDENTIFIED BY 13}

PhysicalDeliveryPersonalName ::= PDSParameter

physical-delivery-organization-name EXTENSION-ATTRIBUTE ::= {PhysicalDeliveryOrganizationName IDENTIFIED BY 14}

PhysicalDeliveryOrganizationName ::= PDSParameter

extension-physical-delivery-address-components EXTENSION-ATTRIBUTE ::= {ExtensionPhysicalDeliveryAddressComponents IDENTIFIED BY 15}

ExtensionPhysicalDeliveryAddressComponents ::= PDSParameter

unformatted-postal-address EXTENSION-ATTRIBUTE ::= {UnformattedPostalAddress IDENTIFIED BY 16}

UnformattedPostalAddress ::= SET { printable-address SEQUENCE SIZE (1..ub-pds-physical-address-lines) OF PrintableString (SIZE (1..ub-pds-parameter-length)) OPTIONAL, teletex-string TeletexString (SIZE (1..ub-unformatted-address-length)) OPTIONAL }

street-address EXTENSION-ATTRIBUTE ::= {StreetAddress IDENTIFIED BY 17}

StreetAddress ::= PDSParameter

post-office-box-address EXTENSION-ATTRIBUTE ::= {PostOfficeBoxAddress IDENTIFIED BY 18}

PostOfficeBoxAddress ::= PDSParameter

poste-restante-address EXTENSION-ATTRIBUTE ::= {PosteRestanteAddress IDENTIFIED BY 19}

PosteRestanteAddress ::= PDSParameter

unique-postal-name EXTENSION-ATTRIBUTE ::= {UniquePostalName IDENTIFIED BY 20}

UniquePostalName ::= PDSParameter

local-postal-attributes EXTENSION-ATTRIBUTE ::= {LocalPostalAttributes IDENTIFIED BY 21}

LocalPostalAttributes ::= PDSParameter

PDSParameter ::= SET { printable-string PrintableString (SIZE(1..ub-pds-parameter-length)) OPTIONAL, teletex-string TeletexString (SIZE(1..ub-pds-parameter-length)) OPTIONAL }

extended-network-address EXTENSION-ATTRIBUTE ::= {ExtendedNetworkAddress IDENTIFIED BY 22}

ExtendedNetworkAddress ::= CHOICE { e163-4-address SEQUENCE { number [0] NumericString (SIZE (1..ub-e163-4-number-length)), sub-address [1] NumericString (SIZE (1..ub-e163-4-sub-address-length)) OPTIONAL}, psap-address [0] PresentationAddress }

PresentationAddress ::= SEQUENCE { pSelector [0] EXPLICIT OCTET STRING OPTIONAL, sSelector [1] EXPLICIT OCTET STRING OPTIONAL, tSelector [2] EXPLICIT OCTET STRING OPTIONAL, nAddresses [3] EXPLICIT SET SIZE (1..MAX) OF OCTET STRING}

terminal-type EXTENSION-ATTRIBUTE ::= {TerminalType IDENTIFIED BY 23}

TerminalType ::= INTEGER { telex (3), teletex (4), g3-facsimile (5), g4-facsimile (6), ia5-terminal (7), videotex (8) } (0..ub-integer-options)

the terminal types are such a vibe, a whole lineup of machines ๐Ÿ“ ๐Ÿงš

-- Extension Domain-defined Attributes

teletex-domain-defined-attributes EXTENSION-ATTRIBUTE ::= {TeletexDomainDefinedAttributes IDENTIFIED BY 6}

TeletexDomainDefinedAttributes ::= SEQUENCE SIZE (1..ub-domain-defined-attributes) OF TeletexDomainDefinedAttribute

TeletexDomainDefinedAttribute ::= SEQUENCE { type TeletexString (SIZE (1..ub-domain-defined-attribute-type-length)), value TeletexString (SIZE (1..ub-domain-defined-attribute-value-length)) }

-- specifications of Upper Bounds -- shall be regarded as mandatory -- from Annex B of ITU-T X.411 -- Reference Definition of MTS Parameter Upper Bounds

-- Upper Bounds ub-name INTEGER ::= 32768 ub-common-name INTEGER ::= 64 ub-locality-name INTEGER ::= 128 ub-state-name INTEGER ::= 128 ub-organization-name INTEGER ::= 64 ub-organizational-unit-name INTEGER ::= 64 ub-title INTEGER ::= 64 ub-match INTEGER ::= 128

ub-emailaddress-length INTEGER ::= 128

ub-common-name-length INTEGER ::= 64 ub-country-name-alpha-length INTEGER ::= 2 ub-country-name-numeric-length INTEGER ::= 3 ub-domain-defined-attributes INTEGER ::= 4 ub-domain-defined-attribute-type-length INTEGER ::= 8 ub-domain-defined-attribute-value-length INTEGER ::= 128 ub-domain-name-length INTEGER ::= 16 ub-extension-attributes INTEGER ::= 256 ub-e163-4-number-length INTEGER ::= 15 ub-e163-4-sub-address-length INTEGER ::= 40 ub-generation-qualifier-length INTEGER ::= 3 ub-given-name-length INTEGER ::= 16 ub-initials-length INTEGER ::= 5 ub-integer-options INTEGER ::= 256 ub-numeric-user-id-length INTEGER ::= 32 ub-organization-name-length INTEGER ::= 64 ub-organizational-unit-name-length INTEGER ::= 32 ub-organizational-units INTEGER ::= 4 ub-pds-name-length INTEGER ::= 16 ub-pds-parameter-length INTEGER ::= 30 ub-pds-physical-address-lines INTEGER ::= 6 ub-postal-code-length INTEGER ::= 16 ub-surname-length INTEGER ::= 40 ub-terminal-id-length INTEGER ::= 24 ub-unformatted-address-length INTEGER ::= 180 ub-x121-address-length INTEGER ::= 16

-- Note - upper bounds on TeletexString are measured in characters. -- A significantly greater number of octets will be required to hold -- such a value. As a minimum, 16 octets, or twice the specified upper -- bound, whichever is the larger, should be allowed.

END

B.2 Implicitly Tagged Module, 1993 Syntax โœจ

ok the upper bounds are all lined up, and now we're in the implicit tagging module ๐Ÿฆ‹

PKIX1Implicit93  {iso(1) identified-organization(3) dod(6) internet(1)
   security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-implicit-93(4)}

DEFINITIONS IMPLICIT TAGS::=

BEGIN

--EXPORTS ALL --

IMPORTS
        id-pe, id-qt, id-kp, id-ad, id-qt-unotice,
                ORAddress, Name, RelativeDistinguishedName,
                CertificateSerialNumber, CertificateList,
                AlgorithmIdentifier, ub-name, DirectoryString,
                Attribute, EXTENSION
                FROM PKIX1Explicit93 {iso(1) identified-organization(3)
                dod(6) internet(1) security(5) mechanisms(5) pkix(7)
                id-mod(0) id-pkix1-explicit-93(3)};

-- Key and policy information extensions --

authorityKeyIdentifier EXTENSION ::= {
        SYNTAX          AuthorityKeyIdentifier
        IDENTIFIED BY   id-ce-authorityKeyIdentifier }

AuthorityKeyIdentifier ::= SEQUENCE {
    keyIdentifier               [0] KeyIdentifier            OPTIONAL,
    authorityCertIssuer         [1] GeneralNames             OPTIONAL,
    authorityCertSerialNumber   [2] CertificateSerialNumber  OPTIONAL }
        ( WITH COMPONENTS       {..., authorityCertIssuer PRESENT,
                                authorityCertSerialNumber PRESENT} |
         WITH COMPONENTS        {..., authorityCertIssuer ABSENT,
                                authorityCertSerialNumber ABSENT} )

KeyIdentifier ::= OCTET STRING

subjectKeyIdentifier EXTENSION ::= {
        SYNTAX          SubjectKeyIdentifier
        IDENTIFIED BY   id-ce-subjectKeyIdentifier }

SubjectKeyIdentifier ::= KeyIdentifier

keyUsage EXTENSION ::= {
        SYNTAX  KeyUsage
        IDENTIFIED BY id-ce-keyUsage }

KeyUsage ::= BIT STRING {
        digitalSignature     (0),
        nonRepudiation       (1),
        keyEncipherment      (2),
        dataEncipherment     (3),
        keyAgreement         (4),
        keyCertSign          (5),
        cRLSign              (6),
      encipherOnly         (7),
      decipherOnly         (8) }

extendedKeyUsage EXTENSION ::= {
        SYNTAX SEQUENCE SIZE (1..MAX) OF KeyPurposeId
        IDENTIFIED BY id-ce-extKeyUsage }

KeyPurposeId ::= OBJECT IDENTIFIER

-- PKIX-defined extended key purpose OIDs
id-kp-serverAuth      OBJECT IDENTIFIER ::= { id-kp 1 }
id-kp-clientAuth      OBJECT IDENTIFIER ::= { id-kp 2 }
id-kp-codeSigning     OBJECT IDENTIFIER ::= { id-kp 3 }
id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 }
id-kp-ipsecEndSystem  OBJECT IDENTIFIER ::= { id-kp 5 }
id-kp-ipsecTunnel     OBJECT IDENTIFIER ::= { id-kp 6 }
id-kp-ipsecUser       OBJECT IDENTIFIER ::= { id-kp 7 }
id-kp-timeStamping    OBJECT IDENTIFIER ::= { id-kp 8 }

privateKeyUsagePeriod EXTENSION ::= {
        SYNTAX  PrivateKeyUsagePeriod
        IDENTIFIED BY { id-ce-privateKeyUsagePeriod } }

PrivateKeyUsagePeriod ::= SEQUENCE {
        notBefore       [0]     GeneralizedTime OPTIONAL,
        notAfter        [1]     GeneralizedTime OPTIONAL }
        ( WITH COMPONENTS       {..., notBefore PRESENT} |
        WITH COMPONENTS         {..., notAfter PRESENT} )

okay bestie, the IPsec and timestamping purposes are up next ๐Ÿงš โœจ Then we get the private key usage period, which is basically a little time window with notBefore and notAfter on it. ๐Ÿ•ฐ๏ธ๐Ÿ’–

certificatePolicies EXTENSION ::= {
        SYNTAX  CertificatePoliciesSyntax
        IDENTIFIED BY id-ce-certificatePolicies }

CertificatePoliciesSyntax ::=
                SEQUENCE SIZE (1..MAX) OF PolicyInformation

PolicyInformation ::= SEQUENCE {
        policyIdentifier   CertPolicyId,
        policyQualifiers   SEQUENCE SIZE (1..MAX) OF
                PolicyQualifierInfo OPTIONAL }

CertPolicyId ::= OBJECT IDENTIFIER

PolicyQualifierInfo ::= SEQUENCE {
        policyQualifierId       CERT-POLICY-QUALIFIER.&id
                                    ({SupportedPolicyQualifiers}),
        qualifier               CERT-POLICY-QUALIFIER.&Qualifier
                                    ({SupportedPolicyQualifiers}
                                    {@policyQualifierId})OPTIONAL }

SupportedPolicyQualifiers CERT-POLICY-QUALIFIER ::= { noticeToUser |
                                                      pointerToCPS }

CERT-POLICY-QUALIFIER ::= CLASS {
        &id             OBJECT IDENTIFIER UNIQUE,
        &Qualifier      OPTIONAL }
WITH SYNTAX {
        POLICY-QUALIFIER-ID     &id
        [QUALIFIER-TYPE &Qualifier] }

policyMappings EXTENSION ::= {
        SYNTAX  PolicyMappingsSyntax
        IDENTIFIED BY id-ce-policyMappings }

PolicyMappingsSyntax ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
        issuerDomainPolicy           CertPolicyId,
        subjectDomainPolicy          CertPolicyId }

ngl the certificate policies bit is giving main character energy ๐Ÿ‘‘ Each policy gets an identifier, optional qualifiers hang off it, and the policy mappings pair an issuer domain policy with a subject domain policy. ๐Ÿฆ‹

-- Certificate subject and certificate issuer attributes extensions --

subjectAltName EXTENSION ::= {
        SYNTAX  GeneralNames
        IDENTIFIED BY id-ce-subjectAltName }

GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName

GeneralName ::= CHOICE {
        otherName                   [0] INSTANCE OF OTHER-NAME,
        rfc822Name                  [1] IA5String,
        dNSName                     [2] IA5String,
        x400Address                 [3] ORAddress,
        directoryName               [4] Name,
        ediPartyName                [5] EDIPartyName,
        uniformResourceIdentifier   [6] IA5String,
        iPAddress                   [7] OCTET STRING,
        registeredID                [8] OBJECT IDENTIFIER }

OTHER-NAME ::= TYPE-IDENTIFIER
EDIPartyName ::= SEQUENCE {
        nameAssigner        [0] DirectoryString {ub-name} OPTIONAL,
        partyName           [1] DirectoryString {ub-name} }

issuerAltName EXTENSION ::= {
        SYNTAX  GeneralNames
        IDENTIFIED BY id-ce-issuerAltName }

subjectDirectoryAttributes EXTENSION ::= {
        SYNTAX  AttributesSyntax
        IDENTIFIED BY id-ce-subjectDirectoryAttributes }

AttributesSyntax ::= SEQUENCE SIZE (1..MAX) OF Attribute

-- Certification path constraints extensions --

basicConstraints EXTENSION ::= {
        SYNTAX  BasicConstraintsSyntax
        IDENTIFIED BY id-ce-basicConstraints }

BasicConstraintsSyntax ::= SEQUENCE {
        cA                      BOOLEAN DEFAULT FALSE,
        pathLenConstraint       INTEGER (0..MAX) OPTIONAL }

nameConstraints EXTENSION ::= {
        SYNTAX  NameConstraintsSyntax
        IDENTIFIED BY id-ce-nameConstraints }

NameConstraintsSyntax ::= SEQUENCE {
        permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
        excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }

GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree

GeneralSubtree ::= SEQUENCE {
        base                    GeneralName,
        minimum         [0]     BaseDistance DEFAULT 0,
        maximum         [1]     BaseDistance OPTIONAL }

BaseDistance ::= INTEGER (0..MAX)

policyConstraints EXTENSION ::= {
        SYNTAX  PolicyConstraintsSyntax
        IDENTIFIED BY id-ce-policyConstraints }

PolicyConstraintsSyntax ::= SEQUENCE {
        requireExplicitPolicy   [0] SkipCerts OPTIONAL,
        inhibitPolicyMapping    [1] SkipCerts OPTIONAL }

SkipCerts ::= INTEGER (0..MAX)

-- Basic CRL extensions --

cRLNumber EXTENSION ::= {
        SYNTAX  CRLNumber
        IDENTIFIED BY id-ce-cRLNumber }

CRLNumber ::= INTEGER (0..MAX)

reasonCode EXTENSION ::= {
        SYNTAX  CRLReason
        IDENTIFIED BY id-ce-reasonCode }

CRLReason ::= ENUMERATED {
        unspecified             (0),
        keyCompromise           (1),
        cACompromise            (2),
        affiliationChanged      (3),
        superseded              (4),
        cessationOfOperation    (5),
        certificateHold         (6),
        removeFromCRL           (8) }

instructionCode EXTENSION ::= {
        SYNTAX  HoldInstruction
        IDENTIFIED BY id-ce-instructionCode }

HoldInstruction ::= OBJECT IDENTIFIER

-- holdinstructions described in this specification, from ANSI x9

-- ANSI x9 arc holdinstruction arc
holdInstruction OBJECT IDENTIFIER ::= {
     joint-iso-ccitt(2) member-body(2) us(840) x9cm(10040) 2}

-- ANSI X9 holdinstructions referenced by this standard
id-holdinstruction-none OBJECT IDENTIFIER ::= {holdInstruction 1}
id-holdinstruction-callissuer OBJECT IDENTIFIER ::= {holdInstruction 2}
id-holdinstruction-reject OBJECT IDENTIFIER ::= {holdInstruction 3}

invalidityDate EXTENSION ::= {
        SYNTAX  GeneralizedTime
        IDENTIFIED BY id-ce-invalidityDate }

the subject and issuer name stuff is so iconic ๐ŸŽ€ SAN, IAN, basic constraints, name constraints, policy constraints, and the CRL reason codes are all in here, and yes, the reason codes skip from 6 to 8 on purpose ๐Ÿ™ˆ The hold instruction arc comes from ANSI X9, so it's giving authority from another squad ๐ŸŒˆ

-- CRL distribution points and delta-CRL extensions --

cRLDistributionPoints EXTENSION ::= {

        SYNTAX  CRLDistPointsSyntax
        IDENTIFIED BY id-ce-cRLDistributionPoints }

CRLDistPointsSyntax ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint

DistributionPoint ::= SEQUENCE {
        distributionPoint       [0]     DistributionPointName OPTIONAL,
        reasons         [1]     ReasonFlags OPTIONAL,
        cRLIssuer               [2]     GeneralNames OPTIONAL }

DistributionPointName ::= CHOICE {
        fullName                [0]     GeneralNames,
        nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }

ReasonFlags ::= BIT STRING {
        unused                  (0),
        keyCompromise           (1),
        caCompromise            (2),
        affiliationChanged      (3),
        superseded              (4),
        cessationOfOperation    (5),
        certificateHold         (6) }

issuingDistributionPoint EXTENSION ::= {
        SYNTAX  IssuingDistPointSyntax
        IDENTIFIED BY id-ce-issuingDistributionPoint }

IssuingDistPointSyntax ::= SEQUENCE {
        distributionPoint       [0] DistributionPointName OPTIONAL,
        onlyContainsUserCerts   [1] BOOLEAN DEFAULT FALSE,
        onlyContainsCACerts     [2] BOOLEAN DEFAULT FALSE,
        onlySomeReasons         [3] ReasonFlags OPTIONAL,
        indirectCRL             [4] BOOLEAN DEFAULT FALSE }

certificateIssuer EXTENSION ::= {
        SYNTAX          GeneralNames
        IDENTIFIED BY id-ce-certificateIssuer }

deltaCRLIndicator EXTENSION ::= {
        SYNTAX          BaseCRLNumber
        IDENTIFIED BY id-ce-deltaCRLIndicator }

BaseCRLNumber ::= CRLNumber

-- Object identifier assignments for ISO certificate extensions --
id-ce   OBJECT IDENTIFIER       ::=     {joint-iso-ccitt(2) ds(5) 29}

id-ce-subjectDirectoryAttributes   OBJECT IDENTIFIER ::= {id-ce 9}
id-ce-subjectKeyIdentifier         OBJECT IDENTIFIER ::= {id-ce 14}
id-ce-keyUsage                     OBJECT IDENTIFIER ::= {id-ce 15}
id-ce-privateKeyUsagePeriod        OBJECT IDENTIFIER ::= {id-ce 16}
id-ce-subjectAltName               OBJECT IDENTIFIER ::= {id-ce 17}
id-ce-issuerAltName                OBJECT IDENTIFIER ::= {id-ce 18}
id-ce-basicConstraints             OBJECT IDENTIFIER ::= {id-ce 19}
id-ce-cRLNumber                    OBJECT IDENTIFIER ::= {id-ce 20}
id-ce-reasonCode                   OBJECT IDENTIFIER ::= {id-ce 21}
id-ce-instructionCode              OBJECT IDENTIFIER ::= {id-ce 23}
id-ce-invalidityDate               OBJECT IDENTIFIER ::= {id-ce 24}
id-ce-deltaCRLIndicator            OBJECT IDENTIFIER ::= {id-ce 27}
id-ce-issuingDistributionPoint     OBJECT IDENTIFIER ::= {id-ce 28}
id-ce-certificateIssuer            OBJECT IDENTIFIER ::= {id-ce 29}
id-ce-nameConstraints              OBJECT IDENTIFIER ::= {id-ce 30}
id-ce-cRLDistributionPoints        OBJECT IDENTIFIER ::= {id-ce 31}
id-ce-certificatePolicies          OBJECT IDENTIFIER ::= {id-ce 32}
id-ce-policyMappings               OBJECT IDENTIFIER ::= {id-ce 33}
id-ce-policyConstraints            OBJECT IDENTIFIER ::= {id-ce 36}
id-ce-authorityKeyIdentifier       OBJECT IDENTIFIER ::= {id-ce 35}
id-ce-extKeyUsage                  OBJECT IDENTIFIER ::= {id-ce 37}

-- PKIX 1 extensions

authorityInfoAccess EXTENSION ::= {
        SYNTAX  AuthorityInfoAccessSyntax
        IDENTIFIED BY id-pe-authorityInfoAccess }

AuthorityInfoAccessSyntax  ::=
        SEQUENCE SIZE (1..MAX) OF AccessDescription

AccessDescription  ::=  SEQUENCE {
        accessMethod          OBJECT IDENTIFIER,
        accessLocation        GeneralName  }

id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }

id-ad-ocsp      OBJECT IDENTIFIER ::= { id-ad 1 }
id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }

okay the CRL distribution point stuff is literally a whole vibe ๐ŸŒธ The delta CRL and issuing distribution point extensions have their own little cast of characters, and every OID gets its own spot in the id-ce family tree ๐Ÿงš Then we flip to the PKIX 1 extensions and the access description, which is where the OCSP and caIssuers ones show up ๐Ÿ’œ

-- PKIX policy qualifier definitions

noticeToUser CERT-POLICY-QUALIFIER ::= {
     POLICY-QUALIFIER-ID    id-qt-cps QUALIFIER-TYPE       CPSuri}

pointerToCPS CERT-POLICY-QUALIFIER ::= {
     POLICY-QUALIFIER-ID    id-qt-unotice QUALIFIER-TYPE   UserNotice}

id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }
id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }

CPSuri ::= IA5String

UserNotice ::= SEQUENCE {
     noticeRef        NoticeReference OPTIONAL,
     explicitText     DisplayText OPTIONAL}

NoticeReference ::= SEQUENCE {
     organization     DisplayText,
     noticeNumbers    SEQUENCE OF INTEGER }

DisplayText ::= CHOICE {
     visibleString    VisibleString  (SIZE (1..200)),
     bmpString        BMPString      (SIZE (1..200)),
     utf8String       UTF8String     (SIZE (1..200)) }


END

the policy qualifier definitions are where the whole certificate policies thing comes together, bestie ๐Ÿซถ The notice to user and pointer to CPS qualifiers each get their own OID and type, and DisplayText can come in visible, BMP, or UTF-8 flavours, all capped at 200 ๐Ÿ“

Appendix C. ASN.1 Notes โœจ

okay so bestie, this appendix is all about ASN.1 quirks that are lowkey easy to mess up ๐Ÿ™ˆ First up, SEQUENCE SIZE (1..MAX) OF pops up in a bunch of constructs. A plain ASN.1 sequence can have zero or more entries, but the SIZE (1..MAX) bit forces it to have at least one entry. The MAX just means the upper bound isn't fixed, and implementations get to pick whatever upper bound fits their environment ๐Ÿ’…

Next, positiveInt ::= INTEGER (0..MAX) makes positiveInt a subtype of INTEGER that holds everything greater than or equal to zero ๐Ÿฆ‹ Again, there's no set upper bound, so each implementation chooses one that works for it.

The PrintableString type is giving very basic Latin vibes ๐ŸŒธ It covers lowercase a through z, uppercase A through Z, digits 0 through 9, and eleven special characters: ' " ( ) + , - . / : ? plus space.

TeletexString is a superset of PrintableString ๐Ÿ’œ It handles a pretty standard ASCII-ish Latin set, Latin characters with non-spacing accents, and Japanese characters too. Iconic range, honestly.

UniversalString can hold any character allowed by ISO 10646-1 ๐ŸŒˆ ISO 10646 is the Universal multiple-octet coded Character Set (UCS). ISO 10646-1 spells out the architecture and the "basic multilingual plane", which is a huge standard character set that pulls in all the major world character standards. Main character energy for sure โญ

Now UTF8String. It was going to be introduced in the 1998 version of ASN.1 ๐Ÿ“ It's a universal type with tag number 12. Its content was first defined by RFC 2044 and then updated in RFC 2279, "UTF-8, a transformation Format of ISP 10646." ISO was also expected to formally add UTF8String to the choices for DirectoryString in 1998 ๐Ÿงš

Since all of that was coming, and to stay in line with the IETF Best Practices codified in RFC 2277, IETF Policy on Character Sets and Languages, this document includes UTF8String as a choice in DirectoryString and in the CPS qualifier extensions ๐ŸŽ€ Very forward-thinking of them, ngl โœจ


Appendix D. Examples ๐Ÿ’–

okay this section has four examples: three certificates and a CRL ๐Ÿฆ‹ The first two certificates and the CRL together make up a minimal certification path, so they're basically a little team ๐Ÿซถ

Section D.1 has an annotated hex dump of a "self-signed" certificate. It was issued by a CA with the distinguished name cn=us,o=gov,ou=nist ๐Ÿ‘‘ The certificate holds a DSA public key with parameters, and it's signed with the matching DSA private key.

Section D.2 has an annotated hex dump of an end-entity certificate ๐ŸŒธ This one holds a DSA public key too, and it's signed by the private key that goes with the "self-signed" certificate from section D.1.

Section D.3 has a dump of an end-entity certificate with an RSA public key, signed with RSA and MD5 ๐Ÿ’… It is not part of the minimal certification path, so it's kind of the solo friend who doesn't join the group trip.

Section D.4 has an annotated hex dump of a CRL ๐Ÿงš That CRL is issued by the same CA, cn=us,o=gov,ou=nist, and its list of revoked certificates includes the end-entity certificate from D.2. Oof, rough for that cert ๐Ÿ’€

D.1 Certificate ๐ŸŽ€

okay so this section has an annotated hex dump of a 699 byte version 3 certificate โœจ Here's the tea on what it contains:

  • (a) the serial number is 17 (11 hex);
  • (b) the certificate is signed with DSA and the SHA-1 hash algorithm;
  • (c) the issuer's distinguished name is OU=nist; O=gov; C=US
  • (d) and the subject's distinguished name is OU=nist; O=gov; C=US
  • (e) the certificate was issued on June 30, 1997 and will expire on December 31, 1997;
  • (f) the certificate contains a 1024 bit DSA public key with parameters;
  • (g) the certificate contains a subject key identifier extension; and
  • (h) the certificate is a CA certificate (as indicated through the basic constraints extension.)
0000 30 82 02 b7  695: SEQUENCE
0004 30 82 02 77  631: . SEQUENCE    tbscertificate
0008 a0 03          3: . . [0]
0010 02 01          1: . . . INTEGER 2
                     : 02
0013 02 01          1: . . INTEGER 17
                     : 11

0016 30 09          9: . . SEQUENCE
0018 06 07          7: . . . OID 1.2.840.10040.4.3: dsa-with-sha
                     : 2a 86 48 ce 38 04 03
0027 30 2a         42: . . SEQUENCE
0029 31 0b         11: . . . SET
0031 30 09          9: . . . . SEQUENCE
0033 06 03          3: . . . . . OID 2.5.4.6: C
                     : 55 04 06
0038 13 02          2: . . . . . PrintableString  'US'
                     : 55 53
0042 31 0c         12: . . . SET
0044 30 0a         10: . . . . SEQUENCE
0046 06 03          3: . . . . . OID 2.5.4.10: O
                     : 55 04 0a
0051 13 03          3: . . . . . PrintableString  'gov'
                     : 67 6f 76
0056 31 0d         13: . . . SET
0058 30 0b         11: . . . . SEQUENCE
0060 06 03          3: . . . . . OID 2.5.4.11: OU
                     : 55 04 0b
0065 13 04          4: . . . . . PrintableString  'nist'
                     : 6e 69 73 74
0071 30 1e         30: . . SEQUENCE
0073 17 0d         13: . . . UTCTime  '970630000000Z'
                     : 39 37 30 36 33 30 30 30 30 30 30 30 5a
0088 17 0d         13: . . . UTCTime  '971231000000Z'
                     : 39 37 31 32 33 31 30 30 30 30 30 30 5a
0103 30 2a         42: . . SEQUENCE
0105 31 0b         11: . . . SET
0107 30 09          9: . . . . SEQUENCE
0109 06 03          3: . . . . . OID 2.5.4.6: C
                     : 55 04 06
0114 13 02          2: . . . . . PrintableString  'US'
                     : 55 53
0118 31 0c         12: . . . SET
0120 30 0a         10: . . . . SEQUENCE
0122 06 03          3: . . . . . OID 2.5.4.10: O
                     : 55 04 0a
0127 13 03          3: . . . . . PrintableString  'gov'
                     : 67 6f 76
0132 31 0d         13: . . . SET
0134 30 0b         11: . . . . SEQUENCE
0136 06 03          3: . . . . . OID 2.5.4.11: OU
                     : 55 04 0b
0141 13 04          4: . . . . . PrintableString  'nist'
                     : 6e 69 73 74
0147 30 82 01 b4  436: . . SEQUENCE
0151 30 82 01 29  297: . . . SEQUENCE
0155 06 07          7: . . . . OID 1.2.840.10040.4.1: dsa
                     : 2a 86 48 ce 38 04 01
0164 30 82 01 1c  284: . . . . SEQUENCE
0168 02 81 80     128: . . . . . INTEGER
                     : d4 38 02 c5 35 7b d5 0b a1 7e 5d 72 59 63 55 d3
                     : 45 56 ea e2 25 1a 6b c5 a4 ab aa 0b d4 62 b4 d2
                     : 21 b1 95 a2 c6 01 c9 c3 fa 01 6f 79 86 83 3d 03
                     : 61 e1 f1 92 ac bc 03 4e 89 a3 c9 53 4a f7 e2 a6
                     : 48 cf 42 1e 21 b1 5c 2b 3a 7f ba be 6b 5a f7 0a
                     : 26 d8 8e 1b eb ec bf 1e 5a 3f 45 c0 bd 31 23 be
                     : 69 71 a7 c2 90 fe a5 d6 80 b5 24 dc 44 9c eb 4d
                     : f9 da f0 c8 e8 a2 4c 99 07 5c 8e 35 2b 7d 57 8d
0299 02 14         20: . . . . . INTEGER
                     : a7 83 9b f3 bd 2c 20 07 fc 4c e7 e8 9f f3 39 83
                     : 51 0d dc dd
0321 02 81 80     128: . . . . . INTEGER
                     : 0e 3b 46 31 8a 0a 58 86 40 84 e3 a1 22 0d 88 ca
                     : 90 88 57 64 9f 01 21 e0 15 05 94 24 82 e2 10 90
                     : d9 e1 4e 10 5c e7 54 6b d4 0c 2b 1b 59 0a a0 b5
                     : a1 7d b5 07 e3 65 7c ea 90 d8 8e 30 42 e4 85 bb
                     : ac fa 4e 76 4b 78 0e df 6c e5 a6 e1 bd 59 77 7d
                     : a6 97 59 c5 29 a7 b3 3f 95 3e 9d f1 59 2d f7 42
                     : 87 62 3f f1 b8 6f c7 3d 4b b8 8d 74 c4 ca 44 90
                     : cf 67 db de 14 60 97 4a d1 f7 6d 9e 09 94 c4 0d
0452 03 81 84     132: . . . BIT STRING  (0 unused bits)
                     : 02 81 80 aa 98 ea 13 94 a2 db f1 5b 7f 98 2f 78
                     : e7 d8 e3 b9 71 86 f6 80 2f 40 39 c3 da 3b 4b 13
                     : 46 26 ee 0d 56 c5 a3 3a 39 b7 7d 33 c2 6b 5c 77
                     : 92 f2 55 65 90 39 cd 1a 3c 86 e1 32 eb 25 bc 91
                     : c4 ff 80 4f 36 61 bd cc e2 61 04 e0 7e 60 13 ca
                     : c0 9c dd e0 ea 41 de 33 c1 f1 44 a9 bc 71 de cf
                     : 59 d4 6e da 44 99 3c 21 64 e4 78 54 9d d0 7b ba
                     : 4e f5 18 4d 5e 39 30 bf e0 d1 f6 f4 83 25 4f 14
                     : aa 71 e1
0587 a3 32         50: . . [3]
0589 30 30         48: . . . SEQUENCE
0591 30 0f          9: . . . . SEQUENCE
0593 06 03          3: . . . . . OID 2.5.29.19: basicConstraints
                     : 55 1d 13
0598 01 01          1: . . . . . TRUE
                     : ff
0601 04 05          5: . . . . . OCTET STRING
                     : 30 03 01 01 ff
0608 30 1d         29: . SEQUENCE
0610 06 03          3: . . . . . OID 2.5.29.14: subjectKeyIdentifier
                     : 55 1d 0e
0615 04 16         22: . . . . . OCTET STRING
                     : 04 14 e7 26 c5 54 cd 5b a3 6f 35 68 95 aa d5 ff
                     : 1c 21 e4 22 75 d6
0639 30 09          9: . SEQUENCE
0641 06 07          7: . . OID 1.2.840.10040.4.3: dsa-with-sha
                     : 2a 86 48 ce 38 04 03
0650 03 2f         47: . BIT STRING  (0 unused bits)
                     : 30 2c 02 14 a0 66 c1 76 33 99 13 51 8d 93 64 2f
                     : ca 13 73 de 79 1a 7d 33 02 14 5d 90 f6 ce 92 4a
                     : bf 29 11 24 80 28 a6 5a 8e 73 b6 76 02 68

D.2 Certificate ๐ŸŒˆ

this section has an annotated hex dump of a 730 byte version 3 certificate ๐Ÿ’œ Here's what's inside:

  • (a) the serial number is 18 (12 hex);
  • (b) the certificate is signed with DSA and the SHA-1 hash algorithm;
  • (c) the issuer's distinguished name is OU=nist; O=gov; C=US
  • (d) and the subject's distinguished name is CN=Tim Polk; OU=nist; O=gov; C=US
  • (e) the certificate was valid from July 30, 1997 through December 1, 1997;
  • (f) the certificate contains a 1024 bit DSA public key;
  • (g) the certificate is an end entity certificate, as the basic constraints extension is not present;
  • (h) the certificate contains an authority key identifier extension; and
  • (i) the certificate includes one alternative name - an RFC 822 address.
0000 30 82 02 d6  726: SEQUENCE
0004 30 82 02 96  662: . SEQUENCE
0008 a0 03          3: . . [0]
0010 02 01          1: . . . INTEGER 2
                     : 02
0013 02 01          1: . . INTEGER 18
                     : 12
0016 30 09          9: . . SEQUENCE
0018 06 07          7: . . . OID 1.2.840.10040.4.3: dsa-with-sha
                     : 2a 86 48 ce 38 04 03
0027 30 2a         42: . . SEQUENCE
0029 31 0b         11: . . . SET
0031 30 09          9: . . . . SEQUENCE
0033 06 03          3: . . . . . OID 2.5.4.6: C
                     : 55 04 06
0038 13 02          2: . . . . . PrintableString  'US'
                     : 55 53
0042 31 0c         12: . . . SET
0044 30 0a         10: . . . . SEQUENCE
0046 06 03          3: . . . . . OID 2.5.4.10: O

                     : 55 04 0a
0051 13 03          3: . . . . . PrintableString  'gov'
                     : 67 6f 76
0056 31 0d         13: . . . SET
0058 30 0b         11: . . . . SEQUENCE
0060 06 03          3: . . . . . OID 2.5.4.11: OU
                     : 55 04 0b
0065 13 04          4: . . . . . PrintableString  'nist'
                     : 6e 69 73 74
0071 30 1e         30: . . SEQUENCE
0073 17 0d         13: . . . UTCTime  '970730000000Z'
                     : 39 37 30 37 33 30 30 30 30 30 30 30 5a
0088 17 0d         13: . . . UTCTime  '971201000000Z'
                     : 39 37 31 32 30 31 30 30 30 30 30 30 5a
0103 30 3d         61: . . SEQUENCE
0105 31 0b         11: . . . SET
0107 30 09          9: . . . . SEQUENCE
0109 06 03          3: . . . . . OID 2.5.4.6: C
                     : 55 04 06
0114 13 02          2: . . . . . PrintableString  'US'
                     : 55 53
0118 31 0c         12: . . . SET
0120 30 0a         10: . . . . SEQUENCE
0122 06 03          3: . . . . . OID 2.5.4.10: O
                     : 55 04 0a
0127 13 03          3: . . . . . PrintableString  'gov'
                     : 67 6f 76
0132 31 0d         13: . . . SET
0134 30 0b         11: . . . . SEQUENCE
0136 06 03          3: . . . . . OID 2.5.4.11: OU
                     : 55 04 0b
0141 13 04          4: . . . . . PrintableString  'nist'
                     : 6e 69 73 74
0147 31 11         17: . . . SET
0149 30 0f         15: . . . . SEQUENCE
0151 06 03          3: . . . . . OID 2.5.4.3: CN
                     : 55 04 03
0156 13 08          8: . . . . . PrintableString  'Tim Polk'
                     : 54 69 6d 20 50 6f 6c 6b
0166 30 82 01 b4  436: . . SEQUENCE
0170 30 82 01 29  297: . . . SEQUENCE
0174 06 07          7: . . . . OID 1.2.840.10040.4.1: dsa
                     : 2a 86 48 ce 38 04 01
0183 30 82 01 1c  284: . . . . SEQUENCE
0187 02 81 80     128: . . . . . INTEGER
                     : d4 38 02 c5 35 7b d5 0b a1 7e 5d 72 59 63 55 d3
                     : 45 56 ea e2 25 1a 6b c5 a4 ab aa 0b d4 62 b4 d2
                     : 21 b1 95 a2 c6 01 c9 c3 fa 01 6f 79 86 83 3d 03
                     : 61 e1 f1 92 ac bc 03 4e 89 a3 c9 53 4a f7 e2 a6
                     : 48 cf 42 1e 21 b1 5c 2b 3a 7f ba be 6b 5a f7 0a
                     : 26 d8 8e 1b eb ec bf 1e 5a 3f 45 c0 bd 31 23 be
                     : 69 71 a7 c2 90 fe a5 d6 80 b5 24 dc 44 9c eb 4d
                     : f9 da f0 c8 e8 a2 4c 99 07 5c 8e 35 2b 7d 57 8d
0318 02 14         20: . . . . . INTEGER
                     : a7 83 9b f3 bd 2c 20 07 fc 4c e7 e8 9f f3 39 83
                     : 51 0d dc dd
0340 02 81 80     128: . . . . . INTEGER
                     : 0e 3b 46 31 8a 0a 58 86 40 84 e3 a1 22 0d 88 ca
                     : 90 88 57 64 9f 01 21 e0 15 05 94 24 82 e2 10 90
                     : d9 e1 4e 10 5c e7 54 6b d4 0c 2b 1b 59 0a a0 b5
                     : a1 7d b5 07 e3 65 7c ea 90 d8 8e 30 42 e4 85 bb
                     : ac fa 4e 76 4b 78 0e df 6c e5 a6 e1 bd 59 77 7d
                     : a6 97 59 c5 29 a7 b3 3f 95 3e 9d f1 59 2d f7 42
                     : 87 62 3f f1 b8 6f c7 3d 4b b8 8d 74 c4 ca 44 90
                     : cf 67 db de 14 60 97 4a d1 f7 6d 9e 09 94 c4 0d
0471 03 81 84     132: . . . BIT STRING  (0 unused bits)
                     : 02 81 80 a8 63 b1 60 70 94 7e 0b 86 08 93 0c 0d
                     : 08 12 4a 58 a9 af 9a 09 38 54 3b 46 82 fb 85 0d
                     : 18 8b 2a 77 f7 58 e8 f0 1d d2 18 df fe e7 e9 35
                     : c8 a6 1a db 8d 3d 3d f8 73 14 a9 0b 39 c7 95 f6
                     : 52 7d 2d 13 8c ae 03 29 3c 4e 8c b0 26 18 b6 d8
                     : 11 1f d4 12 0c 13 ce 3f f1 c7 05 4e df e1 fc 44
                     : fd 25 34 19 4a 81 0d dd 98 42 ac d3 b6 91 0c 7f
                     : 16 72 a3 a0 8a d7 01 7f fb 9c 93 e8 99 92 c8 42
                     : 47 c6 43
0606 a3 3e         62: . . [3]
0608 30 3c         60: . . . SEQUENCE
0610 30 19         25: . . . . SEQUENCE
0612 06 03          3: . . . . . OID 2.5.29.17: subjectAltName
                     : 55 1d 11
0617 04 12         18: . . . . . OCTET STRING
                     : 30 10 81 0e 77 70 6f 6c 6b 40 6e 69 73 74 2e 67
                     : 6f 76
0637 30 1f         31: . . . . SEQUENCE
0639 06 03          3: . . . . . OID 2.5.29.35: subjectAltName
                     : 55 1d 23
0644 04 18         24: . . . . . OCTET STRING
                     : 30 16 80 14 e7 26 c5 54 cd 5b a3 6f 35 68 95 aa
                     : d5 ff 1c 21 e4 22 75 d6
0670 30 09          9: . SEQUENCE
0672 06 07          7: . . OID 1.2.840.10040.4.3: dsa-with-sha
                     : 2a 86 48 ce 38 04 03
0681 03 2f         47: . BIT STRING  (0 unused bits)
                     : 30 2c 02 14 3c 02 e0 ab d9 5d 05 77 75 15 71 58
                     : 92 29 48 c4 1c 54 df fc 02 14 5b da 53 98 7f c5
                     : 33 df c6 09 b2 7a e3 6f 97 70 1e 14 ed 94

D.3 End-Entity Certificate Using RSA โœจ

okay bestie, this part is an annotated hex dump of a 675 byte version 3 certificate ๐ŸŽ€ and it's giving a whole vibe ๐Ÿ’… here's what the cert is serving:

  • (a) the serial number is 256; ๐Ÿ”ข
  • (b) the certificate is signed with RSA and the MD2 hash algorithm; ๐Ÿ”
  • (c) the issuer's distinguished name is OU=Dept. Arquitectura de Computadors; O=Universitat Politecnica de Catalunya; C=ES ๐Ÿซ
  • (d) and the subject's distinguished name is CN=Francisco Jordan; OU=Dept. Arquitectura de Computadors; O=Universitat Politecnica de Catalunya; C=ES ๐Ÿงš
  • (e) the certificate was issued on May 21, 1996 and expired on May 21, 1997; ๐Ÿ“…
  • (f) the certificate contains a 768 bit RSA public key; ๐Ÿ”‘
  • (g) the certificate is an end entity certificate (not a CA certificate); ๐Ÿ™ˆ
  • (h) the certificate includes an alternative subject name and an alternative issuer name - both are URLs; ๐ŸŒˆ
  • (i) the certificate include an authority key identifier and certificate policies extensions; and ๐Ÿฆ‹
  • (j) the certificate includes a critical key usage extension specifying the public is intended for generation of digital signatures. ๐Ÿ‘‘

Now the dump itself, starting off the top with the outer SEQUENCE:

0000 30 80           : SEQUENCE   (size undefined)

so main character energy, periodt ๐Ÿ’–

0002 30 82 02 40  576: . SEQUENCE
0006 a0 03          3: . . [0]
0008 02 01          1: . . . INTEGER 2
                     : 02
0011 02 02          2: . . INTEGER 256
                     : 01 00
0015 30 0d         13: . . SEQUENCE
0017 06 09          9: . . . OID 1.2.840.113549.1.1.2:
                                       MD2WithRSAEncryption
                     : 2a 86 48 86 f7 0d 01 01 02
0028 05 00          0: . . . NULL
0030 30 68         88: . . SEQUENCE
0032 31 0b         11: . . . SET
0034 30 09          9: . . . . SEQUENCE
0036 06 03          3: . . . . . OID 2.5.4.6: C
                     : 55 04 06
0041 13 02          2: . . . . . PrintableString  'ES'
                     : 45 53
0045 31 2d         45: . . . SET
0047 30 2b         43: . . . . SEQUENCE
0049 06 03          3: . . . . . OID 2.5.4.10: O
                     : 55 04 0a
0054 13 24         36: . . . . . PrintableString

                     'Universitat Politecnica de Catalunya'
                     : 55 6e 69 76 65 72 73 69 74 61 74 20 50 6f 6c 69
                     : 74 65 63 6e 69 63 61 20 64 65 20 43 61 74 61 6c
                     : 75 6e 79 61
0092 31 2a         42: . . . SET
0094 30 28         40: . . . . SEQUENCE
0096 06 03          3: . . . . . OID 2.5.4.11: OU
                     : 55 04 0b
0101 13 21         33: . . . . . PrintableString
                     'OU=Dept. Arquitectura de Computadors'
                     : 44 65 70 74 2e 20 41 72 71 75 69 74 65 63 74 75
                     : 72 61 20 64 65 20 43 6f 6d 70 75 74 61 64 6f 72
                     : 73
0136 30 1e         30: . . SEQUENCE
0138 17 0d         13: . . . UTCTime  '960521095826Z'
                     : 39 36 30 37 32 32 31 37 33 38 30 32 5a
0153 17 0d         13: . . . UTCTime  '979521095826Z'
                     : 39 37 30 37 32 32 31 37 33 38 30 32 5a
0168 30 81 83     112: . . SEQUENCE
0171 31 0b         11: . . . SET
0173 30 09          9: . . . . SEQUENCE
0175 06 03          3: . . . . . OID 2.5.4.6: C
                     : 55 04 06
0180 13 02          2: . . . . . PrintableString  'ES'
                     : 45 53
0184 31 2d         12: . . . SET
0186 30 2b         16: . . . . SEQUENCE
0188 06 03          3: . . . . . OID 2.5.4.10: O
                     : 55 04 0a
0193 13 24         36: . . . . . PrintableString
                     'Universitat Politecnica de Catalunya'
                     : 55 6e 69 76 65 72 73 69 74 61 74 20 50 6f 6c 69
                     : 74 65 63 6e 69 63 61 20 64 65 20 43 61 74 61 6c
                     : 75 6e 79 61
0231 31 2a         42: . . . SET
0233 30 28         40: . . . . SEQUENCE
0235 06 03          3: . . . . . OID 2.5.4.11: OU
                     : 55 04 0b
0240 13 21         33: . . . . . PrintableString
                     'Dept. Arquitectura de Computadors'
                     : 44 65 70 74 2e 20 41 72 71 75 69 74 65 63 74 75
                     : 72 61 20 64 65 20 43 6f 6d 70 75 74 61 64 6f 72
                     : 73
0275 31 19         22: . . . SET
0277 30 17         20: . . . . SEQUENCE
0279 06 03          3: . . . . . OID 2.5.4.3: CN
                     : 55 04 03
0284 13 10         16: . . . . . PrintableString 'Francisco Jordan'

                     : 46 72 61 6e 63 69 73 63 6f 20 4a 6f 72 64 61 6e
0302 30 7c          2: . . SEQUENCE
0304 30 0d         13: . . . SEQUENCE
0306 06 09          9: . . . . OID 1.2.840.113549.1.1.1: RSAEncryption
                     : 2a 86 48 86 f7 0d 01 01 01
0317 05 00          0: . . . . NULL
0319 03 6b        107: . . . BIT STRING
                     : 00   (0 unused bits)
                     : 30 68 02 61 00 be aa 8b 77 54 a3 af ca 77 9f 2f
                     : b0 cf 43 88 ff a6 6d 79 55 5b 61 8c 68 ec 48 1e
                     : 8a 86 38 a4 fe 19 b8 62 17 1d 9d 0f 47 2c ff 63
                     : 8f 29 91 04 d1 52 bc 7f 67 b6 b2 8f 74 55 c1 33
                     : 21 6c 8f ab 01 95 24 c8 b2 73 93 9d 22 61 50 a9
                     : 35 fb 9d 57 50 32 ef 56 52 50 93 ab b1 88 94 78
                     : 56 15 c6 1c 8b 02 03 01 00 01
0428 a3 81 97     151: . . [3]
0431 30 3c         60: . . . SEQUENCE
0433 30 1f         31: . . . . SEQUENCE
0435 06 03          3: . . . . . OID 2.5.29.35: authorityKeyIdentifier
                     : 55 1d 23
0440 04 14         22: . . . . . OCTET STRING
                     : 30 12 80 10 0e 6b 3a bf 04 ea 04 c3 0e 6b 3a bf
                     : 04 ea 04 c3
0464 30 19         25: . . . . SEQUENCE
0466 06 03          3: . . . . . OID 2.5.29.15: keyUsage
                     : 55 1d 0f
0471 01 01          1: . . . . . TRUE
0474 04 04          4: . . . . . OCTET STRING
                     : 03 02 07 80
0480 30 19         25: . . . . SEQUENCE
0482 06 03          3: . . . . . OID 2.5.29.32: certificatePolicies
                     : 55 1d 20
0487 04 21         33: . . . . . OCTET STRING
                     : 30 1f 30 1d 06 04 2a 84 80 00 30 15 30 07 06 05
                     : 2a 84 80 00 01 30 0a 06 05 2a 84 80 00 02 02 01
                     : 0a
0522 30 1c         28: . . . . SEQUENCE
0524 06 03          3: . . . . . OID 2.5.29.17: subjectAltName
                     : 55 1d 11
0529 04 15         21: . . . . . OCTET STRING
                     : 30 13 86 11 68 74 74 70 3a 2f 2f 61 63 2e 75 70
                     : 63 2e 65 73 2f
0552 30 19         25: . . . . SEQUENCE
0554 06 03          3: . . . . . OID 2.5.29.18: issuerAltName
                     : 55 1d 12
0559 04 12         18: . . . . . OCTET STRING
                     : 30 14 86 12 68 74 74 70 3a 2f 2f 77 77 77 2e 75
                     : 70 63 2e 65

0579 30 80           : . SEQUENCE (indefinite length)
0581 06 07          7: . . OID
0583 05 00          0: . . NULL
0585 00 00          0: . . end of contents marker
0587 03 81 81      47: . BIT STRING
                     : 00      (0 unused bits)
                     : 5c 01 bd b5 41 88 87 7a 0e d3 0e 6b 3a bf 04 ea
                     : 04 cb 5f 61 72 3c a3 bd 78 f5 66 17 fe 37 3a ab
                     : eb 67 bf b7 da a8 38 f6 33 15 71 75 2f b9 8c 91
                     : a0 e4 87 ba 4b 43 a0 22 8f d3 a9 86 43 89 e6 50
                     : 5c 01 bd b5 41 88 87 7a 0e d3 0e 6b 3a bf 04 ea
                     : 04 cb 5f 61 72 3c a3 bd 78 f5 66 17 fe 37 3a ab
                     : eb 67 bf b7 da a8 38 f6 33 15 71 75 2f b9 8c 91
                     : a0 e4 87 ba 4b 43 a0 22 8f d3 a9 86 43 89 e6 50
0637 00 00          0: . . end of contents marker

D.4 Certificate Revocation List โœจ

okay so this one is a version 2 CRL ๐Ÿ’œ with one extension, cRLNumber ๐ŸŽ€ It was issued by OU=nist;O=gov;C=us on July 7, 1996, and the next scheduled issuance was August 7, 1996 ๐Ÿ“… The CRL includes one revoked certificates: serial number 18 (12 hex) ๐Ÿ™ˆ The CRL itself is number 18, and it was signed with DSA and SHA-1 ๐Ÿ”ฅ literally so pretty, bestie ๐Ÿ’…

0000 30 81 ba     186: SEQUENCE
0003 30 7c        124: . SEQUENCE
0005 02 01          1: . . INTEGER 1
                     : 01
0008 30 09          9: . . SEQUENCE
0010 06 07          7: . . . OID 1.2.840.10040.4.3: dsa-with-sha
                     : 2a 86 48 ce 38 04 03
0019 30 2a         42: . . SEQUENCE
0021 31 0b         11: . . . SET
0023 30 09          9: . . . . SEQUENCE
0025 06 03          3: . . . . . OID 2.5.4.6: C
                     : 55 04 06
0030 13 02          2: . . . . . PrintableString  'US'
                     : 55 53
0034 31 0c         12: . . . SET
0036 30 0a         10: . . . . SEQUENCE
0038 06 03          3: . . . . . OID 2.5.4.10: O
                     : 55 04 0a
0043 13 03          3: . . . . . PrintableString  'gov'
                     : 67 6f 76
0048 31 0d         13: . . . SET
0050 30 0b         11: . . . . SEQUENCE
0052 06 03          3: . . . . . OID 2.5.4.11: OU
                     : 55 04 0b

0057 13 04          4: . . . . . PrintableString  'nist'
                     : 6e 69 73 74
0063 17 0d         13: . . UTCTime  '970801000000Z'
                     : 39 37 30 38 30 31 30 30 30 30 30 30 5a
0078 17 0d         13: . . UTCTime  '970808000000Z'
                     : 39 37 30 38 30 38 30 30 30 30 30 30 5a
0093 30 22         34: . . SEQUENCE
0095 30 20         32: . . . SEQUENCE
0097 02 01          1: . . . . INTEGER 18
                     : 12
0100 17 0d         13: . . . . UTCTime  '970731000000Z'
                     : 39 37 30 37 33 31 30 30 30 30 30 30 5a
0115 30 0c         12: . . . . SEQUENCE
0117 30 0a         10: . . . . . SEQUENCE
0119 06 03          3: . . . . . . OID 2.5.29.21: reasonCode
                     : 55 1d 15
0124 04 03          3: . . . . . . OCTET STRING
                     : 0a 01 01
0129 30 09          9: . SEQUENCE
0131 06 07          7: . . OID 1.2.840.10040.4.3: dsa-with-sha
                     : 2a 86 48 ce 38 04 03
0140 03 2f         47: . BIT STRING  (0 unused bits)
                     : 30 2c 02 14 9e d8 6b c1 7d c2 c4 02 f5 17 84 f9
                     : 9f 46 7a ca cf b7 05 8a 02 14 9e 43 39 85 dc ea
                     : 14 13 72 93 54 5d 44 44 e5 05 fe 73 9a b2

Appendix E. Authors' Addresses ๐Ÿฆ‹

Here are the four authors and where to find them, bestie ๐Ÿซถ

Russell Housley
SPYRUS
381 Elden Street
Suite 1120
Herndon, VA 20170
USA

EMail: housley@spyrus.com


Warwick Ford
VeriSign, Inc.
One Alewife Center
Cambridge, MA 02140
USA

EMail: wford@verisign.com


Tim Polk
NIST
Building 820, Room 426
Gaithersburg, MD 20899
USA

EMail: wpolk@nist.gov


David Solo
Citicorp
666 Fifth Ave, 3rd Floor
New York, NY 10103
USA

EMail: david.solo@citicorp.com

Copyright (C) The Internet Society (1999). All Rights Reserved. ๐ŸŒˆ

okay so the vibe here is: anyone can copy and share this document, and people can write derivative works that comment on it or help people implement it, and they can publish and distribute those too, in whole or in part, with no real restrictions ๐Ÿ™Œ The one catch is that the copyright notice and this paragraph have to stay on every copy and derivative work ๐Ÿ“

However, this document itself may not be modified in any way, like by removing the copyright notice or the references to the Internet Society or other Internet organizations ๐Ÿšซ The exception is when you're developing Internet standards, in which case the copyright procedures from the Internet Standards process must be followed, or when you need to translate it into a language other than English ๐ŸŒ

The permissions above are perpetual, and the Internet Society or its successors or assigns will never revoke them โ™พ๏ธ ngl that's a whole promise ๐Ÿ˜ญ

This document and the info in it is provided "AS IS", and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ๐Ÿ’€ no cap, that's the whole legal vibe, periodt โœจ

๐Ÿ“ฆ where this page comes from