Files
fusion/scripts/sign-windows.ps1
Dustin Byrne d37f887552 feat(HAI-080): add code signing for macOS and Windows release binaries
- Add macOS signing script with codesign, notarization, and stapling support
- Add Windows signing script using signtool with PFX certificate
- Integrate signing steps into release and test-release workflows
- Add signing workflow tests and verification coverage
- Add CODE_SIGNING.md documentation and update README
2026-03-26 01:03:16 -04:00

79 lines
3.0 KiB
PowerShell

# sign-windows.ps1 — Authenticode sign a Windows binary.
#
# Usage:
# $env:WINDOWS_CERTIFICATE_BASE64 = "..."
# $env:WINDOWS_CERTIFICATE_PASSWORD = "..."
# pwsh scripts/sign-windows.ps1 path\to\binary.exe
#
# Environment variables (all required):
# WINDOWS_CERTIFICATE_BASE64 — Base64-encoded .pfx code signing certificate
# WINDOWS_CERTIFICATE_PASSWORD — Password for the .pfx certificate
param(
[Parameter(Mandatory = $true, Position = 0)]
[string]$BinaryPath
)
$ErrorActionPreference = "Stop"
# ── Validate arguments ────────────────────────────────────────────────
if (-not (Test-Path $BinaryPath)) {
Write-Error "ERROR: Binary not found: $BinaryPath"
exit 1
}
# ── Validate environment variables ────────────────────────────────────
$requiredVars = @("WINDOWS_CERTIFICATE_BASE64", "WINDOWS_CERTIFICATE_PASSWORD")
foreach ($var in $requiredVars) {
if (-not [System.Environment]::GetEnvironmentVariable($var)) {
Write-Error "ERROR: Required environment variable $var is not set."
exit 1
}
}
Write-Host "==> Signing Windows binary: $BinaryPath"
# ── Decode certificate to temporary file ──────────────────────────────
$certFile = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), "signing-cert-$(Get-Random).pfx")
try {
# Decode base64 certificate
$certBytes = [System.Convert]::FromBase64String($env:WINDOWS_CERTIFICATE_BASE64)
[System.IO.File]::WriteAllBytes($certFile, $certBytes)
Write-Host "==> Certificate decoded to temporary file."
# ── Sign the binary ───────────────────────────────────────────────
Write-Host "==> Signing with signtool..."
& signtool sign `
/f $certFile `
/p $env:WINDOWS_CERTIFICATE_PASSWORD `
/tr http://timestamp.digicert.com `
/td sha256 `
/fd sha256 `
$BinaryPath
if ($LASTEXITCODE -ne 0) {
Write-Error "ERROR: signtool sign failed with exit code $LASTEXITCODE"
exit 1
}
Write-Host "==> Sign complete. Verifying..."
# ── Verify the signature ──────────────────────────────────────────
& signtool verify /pa $BinaryPath
if ($LASTEXITCODE -ne 0) {
Write-Error "ERROR: signtool verify failed with exit code $LASTEXITCODE"
exit 1
}
Write-Host "==> ✓ Binary signed and verified: $BinaryPath"
}
finally {
# ── Clean up temporary certificate file ───────────────────────────
if (Test-Path $certFile) {
Remove-Item -Force $certFile
Write-Host "==> Temporary certificate file removed."
}
}