Export Certificates in Multiple Formats Using PowerShell

Page content

How to Export Certificates in Multiple Formats Using PowerShell

Introduction

Certificates are a crucial part of any IT infrastructure, dealing with secure communications and data protection. Managing them effectively is vital. Today, I am looking at a versatile PowerShell script that simplifies the process of exporting certificates from the Windows Certificate Store in various formats: PEM, PFX, and CER.

What Does the Script Do?

This PowerShell script allows IT administrators and security professionals to:

  • Export a certificate’s public key, private key, and its chain.
  • Choose between PEM, PFX, and CER formats.
  • Handle certificates identified by their Common Name (CN).

The flexibility of exporting in different formats is essential for diverse IT environments and use cases, whether it’s for configuring a web server, securing a mail server, or simply backing up your certificates.

Key Features

  • PEM Export: Extracts both the certificate and its private key (if exportable) to separate .pem files. Additionally, it exports the entire certificate chain in a different PEM file.
  • PFX Export: Bundles the certificate with its private key into a single .pfx file, commonly used for import into other Windows servers or systems.
  • CER Export: Outputs the public key of the certificate in a .cer file, suitable for distribution where the private key should remain confidential.

Prerequisites

Before running the script, ensure:

  1. PowerShell is installed on your system.
  2. You have the necessary permissions to access the Windows Certificate Store.
  3. The private keys of the certificates you wish to export are marked as exportable.

How to Use the Script

  1. Download the Script: Save the script as Export-Certificate.ps1.
<#
.SYNOPSIS
Export a certificate to PEM and/or PFX format.

.DESCRIPTION
This script finds a specified certificate by its Common Name (CN) in the Windows Certificate Store and exports it to PEM and/or PFX format.

.PARAMETER CertificateName
The Common Name (CN) of the certificate to export.

.PARAMETER ExportPEM
Boolean flag to export the certificate to PEM format.

.PARAMETER ExportPFX
Boolean flag to export the certificate to PFX format.

.EXAMPLE
.\Export-Certificate.ps1 -CertificateName "MyCertificate" -ExportPEM $true -ExportPFX $true

This command exports the certificate with the specified name to both PEM and PFX formats.

.NOTES
For PEM export, the private key of the certificate must be marked as exportable.

#>
param(
    [Parameter(Mandatory=$true)]
    [string]$CertificateName,

    [Parameter(Mandatory=$false)]
    [bool]$ExportPEM = $false,

    [Parameter(Mandatory=$false)]
    [bool]$ExportPFX = $false
)

# Function to sanitize file name
function Sanitize-FileName {
    param (
        [Parameter(Mandatory=$true)][string]$name
    )

    # Replace illegal characters with an underscore
    return $name -replace "[^\w\d]", "_"
}

# Function to find a certificate by CN
function Find-Certificate {
    param (
        [Parameter(Mandatory=$true)][string]$certName
    )

    $certPath = "Cert:\LocalMachine\My"
    $cert = Get-ChildItem -Path $certPath | Where-Object { $_.Subject -like "*CN=$certName*" }
    if ($null -eq $cert) {
        Write-Error "Certificate with CN '$certName' not found."
        return $null
    }

    return $cert
}

# Function to export certificate to PEM format
function Export-ToPEM {
    param (
        [Parameter(Mandatory=$true)][System.Security.Cryptography.X509Certificates.X509Certificate2]$cert
    )

    $sanitizedCertName = Sanitize-FileName -name $CertificateName
    $currentPath = Get-Location
    $certOutputPath = "$currentPath\$sanitizedCertName.pem"
    $keyOutputPath = "$currentPath\$sanitizedCertName-key.pem"

    # Export the certificate to PEM format
    $certBytes = [System.Security.Cryptography.X509Certificates.X509ContentType]::Cert
    $certEncoded = [System.Convert]::ToBase64String($cert.Export($certBytes), [System.Base64FormattingOptions]::InsertLineBreaks)
    $certPem = "-----BEGIN CERTIFICATE-----`n$certEncoded`n-----END CERTIFICATE-----"
    [System.IO.File]::WriteAllText($certOutputPath, $certPem)

    # Export the private key to PEM format
    $privateKey = $cert.PrivateKey
    $privateKeyBytes = $privateKey.ExportCspBlob($true)
    $privateKeyBase64 = [System.Convert]::ToBase64String($privateKeyBytes, [System.Base64FormattingOptions]::InsertLineBreaks)
    $privateKeyPem = "-----BEGIN PRIVATE KEY-----`n$privateKeyBase64`n-----END PRIVATE KEY-----"
    [System.IO.File]::WriteAllText($keyOutputPath, $privateKeyPem)
}

# Function to export certificate to PFX format
function Export-ToPFX {
    param (
        [Parameter(Mandatory=$true)][System.Security.Cryptography.X509Certificates.X509Certificate2]$cert
    )

    $sanitizedCertName = Sanitize-FileName -name $CertificateName
    $currentPath = Get-Location
    $certOutputPath = "$currentPath\$sanitizedCertName.pfx"

    # Export the certificate to PFX format
    $securePassword = Read-Host -AsSecureString "Enter password for PFX file"
    Export-PfxCertificate -Cert $cert -FilePath $certOutputPath -Password $securePassword
}

# Function to export the public key of the certificate to a .cer file
function Export-ToCER {
    param (
        [Parameter(Mandatory=$true)][System.Security.Cryptography.X509Certificates.X509Certificate2]$cert
    )

    $sanitizedCertName = Sanitize-FileName -name $CertificateName
    $currentPath = Get-Location
    $cerOutputPath = "$currentPath\$sanitizedCertName.cer"

    # Export the public key of the certificate to a .cer file
    $certBytes = [System.Security.Cryptography.X509Certificates.X509ContentType]::Cert
    $certEncoded = $cert.Export($certBytes)
    [System.IO.File]::WriteAllBytes($cerOutputPath, $certEncoded)
}

# Main script execution logic
$cert = Find-Certificate -certName $CertificateName

if ($null -eq $cert) {
    return
}

# Export to PEM if selected
if ($ExportPEM) {
    Export-ToPEM -cert $cert
}

# Export to PFX if selected
if ($ExportPFX) {
    Export-ToPFX -cert $cert
}

# Export to .CER if selected
if ($ExportCER) {
    Export-ToCER -cert $cert
}

# Export to all formats if no specific format is selected
if (-not $ExportPEM -and -not $ExportPFX -and -not $ExportCER) {
    Export-ToPEM -cert $cert
    Export-ToPFX -cert $cert
    Export-ToCER -cert $cert
}

Write-Host "Certificate export completed."
  1. Run the Script: Open PowerShell and navigate to the directory containing the script. Run the script using the following syntax:

    .\Export-Certificate.ps1 -CertificateName "YourCertificateCN" -ExportPEM $true -ExportPFX $true -ExportCER $true
    

    Replace YourCertificateCN with the Common Name of your certificate.

  2. Check the Results: The script exports the files to the current directory. You’ll find the certificate, its chain, and the public key in separate files.

Conclusion

This PowerShell script is a handy tool to manage and export certificates in a format that suits their needs. It simplifies what can often be a complex and time-consuming process, making certificate management more efficient and less error-prone.

Remember, always handle certificate and key files securely and ensure they are stored and transmitted safely.