Generate CSR including certificate template information with OpenSSL

10,352

At the top of your openssl.conf enter:

[ OIDs ]

certificateTemplateName = 1.3.6.1.4.1.311.20.2

In your [req_attributes]:

certificateTemplateName = ASN1:PRINTABLESTRING:CustomUserOffline

You could, of course, skip the definition of the OID, just like you did in your question, and use the OID directly.


Using the following openssl config file:

oid_section = OIDs

[ OIDs ]

# This uses the short name of the template:
certificateTemplateName = 1.3.6.1.4.1.311.20.2

# Use this instead if you need to refer to the template by OID:
# certificateTemplateOID = 1.3.6.1.4.1.311.21.7  

  [ req ]

prompt             = no
string_mask        = default

# The size of the keys in bits:
default_bits       = 2048
distinguished_name = req_dn
req_extensions     = req_ext

[ req_dn ]

# Note that the following are in 'reverse order' to what you'd expect to see in
# Windows and the numbering is irrelevant as long as each line's number differs.

# Domain Components style:
# Server name:
# 2.DC = com
# 1.DC = example
# commonName = Acme Web Server

# Locality style:
# countryName = GB
# stateOrProvinceName = London
# localityName = Letsby Avenue
# organizationName = Acme
# organizationalUnitName = IT Dept
# organizationalUnitName = Web Services
# commonName = Acme Web Server

# Or traditional org style:
countryName = GB
organizationName = Acme
organizationalUnitName = IT Dept
2.organizationalUnitName = Web Services
commonName = Acme Web Server

[ req_ext ]

#basicConstraints=critical,CA:TRUE

# This requests a certificate using the 'CustomUserOffline' template.  Check with the CA for the correct name to use,
# or alternatively comment it out and let the CA apply it:
certificateTemplateName = ASN1:PRINTABLESTRING:CustomUserOffline

subjectAltName = @alt_names

[alt_names]
# To copy the CN (in the case of a DNS name in the CN) use:
# DNS = ${req_dn::commonName}
DNS.1 = www.example.com
DNS.2 = example.com

This results in the following extract when viewed using openssl req -in usercert.csr -noout -text:

    Attributes:
    Requested Extensions:
        1.3.6.1.4.1.311.20.2:
            ..CustomUserOffline

and the following extract when viewed with certutil usercert.csr:

  Attribute[0]: 1.2.840.113549.1.9.14 (Certificate Extensions)
    Value[0][0], Length = 4d
Certificate Extensions: 2
    1.3.6.1.4.1.311.20.2: Flags = 0, Length = 13
    Certificate Template Name (Certificate Type)
        CustomUserOffline
Share:
10,352
Chris
Author by

Chris

I'm a systems and networks engineer; Microsoft and VMware certified. I also like to write code and play retro games.

Updated on September 18, 2022

Comments

  • Chris
    Chris over 1 year

    I'm generating a CSR with OpenSSL using the following configuration file:

    [ req ]
    default_bits           = 2048
    default_keyfile        = usercert.key
    distinguished_name     = req_distinguished_name
    attributes             = req_attributes
    prompt                 = no
    
    [ req_distinguished_name ]
    C            = FR
    L            = Paris
    OU           = IT
    CN           = FirstName LastName
    
    [ req_attributes ]
    1.3.6.1.4.1.311.13.2.1 = CertificateTemplate=CustomUserOffline
    

    My goal here is to include the template name in the CSR in order for a Windows CA to be able to process it.

    I use the following command line to generate the CSR:

    openssl req -new -key usercert.key -out usercert.csr -config usercert.cnf
    

    I get no error when running it and I can verify the CSR with the following command:

    openssl req -text -noout -verify -in usercert.csr
    
    verify OK
    Certificate Request:
        Data:
            Version: 1 (0x0)
            Subject: C = FR, L = Paris, OU = IT, CN = FirstName LastName
            Subject Public Key Info:
                Public Key Algorithm: rsaEncryption
                    RSA Public-Key: (2048 bit)
                    Modulus:
                        00:af:85:28:40:84:d8:8a:58:35:86:b8:f5:25:b2:
                        ...
                        05:8d:57:cc:a0:4c:8f:da:f3:f4:a7:57:76:51:e2:
                        56:25
                    Exponent: 65537 (0x10001)
            Attributes:
                1.3.6.1.4.1.311.13.2.1   :CertificateTemplate=CustomUserOffline
        Signature Algorithm: sha256WithRSAEncryption
             1e:4e:9b:6d:24:75:81:5f:be:52:58:ba:79:a1:ac:c8:d6:c9:
             ...
             40:2d:b6:fc
    

    But when I try to verify the CSR with certutil usercert.csr on Windows I get the following error:

    PKCS10 Certificate Request:
    Version: 1
    Subject:
        CN=FirstName LastName
        OU=IT
        L=Paris
        C=FR
      Name Hash(sha1): ab6adbd772e0ca2a0fce4a32abfdd1645686c0b9
      Name Hash(md5): 21d7edb09130201e880133c245617304
    
    Public Key Algorithm:
        Algorithm ObjectId: 1.2.840.113549.1.1.1 RSA (RSA_SIGN)
        Algorithm Parameters:
        05 00
    Public Key Length: 2048 bits
    Public Key: UnusedBits = 0
        0000  30 82 01 0a 02 82 01 01  00 af 85 28 40 84 d8 8a
        ...
        0100  f3 f4 a7 57 76 51 e2 56  25 02 03 01 00 01
    Request Attributes: 1
      1 attributes:
    
      Attribute[0]: 1.3.6.1.4.1.311.13.2.1 (Enrollment Name Value Pair)
        Value[0][0], Length = 27
    Cannot decode object: The data is invalid. 0x8007000d (WIN32: 13 ERROR_INVALID_DATA)
    CertUtil: -dump command FAILED: 0x8007000d (WIN32: 13 ERROR_INVALID_DATA)
    CertUtil: The data is invalid.
    

    It seems that the custom attribute is recognized as 1.3.6.1.4.1.311.13.2.1 (Enrollment Name Value Pair) is displayed but then I guess the name/value pair CertificateTemplate=CustomUserOffline is not in the proper format.
    How can I fix it?

    A few notes:

    • I'm using OpenSSL to generate the CSR because in the end it will be a Linux client generating the CSR

    • I'm aware of the certreq -attrib "CertificateTemplate:CustomUserOffline" -submit usercert.csr command, but the request will be submitted through C# code using the certenroll API so that's why I would like to include the certificate template information directly in the CSR.

  • Chris
    Chris almost 5 years
    It works as expected, so in fact the key thing is to use the proper OID :) and make sure it's in the certificate extensions not attributes. Also I noticed that it works if I use the ASN1:UTF8String prefix. Any recommendation on which type should be used?
  • garethTheRed
    garethTheRed almost 5 years
    It depends on what characters you use in your template names and the characters that Microsoft allow. Here's a link on the differences. I tend to use A-Za-z0-9 in my tempate names, so either would work.
  • Chris
    Chris almost 5 years
    It makes sense, thank you.
  • bgStack15
    bgStack15 almost 4 years
    Use the template name (the one without spaces) and not the Display Name (the one with the spaces, most likely)!