← Field Guide

CERTIFICATE WORKSHOP / WINDOWS · 7 MIN READ

Create and Export Certificates with PowerShell.

Use Windows’ certificate store when the private key already belongs to Windows. Use the OpenSSL workflow when your inputs are separate PEM files.

Windows examples. These use the Windows PKI module and certreq.exe, not PowerShell alone on Linux or macOS. Use a protected working folder, replace example names with names you control, and check that output files do not already exist. No command here uploads your key or creates public trust.

Check the Required Commands

Windows PowerShell
Get-Command New-SelfSignedCertificate, Export-PfxCertificate, Get-PfxData

The examples use Cert:\CurrentUser\My so you do not need to alter the machine-wide store for a lab. Production services may need a machine-store certificate and explicit private-key permissions; follow that service’s deployment instructions.

Create a Short-lived Lab Certificate

Windows / Self-signed Test Certificate
$certOptions = @{
    DnsName = 'lab.aboutssl.info'
    CertStoreLocation = 'Cert:\CurrentUser\My'
    Type = 'SSLServerAuthentication'
    KeyAlgorithm = 'RSA'
    KeyLength = 3072
    HashAlgorithm = 'SHA256'
    KeyExportPolicy = 'Exportable'
    NotAfter = (Get-Date).AddDays(30)
}
$tlsCert = New-SelfSignedCertificate @certOptions
$tlsCert | Format-List Subject, Thumbprint, NotAfter, HasPrivateKey

This creates a new exportable RSA key and a self-signed certificate for a lab. It does not make that name trusted or establish control of its DNS. Exportability is intentional for this PFX exercise; non-exportable production keys may be preferable when the service supports them.

Export the Lab Certificate

Windows / Password-protected Export
$pfxPassword = Read-Host 'Password for the PFX' -AsSecureString
$exportOptions = @{
    Cert = $tlsCert
    FilePath = '.\lab.aboutssl.info.pfx'
    Password = $pfxPassword
    ChainOption = 'BuildChain'
    CryptoAlgorithmOption = 'AES256_SHA256'
    NoClobber = $true
}
Export-PfxCertificate @exportOptions

The password is entered as a SecureString, not as a literal in your history. -NoClobber prevents replacing an existing PFX. A self-signed leaf does not magically acquire a public CA chain when exported.

Request a CA-signed Certificate with certreq

The following creates a CSR and an associated key in the current user context. Keep the same user and machine for accepting the CA response. The CA must validate the request and issue the certificate; creating a CSR alone is not issuance.

Windows PowerShell / Native CSR
$requestConfig = @'
[Version]
Signature="$Windows NT$"
[NewRequest]
Subject = "CN=aboutssl.info"
KeyAlgorithm = RSA
KeyLength = 3072
HashAlgorithm = SHA256
ProviderName = "Microsoft Software Key Storage Provider"
MachineKeySet = FALSE
Exportable = TRUE
RequestType = PKCS10
KeyUsage = 0xa0
[Extensions]
2.5.29.17 = "{text}"
_continue_ = "DNS=aboutssl.info&"
_continue_ = "DNS=www.aboutssl.info"
[EnhancedKeyUsageExtension]
OID = 1.3.6.1.5.5.7.3.1
'@
Set-Content -LiteralPath .\aboutssl.inf -Value $requestConfig -Encoding ascii
certreq.exe -user -new .\aboutssl.inf .\aboutssl.csr
if ($LASTEXITCODE -ne 0) { throw 'CSR creation failed.' }

Inspect the CSR and send only that request through your CA’s approved process. Do not send your private key. Save its signed response as aboutssl-issued.cer, then accept it under the same user:

Accept the CA Response
certreq.exe -user -accept .\aboutssl-issued.cer
if ($LASTEXITCODE -ne 0) { throw 'Certificate acceptance failed.' }

Ensure the correct intermediate certificates are available to Windows from an authenticated CA source. Do not solve chain errors by blindly placing unknown roots into a trusted root store.

Export One Existing Certificate and Its Chain

List the certificates and select the exact thumbprint. Do not export the entire personal store:

Find the Certificate
Get-ChildItem Cert:\CurrentUser\My |
    Format-List Subject, Thumbprint, NotAfter, HasPrivateKey
Export the Selected Certificate
$thumbprint = (Read-Host 'Thumbprint of the one certificate to export').Replace(' ', '')
$tlsCert = Get-Item -LiteralPath ('Cert:\CurrentUser\My\' + $thumbprint)
if (-not $tlsCert.HasPrivateKey) { throw 'This certificate has no associated private key.' }
$pfxPassword = Read-Host 'Password for the PFX' -AsSecureString
$exportOptions = @{
    Cert = $tlsCert
    FilePath = '.\aboutssl.info.pfx'
    Password = $pfxPassword
    ChainOption = 'BuildChain'
    CryptoAlgorithmOption = 'AES256_SHA256'
    NoClobber = $true
}
Export-PfxCertificate @exportOptions

BuildChain includes the chain Windows can construct. Missing CA certificates, missing keys and non-exportable keys can prevent the intended export. A certificate file imported without its original key is not enough.

Read Back the PFX

Inspect Public Certificate Details
$pfxPassword = Read-Host 'Password for the PFX' -AsSecureString
$pfxData = Get-PfxData -FilePath .\aboutssl.info.pfx -Password $pfxPassword
$pfxData.EndEntityCertificates | Format-List Subject, Issuer, NotAfter
$pfxData.OtherCertificates | Format-List Subject, Issuer, NotAfter

Review the leaf and other certificates before deployment. An import-compatible file is not proof that your service is using it. Check the binding, service identity permissions and the public TLS result afterward.

For separate certificate, key and chain PEM files, follow Build the Complete PFX. Those OpenSSL commands can also be run from PowerShell; do not assume that Export-PfxCertificate merges arbitrary PEM files.