How to sign a PowerShell script easily?

To do the signing you can use the Set-AuthenticodeSignature cmdlet. This, of course, requires a certificate. If you have a Certificate Authority (unlikely) that will be able to create a code signing certificate. Otherwise there are various tools to create a self-signed certificate.

You install the certificate in your certificate store (open the .cer or .pfx file in Windows Explorer to do this), and then pass it to Set-AuthenticodeSignature (the cert: provider/drive gives access to certificates in your store).

Use

help about_signing

or the online version of that help topic for details (including creating a self-signed certificate using the Windows SDK tools[1]).

[1] I assume this is the big download you're referring to: you can just install the bits you need, or make use of other tools (OpenSSL includes certificate generation). Getting the SDK is, for this purpose, a one-off activity.


I use this PowerShell script:

## sign-script.ps1
## Sign a powershell script with a Thawte certificate and 
## timestamp the signature
##
## usage: ./sign-script.ps1 c:\foo.ps1 

param([string] $file=$(throw “Please specify a script filepath.”)) 

$certFriendlyName = "Thawte Code Signing"
$cert = gci cert:\CurrentUser\My -codesigning | where -Filter 
  {$_.FriendlyName -eq $certFriendlyName}

# https://www.thawte.com/ssl-digital-certificates/technical-  
#   support/code/msauth.html#timestampau
# We thank VeriSign for allowing public use of their timestamping server.
# Add the following to the signcode command line: 
# -t http://timestamp.verisign.com/scripts/timstamp.dll 
$timeStampURL = "http://timestamp.verisign.com/scripts/timstamp.dll"

if($cert) {
    Set-AuthenticodeSignature -filepath $file -cert $cert -IncludeChain All -   
      TimeStampServer $timeStampURL
}
else {
    throw "Did not find certificate with friendly name of `"$certFriendlyName`""
}

Once I had the certificate, I wanted to use imported on my user account. This regkey gave me an option, Sign, in the context menu (I'm using Windows 7). If the certificate you want to sign with is stored differently, just change the PowerShell command at the end.

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Classes\Microsoft.PowerShellScript.1]

[HKEY_CURRENT_USER\Software\Classes\Microsoft.PowerShellScript.1\Shell]

[HKEY_CURRENT_USER\Software\Classes\Microsoft.PowerShellScript.1\Shell\Sign]

[HKEY_CURRENT_USER\Software\Classes\Microsoft.PowerShellScript.1\Shell\Sign\Command]
@="C:\\\Windows\\\System32\\\WindowsPowerShell\\\v1.0\\\powershell.exe -command Set-AuthenticodeSignature '%1' @(Get-ChildItem cert:\\\CurrentUser\\\My -codesigning)[0]"