Other posts in the series:


Hello folks! Today I'm starting with a series of a topics where I will cover how to use certificate enrollment APIs with Windows PowerShell.

Target audience

Target audience for the series is (but not limited to): Systems Administrators, PKI administrators, geeks. While I'll try to keep things as simple as possible, there will be some low-level details (300+) which you can ignore if you don't understand them.

Abstract

Prior to Windows Server 2008 and Windows Vista, certificate enrollment APIs were exposed by XEnroll COM interfaces which were not very powerful and fairly complex to use. You even can compare certificate request wizards in Windows XP and in Windows Vista. Windows Vista and Windows Server 2008 introduced a brandy new certificate enrollment experience with a set of powerful and flexible COM interfaces — CertEnroll. CertEnroll interfaces are described here: Certificate Enrollment API. And we will discuss about these APIs.

Basic concepts

Let's define few key notes before you start. What is certificate request? Certificate request is a signed content that contains required information that is used by CA server to construct certificate. The following information is usually included in requests:

  • Certificate subject — the Subject field in the certificate that describes the particular certificate holder;
  • Public key — public key is a mandatory part of any X.509 certificate which is used by various cryptographic operations — data encryption/decryption and signing.
  • Optional attributes and extensions — attributes are used by CA server to help construct the certificate and mostly is not included in the issued certificate. For example, information about the client, Cryptographic Service Provider (CSP) that was used during key generation. Certificate extensions are usually included in issued certificates and provides additional information about the certificate holder and/or how the certificate should be used. For example, the requestor can include Enhanced Key Usage (EKU) extension to identify for which application purposes the certificate can be used (client authentication or code signing). With Enterprise CAs, the Certificate Template extension is mandatory and always should be included in the request.

    However this information is optional. For example, if you are using Enterprise CA, you can put the minimum required information and the rest will be added by the CA from certificate template settings. But the best practice dictates that it is recommended to put enough information about desired certificate.
  • Signature — any certificate request is digitally signed by the private key. Request signing helps CA to ensure that the request was not modified since it was created. The content is signed by private key generated during request creation. Since public key is included in the request, it is easy to verify digital signature.

in fact, certificate extensions is not a dedicated field and is an attribute with the well-known OID = 1.2.840.113549.1.9.14.

Certificate request types

Probably you heard these abbreviations like PKCS#10, PKCS#7, CMS, CMC? While previous information is clear and almost self-explanatory, these abbreviations are not. PKCS is Public-Key Cryptography Standards. There are a lot of such standards identified by numbers: PKCS#1, PKCS#1.2, PKCS#8, PKCS#9, PKCS#10, PKCS#12 and so on. CMS is Cryptography Message Syntax which provides a method for digitally signing data, digesting data, encrypting data, and authenticating data.

Talking about out subject, we will mostly deal with PKCS#10 — which is the only standard which represents actual certificate request. You can argue that you have a ton of CMC requests. In a fact, PKCS#7 and CMC are wrappers or containers. PKCS#7 message may wrap a PKCS#10 request and add additional information.

A common example of PKCS#7 container is Enroll On Behalf Of (EOBO). When you perform EOBO, actual request is generated by using PKCS#10. You may remember that EOBO requests are signed by enrollment agent. Enrollment agent's certificate and signature must be added to the request. Since PKCS#10 was not originally intended to handle such situations, the whole request is wrapped to PKCS#7 message. And everything becomes simple: actual PKCS#10 is added to PKCS#7 as a nested object. Enrollment agent's certificate is included as another nested object and the whole content is signed:

PKCS#7 basic structure

Actually PKCS#7 may contain a variety of cryptographic messages. For example, PKCS#7 containers are used by Key Archival. When you export archived key from CA database, exported blob is PKCS#7 message which wraps underlying encrypted object and additional information.

I think, there is enough of theory and in the next post we will start with practice. Keep alive!

to be continued…


Share this article:

Comments:

Alex

Vadims-

Question about creating the PrivateKey object, why include the KeyUsage property in the HashTable when setting the KeySpec propery to 1 (XCN_AT_KEYEXCHANGE)?

I noticed that no matter what values I provided for KeyUsage, the value of said property in the instantiated object was always coming back as 5. I could change it after creation, but not as part of the creation. Then I read the documentation about KeySpec HERE and it provided the answer as to why this was happening:

"If you specify XCN_AT_KEYEXCHANGE, the KeyUsage property is set to XCN_NCRYPT_ALLOW_DECRYPT_FLAG | XCN_NCRYPT_ALLOW_KEY_AGREEMENT_FLAG."

Looking at the allowable values in the X509PrivateKeyUsageFlags enumeration listed HERE those two values are 0x1 and 0x4 respectively which sum to 0x5. Maybe this behavior was different back in 2012 when the article was originally written?

Alex

Alex

Disregard my comment here...somehow I managed to post it in Part 1 when it was intended for Part 2.


Post your comment:

Please, solve this little equation and enter result below. Captcha