jackailocal / factory /powershell /Sign-Executables.ps1
jackboy70's picture
Deploy: accurate lite-builder note
f25362a
Raw
History Blame Contribute Delete
2.61 kB
# Signs Windows executables with Authenticode so SmartScreen and antivirus
# engines can establish publisher reputation. Without a signature, customers
# see "Windows protected your PC" on every launch.
#
# Configuration (environment variables):
# JACKAI_SIGN_CERT_THUMBPRINT thumbprint of a cert in the CurrentUser/LocalMachine store
# JACKAI_SIGN_PFX path to a .pfx file (alternative to thumbprint)
# JACKAI_SIGN_PFX_PASSWORD password for the .pfx
# JACKAI_TIMESTAMP_URL RFC3161 timestamp server (default: DigiCert)
#
# If neither JACKAI_SIGN_CERT_THUMBPRINT nor JACKAI_SIGN_PFX is set, the script
# warns and exits 0 so development builds keep working unsigned.
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string[]]$Path
)
$ErrorActionPreference = "Stop"
$thumbprint = $env:JACKAI_SIGN_CERT_THUMBPRINT
$pfxPath = $env:JACKAI_SIGN_PFX
if (-not $thumbprint -and -not $pfxPath) {
Write-Warning "Code signing skipped: set JACKAI_SIGN_CERT_THUMBPRINT or JACKAI_SIGN_PFX to sign release builds. Unsigned builds trigger SmartScreen warnings for customers."
exit 0
}
$timestampUrl = if ($env:JACKAI_TIMESTAMP_URL) { $env:JACKAI_TIMESTAMP_URL } else { "http://timestamp.digicert.com" }
$signtool = Get-Command signtool.exe -ErrorAction SilentlyContinue
if (-not $signtool) {
$kitsRoot = "${env:ProgramFiles(x86)}\Windows Kits\10\bin"
if (Test-Path $kitsRoot) {
$candidate = Get-ChildItem -Path $kitsRoot -Recurse -Filter signtool.exe -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -match "x64" } |
Sort-Object FullName -Descending |
Select-Object -First 1
if ($candidate) { $signtool = $candidate.FullName }
}
}
if (-not $signtool) { throw "signtool.exe not found. Install the Windows SDK or add signtool to PATH." }
$signtoolPath = if ($signtool -is [string]) { $signtool } else { $signtool.Source }
foreach ($file in $Path) {
if (!(Test-Path $file -PathType Leaf)) { throw "Cannot sign missing file: $file" }
$arguments = @("sign", "/fd", "SHA256", "/td", "SHA256", "/tr", $timestampUrl)
if ($thumbprint) {
$arguments += @("/sha1", $thumbprint)
} else {
$arguments += @("/f", $pfxPath)
if ($env:JACKAI_SIGN_PFX_PASSWORD) { $arguments += @("/p", $env:JACKAI_SIGN_PFX_PASSWORD) }
}
$arguments += $file
& $signtoolPath @arguments
if ($LASTEXITCODE -ne 0) { throw "signtool failed for $file (exit $LASTEXITCODE)" }
& $signtoolPath verify /pa $file
if ($LASTEXITCODE -ne 0) { throw "signature verification failed for $file" }
Write-Host "Signed: $file" -ForegroundColor Green
}