Create X509 client certificates

When developing clients that use X509 certificates to authenticate to a server using TLS, you might need to create client certificates signed by your CA.

The right way to create client certificates is by producing a Certificate Singing Request with openssl, send it to your CA, and process the response.

If you already have the private key of your CA you can simplify this flow by using the New-SelfSignedCertificate powershell cmdlet to create the signed certificate, and it will be added to your local certificate store.

Note: Despite the cmdlet, since it can be used to produced ca signed certificates, instead of self-signed.

The script below helps you with this process, and by using openssl though WSL it also produces the common PEM/KEY files to use the certificates in other environments where the certificate store might not be available.

Load the CA certificate

Assuming you have the CA certificate already available in your CurrentUser/My certificate store, you can load it in a powershell session by its thumbprint:

$root = gci "cert:\CurrentUser\my\<CA-thumbprint>"

Create your client certificate with a custom CN

$certName = "<Client-CN>"
$cert = New-SelfSignedCertificate `
        -CertStoreLocation cert:\CurrentUser\my `
        -Subject $certName `
        -Signer $root `
        -HashAlgorithm SHA256 `
        -NotAfter (Get-Date).AddMonths(24) `
        -KeyUsage KeyEncipherment, DataEncipherment, DigitalSignature, NonRepudiation
Write-Host $cert.Subject $cert.Thumbprint 

The certificate is now available in your local store (you can access the store by running start certmgr.msc)

Export the public key to DER format

To export the public key certificate

Export-Certificate -Cert $cert -FilePath "$certname.bin.cer" -TYPE CERT

this file is a binary representation you can use in Windows machines, to convert the file to a PEM format use:

certutil -encode "$certname.bin.cer" "$certname.pem"

Export the private key as a PFX file

PFX files allows to export the private key, and protect they key with a password. In PowerShell you will require a SecureString

$keyPwd = ConvertTo-SecureString -String "<PFX-Password>" -Force -AsPlainText
Export-PfxCertificate -Cert $cert -FilePath "$certname.pfx" -Password $keyPwd

Export the private key as a secure KEY file

OpenSSL allows to extract the PFX to a key file using the PEM format, and protect the key with another password. To automate the script you can use the passin arguments. Assuming you want to use the same password for both files the script will look like:

Note that OpenSSL does not support PowerShell secure strings, so the password must be converted to clear text by using the PtrToStringAuto method.

$txtPwd = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($keyPwd))
$bashCmd = "openssl pkcs12 -in '$certname.pfx' -out '$certname.secure.key' -nodes -passin pass:'$txtPwd' -passout pass:'$txtPwd'"
bash -c $bashCmd

Export the private key as a RSA key

There are some cases where you might need the PEM/KEY files, but you don’t want to protect the key with a password. Keep in mind that this option produces an *Unprotected Private Key, so you must use it with caution:

$bashcmd = "openssl rsa -in '$certname.secure.key' -out '$certname.key'"
bash -c $bashCmd

Summary

This script is a convenient tool to simplify your development process when you need to create client certificates signed by a custom CA without using the CSR flow.

The full script is available in this gist

 Date: October 1, 2022
 Tags: 

Previous
⏪ Demystifying Azure IoT Hub Device SDKs

Next
The IoT Pattern. A .NET implementation for MQTT ⏩