- 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
79 lines
3.0 KiB
PowerShell
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."
|
|
}
|
|
}
|