How to sign a PowerShell script easily?
Solution 1
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.
Solution 2
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]"
Solution 3
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`""
}
Tung
Updated on September 17, 2022Comments
-
Tung over 1 year
I'd prefer using the AllSigned execution policy with PowerShell, but self-signing my scripts seems to require several hundreds of megabytes of downloading and installation and the signing process seems to be a hassle.
Is there a simpler way to sign a PowerShell script than described in the documentation?
-
Tung over 14 yearsI'm accepting this answer and assuming that there is no shortcut and signing just needs to be done as mentioned in the docs.
-
Richard over 14 yearsLike quite a few "developer-y" things the initial set up and learning is hard, but the actual practice (especially if done regularly) isn't.
-
alfredtofu over 3 yearsThis worked for me for years until I changed the default app for .ps1 files from "Notepad" to "Visual Studio Code". After I made that change, I lost the "Sign" option in the Explorer context menu. Switching the default app back to "Notepad" restored the "Sign" option in the explorer context menu.
-
alfredtofu over 3 yearsThis trick also works for Powershell module files by creating the same set of keys as in the answer but substituting
Microsoft.PowerShellModule.1
forMicrosoft.PowerShellScript.1
. -
S. Melted over 3 yearsFor anyone who needs to make a self signed cert to do the above I found these two links helpful: serverfault.com/questions/824574/… and github.com/PowerShell/PowerShell/issues/4753
-
HackSlash over 3 yearsHow can you use a script to sign a script? Wouldn't your script signing script need to be signed?