PowerShell Script to Use SSL Certificate in Windows Remote Desktop (RDP)
Changelog:
| Date | Change |
|---|---|
| 2025-02-08 | Fixed X509Certificate import to align with .NET updates. |
# GUI steps: https://superuser.com/a/1093160
$ErrorActionPreference = "Stop"
$fileURI = "https://example.com/certificate.pfx"
# $pfxPath = "C:\path\to\your\domain.pfx"
$pfxPassword = ""
## Download the pfx file
# Get a temporary file path
$pfxPath = [System.IO.Path]::GetTempFileName()
# Download the file to the temp file
Invoke-WebRequest -Uri $fileURI -OutFile $pfxPath
Write-Host "File downloaded to temporary file: $pfxPath"
## Import pfx file
# Import the PFX file into the Personal (My) certificate store for the Local Machine
# $certStore = "Cert:\LocalMachine\My"
# $pfx = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$flags = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet `
-bor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet
# $pfx.Import($pfxPath, $pfxPassword, $flags) # Failed in the newer version of .NET
$pfx = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($pfxPath, $pfxPassword, $flags)
# Get the thumbprint of the newly imported certificate, which would be used later
$thumbprint = $pfx.Thumbprint
# Delete the temporary file after use
Remove-Item -Path $pfxPath -Force
# Add the certificate to the store
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My", "LocalMachine")
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
$store.Add($pfx)
$store.Close()
Write-Host "Certificate imported successfully into Local Machine\Personal store."
## Set permissions on the private key
# Find the most recent file in the private key folder (C:\ProgramData\Microsoft\Crypto\Keys)
$keyFolder = "C:\ProgramData\Microsoft\Crypto\Keys"
$latestKeyFile = Get-ChildItem -Path $keyFolder | Sort-Object LastWriteTime -Descending | Select-Object -First 1
$keyPath = $latestKeyFile.FullName
Write-Host "Latest private key file: $keyPath"
# Set the permissions on the private key
$acl = Get-Acl $keyPath
$user = "NETWORK SERVICE"
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($user, "Read", "Allow")
$acl.AddAccessRule($rule)
Set-Acl -Path $keyPath -AclObject $acl
Write-Host "Permissions set for user $user on private key."
## Modify the registry to use the certificate
# Convert the SHA1 thumbprint (hex string) to an array
$sha1Bytes = for ($i = 0; $i -lt $thumbprint.Length; $i += 2) {
[Convert]::ToByte($thumbprint.Substring($i, 2), 16)
}
# Define the registry path and value name
$regPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"
$valueName = "SSLCertificateSHA1Hash"
# Write the binary value to the registry (cast explicitly as Byte[])
Set-ItemProperty -Path $regPath -Name $valueName -Value ([Byte[]]$sha1Bytes)
Write-Host "SHA1 thumbprint successfully written to the registry as a binary value."
# Define the RDP service name
$serviceName = "TermService"
# Restart the RDP service
# Restart-Service -Name $serviceName -Force
Write-Host "RDP service restarted successfully."
Comments