diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9d8f54e85..65f9f8c71 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -274,7 +274,7 @@ jobs: name: lib_dist path: libsrc/ffdec_lib/dist exe: - name: Generate EXE + name: Generate EXEs runs-on: ubuntu-latest concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} @@ -351,12 +351,37 @@ jobs: xvfb-run wine $WINEPREFIX/resourcehacker/ResourceHacker.exe -open $WINEPREFIX/versioninfo.rc -save $WINEPREFIX/versioninfo.res -action compile xvfb-run wine $WINEPREFIX/resourcehacker/ResourceHacker.exe -open $WINEPREFIX/ffdec.exe -save $WINEPREFIX/ffdec.exe -action addoverwrite -res $WINEPREFIX/versioninfo.res -mask "Version Info,1" cp $WINEPREFIX/ffdec.exe resources/ffdec.exe + - name: Upload EXE uses: actions/upload-artifact@v4 with: name: unsigned_exe path: resources/ffdec.exe + - name: Generate CLI EXE version info + run: | + sed -i \ + -e 's/@MAJOR@/${{ needs.compute-version.outputs.verMajor }}/g' \ + -e 's/@MINOR@/${{ needs.compute-version.outputs.verMinor }}/g' \ + -e 's/@RELEASE@/${{ needs.compute-version.outputs.verRelease }}/g' \ + -e 's/@BUILD@/${{ needs.compute-version.outputs.verBuild }}/g' \ + -e 's/@VERSION@/${{ needs.compute-version.outputs.verShort }}/g' \ + versioninfo-cli.rc + - name: Replace CLI EXE version info + run: | + export WINEPREFIX=$(pwd)/tools/wine + cp resources/ffdec-cli.exe $WINEPREFIX/ffdec-cli.exe + cp versioninfo-cli.rc $WINEPREFIX/versioninfo-cli.rc + xvfb-run wine $WINEPREFIX/resourcehacker/ResourceHacker.exe -open $WINEPREFIX/versioninfo-cli.rc -save $WINEPREFIX/versioninfo-cli.res -action compile + xvfb-run wine $WINEPREFIX/resourcehacker/ResourceHacker.exe -open $WINEPREFIX/ffdec-cli.exe -save $WINEPREFIX/ffdec-cli.exe -action addoverwrite -res $WINEPREFIX/versioninfo-cli.res -mask "Version Info,1" + cp $WINEPREFIX/ffdec-cli.exe resources/ffdec-cli.exe + + - name: Upload CLI EXE + uses: actions/upload-artifact@v4 + with: + name: unsigned_cli_exe + path: resources/ffdec-cli.exe + #--- Note: Windows runner cannot run Resource Hacker for some reason # exe: # name: Generate EXE @@ -464,6 +489,12 @@ jobs: with: name: unsigned_exe path: dist/ + + - name: Download unsigned CLI EXE artifact + uses: actions/download-artifact@v4 + with: + name: unsigned_cli_exe + path: dist/ - name: Set up JDK uses: actions/setup-java@v4 @@ -644,7 +675,68 @@ jobs: shell: pwsh run: | $signtool = "${{ steps.signtool.outputs.path }}" - & $signtool verify /pa /v "dist/ffdec.exe" + & $signtool verify /pa /v "dist/ffdec.exe" + + - name: Sign CLI EXE with KMS key + shell: pwsh + run: | + $signtool = "${{ steps.signtool.outputs.path }}" + $kc = "projects/$env:GCP_PROJECT_ID/locations/$env:GCP_LOCATION/keyRings/$env:KMS_KEYRING/cryptoKeys/$env:KMS_KEY/cryptoKeyVersions/$env:KMS_KEY_VERSION" + + $ErrorActionPreference = 'Stop' + + $exe = $signtool + $args = @( + "sign", + "/v", + "/debug", + "/fd", "sha256", + "/tr", "http://timestamp.sectigo.com?td=sha256", + "/td", "sha256", + "/f", "$env:CERT_PATH", + "/csp", "Google Cloud KMS Provider", + "/kc", "$kc", + "dist/ffdec-cli.exe" + ) + + # --- retry policy --- + $maxAttempts = 5 + $delaySeconds = 10 + $needle = "SignTool Error: An unexpected internal error has occurred" + + for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) { + Write-Host "Attempt $attempt/${maxAttempts}: $exe $($args -join ' ')" + + $output = & $exe @args 2>&1 | Out-String + $exitCode = $LASTEXITCODE + + if ($output) { Write-Host $output.TrimEnd() } + + if ($exitCode -eq 0) { + Write-Host "Succeeded." + exit 0 + } + + $hasNeedle = $output -match [regex]::Escape($needle) + + if ($hasNeedle -and $attempt -lt $maxAttempts) { + Write-Warning "Detected transient SignTool internal error. Retrying in $delaySeconds seconds..." + Start-Sleep -Seconds $delaySeconds + continue + } + + if ($hasNeedle) { + throw "Failed after $maxAttempts attempts due to repeated SignTool internal error (exit code $exitCode)." + } else { + throw "Command failed (exit code $exitCode). Output did not match retry condition." + } + } + + - name: Verify CLI EXE signature + shell: pwsh + run: | + $signtool = "${{ steps.signtool.outputs.path }}" + & $signtool verify /pa /v "dist/ffdec-cli.exe" - name: Get Msi tools path @@ -755,8 +847,14 @@ jobs: uses: actions/upload-artifact@v4 with: name: signed_exe - path: dist/ffdec.exe + path: dist/ffdec.exe + - name: Upload signed CLI EXE artifact + uses: actions/upload-artifact@v4 + with: + name: signed_cli_exe + path: dist/ffdec-cli.exe + - name: Rename MSI shell: cmd run: | @@ -816,7 +914,13 @@ jobs: with: name: signed_exe path: dist/ - + + - name: Download signed CLI EXE artifact + uses: actions/download-artifact@v4 + with: + name: signed_cli_exe + path: dist/ + - name: Download signed MSI artifact uses: actions/download-artifact@v4 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index db9f3efa6..a7f3b5528 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. - [#1209], [#1850], [#2619] Debugging SWF in the web browser (Debug listening capability - only for SWFs previously prepared by FFDec) - TTF export - setting italic / bold flags in the font +- ffdec-cli.exe is signed ### Fixed - Metadata formatting diff --git a/versioninfo-cli.rc b/versioninfo-cli.rc new file mode 100644 index 000000000..6113bf3fa --- /dev/null +++ b/versioninfo-cli.rc @@ -0,0 +1,28 @@ +1 VERSIONINFO +FILEVERSION @MAJOR@,@MINOR@,@RELEASE@,@BUILD@ +PRODUCTVERSION @MAJOR@,@MINOR@,@RELEASE@,@BUILD@ +FILEOS 0x40004 +FILETYPE 0x1 +{ +BLOCK "StringFileInfo" +{ + BLOCK "000004B0" + { + VALUE "ProductName", "JPEXS Free Flash Decompiler CLI launcher" + VALUE "FileDescription", "JPEXS Free Flash Decompiler CLI launcher" + VALUE "ProductVersion", "@VERSION@" + VALUE "FileVersion", "@VERSION@" + VALUE "InternalName", "Launch5j" + VALUE "OriginalFilename", "ffdec-cli.exe" + VALUE "LegalCopyright", "JPEXS" + VALUE "CompanyName", "JPEXS" + VALUE "LegalTrademarks", "JPEXS" + VALUE "Comments", "-" + } +} + +BLOCK "VarFileInfo" +{ + VALUE "Translation", 0x0000 0x04B0 +} +}