PowerShell Certificate Commands

Comprehensive guide to managing certificates using PowerShell cmdlets and PKI module.

Viewing Certificates

List certificates in store

View certificates using Cert: provider:

# List all certificates in current user's Personal store
Get-ChildItem Cert:\CurrentUser\My

# List all certificates in Local Machine's Personal store
Get-ChildItem Cert:\LocalMachine\My

# List all certificates in Trusted Root store
Get-ChildItem Cert:\LocalMachine\Root

# Recursive list of all certificates
Get-ChildItem Cert:\ -Recurse

View certificate details

Display detailed certificate information:

# Get certificate by thumbprint
$cert = Get-ChildItem Cert:\CurrentUser\My | Where-Object {$_.Thumbprint -eq "ABC123..."}

# Display certificate details
$cert | Format-List *

# View subject
$cert.Subject

# View expiration date
$cert.NotAfter

# View issuer
$cert.Issuer

# Check if cert has private key
$cert.HasPrivateKey

Search certificates

Find certificates by various properties:

# Find by subject name
Get-ChildItem Cert:\CurrentUser\My | Where-Object {$_.Subject -like "*example.com*"}

# Find expiring soon (within 30 days)
$expiringCerts = Get-ChildItem Cert:\ -Recurse | Where-Object {$_.NotAfter -lt (Get-Date).AddDays(30)}

# Find certificates with private keys
Get-ChildItem Cert:\CurrentUser\My | Where-Object {$_.HasPrivateKey -eq $true}

# Find code signing certificates
Get-ChildItem Cert:\ -Recurse | Where-Object {$_.EnhancedKeyUsageList -like "*Code Signing*"}

Installing and Importing Certificates

Import certificate file

Import .cer or .pfx files into certificate store:

# Import .cer file to Current User's Personal store
Import-Certificate -FilePath "C:\Certs\certificate.cer" -CertStoreLocation Cert:\CurrentUser\My

# Import to Trusted Root store (requires admin)
Import-Certificate -FilePath "C:\Certs\root-ca.cer" -CertStoreLocation Cert:\LocalMachine\Root

# Import PFX with password
$password = Read-Host -AsSecureString -Prompt "Enter password"
Import-PfxCertificate -FilePath "C:\Certs\certificate.pfx" -CertStoreLocation Cert:\CurrentUser\My -Password $password

# Import PFX with exportable private key
Import-PfxCertificate -FilePath "C:\Certs\certificate.pfx" -CertStoreLocation Cert:\CurrentUser\My -Password $password -Exportable

Import from byte array

Import certificate from raw bytes:

# Read certificate bytes
$certBytes = [System.IO.File]::ReadAllBytes("C:\Certs\certificate.cer")

# Create certificate object
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($certBytes)

# Add to store
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My", "CurrentUser")
$store.Open("ReadWrite")
$store.Add($cert)
$store.Close()

Exporting Certificates

Export certificate without private key

Export to .cer file:

# Get certificate by thumbprint
$cert = Get-ChildItem Cert:\CurrentUser\My | Where-Object {$_.Thumbprint -eq "ABC123..."}

# Export to .cer file
$cert | Export-Certificate -FilePath "C:\Export\certificate.cer"

# Export in DER format (default)
$cert | Export-Certificate -FilePath "C:\Export\certificate.cer" -Type CERT

# Export Base64-encoded
[System.IO.File]::WriteAllText("C:\Export\certificate.cer", [System.Convert]::ToBase64String($cert.RawData), [System.Text.Encoding]::ASCII)

Export certificate with private key

Export to .pfx file with password:

# Get certificate with private key
$cert = Get-ChildItem Cert:\CurrentUser\My | Where-Object {$_.Thumbprint -eq "ABC123..." -and $_.HasPrivateKey}

# Set password for PFX
$password = ConvertTo-SecureString -String "YourStrongPassword" -Force -AsPlainText

# Export to PFX
$cert | Export-PfxCertificate -FilePath "C:\Export\certificate.pfx" -Password $password

# Export with chain
$cert | Export-PfxCertificate -FilePath "C:\Export\certificate.pfx" -Password $password -ChainOption BuildChain

Creating Self-Signed Certificates

Create self-signed certificate

Generate self-signed certificate for testing:

# Basic self-signed cert
$cert = New-SelfSignedCertificate -DnsName "example.com" -CertStoreLocation Cert:\CurrentUser\My

# Self-signed with validity period
$cert = New-SelfSignedCertificate -DnsName "example.com" \
    -CertStoreLocation Cert:\CurrentUser\My \
    -NotAfter (Get-Date).AddYears(1)

# Self-signed for code signing
$cert = New-SelfSignedCertificate -Type CodeSigningCert \
    -Subject "CN=MyCodeSigning" \
    -CertStoreLocation Cert:\CurrentUser\My

# Self-signed for document encryption
$cert = New-SelfSignedCertificate -Type DocumentEncryptionCert \
    -Subject "CN=MyDocEncryption" \
    -CertStoreLocation Cert:\CurrentUser\My

Create with SANs and advanced options

Self-signed certificate with multiple domains:

# Certificate with Subject Alternative Names
$cert = New-SelfSignedCertificate \
    -DnsName "example.com", "www.example.com", "api.example.com" \
    -CertStoreLocation Cert:\LocalMachine\My \
    -KeyAlgorithm RSA \
    -KeyLength 4096 \
    -HashAlgorithm SHA256 \
    -NotAfter (Get-Date).AddYears(2) \
    -FriendlyName "Example.com SSL Certificate" \
    -KeyExportPolicy Exportable

Managing Certificate Stores

Remove certificate from store

Delete certificate by thumbprint:

# Remove from Current User's Personal store
$cert = Get-ChildItem Cert:\CurrentUser\My | Where-Object {$_.Thumbprint -eq "ABC123..."}
$cert | Remove-Item

# Remove from Local Machine (requires admin)
$cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Thumbprint -eq "ABC123..."}
$cert | Remove-Item

# Remove all expired certificates from Current User
Get-ChildItem Cert:\CurrentUser\My | Where-Object {$_.NotAfter -lt (Get-Date)} | Remove-Item

Copy certificate between stores

Move or copy certificate to different store:

# Get source certificate
$cert = Get-ChildItem Cert:\CurrentUser\My | Where-Object {$_.Thumbprint -eq "ABC123..."}

# Copy to Trusted People store
$cert | Export-Certificate -FilePath "temp.cer"
Import-Certificate -FilePath "temp.cer" -CertStoreLocation Cert:\CurrentUser\TrustedPeople
Remove-Item "temp.cer"

Certificate Validation and Verification

Verify certificate chain

Build and validate certificate chain:

# Get certificate
$cert = Get-ChildItem Cert:\CurrentUser\My | Where-Object {$_.Thumbprint -eq "ABC123..."}

# Build chain
$chain = New-Object System.Security.Cryptography.X509Certificates.X509Chain
$chain.Build($cert)

# Check if chain is valid
if ($chain.ChainStatus.Length -eq 0) {
    Write-Host "Certificate chain is valid"
} else {
    Write-Host "Certificate chain has issues:"
    $chain.ChainStatus | Format-Table Status, StatusInformation
}

# View chain elements
$chain.ChainElements | ForEach-Object {
    $_.Certificate | Format-List Subject, Issuer, NotAfter
}

Test SSL/TLS connection

Validate remote server's certificate:

# Test HTTPS endpoint
Test-NetConnection -ComputerName example.com -Port 443

# Get server certificate via PowerShell
$request = [System.Net.WebRequest]::Create("https://example.com")
try {
    $request.GetResponse() | Out-Null
} catch {
    # Connection may fail, but we can still get cert
}
$cert = $request.ServicePoint.Certificate

# View certificate details
$cert | Format-List *

IIS SSL Certificate Management

Get IIS site bindings

List SSL bindings for IIS websites:

# Import IIS module
Import-Module WebAdministration

# List all HTTPS bindings
Get-WebBinding | Where-Object {$_.protocol -eq "https"}

# Get bindings for specific site
Get-WebBinding -Name "Default Web Site" | Where-Object {$_.protocol -eq "https"}

# View certificate thumbprint for binding
$binding = Get-WebBinding -Name "Default Web Site" | Where-Object {$_.protocol -eq "https"}
$binding.certificateHash

Create IIS SSL binding

Bind certificate to IIS site:

# Get certificate
$cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Subject -like "*example.com*"}

# Create HTTPS binding
New-WebBinding -Name "Default Web Site" \
    -Protocol https \
    -Port 443 \
    -HostHeader "example.com" \
    -SslFlags 1  # SNI

# Associate certificate with binding
$binding = Get-WebBinding -Name "Default Web Site" -Protocol https -HostHeader "example.com"
$binding.AddSslCertificate($cert.Thumbprint, "My")

Update IIS certificate

Replace certificate for existing binding:

# Get new certificate
$newCert = Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Thumbprint -eq "NEW_THUMBPRINT"}

# Get binding
$binding = Get-WebBinding -Name "Default Web Site" -Protocol https

# Remove old certificate association
$binding.RemoveSslCertificate()

# Add new certificate
$binding.AddSslCertificate($newCert.Thumbprint, "My")

Automation Scripts

Monitor certificate expiration

Script to check expiring certificates:

# Check certificates expiring in 30 days
$daysThreshold = 30
$expiringDate = (Get-Date).AddDays($daysThreshold)

$expiringCerts = Get-ChildItem Cert:\ -Recurse | Where-Object {
    $_.NotAfter -lt $expiringDate -and $_.NotAfter -gt (Get-Date)
}

if ($expiringCerts) {
    Write-Host "Certificates expiring within $daysThreshold days:"
    $expiringCerts | ForEach-Object {
        [PSCustomObject]@{
            Subject = $_.Subject
            Thumbprint = $_.Thumbprint
            Expires = $_.NotAfter
            DaysRemaining = ($_.NotAfter - (Get-Date)).Days
            Store = $_.PSPath
        }
    } | Format-Table -AutoSize
} else {
    Write-Host "No certificates expiring within $daysThreshold days"
}

Bulk certificate export

Export all certificates from a store:

# Create export directory
$exportPath = "C:\CertBackup"
New-Item -Path $exportPath -ItemType Directory -Force

# Export all certs from Personal store
Get-ChildItem Cert:\CurrentUser\My | ForEach-Object {
    $filename = "$exportPath\$($_.Thumbprint).cer"
    $_ | Export-Certificate -FilePath $filename
    Write-Host "Exported: $($_.Subject) to $filename"
}

See Also

Important Notes

PowerShell Version:

Many PKI cmdlets require PowerShell 3.0+. For older versions, use .NET classes directly.

Administrator Rights:

Operations on LocalMachine certificate stores require running PowerShell as Administrator.

Certificate Provider:

The Cert: provider allows navigation of certificate stores like file system directories.

Secure Passwords:

Always use SecureString for passwords, never plain text. Use ConvertTo-SecureString or Read-Host -AsSecureString.

Private Key Export:

Certificate must be marked as exportable during import to allow private key export later.

IIS Module:

WebAdministration module must be imported for IIS certificate management (Import-Module WebAdministration).

Store Locations:

Common paths: Cert:\\CurrentUser\\My (Personal), Cert:\\LocalMachine\\Root (Trusted Root), Cert:\\LocalMachine\\CA (Intermediate).

Documentation:

Microsoft PKI cmdlets: docs.microsoft.com/powershell/module/pki