Additions to the CPolydorou.Security Powershell Module

This post has been triggered by a project that I'm currently working on that involves nginx and containers. As part of the nginx configuration, I had to create a certificate key pair that was going to be used in order to secure traffic towards nginx.

The challenge I faced was to convert the PFX certificate that was handed to me by the Certificate Authority team to the format nginx understood. Considering that this was a process that I'd followed many times in the past (and also blogged about), I decided to update a Powershell module of mine named CPolydorou.Security in order to make the use of OpenSSL friendlier to the Windows administrator. 

The four new functions that are included in the latest version (1.2.0) are:

  • Export-ServerCertificateFromPFX
  • Export-CertificateChainFromPFX
  • Export-PrivateKeyFromPFX
  • Decrypt-PrivateKey
Let's go through them one-by-one to see how they can help! For the examples demostrated below, I've created secure string objects for the passphrases when reading the PFX and saving the private key, named pass and key respectively.

Export-ServerCertificateFromPFX
This command will extract the certificate from the PFX file and save it in a new file using Base64 encoding. This is the most crucial part of the certificate key pair since this file is presented to the clients in order to validate the server's identity.

A typical execution of this command would be:

PS C:\Certificate> Export-ServerCertificateFromPFX -PFXFilePath .\certificate.pfx -PFXPassphrase $pass

PS C:\Certificate> Get-ChildItem

    Directory: C:\Certificate

Mode    LastWriteTime      Length Name
----    -------------      ------ ----
-a----  24/6/2021 3:29 μμ  6022   certificate.pfx
-a----  29/6/2021 7:16 μμ  2264   certificate.pfx.crt

The server certificate has been exported from the "certificate.pfx" file to a file named "certificate.pfx.crt" in the same directory. 

Export-CertificateChainFromPFX
Part of the PFX file are usually the rest of the certificates in its path, that is the Root Authority CA and any Intermediate Authority CA certificates. This is what is called the chain of the certificate. Many web servers and application delivery controllers require those certificates to be in seperate files in order to form the path of the certificate to be presented to the client. Using the Export-CertificateChainFromPFX function you'll be able to export those certificates and save them in a seperate file. In case you need to have seperate certificates for each authority, you can split the files up using a text editor, since the format here is also Base64.

The way to export the chain is similar to the way we exported the certificate:

PS C:\Certificate> Export-CertificateChainFromPFX -PFXFilePath .\certificate.pfx -PFXPassphrase $pass -OpenSSLOutput:$true -Verbose
VERBOSE: Extracting certificate chain from PFX file: .\certificate.pfx
VERBOSE: Saving exported certificate at: C:\Certificate\certificate.pfx.chain.crt
StandardError                                                  ExitCode StandardOutput
-------------                                                  -------- --------------
WARNING: can't open config file: /usr/local/ssl/openssl.cnf... 0

PS C:\Users\admin\Desktop\Certificate> Get-ChildItem

    Directory: C:\Users\admin\Desktop\Certificate

Mode   LastWriteTime     Length Name
----   -------------     ------ ----
-a---- 24/6/2021 3:29 μμ 6022   certificate.pfx
-a---- 29/6/2021 7:24 μμ 2072   certificate.pfx.chain.crt
-a---- 29/6/2021 7:16 μμ 2264   certificate.pfx.crt

Here I've selected to return the output of the OpenSSL invocation as the output of the command and also enable verbose output in order to verify the location of the new file. As you can see, a new file named "certificate.pfx.chain.crt" has been created.

Export-PrivateKeyFromPFX
The second most important part of a PFX file is the private key included in it. This is the part of the key pair that is used on the server that will be encrypting the information, nginx or apache in the majority of the cases. The Export-PrivateKeyFromPFX file fuction will create a new file that will contain only the private key and the file will be encrypted using a passphrase in order to secure it.

To export the private key from a PFX file, use the Export-PrivateKeyFromPFX function like below:

PS C:\Certificate> Export-PrivateKeyFromPFX -PFXFilePath .\certificate.pfx -PFXPassphrase $pass -KeyPassphrase $key

PS C:\Certificate> Get-ChildItem

    Directory: C:\Users\admin\Desktop\Certificate

Mode   LastWriteTime     Length Name
----   -------------     ------ ----
-a---- 24/6/2021 3:29 μμ 6022   certificate.pfx
-a---- 29/6/2021 7:24 μμ 2072   certificate.pfx.chain.crt
-a---- 29/6/2021 7:16 μμ 2264   certificate.pfx.crt
-a---- 29/6/2021 7:42 μμ 3604   certificate.pfx.key

A new file named "certificate.pfx.key" has been created and encrypted using the passphrase in the variable "key".

Decrypt-PrivateKey
The previou command will export the private key to an encrypted file and in the majority of the cases you'll have to export it to a plain text file. The Decrypt-PrivateKey function will create a new file that will contain the private key in a Base64 format and not encrypted.

The most common way to invoke the Decrypt-PrivateKey function would be:

PS C:\Certificate> Decrypt-PrivateKey -PrivateKeyFilePath .\certificate.pfx.key -PrivateKeyPassphrase $key

PS C:\Certificate> Get-ChildItem

    Directory: C:\Certificate

Mode   LastWriteTime     Length Name
----   -------------     ------ ----
-a---- 24/6/2021 3:29 μμ 6022   certificate.pfx
-a---- 29/6/2021 7:24 μμ 2072   certificate.pfx.chain.crt
-a---- 29/6/2021 7:16 μμ 2264   certificate.pfx.crt
-a---- 29/6/2021 7:42 μμ 3604   certificate.pfx.key
-a---- 29/6/2021 7:48 μμ 3247   certificate.pfx.key.plainkey

The file "certificate.pfx.key.plainkey" now contains the unprotected private key.

If you try to get the content of the certificate or private key (plain) files, it should look like the below:

PS C:\Certificate> Get-Content .\certificate.pfx.crt
Bag Attributes
    1.3.6.1.4.1.311.17.3.121: 00
    localKeyID: 01 00 00 00
    1.3.6.1.4.1.311.17.3.71: 43 00 61 00 74 00 65 00 6E 00 61 00 45 00 78 00 70 00 6F 
friendlyName: Test Certificate
subject=/CN=test.com
issuer=/CN=TestRootCA
-----BEGIN CERTIFICATE-----
MIIFbzCCA1egAwIBAgIQGS4atYgz0Z5MByyH2i6yLjANBgkqhkiG9w0BAQ0FADAa
MRgwFgYDVQQDDA9DYXRlbmFQb0NSb290Q0EwHhcNMjEwNjI0MTEzMzA3WhcNMjMw
NjI0MTEzMzA3WjAfMR0wGwYDVQQDDBRxdWlja3NwaW5jYXNpbm9zLmNvbTCCAiIw
DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANloKnIY0CuMjaB5VcOEh84fzt0P
HWc3l158qBIvcmueNj+amhXBhWdg7Ak7of7/fQYgXH3hJlAHeL7v2TqMx5JRPKNZ
-----END CERTIFICATE-----


You can install the latest version of the module from Powershell Gallery using the command:

1
Install-Module -Name CPolydorou.Security -AllowClobber -Scope CurrentUser

I've also written a blog post on how to convert certificates in the past, that is available here.

Popular posts from this blog

Domain Controller Machine Password Reset

Configuring a Certificate on Exchange Receive Connector

Running Multiple NGINX Ingress Controllers in AKS