RFC 4211

Internet X.509 Public Key Infrastructure Certificate Request Message Format (CRMF)

๐Ÿ“… published September 2005, from ietf

RFC 4211: Internet X.509 Public Key Infrastructure Certificate Request Message Format (CRMF) ๐ŸŽ€

Okay bestie, let's start with the basics! ๐Ÿ’– This doc was written by J. Schaad from Soaring Hawk Consulting and published in September 2005 as a Standards Track document. It's in the Network Working Group stream, and it obsoletes RFC 2511 โœจ, so if you see that old one floating around, this is the upgrade. It doesn't update anything else.

Status of This Memo

This document is an Internet standards track protocol for the Internet community, and it's asking for discussion and suggestions for improvements ๐Ÿงš. If you want the current standardization state of this protocol, go check the current edition of "Internet Official Protocol Standards" (STD 1). Distribution of this memo is unlimited, so share away ๐Ÿ’….

Copyright (C) The Internet Society (2005). ๐ŸŒธ

Abstract

Okay, so this document describes the Certificate Request Message Format (CRMF), including its syntax and semantics ๐Ÿฆ‹. It's used to send a request for a certificate to a Certification Authority (CA), possibly through a Registration Authority (RA), so that an X.509 certificate can be produced. The request usually carries a public key along with its associated registration information. The big twist is that this document does not define a certificate request protocol, so it's more of a building block than a full system ๐Ÿซถ.

Table Of Contents

   1. Introduction and Terminology ....................................3
   2. Overview ........................................................3
      2.1. Changes since RFC 2511 .....................................4
   3. CertReqMessage Syntax ...........................................4
   4. Proof-of-Possession (POP) .......................................5
      4.1. Signature Key POP ..........................................7
      4.2. Key Encipherment Keys ......................................9
           4.2.1. Private Key Info Content Type ......................11
           4.2.2. Private Key Structures .............................12
           4.2.3. Challenge-Response Guidelines ......................13
      4.3. Key Agreement Keys ........................................14
      4.4. Use of Password-Based MAC .................................14
   5. CertRequest syntax .............................................16
   6. Controls Syntax ................................................18
      6.1. Registration Token Control ................................18
      6.2. Authenticator Control .....................................19
      6.3. Publication Information Control ...........................19
      6.4. Archive Options Control ...................................21
      6.5. OldCert ID Control ........................................23
      6.6. Protocol Encryption Key Control ...........................23
   7. RegInfo Controls ...............................................23
      7.1. utf8Pairs .................................................23
      7.2. certReq ...................................................24
   8. Object Identifiers .............................................24
   9. Security Considerations ........................................25
   10. References ....................................................26
      10.1. Normative References .....................................26
      10.2. Informative References ...................................27
   11. Acknowledgements ..............................................28
   Appendix A.  Use of RegInfo for Name-Value Pairs ..................29
      A.1.  Defined Names ............................................29
      A.2.  IssuerName, SubjectName, and Validity Value Encoding .....29
   Appendix B.  ASN.1 Structures and OIDs ............................32
   Appendix C.  Why do Proof-of-Possession (POP) .....................38

1. Introduction and Terminology โœจ

Okay so this doc describes the Certificate Request Message Format (CRMF) ๐Ÿ’–. A Certificate Request Message object gets used inside a protocol to send a certificate request to a Certification Authority (CA), possibly through a Registration Authority (RA), so an X.509 certificate can be produced. The request will typically include a public key and the associated registration information.

Here's the lowkey important bit: the certificate request object in this document is not a stand-alone protocol ๐Ÿ™ˆ. It's designed to be used by an externally defined Certificate Request Protocol (CRP). The referencing protocol is expected to decide which algorithms get used, and which registration information and control structures get defined. Lots of the requirements in this document point back to that referencing CRP, so keep that in mind as you read ๐ŸŽ€.

Certificate requests can come from three places: an RA asking for a certificate on behalf of a Subject, a CA asking another CA for a cross-certificate, or an End Entity (EE) asking directly ๐ŸŒˆ.

The key words "MUST", "REQUIRED", "SHOULD", "RECOMMENDED", and "MAY" in this document (in uppercase, as shown) are to be interpreted as described in RFC 2119 [RFC2119]. ๐Ÿ‘‘

2. Overview ๐Ÿฆ‹

Building a certification request is a multi-step glow-up, bestie ๐Ÿ’…:

a) A CertRequest object gets constructed. It may include the public key, all or part of the Subject name, other requested certificate fields, and extra control information tied to the registration process. Depending on the CRP, the Subject can specify this info (and an RA can potentially modify it), or the RA can specify it based on what it knows about the Subject or on documentation the Subject showed.

b) If required, a proof-of-possession value gets calculated. This proves you hold the private key that matches the public key you're asking a certificate for ๐Ÿ”.

c) Extra registration information can be combined with the proof-of-possession value and the CertRequest structure to form a CertReqMessage. Both the Subject and an RA can add registration information ๐Ÿ“.

d) The CertReqMessage gets securely sent to a CA. The specific secure transport methods are up to each CRP that refers to this document ๐Ÿšš.

2.1. Changes since RFC 2511 ๐Ÿ’œ

Here's the tea on what changed since RFC 2511 โ˜•:

  1. Addition of an introduction section.
  2. Addition of the concept of a CRP and language relating to CRPs.
  3. In section 6.2, changed regToken to authenticator.
  4. Add information describing the contents of the EncryptedValue structure.
  5. Changed name and contents of OID {id-regInfo 1}.
  6. Added text detailing what goes into the fields of the different structures defined in the document.
  7. Replaced Appendix A with a reference to [RFC2875]. The only difference is that the old text specified to use subject alt name instead of subject name if subject name was empty. This is not possible for a CA certificate issued using PKIX. It would however be useful to update RFC 2875 to have this fallback position.
  8. Insert Appendix C describing why POP is necessary and what some of the different POP attacks are.
  9. pop field in the CertReqMsg structure has been renamed to popo to avoid confusion between POP and pop.
  10. The use of the EncryptedValue structure has been deprecated in favor of the EnvelopedData structure.
  11. Add details on how private keys are to be structured when encrypted.
  12. Allow for POP on key agreement algorithms other than DH.

3. CertReqMessage Syntax ๐ŸŽ€

A certificate request message is made of three things: the certificate request, an optional proof-of-possession field, and an optional registration information field. Here's the grammar, straight from the source ๐Ÿ’…:

   CertReqMessages ::= SEQUENCE SIZE (1..MAX) OF CertReqMsg

   CertReqMsg ::= SEQUENCE {
      certReq   CertRequest,
      popo       ProofOfPossession  OPTIONAL,
      -- content depends upon key type
      regInfo   SEQUENCE SIZE(1..MAX) of AttributeTypeAndValue OPTIONAL
   }

So what does each field actually mean? โœจ

  • certReq holds the template of the certificate being requested. The Subject (or someone acting for them) fills in the template, and you don't have to fill in every field. Section 5 has the details ๐ŸŒธ.
  • popo holds the value that shows the entity identified as the Subject really has the matching private key ๐Ÿ”‘. Its structure and content depend on the public key algorithm and on the mode it's used in (encryption or signature). That mode comes from the KeyUsage field of the certificate to be issued. Section 4 has the details ๐Ÿ’–.
  • regInfo field SHOULD contain only supplementary information about the context of the certificate request, but only where that info is needed to fulfill the request. This could be subscriber contact info, billing info, or other ancillary stuff that helps get the request done ๐Ÿงš.

Information that's directly related to the certificate content SHOULD be included in the certReq content. Heads up though: if an RA adds extra certReq content, that can invalidate the popo field (it depends on which POP method is used), so be careful ๐Ÿ™ˆ. That means data meant for the certificate content MAY be provided in regInfo instead.

It's the referencing CRP's job to define the details of what can go in the regInfo field. This document describes one method of encoding that information, and you'll find the details in Appendix A ๐Ÿฆ‹.

4. Proof-of-Possession (POP) โœจ

okay bestie, this section is about proof-of-possession (POP) and it's giving "prove you actually own the key" ๐Ÿ”‘๐Ÿ’…. The goal is to stop certain attacks (see Appendix C) and let the CA/RA check that the binding between a subject and a key pair is legit ๐Ÿซถ. So the PKI management structures let a subject prove it has possession of, meaning it can actually use, the private key that matches the public key it wants a certificate for ๐ŸŽ€. A CRP can choose how it enforces POP, like out-of-band procedures or the in-band CRMF message ๐Ÿงš. Inside one CRP, CAs and RAs pick from the POP methods on offer, which is a local policy thing โœจ. A CRP SHOULD define which POP methods are required, or give clients a way to discover the POP methods it supports ๐Ÿ’œ.

Any CRP referencing this document MUST enforce POP by some means ๐Ÿ˜ค. Lowkey, plenty of non-PKIX operational protocols are out there (various electronic mail protocols, for example) that don't explicitly check the binding between the end entity and the private key ๐Ÿ’€. Until operational protocols that DO verify the binding (for signature, encryption, and key agreement key pairs) exist and are ubiquitous, you can't assume the CA/RA verified it ๐Ÿ™ˆ. So honestly, nobody can truly know if the binding between the public key and the identity in the certificate is correct ๐Ÿ˜ญ.

POP looks different depending on the type of key the certificate is for ๐ŸŒธ. If a key can be used for multiple purposes (like a signing and decryption RSA key), then any of the methods MAY be used ๐Ÿฆ‹. Protocol designers need to be aware that hardware limits can affect which POP methods are usable, e.g., if the private key lives in a hardware token ๐Ÿ”ฅ.

This spec covers cases where POP is validated by the CA, the RA, or both ๐Ÿ‘‘. Some policies require the CA to verify POP during issuance, and in that case the RA MUST forward the end entity's CertRequest and ProofOfPossession fields unaltered to the CA ๐Ÿ“. (The RA could verify the POP itself and reject failing requests instead of forwarding them to the CA, which is iconic.) If policy doesn't require the CA to verify POP, the RA SHOULD forward the end entity's request and proof, unaltered, to the CA the same way ๐ŸŒˆ. If that's not possible (for example, because the RA verifies POP by an out-of-band method), then the RA uses the raVerified element to attest to the CA that the required proof was validated ๐Ÿซถ. And if the CA/RA uses an out-of-band method to verify POP (like physically delivering CA/RA-generated private keys), then the ProofOfPossession field is omitted ๐Ÿงš.

ProofOfPossession ::= CHOICE {
    raVerified        [0] NULL,
    signature         [1] POPOSigningKey,
    keyEncipherment   [2] POPOPrivKey,
    keyAgreement      [3] POPOPrivKey }

Here's what each ProofOfPossession field means ๐Ÿ’–:

  • raVerified says the RA has done the POP required on the certificate request. An RA uses this field when 1) the CA isn't required to do its own POP verification AND 2) the RA needs to change the contents of the certReq field. CRPs MUST provide a method for the RA to sign the ProofOfPossession. A requestor MUST NOT set this field, and an RA/CA MUST NOT accept a ProofOfPossession where the requestor sets this field ๐Ÿšซ.
  • signature is for performing POP with signature keys. The details are in Section 4.1 โœจ.
  • keyEncipherment is for performing POP with key encipherment (encryption-based) keys, i.e., RSA. The details are in Section 4.2 ๐ŸŒธ.
  • keyAgreement is for performing POP with key agreement type encryption keys, i.e., DH. The details are in Section 4.3 ๐Ÿฆ‹.

4.1. Signature Key POP

okay so POP for a signature key happens by doing a signature operation on some data that contains the identity the certificate is wanted for ๐Ÿ’…. There are three cases to look at when doing POP for a signature key ๐ŸŽ€:

  1. The certificate subject hasn't established an authenticated identity with a CA/RA yet, but has a password and identity string from the CA/RA. Here, the POPOSigningKeyInput structure gets filled out using the publicKeyMAC choice for authInfo, and the password and identity are used to compute the publicKeyMAC value. The public key for the certificate being requested goes in both the POPOSigningKeyInput and the Certificate Template structures. The signature field is computed over the DER-encoded POPOSigningKeyInput structure ๐Ÿ”.
  2. The CA/RA has already established an authenticated identity for the certificate subject, but the requestor isn't putting it into the certificate request. Here, the POPOSigningKeyInput structure gets filled out using the sender choice for authInfo. The public key for the certificate being requested goes in both the POPOSigningKeyInput and the Certificate Template structures. The signature field is computed over the DER-encoded POPOSigningKeyInput structure ๐ŸŒˆ.
  3. The certificate subject puts its name in the Certificate Template structure along with the public key. In this case the poposkInput field is omitted from the POPOSigningKey structure. The signature field is computed over the DER-encoded certificate template structure โญ.
POPOSigningKey ::= SEQUENCE {
    poposkInput         [0] POPOSigningKeyInput OPTIONAL,
    algorithmIdentifier     AlgorithmIdentifier,
    signature               BIT STRING }

Here's the rundown on POPOSigningKey fields ๐Ÿงš:

  • poposkInput holds the data to be signed, when it's present. This field MUST be present when the certificate template does NOT contain both the public key value and a subject name value ๐Ÿ’œ.
  • algorithmIdentifier identifies the signature algorithm and its associated parameters used to produce the POP value โœจ.
  • signature contains the POP value produced. If poposkInput is present, the signature is computed over the DER-encoded value of poposkInput. If poposkInput is absent, the signature is computed over the DER-encoded value of certReq ๐Ÿซถ.
POPOSigningKeyInput ::= SEQUENCE {
    authInfo            CHOICE {
        sender              [0] GeneralName,
        -- used only if an authenticated identity has been
        -- established for the sender (e.g., a DN from a
        -- previously-issued and currently-valid certificate)
        publicKeyMAC        PKMACValue },
        -- used if no authenticated GeneralName currently exists for
        -- the sender; publicKeyMAC contains a password-based MAC
        -- on the DER-encoded value of publicKey
    publicKey           SubjectPublicKeyInfo }  -- from CertTemplate

And the POPOSigningKeyInput fields ๐Ÿ“:

  • sender contains an authenticated identity that was previously established for the subject ๐Ÿ”.
  • publicKeyMAC contains a computed value that uses a shared secret between the CA/RA and the certificate requestor ๐ŸŒธ.
  • publicKey contains a copy of the public key from the certificate template. This MUST be exactly the same value as is contained in the certificate template ๐Ÿ’–.
PKMACValue ::= SEQUENCE {
   algId  AlgorithmIdentifier,
   value  BIT STRING }

PKMACValue is the one with the fields ๐Ÿฆ‹:

  • algId identifies the algorithm used to compute the MAC value. All implementations MUST support id-PasswordBasedMAC. The details on this algorithm are in Section 4.4 ๐Ÿ‘‘.
  • value contains the computed MAC value. The MAC value is computed over the DER-encoded public key of the certificate subject ๐ŸŒˆ.

Last bit, and it's important ๐Ÿ”ฅ: the CA/RA figures out which shared secret to use by looking at 1) the general name field in the certificate request, or 2) either the regToken (see Section 6.1) or authToken (see Section 6.2) controls ๐Ÿซถ.

4.2. Key Encipherment Keys โœจ

okay so POP for key encipherment keys is done in one of three ways ๐Ÿ’– The private key can be handed over to the CA/RA ๐Ÿ”‘, an encrypted challenge from the CA/RA can get decrypted (that's the direct method) ๐Ÿฆ‹, or the created cert can be sent back encrypted and used as the challenge response (the indirect method) ๐Ÿงš

POPOPrivKey ::= CHOICE {
    thisMessage       [0] BIT STRING,   -- deprecated
    subsequentMessage [1] SubsequentMessage,
    dhMAC             [2] BIT STRING,   -- deprecated
    agreeMAC          [3] PKMACValue,
    encryptedKey      [4] EnvelopedData }
  -- for keyAgreement (only), possession is proven in this message
  -- (which contains a MAC (over the DER-encoded value of the
  -- certReq parameter in CertReqMsg, which must include both subject
  -- and publicKey) based on a key derived from the end entity's
  -- private DH key and the CA's public DH key);
  -- the dhMAC value MUST be calculated as per the directions given
  -- in RFC 2875 for static DH proof-of-possession.
SubsequentMessage ::= INTEGER {
    encrCert (0),
    challengeResp (1) }

the fields of POPOPrivKey mean the following ๐Ÿ‘€

  • thisMessage holds the encrypted private key that a certificate is being issued for. Possession of the private key is proved by handing it to the CA/RA. This field was typed incorrectly when the spec was first written ๐Ÿ™ˆ The correct way to use it is to create an EncryptedValue structure where the encrypted content is the private key, and then wrap that EncryptedValue structure in the BIT STRING type. This field has been deprecated in favor of encryptedKey.
  • subsequentMessage shows that the POP will be finished by decrypting a message from the CA/RA and sending back a response. The type of message to decrypt is set by the value used.
    • encrCert means the issued certificate gets returned in encrypted form. The requestor is required to decrypt the certificate and prove success to the CA/RA. The details are given by the CRP.
    • challengeResponse means a challenge message gets sent from the CA/RA to the requestor. The details of the challenge message and the response are to be provided by the CRP.
  • dhMAC is for Diffie-Hellman key agreement keys ๐ŸŒธ It holds a computed MAC that is made using the requestor's private key and the CA/RA public key. Using this field is deprecated in favor of the agreeMAC field. Details are in section 4.3.
  • agreeMAC is for key agreement keys ๐Ÿ’œ It holds a computed MAC made using the requestor's private key and a matching CA/RA public key. Details are in section 4.3.
    • macAlg holds the algorithm that identifies the method used to compute the MAC value.
    • macValue holds the computed MAC value.
  • encryptedKey holds the encrypted private key that matches the public key the certificate is for. It also carries an identification value showing it was built by the requestor of the certificate. The enveloped content type MUST be id-ct-encKeyWithID.

It is expected that protocols that use this spec will include the confirmation and challenge-response messages needed for a complete protocol ๐ŸŽ€


4.2.1. Private Key Info Content Type

this content type is used for 1) proving possession of private keys and 2) escrowing private keys (using the archive options control in section 6.4) ๐Ÿ—๏ธ The structure is based on the private key info structure from [PKCS8], but it has one deliberate difference. There's a potential attack on escrow agents if they decrypt the private key without knowing who the encrypted key is supposed to belong to ๐Ÿ˜ฌ An attacker could intercept the encrypted private key, build a certificate request around it, and then ask for a recovery operation on that private key.

this content type and its structure are:

id-ct-encKeyWithID OBJECT IDENTIFIER ::= {id-ct 21}

EncKeyWithID ::= SEQUENCE {
  privateKey           PrivateKeyInfo,
  identifier CHOICE {
    string               UTF8String,
    generalName          GeneralName
  } OPTIONAL
}

PrivateKeyInfo ::= SEQUENCE {
   version                   INTEGER,
   privateKeyAlgorithm       AlgorithmIdentifier,
   privateKey                OCTET STRING,
   attributes                [0] IMPLICIT Attributes OPTIONAL
}
Attributes ::= SET OF Attribute

the fields of EncKeyWithID are defined as:

  • privateKey contains the encoded private key. Definitions for three private key formats are included in this document. Specs for asymmetric algorithms need to include both the public and private key definitions for consistency ๐Ÿ’…
  • identifier contains a name that the CA/RA can associate with the requestor. This will usually be either the DN of a certificate or a text token that both the requestor and the CA/RA know ๐Ÿซถ This field MUST be present if the purpose is to prove possession of the private key. The field SHOULD be present if archiving a key and the archive agent is expected to decrypt the key.

the fields of PrivatekeyInfo are define as:

  • version MUST be the value 0
  • privateKeyAlgorithm contains the identifier for the private key object
  • privateKey is an octet string whose contents is the private key, and whose format is defined by the value of privateKeyAlgorithm
  • attributes is a set of attributes. They are extended information that is part of the private key information

4.2.2. Private Key Structures

we're defining the structures here to be used for three algorithms ๐Ÿงš

4.2.2.1. D-H Private Keys

when creating a PrivateKeyInfo for a D-H key, the following rules apply:

  1. The privateKeyAlgorithm MUST be set to id-dh-private-number. The parameter for id-dh-private-number is DomainParameters (imported from [PKIXALG]).
  2. The ASN structure for privateKey MUST be
DH-PrivateKey ::= INTEGER
  1. The attributes field MUST be omitted.

4.2.2.2. DSA Private Keys

when creating a PrivateKeyInfo for a DSA key, the following rules apply:

  1. The privateKeyAlgorithm MUST be set to id-dsa. The parameters for id-dsa is Dss-Parms (imported from [PKIXALG]).
  2. The ASN structure for privateKey MUST be
DSA-PrivateKey ::= INTEGER
  1. The attributes field MUST be omitted.

4.2.2.3. RSA Private Keys

when creating a PrivateKeyInfo for an RSA key, the following rules apply:

  1. The privateKeyAlgorithm MUST be set to rsaEncryption.
  2. The ASN structure for privateKey MUST be RSAPrivateKey (defined in [PKCS1])
  3. The attributes field MUST be omitted.

4.2.3. Challenge-Response Guidelines

this part gives enrollment protocol authors some guidelines on how an indirect proof-of-possession is supposed to work, plus the spots where you need to be careful when building the messages for this POP method ๐Ÿ”

  1. The original enrollment request includes some kind of proof of identity and the public portion of the encryption key. Note that the proof of identity needs to cover the public portion of the encryption key to prevent substitution attacks (where the attacker swaps your public key for their own) ๐Ÿ•ต๏ธโ€โ™€๏ธ
  2. The response message from the server includes an encrypted data value of some type. That value needs to be authenticated in some way as having come from the server. The spec needs to include the specifics of how this value is returned for each key type. For RSA keys, the value can be specified as being directly encrypted by the RSA public key. This will not work for a D-H key, where you need to specify an indirect mechanism to encrypt the value ๐ŸŒˆ
  3. The second request message includes a hash of the decrypted value. This message MUST NOT be just the hash of the encrypted value, because one should never "sign" a completely random value ๐Ÿ™…โ€โ™€๏ธ It's desirable to include information such as the identity string in the hashing process so that this is made explicit. This returned value MUST be included in a second proof of identity.

it is strongly suggested that transaction identifiers and nonce values be required when performing indirect POP ๐Ÿฆ‹ This lets you 1) tie the different messages in the process together and 2) let each entity inject some amount of random data into the process of doing identity proofs.


4.3. Key Agreement Keys

okay, POP for key agreement keys is done in one of four ways ๐Ÿ‘‘ The first three are identical to the ones above for key encryption keys. The fourth one takes advantage of the fact that a shared secret is produced, and that value can be used to MAC information ๐Ÿงช

when the direct or indirect encryption methods from above are used, the CA/RA will need to create an ephemeral key for the cases where the encryption algorithm parameters don't match between the CA/RA and the requestor ๐Ÿ’ซ

the end entity may also MAC the certificate request (using a shared secret key derived from a computation) as a fourth option for demonstrating POP ๐Ÿ“ This option may be used only if the CA/RA already has a certificate that is known to the end entity, and if the Subject is able to use the CA/RA's parameters.

for the DH key agreement algorithm, all implementations MUST support the static DH Proof-of-Possession ๐Ÿ’– Details on this algorithm can be found in section 3 of [RFC2875]. NOTE: If either the subject or issuer name in the CA certificate is empty, then the alternative name should be used in its place. ๐Ÿซถ

4.4. Use of Password-Based MAC ๐Ÿ”

okay so this MAC algorithm is giving shared-secret energy ๐Ÿ” It takes a password and uses it to compute a check value over some info. The whole point is that without the password, you can't compute the correct check value, no cap. The sneaky bit is that it runs the one-way function a bunch of times on purpose, so anyone trying dictionary attacks on the password has to slow down and suffer ๐Ÿ’€

The algorithm identifier and parameter structure for Password-Based MAC is:

   id-PasswordBasedMAC OBJECT IDENTIFIER ::=
                                      { 1 2 840 113533 7 66 13}

   PBMParameter ::= SEQUENCE {
      salt                OCTET STRING,
      owf                 AlgorithmIdentifier,
      iterationCount      INTEGER,
      mac                 AlgorithmIdentifier
      )

Here's what the fields of PEMParameter mean, bestie ๐ŸŽ€

salt is a randomly generated value that gets used when computing the key for the MAC process. The salt SHOULD be at least 8 octets (64 bits) long.

owf tells you which algorithm, and its parameters, get used to compute the key for the MAC process. All implementations MUST support SHA-1. โœจ

iterationCount is how many times the hash gets applied during key computation. The iterationCount MUST be a minimum of 100. Lots of people suggest using values as high as 1000 iterations as the minimum, which is giving careful energy ๐Ÿงš There's a trade-off here between protecting the password from attacks and the time the server spends processing all those iterations when deriving passwords. Hashing is generally considered a cheap operation, but that may not be true for all hash functions in the future ๐Ÿ‘€

mac identifies the algorithm and its parameters for the MAC function to be used. All implementations MUST support HMAC-SHA1 [HMAC]. All implementations SHOULD support DES-MAC and Triple-DES-MAC [PKCS11]. ๐ŸŒธ

Here's the pseudo-code for the algorithm, slay ๐Ÿ’…

   Inputs:
          pw   - an octet string containing the user's password
          data - an octet string containing the value to be MAC-ed
          Iter - iteration count

   Output:
          MAC  - an octet string containing the resultant MAC value

   1.  Generate a random salt value S

   2.  Append the salt to the pw.  K = pw || salt.

   3.  Hash the value of K.  K = HASH(K)

   4.  If Iter is greater than zero.  Iter = Iter - 1.  Goto step 3.

   5.  Compute an HMAC as documented in [HMAC].

       MAC = HASH( K XOR opad, HASH( K XOR ipad, data) )

       Where opad and ipad are defined in [HMAC].

5. CertRequest syntax โœจ

okay so the CertRequest syntax is made of three things: a request identifier, a template of certificate content, and an optional sequence of control information ๐Ÿฆ‹

   CertRequest ::= SEQUENCE {
      certReqId     INTEGER,        -- ID for matching request and reply
      certTemplate  CertTemplate, --Selected fields of cert to be issued
      controls      Controls OPTIONAL } -- Attributes affecting issuance

   CertTemplate ::= SEQUENCE {
      version      [0] Version               OPTIONAL,
      serialNumber [1] INTEGER               OPTIONAL,
      signingAlg   [2] AlgorithmIdentifier   OPTIONAL,
      issuer       [3] Name                  OPTIONAL,
      validity     [4] OptionalValidity      OPTIONAL,
      subject      [5] Name                  OPTIONAL,
      publicKey    [6] SubjectPublicKeyInfo  OPTIONAL,
      issuerUID    [7] UniqueIdentifier      OPTIONAL,
      subjectUID   [8] UniqueIdentifier      OPTIONAL,
      extensions   [9] Extensions            OPTIONAL }

   OptionalValidity ::= SEQUENCE {
      notBefore  [0] Time OPTIONAL,
      notAfter   [1] Time OPTIONAL } --at least one must be present

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

Here's what the fields of CertRequest mean, bestie ๐Ÿ’–

certReqId is an integer the certificate requestor uses to match a specific certificate request with its certificate response. Main character matching energy ๐Ÿงš

certTemplate is a template of an X.509 certificate. The requestor fills in the fields where it wants specific values. More details on the fields are below ๐Ÿ“

controls holds attributes that aren't part of the certificate, but control the context the certificate gets issued in. You can find details on the controls defined in this document in section 6. Other documents may define other controls. CRPs are responsible for specifying which controls are required. ๐ŸŒˆ

Now the fields of CertTemplate, which are giving detail-oriented queen ๐Ÿ‘‘

version MUST be 2 if supplied. It SHOULD be omitted. ๐Ÿ™ˆ

serialNumber MUST be omitted. The CA assigns this field during certificate creation, so the requestor doesn't get a say ๐Ÿ’…

signingAlg MUST be omitted. Also assigned by the CA during certificate creation. Not you, not your call ๐Ÿ’€

issuer is normally omitted. It would get filled in with the CA that the requestor wants to issue the certificate, in situations where an RA is servicing more than one CA. ๐Ÿฆ‹

validity is normally omitted too. It can be used to request that certificates either start at some point in the future or expire at some specific time. A common case is when a cross certificate is issued for a CA. The validity of an existing certificate goes in this field, so the new certificate has the same validity period as the existing one, iconic โœจ If validity is not omitted, then at least one of the sub-fields MUST be specified. The sub-fields are:

  • notBefore contains the requested start time of the certificate. The time follows the same rules as the notBefore time in [PROFILE].
  • notAfter contains the requested expiration time of the certificate. The time follows the same rules as the notAfter time in [PROFILE].

subject gets filled in with the suggested name for the requestor. This would normally be a name that the CA has previously issued to the requestor ๐Ÿซถ

publicKey contains the public key the certificate is being created for. This field MUST be filled in if the requestor generates its own key. The field is omitted if the key is generated by the RA/CA. ๐Ÿ”‘

issuerUID MUST be omitted. This field has been deprecated in [PROFILE]. ๐Ÿฅ€

subjectUID MUST be omitted. This field has also been deprecated in [PROFILE]. ๐Ÿฅ€

extensions contains extensions the requestor wants placed in the certificate. These would generally deal with things like setting the key usage to keyEncipherment ๐Ÿ”ฅ

With the exception of the publicKey field, the CA/RA is permitted to alter any requested field. The requestor needs to check the returned certificate to see if the fields have been set in an acceptable way, so stay alert, bestie ๐Ÿ‘€ CA/RA SHOULD use the template fields if possible. ๐ŸŽ€

There are cases where all the fields of the template can be omitted. If the key generation is happening at the CA/RA, and the identity proof is placed somewhere else (like the id-regCtrl-regToken control below), then the certificate requestor doesn't need to specify any fields at all. Easy breezy ๐Ÿงš


6. Controls Syntax ๐ŸŽ€

okay so the generator of a CertRequest can include one or more control values that relate to how the request gets processed ๐Ÿ’…

   Controls  ::= SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue

The following controls are defined by this document: regToken (section 6.1); authenticator (section 6.2); pkiPublicationInfo (section 6.3); pkiArchiveOptions (section 6.4); oldCertID (section 6.5); protocolEncrKey (section 6.6). Each CRP MUST define the set of controls supported by that protocol. Additional controls may be defined by additional RFCs or by the CRP protocol itself. โœจ

6.1. Registration Token Control ๐ŸŒธ

A regToken control holds one-time information (either based on a secret value or other shared information) that the CA is meant to use to verify the identity of the subject before issuing a certificate ๐Ÿ” When a CA gets a certification request with a value for regToken, it checks that information to confirm the identity claimed in the request.

The value for regToken may be generated by the CA and handed to the subscriber out of band, or it may otherwise be available to both the CA and the subscriber. The security of any out-of-band exchange should be commensurate with the risk the CA will tolerate about accepting an intercepted value from someone other than the intended subscriber. The regToken value is not encrypted on return. If the data is considered sensitive, the requestor needs to shroud it ๐Ÿ™ˆ

The regToken control is only used for initializing an end entity into the PKI. The authenticator control (see section 7.2) can be used for both the initial and subsequent certification requests ๐Ÿฆ‹

In some cases the value for regToken could be a text string or a numeric quantity, like a random number. In the latter case, the value is encoded as a text string representation of the binary quantity. The encoding of regToken SHALL be UTF8String. ๐Ÿ’–

   id-regCtrl-regToken            OBJECT IDENTIFIER ::= { id-regCtrl 1 }

Without prior agreement between the subscriber and CA agents, this value would be a textual shared secret of some type. If a computed value based on that shared secret is to be used instead, it is suggested that the CRP define a new registration control for that specific computation. ๐Ÿงš

6.2. Authenticator Control ๐ŸŒˆ

An authenticator control holds information that gets used on an ongoing basis to set up a non-cryptographic identity check when talking to the CA. Examples include: mother's maiden name, last four digits of a social security number, or other knowledge-based information shared with the subscriber's CA; a hash of such information; or other information produced for this purpose. The value for an authenticator control may be generated by the subscriber or by the CA. ๐Ÿซถ

In some cases, the value for authenticator could be a text string or a numeric quantity, like a random number. The value in the latter case is encoded as a text string representation of the binary quantity. The encoding of authenticator SHALL be UTF8String. ๐Ÿ’…

   id-regCtrl-authenticator       OBJECT IDENTIFIER ::= { id-regCtrl 2 }

When you're deciding whether to use an authenticator or a regToken, use these guidelines, periodt ๐Ÿ’€ If the value is one-time use, then regToken is the move. If the value has long-term usage, then the authenticator control is the one ๐Ÿฆ‹

6.3. Publication Information Control ๐Ÿ“ฎ

okay so the pkiPublicationInfo control lets subscribers suggest where the CA/RA should publish their certificate ๐Ÿ’Œ but it's advisory, so CAs/RAs are totally allowed to ignore it ๐Ÿซถ the OID and syntax go like this:

id-regCtrl-pkiPublicationInfo  OBJECT IDENTIFIER ::= { id-regCtrl 3 }

PKIPublicationInfo ::= SEQUENCE {
     action     INTEGER {
                  dontPublish (0),
                  pleasePublish (1) },
     pubInfos  SEQUENCE SIZE (1..MAX) OF SinglePubInfo OPTIONAL }

SinglePubInfo ::= SEQUENCE {
      pubMethod    INTEGER {
          dontCare    (0),
          x500        (1),
          web         (2),
          ldap        (3) },
      pubLocation  GeneralName OPTIONAL }

Here's what the PKIPublicationInfo fields mean ๐Ÿ‘€

  • action says whether the requestor wants the CA/RA to publish the cert at all. The two options are:
    • dontPublish means the requester does NOT want the CA/RA publishing it (maybe because they're gonna publish it themselves ๐Ÿ’…). If dontPublish is used, the pubInfos field MUST be omitted.
    • pleasePublish means the requestor DOES want the CA/RA to publish the cert ๐ŸŽ€
  • pubInfos holds the locations where the requestor would like the cert published. It gets left out if dontPublish is picked. If you want specific spots AND you're fine with the CA/RA picking others too, you include multiple SinglePubInfo values, and one of them is dontCare.

And the SinglePubInfo fields ๐Ÿงš

  • pubMethod is the address type for the spot where the requestor wants the cert placed.
    • dontCare means the CA/RA can publish wherever it likes ๐ŸŒˆ If dontCare is used, the pubInfos field MUST be omitted.
    • x500 means the requestor wants the CA/RA to publish in a specific location, given in the x500 field of pubLocation.
    • ldap means the same kind of thing, but the location is in the ldap field of pubLocation.
    • web also means a specific location, this time in the http field of pubLocation.
  • pubLocation holds the address where the cert should end up. Whichever choice goes in the general name field depends on what pubMethod was picked here.

Publication locations can show up in any order, and the CA has to process ALL of them for publishing purposes โœจ

6.4. Archive Options Control ๐Ÿ—„๏ธ

the pkiArchiveOptions control gives subscribers what they need to set up an archive of the private key that matches the public key in the certification request ๐Ÿ” Its OID and syntax:

id-regCtrl-pkiArchiveOptions   OBJECT IDENTIFIER ::= { id-regCtrl 4 }

PKIArchiveOptions ::= CHOICE {
   encryptedPrivKey     [0] EncryptedKey,
   -- the actual value of the private key
   keyGenParameters     [1] KeyGenParameters,
   -- parameters which allow the private key to be re-generated
   archiveRemGenPrivKey [2] BOOLEAN }
   -- set to TRUE if sender wishes receiver to archive the private
   -- key of a key pair that the receiver generates in response to
   -- this request; set to FALSE if no archival is desired.

EncryptedKey ::= CHOICE {
   encryptedValue        EncryptedValue, -- deprecated
   envelopedData     [0] EnvelopedData }
   -- The encrypted private key MUST be placed in the envelopedData
   -- encryptedContentInfo encryptedContent OCTET STRING.

EncryptedValue ::= SEQUENCE {
   intendedAlg   [0] AlgorithmIdentifier  OPTIONAL,
   -- the intended algorithm for which the value will be used
   symmAlg       [1] AlgorithmIdentifier  OPTIONAL,
   -- the symmetric algorithm used to encrypt the value
   encSymmKey    [2] BIT STRING           OPTIONAL,
   -- the (encrypted) symmetric key used to encrypt the value
   keyAlg        [3] AlgorithmIdentifier  OPTIONAL,
   -- algorithm used to encrypt the symmetric key
   valueHint     [4] OCTET STRING         OPTIONAL,
   -- a brief description or identifier of the encValue content
   -- (may be meaningful only to the sending entity, and used only
   -- if EncryptedValue might be re-examined by the sending entity
   -- in the future)
   encValue       BIT STRING }
-- The use of the EncryptedValue field has been deprecated in favor
-- of the EnvelopedData structure.
--
-- When EncryptedValue is used to carry a private key (as opposed to
-- a certificate), implementations MUST support the encValue field
-- containing an encrypted PrivateKeyInfo as defined in [PKCS11],
-- section 12.11.  If encValue contains some other format/encoding
-- for the private key, the first octet of valueHint MAY be used
-- to indicate the format/encoding (but note that the possible values
-- of this octet are not specified at this time).  In all cases, the
-- intendedAlg field MUST be used to indicate at least the OID of
-- the intended algorithm of the private key, unless this information
-- is known a priori to both sender and receiver by some other means.

KeyGenParameters ::= OCTET STRING

Here's what the PKIArchiveOptions fields mean ๐ŸŽ€

  • encryptedPrivKey is an encrypted copy of the private key.
  • keyGenParameters holds the info the requestor needs to regenerate the private key. For example, lots of RSA implementations could send the first random number(s) that got tested for primality ๐Ÿง  The structure that goes here isn't defined in this document. CRPs that define content for this structure MUST define not only what content goes here, but also how that data is shrouded from unauthorized access ๐Ÿ™ˆ
  • archiveRemGenPrivKey shows the requestor wants the key that the CA/RA generated on their behalf to be archived ๐Ÿ—๏ธ

And the EncryptedKey fields ๐Ÿ’–

  • encryptedValue is no longer used. This field has been deprecated along with the EncryptedValue structure ๐Ÿ’€
  • envelopedData holds the encrypted value of the private key. CPRs that use this structure MUST define the entity or entities the data is encrypted for (the EE, escrow agents, CAs) and how that key or set of keys gets determined. Details on building an EnvelopedData structure are in [CMS]. The encrypted content MUST be an id-ct-encKeyWithID. The identifier can be left out unless this structure is also being used for proof-of-possession.

6.5. OldCert ID Control ๐Ÿชช

If it's present, the OldCertID control names the certificate that the current certification request is updating. The OID and syntax are:

id-regCtrl-oldCertID           OBJECT IDENTIFIER ::= { id-regCtrl 5 }

CertId ::= SEQUENCE {
      issuer           GeneralName,
      serialNumber     INTEGER
  }

6.6. Protocol Encryption Key Control ๐Ÿ”‘

If it's present, the protocolEncrKey control specifies a key the CA should use to encrypt its response to CertReqMessages. The OID for this control is id-regCtrl-protocolEncrKey. The parameter structure for this field is SubjectPublicKeyInfo. (This structure is defined in [PROFILE].)

id-regCtrl-protocolEncrKey     OBJECT IDENTIFIER ::= { id-regCtrl 6 }

This control gets used when a CA has something to send the subscriber that needs encrypting, like a private key the CA generated for the subscriber to use ๐Ÿฅบ

7. RegInfo Controls ๐Ÿ“‹

This section covers the controls that go in the regInfo field of the CertReqMsg structure ๐Ÿ’…

7.1. utf8Pairs ๐Ÿ’ฌ

This control is used to pass text-based info from the Subject to an RA, and then on to a CA that's issuing a certificate. The OID for this structure is id-regInfo-utf8Paris, and its type is UTF8String.

   id-regInfo-utf8Pairs    OBJECT IDENTIFIER ::= { id-regInfo 1 }

The name ends with the question mark character ('?'). The value ends with the percent character '%'. Name value pairs can repeat, so the syntax is:

   Name?Value%[Name?Value%]*

The %xx mechanism of [RFC1738] is used to encode '?' (%3f) and '%' (%25) when they aren't being used for their reserved purpose. Names MUST NOT start with a numeric character โœ‹

This control can show up multiple times in the regInfo structure. If the info conflicts, it's up to the local policy on the RA/CA to sort it out ๐Ÿงš

Appendix A has a list of common names and data formats that match fields which usually show up in certificates and directories ๐Ÿ“š

7.2. certReq ๐Ÿ“

This control solves a problem where an RA needs to change the certificate template a Subject proposed, but the Subject already used that template in its POP calculation ๐Ÿ˜ค So the RA can drop a new certificate template into the regInfo sequence.

This control has the OID id-regInfo-certReq and the structure CertRequest. Only one instance of this attribute can be in the regInfo sequence. If this control exists in the regInfo structure, the certificate template in the request gets ignored. The RA MUST copy all data from the core template into this attribute ๐ŸŒธ

   id-regInfo-certReq       OBJECT IDENTIFIER ::= { id-regInfo 2 }

8. Object Identifiers ๐Ÿ†”

The OID id-pkix has the value:

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

   -- arc for Internet X.509 PKI protocols and their components
   id-pkip  OBJECT IDENTIFIER :: { id-pkix pkip(5) }

   -- arc for Registration Controls in CRMF
   id-regCtrl  OBJECT IDENTIFIER ::= { id-pkip regCtrl(1) }
   -- arc for Registration Info in CRMF
   id-regInfo       OBJECT IDENTIFIER ::= { id-pkip id-regInfo(2) }

9. Security Considerations ๐Ÿ”

okay bestie, enrollment protocols are literally full of private info ๐Ÿ˜ญ like private keys, identity numbers, credit card numbers, the whole vibe. The security of any CRP depends on the security mechanisms of the protocol and/or process used to communicate between CAs, RAs and EEs. All protocols must provide for masking, either via encryption or off-line processing, of all subscriber-sensitive information. ๐Ÿ”’

Lots of enrollment protocols set up the initial identity between the CA/RA and the EE with a token ๐ŸŽŸ๏ธ Usually this token gets delivered out-of-band (think the governmental mail system ๐Ÿ“ฌ). The security of any out-of-band exchange needs to be commensurate with the risk that the CA/RA will tolerate when it comes to a third party intercepting the token.

Implementation must implement Proof-of-Possession (POP) values during certificate enrollment processes. A good POP algorithm needs to prove two things: 1) that the key is tied to a specific user and 2) that the user has use of the key in question. Failure to implement POP lets people make certificates where the public key and the name values don't correctly bind, and that's how you get impersonation on signature keys and interception of encrypted messages ๐Ÿ’€

Implementations must use high entropy random number generators in producing private keys. Implementations must randomly generate content-encryption keys, message-authentication keys, initialization vectors (IVs), salt, and padding. Inadequate pseudo-random number generators (PRNGs) used to generate cryptographic keys can result in little or no security. An attacker may find it much easier to reproduce the PRNG environment that produced the keys and search the resulting small set of possibilities, instead of brute forcing the whole key space. Generating quality random numbers is genuinely hard ๐Ÿฅฒ RFC 4086 [RANDOM] offers important guidance in this area, and Appendix 3 of FIPS Pub 186 [DSS] provides one quality PRNG technique โœจ

Implementations must protect private keys. If a signer's private key gets compromised, third parties can masquerade as the signer. If a decryption private key gets compromised, a third party can intercept messages ๐Ÿ˜ฑ

One feature of the certificate message request syntax is that key generation can be performed remotely from the creation of the certificate request. This feature should never be used for generation of signing keys ๐Ÿšซ If signing keys are generated for the user, then an element of repudiation comes into play. The user can claim that an item was signed by the entity that generated the key, as well as by any entity that might have seen the key value during transfer from the generator to the EE. Care must be taken to protect encryption keys by the remote key generator, so they aren't intercepted by a third party. That means the encryption algorithms used need to be secure, and a content encryption key or a key encryption key must be used to mask the private key during transport back to the user. CRP protocols must never assume that a signature key generated by the user can be used to decrypt the package in which an encryption private key is transported ๐Ÿ™…โ€โ™€๏ธ

This document describes a method by which key escrow may be done ๐Ÿ—๏ธ There are several issues to take into account when doing key escrow. First, the client must be able to correctly identify the entity to which a key is to be escrowed, or the CRP must provide a method by which the client can discover this information. A CRP cannot assume that the key escrow agent and the CA are the same entity and thus have the same names. Second, the algorithms used to mask the private key or other key generation information during transport to the escrow agent need to be commensurate with the value of the data being protected by the key. Third, the escrow agent needs to provide sufficient safeguards so that an escrowed key is returned only to entities that should be able to obtain the private key. Generally, this should be restricted to the entity that escrowed the data. Fourth, the escrow database needs to be stored in a secure manner. One common method for doing this is to re-encrypt the data to keys that only the escrow agent has access to. In this case, one may need to escrow the escrow agent key as well. Access to either the escrow agent or the archived key would amount to access to all private keys that have been escrowed with that agent. ๐Ÿšจ


10. References ๐Ÿ“š

10.1. Normative References

  • [PKCS1] Jonsson, J. and B. Kaliski, "Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1", RFC 3447, February 2003.
  • [HMAC] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-Hashing for Message Authentication", RFC 2104, February 1997.
  • [PKCS11] RSA Laboratories, The Public-Key Cryptography Standards - "PKCS #11 v2.11: Cryptographic Token Interface Standard", RSA Security Inc., June 2001.
  • [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
  • [PROFILE] Housley, R., Polk, W., Ford, W., and D. Solo, "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 3280, April 2002.
  • [PKIXALG] Bassham, L., Polk, W., and R. Housley, "Algorithms and Identifiers for the Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 3279, April 2002.
  • [CMS] Housley, R., "Cryptographic Message Syntax (CMS)", RFC 3852, July 2004.
  • [RFC2875] Prafullchandra, H. and J. Schaad, "Diffie-Hellman Proof-of-Possession Algorithms", RFC 2875, July 2000.

10.2. Informative References

  • [DSS] National Institute of Standards and Technology, FIPS Pub 186: Digital Signature Standard, May 1994.
  • [PKCS8] RSA Laboratories, "PKCS #8: Private-Key Information Syntax Standard", PKCS #8 v1.2, November 1993.
  • [RANDOM] Eastlake, D., 3rd, Schiller, J., and S. Crocker, "Randomness Requirements for Security", BCP 106, RFC 4086, June 2005.
  • [RFC2202] Cheng, P. and R. Glenn, "Test Cases for HMAC-MD5 and HMAC-SHA-1", RFC 2202, September 1997.
  • [RFC1738] Berners-Lee, T., Masinter, L., and M. McCahill, "Uniform Resource Locators (URL)", RFC 1738, December 1994.

11. Acknowledgements ๐Ÿซถ

The working group would like to thank Michael Myers, Carlisle Adams, Dave Solo, and David Kemp, who authored the original version of this document ๐Ÿ’œ

The working group also gratefully acknowledges the contributions of Barbara Fox, Warwick Ford, Russ Housley, and John Pawling, whose review and comments significantly clarified and improved the utility of this specification โœจ The members of the ca-talk mailing list also provided significant input with respect to interoperability testing ๐ŸŽ€

The text of Appendix C (Why do POP) was taken from an e-mail message by Al Arsenault and was originally part of the PKIX Roadmap document ๐ŸŒธ


Appendix A. Use of RegInfo for Name-Value Pairs ๐Ÿงš

The "value" field of the id-regInfo-utf8Pairs string (with "tag" field equal to 12 and appropriate "length" field) will contain a series of UTF-8 name/value pairs ๐ŸŒˆ

This Appendix lists some common examples of such pairs for the purpose of promoting interoperability among independent implementations of this specification. It is recognized that this list is not exhaustive and will grow with time and implementation experience ๐Ÿฆ‹

A.1. Defined Names

The following table defines a recommended set of named elements. The value in the column "Name Value" is the exact text string that will appear in the regInfo ๐Ÿ’…

   Name Value
   ----------
   version            -- version of this variation of regInfo use
   corp_company       -- company affiliation of subscriber
   org_unit           -- organizational unit
   mail_firstName     -- personal name component
   mail_middleName    -- personal name component
   mail_lastName      -- personal name component
   mail_email         -- subscriber's email address
   jobTitle           -- job title of subscriber
   employeeID         -- employee identification number or string
   mailStop           -- mail stop
   issuerName         -- name of CA
   subjectName        -- name of Subject
   validity           -- validity interval

For example:

   version?1%corp_company?Example, Inc.%org_unit?Engineering%
   mail_firstName?John%mail_lastName?Smith%jobTitle?Team Leader%
   mail_email?john@example.com%

A.2. IssuerName, SubjectName, and Validity Value Encoding โœจ

okay so whenever issuerName, subjectName, or validity shows up as a named element in id-regInfo-utf8Pairs, the values SHALL use the syntax below ๐Ÿ’… no freestyling, bestie. In this grammar, [] marks something optional, and ::= and | mean what they always mean in BNF. Everything else outside the non-terminal names is a literal terminal, and spaces don't count ๐Ÿฆ‹. Alphabetics are case-sensitive, so no "lowercase is fine" energy ๐Ÿ™ˆ

issuerName  ::= <names>
subjectName ::= <names>
<names>     ::= <name> | <names>:<name>

<validity>  ::= validity ? [<notbefore>]-[<notafter>]

<notbefore> ::= <time>
<notafter>  ::= <time>

Time is UTC time written as YYYYMMDD[HH[MM[SS]]]. HH, MM, and SS default to 00, and they get dropped when they sit at the end of the value and are 00 ๐Ÿ•ฐ๏ธ

Here's a validity encoding:

validity?-19991231%

That's a validity interval with no value for notBefore, and notAfter set to December 31, 1999 ๐ŸŽ†

Each name is one single-character name form identifier, followed by a name value made of one or more UTF-8 characters. Inside a name value, if a character has formatting meaning at an outer level and you need to disambiguate it, the escape sequence %xx SHALL be used, where xx is the hex value for the encoding concerned. The percent symbol is written as %% ๐Ÿ’–

<name> ::= X<xname>|O<oname>|E<ename>|D<dname>|U<uname>|I<iname>

Here are the name forms and their value formats ๐Ÿ‘‘

X.500 directory name form (identifier "X"):

<xname> ::= <rdns>
<rdns>  ::= <rdn> | <rdns> , <rdn>
<rdn>   ::= <avas>
<avas>  ::= <ava> | <avas> + <ava>
<ava>   ::= <attyp> = <avalue>
<attyp> ::= OID.<oid> | <stdat>

A standard attribute type <stdat> is an alphabetic attribute type identifier from this set:

C      (country)
L      (locality)
ST     (state or province)
O      (organization)
OU     (organizational unit)
CN     (common name)
STREET (street address)
E      (E-mail address).

<avalue> is a name component written as a UTF-8 character string of 1 to 64 characters. The catch is that in the IA5 subset of UTF-8, only the characters of ASN.1 PrintableString are allowed ๐Ÿ™ƒ

Other name form (identifier "O"):

<oname> ::= <oid> , <utf8string>

E-mail address (rfc822name) name form (identifier "E"):

<ename> ::= <ia5string>

DNS name form (identifier "D"):

<dname> ::= <ia5string>

URI name form (identifier "U"):

<uname> ::= <ia5string>

IP address (identifier "I"):

<iname> ::= <oid>

And here's a full example, so you can see the vibe ๐Ÿงš

issuerName?XOU=Our CA,O=Example,C=US% subjectName?XCN=John Smith,
      O=Example, C=US, E=john@example.com%

Appendix B. ASN.1 Structures and OIDs ๐ŸŒˆ

bestie, this is the big one โœจ every module, OID, and structure is copied exactly here, so nobody's compiler gets confused ๐Ÿซถ

PKIXCRMF-2005 {iso(1) identified-organization(3) dod(6) internet(1)
security(5) mechanisms(5) pkix(7) id-mod(0) id-mod-crmf2005(36)}

DEFINITIONS IMPLICIT TAGS ::=
BEGIN

IMPORTS
  -- Directory Authentication Framework (X.509)
     Version, AlgorithmIdentifier, Name, Time,
     SubjectPublicKeyInfo, Extensions, UniqueIdentifier, Attribute
        FROM PKIX1Explicit88 {iso(1) identified-organization(3) dod(6)
            internet(1) security(5) mechanisms(5) pkix(7) id-mod(0)
            id-pkix1-explicit(18)} -- found in [PROFILE]

  -- Certificate Extensions (X.509)
     GeneralName
        FROM PKIX1Implicit88 {iso(1) identified-organization(3) dod(6)
               internet(1) security(5) mechanisms(5) pkix(7) id-mod(0)
               id-pkix1-implicit(19)}  -- found in [PROFILE]

  -- Cryptographic Message Syntax
     EnvelopedData
        FROM CryptographicMessageSyntax2004 { iso(1) member-body(2)
             us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16)
             modules(0) cms-2004(24) };  -- found in [CMS]

-- The following definition may be uncommented for use with
-- ASN.1 compilers that do not understand UTF8String.

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

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

-- arc for Internet X.509 PKI protocols and their components

id-pkip  OBJECT IDENTIFIER ::= { id-pkix 5 }

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

id-ct   OBJECT IDENTIFIER ::= { id-smime  1 }  -- content types
-- Core definitions for this module

CertReqMessages ::= SEQUENCE SIZE (1..MAX) OF CertReqMsg

CertReqMsg ::= SEQUENCE {
 certReq   CertRequest,
 popo       ProofOfPossession  OPTIONAL,
 -- content depends upon key type
 regInfo   SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue OPTIONAL }

CertRequest ::= SEQUENCE {
 certReqId     INTEGER,          -- ID for matching request and reply
 certTemplate  CertTemplate,  -- Selected fields of cert to be issued
 controls      Controls OPTIONAL }   -- Attributes affecting issuance

CertTemplate ::= SEQUENCE {
 version      [0] Version               OPTIONAL,
 serialNumber [1] INTEGER               OPTIONAL,
 signingAlg   [2] AlgorithmIdentifier   OPTIONAL,
 issuer       [3] Name                  OPTIONAL,
 validity     [4] OptionalValidity      OPTIONAL,
 subject      [5] Name                  OPTIONAL,
 publicKey    [6] SubjectPublicKeyInfo  OPTIONAL,
 issuerUID    [7] UniqueIdentifier      OPTIONAL,
 subjectUID   [8] UniqueIdentifier      OPTIONAL,
 extensions   [9] Extensions            OPTIONAL }

OptionalValidity ::= SEQUENCE {
 notBefore  [0] Time OPTIONAL,
 notAfter   [1] Time OPTIONAL } -- at least one MUST be present

Controls  ::= SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue
AttributeTypeAndValue ::= SEQUENCE {
 type         OBJECT IDENTIFIER,
 value        ANY DEFINED BY type }

ProofOfPossession ::= CHOICE {
 raVerified        [0] NULL,
 -- used if the RA has already verified that the requester is in
 -- possession of the private key
 signature         [1] POPOSigningKey,
 keyEncipherment   [2] POPOPrivKey,
 keyAgreement      [3] POPOPrivKey }

POPOSigningKey ::= SEQUENCE {
 poposkInput           [0] POPOSigningKeyInput OPTIONAL,
 algorithmIdentifier   AlgorithmIdentifier,
 signature             BIT STRING }
 -- The signature (using "algorithmIdentifier") is on the
 -- DER-encoded value of poposkInput.  NOTE: If the CertReqMsg
 -- certReq CertTemplate contains the subject and publicKey values,
 -- then poposkInput MUST be omitted and the signature MUST be
 -- computed over the DER-encoded value of CertReqMsg certReq.  If
 -- the CertReqMsg certReq CertTemplate does not contain both the
 -- public key and subject values (i.e., if it contains only one
 -- of these, or neither), then poposkInput MUST be present and
 -- MUST be signed.


POPOSigningKeyInput ::= SEQUENCE {
 authInfo            CHOICE {
     sender              [0] GeneralName,
     -- used only if an authenticated identity has been
     -- established for the sender (e.g., a DN from a
     -- previously-issued and currently-valid certificate)
     publicKeyMAC        PKMACValue },
     -- used if no authenticated GeneralName currently exists for
     -- the sender; publicKeyMAC contains a password-based MAC
     -- on the DER-encoded value of publicKey
 publicKey           SubjectPublicKeyInfo }  -- from CertTemplate

PKMACValue ::= SEQUENCE {
algId  AlgorithmIdentifier,
-- algorithm value shall be PasswordBasedMac {1 2 840 113533 7 66 13}
-- parameter value is PBMParameter
value  BIT STRING }

PBMParameter ::= SEQUENCE {
   salt                OCTET STRING,
   owf                 AlgorithmIdentifier,
   -- AlgId for a One-Way Function (SHA-1 recommended)
   iterationCount      INTEGER,
   -- number of times the OWF is applied
   mac                 AlgorithmIdentifier
   -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
}   -- or HMAC [HMAC, RFC2202])

POPOPrivKey ::= CHOICE {
 thisMessage       [0] BIT STRING,         -- Deprecated
 -- possession is proven in this message (which contains the private
 -- key itself (encrypted for the CA))
 subsequentMessage [1] SubsequentMessage,
 -- possession will be proven in a subsequent message
 dhMAC             [2] BIT STRING,         -- Deprecated
 agreeMAC          [3] PKMACValue,
 encryptedKey      [4] EnvelopedData }
 -- for keyAgreement (only), possession is proven in this message
 -- (which contains a MAC (over the DER-encoded value of the
 -- certReq parameter in CertReqMsg, which MUST include both subject
 -- and publicKey) based on a key derived from the end entity's
 -- private DH key and the CA's public DH key);

SubsequentMessage ::= INTEGER {
 encrCert (0),
 -- requests that resulting certificate be encrypted for the
 -- end entity (following which, POP will be proven in a
 -- confirmation message)
 challengeResp (1) }
 -- requests that CA engage in challenge-response exchange with
 -- end entity in order to prove private key possession

-- Object identifier assignments --

-- Registration Controls in CRMF
id-regCtrl OBJECT IDENTIFIER ::= { id-pkip 1 }


id-regCtrl-regToken OBJECT IDENTIFIER ::= { id-regCtrl 1 }
--with syntax:
RegToken ::= UTF8String

id-regCtrl-authenticator OBJECT IDENTIFIER ::= { id-regCtrl 2 }
--with syntax:
Authenticator ::= UTF8String

id-regCtrl-pkiPublicationInfo OBJECT IDENTIFIER ::= { id-regCtrl 3 }
--with syntax:

PKIPublicationInfo ::= SEQUENCE {
action     INTEGER {
             dontPublish (0),
             pleasePublish (1) },
pubInfos  SEQUENCE SIZE (1..MAX) OF SinglePubInfo OPTIONAL }
  -- pubInfos MUST NOT be present if action is "dontPublish"
  -- (if action is "pleasePublish" and pubInfos is omitted,
  -- "dontCare" is assumed)

SinglePubInfo ::= SEQUENCE {
 pubMethod    INTEGER {
     dontCare    (0),
     x500        (1),
     web         (2),
     ldap        (3) },
 pubLocation  GeneralName OPTIONAL }

id-regCtrl-pkiArchiveOptions     OBJECT IDENTIFIER ::= { id-regCtrl 4 }
--with syntax:
PKIArchiveOptions ::= CHOICE {
 encryptedPrivKey     [0] EncryptedKey,
 -- the actual value of the private key
 keyGenParameters     [1] KeyGenParameters,
 -- parameters that allow the private key to be re-generated
 archiveRemGenPrivKey [2] BOOLEAN }
 -- set to TRUE if sender wishes receiver to archive the private
 -- key of a key pair that the receiver generates in response to
 -- this request; set to FALSE if no archival is desired.

EncryptedKey ::= CHOICE {
 encryptedValue        EncryptedValue,   -- Deprecated
 envelopedData     [0] EnvelopedData }
 -- The encrypted private key MUST be placed in the envelopedData
 -- encryptedContentInfo encryptedContent OCTET STRING.

EncryptedValue ::= SEQUENCE {
 intendedAlg   [0] AlgorithmIdentifier  OPTIONAL,
 -- the intended algorithm for which the value will be used
 symmAlg       [1] AlgorithmIdentifier  OPTIONAL,
 -- the symmetric algorithm used to encrypt the value
 encSymmKey    [2] BIT STRING           OPTIONAL,
 -- the (encrypted) symmetric key used to encrypt the value
 keyAlg        [3] AlgorithmIdentifier  OPTIONAL,
 -- algorithm used to encrypt the symmetric key
 valueHint     [4] OCTET STRING         OPTIONAL,
 -- a brief description or identifier of the encValue content
 -- (may be meaningful only to the sending entity, and used only
 -- if EncryptedValue might be re-examined by the sending entity
 -- in the future)
 encValue       BIT STRING }
 -- the encrypted value itself
-- When EncryptedValue is used to carry a private key (as opposed to
-- a certificate), implementations MUST support the encValue field
-- containing an encrypted PrivateKeyInfo as defined in [PKCS11],
-- section 12.11.  If encValue contains some other format/encoding
-- for the private key, the first octet of valueHint MAY be used
-- to indicate the format/encoding (but note that the possible values
-- of this octet are not specified at this time).  In all cases, the
-- intendedAlg field MUST be used to indicate at least the OID of
-- the intended algorithm of the private key, unless this information
-- is known a priori to both sender and receiver by some other means.

KeyGenParameters ::= OCTET STRING
id-regCtrl-oldCertID          OBJECT IDENTIFIER ::= { id-regCtrl 5 }
--with syntax:
OldCertId ::= CertId

CertId ::= SEQUENCE {
 issuer           GeneralName,
 serialNumber     INTEGER }

id-regCtrl-protocolEncrKey    OBJECT IDENTIFIER ::= { id-regCtrl 6 }
--with syntax:
ProtocolEncrKey ::= SubjectPublicKeyInfo

-- Registration Info in CRMF
id-regInfo OBJECT IDENTIFIER ::= { id-pkip 2 }

id-regInfo-utf8Pairs    OBJECT IDENTIFIER ::= { id-regInfo 1 }
--with syntax
UTF8Pairs ::= UTF8String


id-regInfo-certReq       OBJECT IDENTIFIER ::= { id-regInfo 2 }
--with syntax
CertReq ::= CertRequest

-- id-ct-encKeyWithID is a new content type used for CMS objects.
-- it contains both a private key and an identifier for key escrow
-- agents to check against recovery requestors.

id-ct-encKeyWithID OBJECT IDENTIFIER ::= {id-ct 21}

EncKeyWithID ::= SEQUENCE {
  privateKey           PrivateKeyInfo,
  identifier CHOICE {
    string             UTF8String,
    generalName        GeneralName
  } OPTIONAL
}

PrivateKeyInfo ::= SEQUENCE {
   version                   INTEGER,
   privateKeyAlgorithm       AlgorithmIdentifier,
   privateKey                OCTET STRING,
   attributes                [0] IMPLICIT Attributes OPTIONAL
}

Attributes ::= SET OF Attribute

END

Appendix C. Why do Proof-of-Possession (POP) ๐Ÿ”‘โœจ

Okay bestie, let's talk about POP! ๐ŸŽ€ Proof-of-Possession, or POP, means the CA is adequately convinced that whoever asks for a certificate for the public key Y actually has access to the matching private key X. ๐Ÿ’–

POP is a big deal ๐Ÿ‘‘ because it keeps the whole PKI giving trustworthy vibes. At its lowest level, POP stops the "self-inflicted denial of service" ๐Ÿ’€, which is when an entity voluntarily gets a certificate that it can't actually use to sign or to encrypt/decrypt information. But ngl, there are two examples that show POP also blocks sneakier, more serious threats ๐Ÿ˜ญ:

  • POP for signing keys: this one is super important for non-repudiation of transactions ๐Ÿ–‹๏ธ. Say Alice legitimately has private key X and its public key Y ๐Ÿฆ‹. Alice got a certificate containing Y from Charlie, a CA. Then Alice uses X to sign a transaction T โœ๏ธ. Without POP, Mal could also get a certificate from Charlie with that same public key Y ๐Ÿ™ˆ. Now there are two possible plot twists: Mal could claim he was the real signer of T, or Alice could falsely deny signing T and say it was Mal. Since nobody can reliably prove whether Mal did or did not ever possess X, neither claim can be refuted, and the PKI's service and confidence are totally defeated ๐Ÿ’…. (Of course, if Mal really did possess Alice's private key X, no POP mechanism in the world will save her, but that's a different problem ๐Ÿ’€.)

Here's a partial fix ๐ŸŒธ: Alice (as the true signer) can include her certificate, or an identifier of it like a hash of her certificate, in the signed information. This might make it harder for Mal to claim authorship, since he'd have to say he incorrectly included Alice's certificate instead of his own ๐Ÿคจ. But it wouldn't stop Alice from falsely repudiating her actions ๐Ÿ˜ค. The certificate is a public item, so Mal could have inserted Alice's certificate or identifier into the signed transaction, and its presence doesn't prove Alice was the one who took part in the repudiated transaction. The only reliable way to stop this attack is to require that Mal prove he possesses X before his certificate is issued ๐Ÿ”’.

For signing keys used only for authentication, and not for non-repudiation, the threat is lower ๐ŸŒˆ because users may not care about Alice's after-the-fact repudiation, so POP becomes less important. Still, POP SHOULD still be done wherever feasible in this environment, by either off-line or on-line means โœจ.

  • POP for key management keys: POP for key management keys (keys used for key agreement or key exchange) can help prevent undermining confidence in the PKI too ๐Ÿซถ. Picture this: Al is a new instructor in the Computer Science Department of a local university ๐ŸŽ“. He made a draft final exam for his Introduction to Networking course and wants to send a copy to Dorothy, the Department Head, for review before the exam ๐Ÿ“. Of course the exam gets encrypted, because several students have access to the computer system ๐Ÿ”. But a quick search of the certificate repository (for example, searching for all records with subjectPublicKey=Dorothy's-value) reveals that several students have certificates containing the same public key management key as Dorothy ๐Ÿ˜ฑ. If the CA did no POP, Al has no way of knowing whether the students just made these certificates without knowing the matching private key (so it's safe to send the exam to Dorothy), or whether they somehow got Dorothy's private key (so it is absolutely not safe) ๐Ÿšจ. So the PKI's whole job, letting users talk to each other with confidence in who they're talking to, is totally defeated ๐Ÿ’”. If the CA is providing POP, then either no students will have such certificates, or Al can know for sure that the students do know Dorothy's private key and act accordingly ๐Ÿง โœจ.

Author's Address ๐Ÿ–Š๏ธ

Jim Schaad
Soaring Hawk Consulting
PO Box 675
Gold Bar, WA 98251

EMail: jimsch@exmsft.com

Copyright (C) The Internet Society (2005).

This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights.

This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM 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.

Intellectual Property โš–๏ธ

The IETF takes no position regarding the validity or scope of any Intellectual Property Rights or other rights that might be claimed to pertain to the implementation or use of the technology described in this document, or the extent to which any license under such rights might or might not be available; nor does it represent that it has made any independent effort to identify any such rights. Information on the procedures with respect to rights in RFC documents can be found in BCP 78 and BCP 79.

Copies of IPR disclosures made to the IETF Secretariat, and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification, can be obtained from the IETF on-line IPR repository at http://www.ietf.org/ipr.

The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights that may cover technology that may be required to implement this standard. Please address the information to the IETF at ietf-ipr@ietf.org.

Acknowledgement ๐Ÿซถ

Funding for the RFC Editor function is currently provided by the Internet Society. ๐ŸŒท

๐Ÿ“ฆ where this page comes from