Skip to content

Sign with Self-Signed Certificate #44

Sign with Self-Signed Certificate

Sign with Self-Signed Certificate #44

name: Sign with Self-Signed Certificate
on:
workflow_dispatch:
push:
tags:
- 'v*'
permissions:
id-token: write # Required for OIDC authentication with Sigstore
contents: read # Required to read repository contents
jobs:
sign-binaries:
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup certificate from secrets
env:
CERTIFICATE_BASE64: ${{ secrets.CERTIFICATE_BASE64 }}
CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }}
run: |
if ([string]::IsNullOrEmpty($env:CERTIFICATE_BASE64)) {
Write-Host "Certificate not found in secrets. Skipping Windows signing." -ForegroundColor Yellow
echo "SKIP_WINDOWS_SIGNING=true" >> $env:GITHUB_ENV
} else {
Write-Host "Setting up certificate for Windows signing..." -ForegroundColor Cyan
$certBytes = [Convert]::FromBase64String($env:CERTIFICATE_BASE64)
[IO.File]::WriteAllBytes("wfdiag-signing-cert.pfx", $certBytes)
Write-Host "Certificate ready" -ForegroundColor Green
echo "SKIP_WINDOWS_SIGNING=false" >> $env:GITHUB_ENV
}
- name: Install Cosign for Sigstore
uses: sigstore/cosign-installer@v3
with:
cosign-release: 'v2.2.4'
- name: Sign with Windows Certificate and Sigstore
env:
CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }}
run: |
Write-Host "Finding binaries to sign..." -ForegroundColor Cyan
$signedCount = 0
$files = Get-ChildItem -Recurse -Include "*.exe", "*.msi", "*.msix" | Where-Object { $_.Name -notlike "*build*" -and $_.Name -notlike "*temp*" }
foreach ($file in $files) {
$filePath = $file.FullName
Write-Host "Processing: $($file.Name)" -ForegroundColor Yellow
if ($env:SKIP_WINDOWS_SIGNING -eq "false") {
Write-Host "Signing with Windows certificate..." -ForegroundColor Cyan
$signtoolPaths = @(
"${env:ProgramFiles(x86)}\Windows Kits\10\bin\10.0.22621.0\x64\signtool.exe",
"${env:ProgramFiles(x86)}\Windows Kits\10\bin\10.0.22000.0\x64\signtool.exe",
"${env:ProgramFiles(x86)}\Windows Kits\10\bin\10.0.19041.0\x64\signtool.exe"
)
$signtool = $null
foreach ($path in $signtoolPaths) {
if (Test-Path $path) {
$signtool = $path
break
}
}
if ($signtool) {
Write-Host "Using signtool: $signtool" -ForegroundColor Gray
& $signtool sign /f "wfdiag-signing-cert.pfx" /p $env:CERTIFICATE_PASSWORD /fd sha256 /tr "http://timestamp.digicert.com" /td sha256 /d "WindowsForum Diagnostic Tool" /du "https://windowsforum.com" $filePath
if ($LASTEXITCODE -eq 0) {
Write-Host "Windows signature applied" -ForegroundColor Green
} else {
& $signtool sign /f "wfdiag-signing-cert.pfx" /p $env:CERTIFICATE_PASSWORD /fd sha256 /d "WindowsForum Diagnostic Tool" $filePath
}
}
}
Write-Host "Signing with Sigstore..." -ForegroundColor Cyan
cosign sign-blob --yes $filePath --output-signature "$filePath.sig" --output-certificate "$filePath.crt"
$signedCount++
}
Write-Host "Processed $signedCount files" -ForegroundColor Cyan
- name: Verify signatures
run: |
Write-Host "Verifying signatures..." -ForegroundColor Cyan
$files = Get-ChildItem -Recurse -Include "*.exe", "*.msi", "*.msix" | Where-Object { $_.Name -notlike "*build*" -and $_.Name -notlike "*temp*" }
foreach ($file in $files) {
Write-Host "Verifying: $($file.Name)" -ForegroundColor Yellow
$sig = Get-AuthenticodeSignature $file.FullName
Write-Host "Status: $($sig.Status)" -ForegroundColor $(if ($sig.Status -eq "Valid") { "Green" } else { "Yellow" })
}
- name: Create signing report
env:
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_SHA: ${{ github.sha }}
run: |
Write-Host "Creating signing report..." -ForegroundColor Cyan
$reportLines = @(
"# Digital Signing Report",
"Generated: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss UTC')",
"Repository: $env:GITHUB_REPOSITORY",
"Commit: $env:GITHUB_SHA",
"",
"## Signed Files",
""
)
$files = Get-ChildItem -Recurse -Include "*.exe", "*.msi", "*.msix" | Where-Object { $_.Name -notlike "*build*" -and $_.Name -notlike "*temp*" }
foreach ($file in $files) {
$reportLines += "### $($file.Name)"
$reportLines += "- **Size**: $([math]::Round($file.Length / 1MB, 2)) MB"
$reportLines += "- **SHA256**: $(Get-FileHash $file.FullName -Algorithm SHA256 | Select-Object -ExpandProperty Hash)"
$sig = Get-AuthenticodeSignature $file.FullName
$reportLines += "- **Windows Signature**: $($sig.Status)"
$sigFile = "$($file.FullName).sig"
if (Test-Path $sigFile) {
$reportLines += "- **Sigstore Signature**: Present"
}
$reportLines += ""
}
$reportLines | Out-File -FilePath "SIGNING_REPORT.md" -Encoding UTF8
Write-Host "Report saved to SIGNING_REPORT.md" -ForegroundColor Green
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: signed-binaries-with-certificates
path: |
**/*.exe
**/*.msi
**/*.msix
**/*.sig
**/*.crt
SIGNING_REPORT.md
retention-days: 90