1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
# This script uses Set-AuthenticodeSignature to sign a file
# or exe/dll/msi files in a directory using a pfx file.
# If PFX file is not present, script expects a base64 encode certificate
# in WINDOWS_CERTIFICATE environment variable.
# Password can be passed using WINDOWS_CERTIFICATE_PASSWORD environment variable.
# The script only signs previously unsigned files
[CmdletBinding()]
param (
# A path to the certificate file. If missing, env:WINDOWS_CERTIFICATE will be used.
[string]$CertFile,
# A password for the certificate. If missing, env:WINDOWS_CERTIFICATE_PASSWORD will be used.
[string]$Password,
# A file to sign.
[string]$File,
# A directory to sign.
[string]$Directory
)
# Configure the error behavior
$ErrorActionPreference = "Stop"
$PSDefaultParameterValues['*:ErrorAction']='Stop'
# Sign a file, if it was previously unsigned
# We sign using SHA256, as we only support Windows 7+.
function Set-FileSignature {
param (
[String]$InputFile,
$pfxCert
)
if((Get-AuthenticodeSignature $InputFile).Status -ne [System.Management.Automation.SignatureStatus]::Valid) {
Write-Host "Singning file $InputFile"
Set-AuthenticodeSignature `
-FilePath $InputFile `
-Certificate $pfxCert `
-IncludeChain All `
-TimestampServer 'http://timestamp.digicert.com' `
-HashAlgorithm 'sha256' `
-Force
} else {
Write-Host "Skipping file $InputFile as it is already signed"
}
}
# Sanity checks: only allow File or Directory
if ($File -eq "" -and $Directory -eq "") {
Write-Host "-File or -Directory should be provided"
exit 1
} elseif ($File -ne "" -and $Directory -ne "") {
Write-Host "Only one of -File or -Directory should be provided"
exit 1
}
$cleanupPfx = $false
# Check, if we need to retrieve PFX from environment
if($CertFile -eq "") {
Write-Host "Trying to read certificate file from env:WINDOWS_CERTIFICATE"
if(Test-Path "env:WINDOWS_CERTIFICATE") {
$CertFile = "cert.pfx"
[IO.File]::WriteAllBytes($CertFile, [System.Convert]::FromBase64String($env:WINDOWS_CERTIFICATE))
$cleanupPfx = $true
} else {
Write-Host "No certificate is provided"
exit 1
}
}
# Check, if we need to retrieve password from environment
if($Password -eq "") {
if (Test-Path "env:WINDOWS_CERTIFICATE_PASSWORD") {
$Password = $env:WINDOWS_CERTIFICATE_PASSWORD
}
}
$pfx = $null
# Retrieve the actual certificate
if($Password -ne "") {
$securePassword = ConvertTo-SecureString -String $Password -AsPlainText -Force
$pfx = Get-PfxData -FilePath "$CertFile" -Password $securePassword
} else {
$pfx = Get-PfxData -FilePath "$CertFile"
}
$pfxCert = $pfx.EndEntityCertificates[0]
# Perform the code signing.
if ($File -ne "") {
Set-FileSignature -InputFile $File -pfxCert $pfxCert
} else {
Get-ChildItem `
-Path "$Directory" `
-Include *.dll,*.exe,*.msi `
-Recurse `
-File | ForEach-Object {
Set-FileSignature -InputFile $_.FullName -pfxCert $pfxCert
}
}
# Remove PFX file if it was created from environment.
if($cleanupPfx) {
Remove-Item "${CertFile}"
}
|