Building Public Key Infrastructure in Windows

Important note: Due to backend upgrades, the illustrative images used in this post have been lost. As the post is no longer being maintained, they will not be replicated and replaced.

The internet relies on Public Key Infrastructure (PKI) for SSL/TLS certificates for HTTPS operation, code signing, email certificates, and more. While you can read about PKI, I have found that getting your hands dirty and building it is the best way to understand how all the pieces fit together and where things can break.

This guide will walk through the following things:

  • The lab environment used in this guide
  • Setting up a root Certification Authority (CA)
  • Setting up a subordinate CA
  • Issuing and revoking certificates
  • Why PKI matters

Version Information

This section was inspired by "1.1 A Note about Software Versions" from Building Virtual Machine Labs by @da_667

The software that I used in this guide were the ones that I had on hand. Do not worry about using the exact same versions. I suggest updating your software when updates are available, and using the most current software version available.

In future versions, some configuration options might be in different locations or rolled into other options and various aspects of the UI may change. Don't panic. Software changes. Consult the official documentation to see if the option mentioned has been moved.

Versions used

Windows Server 2016 Standard (Desktop Experience), (1607)
Windows 10 Enterprise, pre-Fall Creator's Update

Prerequisite Knowledge

This guide assumes that you know the following:

  • How to install Windows Server 2016
  • How to configure Active Directory Domain Services, DNS, and DHCP
  • How to configure a client for network connectivity
  • Troubleshooting

Lab Structure

There will be four devices in this lab, as seen above.

  • DC01.NotAwful.local is a Windows Server 2016 server and will have a static IP address of It will have the following roles installed: Active Directory Domain Services, DNS, DHCP
  • CA01.NotAwful.local is a Windows Server 2016 server and will have a static IP address of It will have the following role installed: Active Directory Certificate Services
  • Client01.NotAwful.local is a Windows workstation that will receive its IP address through DHCP.
  • NoAwRootCA is a Windows Server 2016 server and will have a static IP address of It is not joined to the NotAwful.local domain. It has the following role installed: Active Directory Certificate Services

Domain Set-Up


  1. Change IP to, DNS
  2. Change Computer name to DC01
  3. Restart
  4. Install Updates
  5. Install the Active Directory Domain Services Role
  6. Configure Active Directory
  7. Restart
  8. Create a user and assign them to the Domain Admins group (use this to configure everything else wherever possible)
  9. Install and configure DHCP


  1. Change IP to, DNS
  2. Change Name to CA01
  3. Restart server
  4. Join to the NotAwful.local domain


  1. Rename computer to Client01
  2. Join to the NotAwful.local domain.

Root Certificate Authority

Setting up NoAwRootCA

We are going to get NoAwRootCA ready to be configured as our Root Certificate Authority.

  1. Change IP to
  2. Change server name to NoAwRootCA
  3. Restart
  4. Open Server Manager, open Add Roles and Features
  5. Select Role-based of feature-based installation. Click Next.
  6. Select the local machine as the installation target. Click Next.
  7. Select Active Directory Certificate Services. Select Add Management Tools from the pop-up. Click Next.
  8. Do not install additional features. Click Next.
  9. Read the information provided on the Active Directory Certificate Services page. Click Next.
  10. Ensure that only Certification Authority is checked. Click next.
  11. Click Install.
  12. Click Close.

Configuring the Root Certificate Authority

Now we are going to get to configuring our Root Certificate Authority. We need to configure our root self-signed certificate and define where the Certification Revocation List (CRL) will be located.

Configure the Standalone Certificate Authority Role

To begin we have to set up our self-signed certificate with which we will use to sign certificates. There are a lot of certificates involved in this whole process.


  1. Open Server Manager and open the Notifications. Select AD CS Configuration. The AD CS configuration window opens to the Credentials step. Enter the Local Administrator details and click next.
  2. On the Role Services step, check Certification Authority. At this point, this should be the only option available. Click next.
  3. Because this server is not domain-joined, the only option available on the Setup Type step is Standalone CA. Select Standalone CA and lick next.
  4. On the CA Type step, select RootCA and click next.
  5. On the Private Key step, select Create New Private Key and click Next.
  6. On the Cryptography step, select RSA#Microsoft Software Key Storage Provider, change the key length to 4096, and select SHA256 as the hash algorithm. Click Next.
  7. On the CA Name step, change the Common Name for this CA to NotAwfulRoot. The Common Name will be used throughout this guide. Do not add a Distinguished Name. Click next.
  8. On the Validity Period step, change the validity period for your root certificate to be valid. I suggest 10 years. Click next.
  9. On the Certificate Database step, leave the database location and database log location with their default settings and click next.
  10. On the confirmation step, review your configuration. Click configure if everything is correct.
  11. The Results page will open and confirm that your configuration succeeded. If this is not the case, you may have to start over. Click close.

Configure the Root CA

Now that the role is properly configured, we have to set up the Root CA to hand off management to a Subordinate Certificate Authority (Sub CA).

  1. On NoAwRootCA, open the Certification Authority window. You can do so from the Server Manager by clicking Tools and selecting Certification Authority from the drop-down menu.
  2. Right-click NotAwfulRoot on the left-hand side and select Properties.
  3. Open the Extensions tab. Select the Authority Information Access (AIA) Extension from the drop-down menu. Click add.
  4. The Add Location window will open. Enter http://ca01.notawful.local/certificate/.
  5. Append <ServerDNSName>_<CAName><CertificateName>.crt to the location. Click OK.
    Note: Ensure Include the AIA extension of issued certificates is checked before moving on.
  6. On the Extensions tab, select the CRL Distribution Point (CDP) extension and click add.
  7. The Add Location window will open. Enter http://ca01.notawful.local/certificate/.
  8. Append <CaName><CRLNameSuffix><DeltaCRLAllowed>.crl in the location field. Click OK.
  9. On the Extensions tab, with the CDP extension selected, highlight your new entry. Ensure that Include in CRLs. Clients Use this this to find Delta CRL locations., Include in the CDP extension of issued certificates. are checked.
  10. Click apply. The computer will prompt you to restart the service, select No then click OK.

Publish the Certification Revocation List and Export Certificates

The information we entered will be appended to our certificate so that when a client attempts to validate a certificate it will validate certificates through the domain-joined subordinate certificate authority. We have to publish our first CRL and our self-signed certificates so we can pass them to CA01.

  1. In the Certification Authority window, right-click Revoked Certificates. Select all tasks, and then select publish.
  2. The Publish CRL window will open. Select New CRL. New CRL should be the only option available at this time. Click OK and close the Certification Authority window.
  3. Open File Explorer. In the top bar type C:\Windows\System32\CertSrv\CertEnroll. Copy these two files to external storage.

Install and Configure CA01

Before we start configuring the Certification Authority role on CA01.NotAwful.local we have to do some initial set-up. Configure the following:

  • Static IP of
  • DNS server of
  • Name the server CA01
  • Join the server to the NotAwful.Local domain.

Once that is finished install the Active Directory Certification Services role on CA01.NotAwful.Local. Installing and initially configuring the AD CS is mostly the same with the following changes:

  • During the Add Roles and Features Wizard, on the Role Services step, select Certification Authority and Certificate Authority Web Enrollment.
  • There will be a Role Services step for Web Server Role (IIS). Leave these settings as default.

Configuring AD CS

There are a few configuration changes that I will highlight here. Other than these few things, the process is roughly the same.

  1. Open the AD CS Configuration window.
  2. On the Credentials step, use a domain admin account that is not named Administrator.
  3. On the Role Services step, select Certification Authority and Certification Authority Web Enrollment.
  4. On the Setup Type step, select Enterprise CA.
  5. On the CA Type step, select Subordinate CA.
  6. Create a new Private Key with a key length of 4096.
  7. Leave the CA Name section with its defaults.
  8. On the Certificate Request step, select Save a certificate request to file on the target machine. The configuration wizard will save it in under C:\ by default.
  9. Leave the database locations at their default settings.
  10. Click Configure.
    This configuration will succeed with warnings. Read the warning text before closing the window. It will explain what we are about to do next.

Copy the certification request file from C:\ to external storage.

A Short Intermission

The next section requires some jumping around across various machines. First we will answer the certification request from CA01 on NoAwRootCA, then we will set up the backend of our CRL, and finally we will get our subordinate certification authority up and running.


We have to answer the request from CA01 and issue it a certificate on our root certificate authority.

  1. Copy the certificate request (.req) file from CA01 to NoAwRootCA.
  2. On NoAwRootCA open the Certification Authority window.
  3. Right-click NotAwfulRoot, select all tasks, then select Submit a new request.... Select the request file that you copied to this device in step 1.
  4. In the Certification Authority window, select Pending Requests. You will see the request that you just imported.
  5. Right-click the request, select All Tasks, and click Issue.
  6. Select Issued Certificates. There will be a new certificate there. Right-click the certificate and select Open.
  7. The Certificate window will open. On the Details tab, select Copy to File....
  8. The Certificate Export Wizard will appear. Click next.
  9. Select Cryptographic Message Syntax Standard - PKCS #7 Certificates (.P7B) and ensure that Include all certificates in the certification path if possible is checked. Click next.
  10. Save the file as NotAwfulLocalCert.p7b. Click next, and on the next page click finish.
  11. Copy the file NotAwfulLocalCert.p7b to external storage.

Now that we have issued CA01 a certificate, we can shut down NoAwRootCA until we have to reissue CA01's certification authority certificate. If the word certificate has not yet lost all meaning, it will soon.


To recap, we have four files to copy to CA01 so we can finish all of it's configuration. The files are:

  • NoAwRootCA_NotAwfulRoot.crt and NotAwfulRoot.crl, which we need to publish on our web server
  • NotAwfulLocalCert.p7b which is CA01's issuing certificate
  1. Copy the three files you created to CA01
  2. Right-click NoAwRootCA_NotAwfulRoot.crt and select Install Certificate.
  3. The Certificate Import Wizard will open. Select Local Machine and click Next.
  4. On the Certificate Store page, select Place all Certificates in the following store, and select Trusted Root Certification Authorities. Click next.
  5. On the final page, click finish. The window will close and after a few moments you will be informed that the import was successful.
  6. Open File Explorer and type C:\inetpub\wwwroot\ into the top bar.
  7. Create a folder called certificate in this folder.
  8. Copy NoAwRootCA_NotAwfulRoot.crt and NotAwfulRoot.crl to C:\inetpub\wwwroot\certificate\
  9. Open the Certification Authority window.
  10. On the left-hand side of the window, right-click NotAwful-CA01-CA and select all tasks, and then select Install CA Certificate...
  11. In the file select window, select NotAwfulLocalCert.p7b. Click open.
  12. On the left-hand side of the window, right-click NotAwful-CA01-CA and select all tasks, and then select Start Service. The window will refresh as the service restarts.
  13. On the left-hand side of the window, right-click NotAwful-CA01-CA and select Properties.
  14. In the Properties window, select the Extensions tab.
  15. Select Authority Information Access (AIA) from the drop-down menu and click Add...
  16. Enter http://www.ca01.notawful.local/AIA. Click OK.
    Note (2018-01-24, 13:37): This path is incorrect. This guide will function despite this. Correction incoming.
  17. Ensure that Include in the AIA extension of issued certificates is checked.
  18. Select CRL Distribution Point (CDP) from the drop-down menu and click Add...
  19. Enter http://www.ca01.notawful.local/CRL. Click OK.
    Note (2018-01-24, 13:37): This path is incorrect. This guide will function despite this. Correction incoming.
  20. Ensure that Include in CRLs. Clients Use this to find Delta CRL locations. and Include in the CDP extension of issued certificates. are checked.
  21. Click apply.

At this point, make sure that you can get to your certificate revocation lists. On Client01, which should be domain-joined, open a browser and navigate to ca01.notawful.local and ca01.notawful.local\certsrv. The first should bring up the IIS splash page. The second should prompt you for domain credentials in order to interact with the CA and see the CRL.

We're done! (Not Really.)

So far we have set up our root certification authority, NoAwRootCA, and issued a certificate that allows CA01 to issue certificates of its own. We still have to issue some certificates, revoke them, and pull the CRL to check them.

Issuing Certificates

If we are going to issue certificates we need to do two things: Create templates for certificates so that when one is requested we don't have to process it manually, and then have someone issue a certificate request. Since we are in an Active Directory environment we can have clients request certificates automatically.

Creating certificate templates

We will create Certificate Templates on CA01. We will create User and Computer templates in this guide.

  1. Open the Certification Authority window.
  2. On the left-hand side, right-click Certificate Templates and select manage.
  3. Right-click the Computer template and select Duplicate Template.
  4. A window will appear. On the Compatibility tab, change the Certification Authority and Certificate Recipient to the lowest device in your environment. You will be shown a list of configuration changes available to the template when you do this.
  5. Under the General tab, fill in the name of your new template.
    Note: Publishing certificates to Active Directory is only needed if the public key/certificate for SMIME/EFS or Cisco ISE is needed in the active directory objects. Special thanks to ThePKIGuy for this information.
  6. Under the Security tab, ensure that Domain Computers have the Read, Enroll, and Autoenroll permissions.
  7. Under the Extensions tab, make sure that the Application Policies are Client Authentication and Server Authentication.
  8. Click OK.

Configure a copy of the User certificate that has the following properties:

  • For User certificates, Domain Users require Read, Enroll, and Autoenroll properties.
  • Under the Subject Name tab, uncheck Include in e-mail name in subject name and E-mail name.
  • Check what the certificate's uses are under the Extensions tab.

On the left-hand side of the Certification Authority window, right-click Certificate Templates, select New, select Certificate Template to Issue and select one of the templates that you just created. Repeat for the second certificate. This will tell your CA to push these certificates out.

Issuing certificates automatically

We will issue certificates to workstations and users in our domain automatically. We will configuring clients to automatically request certificates through group policy. In our activity, Client01 and the domain admin account we created earlier are in the same Organizational Unit (OU).

On DC01:

  1. Copy NoAwRootCA_NotAwfulRoot.crt to DC01.
  2. Open the Group Policy Management Console.
  3. Create a new Group Policy Object (GPO) in the domain and link it to your OU
  4. Right-click your new GPO and select Edit.
  5. On the left-hand side, expand Computer Configuration, expand Policies, expand Windows Settings, expand Security Settings, and select Public Key Policies.
  6. Enable the Certificate Services Client - Certificate Enrollment Policy group policy setting.
  7. Enable the Certificate Services Client - Auto-Enrollment group policy setting. Ensure that both Renew expired certificates, update pending certificates, and remove revokes certificates, and Update certificates that use certificate templates are checked.
  8. Right-click Trusted Root Certification Authorities, and select Import...
  9. The Certificate Import Wizard will appear, again. Click next.
  10. Select your root certificate, NoAwRootCA_NotAwfulRoot.crt and click next.
  11. Let the wizard place all certificates into the Trusted Root Certification Authorities, and click next.
  12. Click finish. After a moment a window will appear to let you know that the certificate has been successfully imported.
  13. Complete steps 5 through 7 under User Configuration rather than Computer Configuration, then close the window.

Did it work?

On Client01, press the windows key and type certificates. Open both Manage User Certificates and Manage Computer Certificates. In both windows under Personal\Certificates you should see a new certificate issued by NotAwful-CA01-CA. You can also go to Trusted Root Certification Authorities\Certificates to see that NotAwfulRoot has been added to your client workstation.


If your certificates aren't present, open up the Command Prompt (cmd.exe) and type gpupdate /force. Once the command has completed you can check your certificates again and they should appear.

Tom published his private key on his blog

That certainly is a problem. I guess we should revoke that certificate and reissue him a new one, and quick!

On CA01, open the Certification Authority and navigate to Issued Certificates. You can right-click his certificate, go to All Tasks, and select Revoke Certificate. Select Key Compromise from the drop-down menu and click Yes. Check Revoked Certificates to make sure that the certificate was revoked. Right-click Revoked Certificates, select All Tasks, and then Publish.

We should publish a New CRL, since not every application checks Delta CRLs. We want to make sure everyone knows that Tom is not trustworthy anymore. His certificate, I mean. His certificate is not trustworthy anymore.

Now we have to make sure that the CRL got published correctly. On Client01, open up a web browser and go to ca01.notawful.local/certsev and log into the web interface. Select Download a CA certificate, certificate chain, or CRL, and download the latest base CRL on the next page. Once that is finished, open the Certificate Revocation List we just downloaded and open the Revocation List tab.


Good, it worked. Even still, Tom created a bunch of additional work for everyone. Not every application checks the CRL, especially if the application is running on an embedded device and has very little memory to operate on.

Additional Information

We took our root CA offline to prevent anyone from being able to compromise the private key used to generate its self-signed certificate, and used our domain-joined CA to actually issue certificates.

Public Key Infrastructure (PKI) revolves around the chaining of trust. We trust our root CA's word that someone below them is the real deal. By extension, we trust that the clients the root CA trust with certain tasks (as determined by the qualities of the certificate) are also trustworthy. If CA in the chain becomes compromised then all the clients and certificates below it become invalid. Likewise if any certificate in the chain expires - that is to say not renewed in time - then all certificates it has issued become invalid.

When certificates become invalid, or are revoked, applications that rely on those trusted certificates can (and hopefully do) break.

We use PKI to issue web server certificates for SSL/TLS, for code signing, encrypting and signing messages, and all other sorts of things. We use components of PKI in near everything we do that involves computers, so having a high-level understanding of it will help you in the future.


It has been quite the trip through this activity. We created a small domain environment, created a root certificate authority and a subordinate certificate authority, and then we issued and revoked some certificates.

Hopefully everyone leaves this guide understanding more about Public Key Infrastructure than they did when they started.

Support the Author

Devon Taylor (They/Them) is a Canadian network architect, security consultant, and blogger. They have experience developing secure network and active directory implementations in low-budget and low-personnel environments. Their blog offers a unique and detailed perspective on security and game design, and they tweet about technology, security, games, and social issues. You can support their work via Patreon (USD), or directly via ko-fi.