Code-Signing PowerShell Scripts (Part 2)

by May 20, 2022

In our previous tip we explained how you can use New-SelfSignedCert to create a self-signed code signing certificate. Today, we’ll use a self-signed or corporate code signing certificate to actually start and digitally sign a Powershell script.

For this, take any PowerShell script file you want. All you need is its path. Also, you need the path to a valid code signing certificate stored in any of Windows certificate stores. Here is a quick recap of part 1 to create a self-signed certificate in case you have no corporate certificate at hand:

$Subject = 'MyPowerShellCode'
$FriendlyName = 'My Valid PowerShell Code'

# expires 5 years from now:
$ExpirationDate = (Get-Date).AddYears(5)

# store in user personal store:
$certStore = 'Cert:CurrentUsermy'

# create certificate:
$cert = New-SelfSignedCertificate -Subject $Subject -Type CodeSigningCert -CertStoreLocation $certStore -FriendlyName $FriendlyName -NotAfter $ExpirationDate

$thumbprint = $cert.Thumbprint

$Path = Join-Path -Path $certStore -ChildPath $thumbprint
Write-Warning "Certificate Path: $Path"

When you run this code, you get a self-signed code signing certificate, and the code returns the path to your generated certificate, i.e.:

 
Cert:CurrentUsermyF4C1F9978D564E143D554F3679746B3A79E1FF87   
 

To use your certificate, read it via Get-Item like so (make sure you adjust the path to match your certificate – each certificate has a unique thumbprint):

 
PS> $myCert = Get-Item -Path Cert:CurrentUsermyF4C1F9978D564E143D554F3679746B3A79E1FF87   
 

To add a digital signature to a PowerShell script file (or any other file that is capable of carrying a digital signature for this matter), use Set-AuthenticodeSignature. Run the demo code below (adjust paths to file and certificate as needed):

# digitally sign this file (adjust path to an existing ps1 file):
$Path = "$env:temptest.ps1"

# adjust this path to point to a valid code signing certificate:
$CertPath = 'Cert:CurrentUsermyF4C1F9978D564E143D554F3679746B3A79E1FF87'

# if it does not exist, create a dummy file
$exists = Test-Path -Path $Path
if ($exists -eq $false)
{
    'Hello World!' | Set-Content -Path $Path -Encoding UTF8
}

# read a code signing certificate to use for signing:
$myCert = Get-Item -Path $CertPath

# add a digital signature to a PS script file:
Set-AuthenticodeSignature -FilePath $Path -Certificate $myCert

# show changes inside script file:
notepad $Path

When you run this code, the script file specified in $Path opens and shows the digital signature that was added to the bottom of your script:

Hello World!

# SIG # Begin signature block
# MIIFcAYJKoZIhvcNAQcCoIIFYTCCBV0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU4QK+x7NLicgrIdzN+Nvxqbuq
# Qv2gggMKMIIDBjCCAe6gAwIBAgIQG5jphqHXvLJFA0oCJTgcpDANBgkqhkiG9w0B

Congrats, you just digitally signed a PowerShell script! We’ll explore the benefits of such a signature in part 3.


Twitter This Tip! ReTweet this Tip!