Skip to main content

Signing the Windows release assets

sign-windows-assets.sh Authenticode-signs the Windows .exe payloads that the DeepPhe Launcher downloads at install time, then re-uploads them in place on the DeepPhe/DeepPhe-Dist releases. Signing uses a YubiKey (PIV slot 9a) through jsign.

You normally trigger it via the full build:

./build-all.sh --sign

…or run it directly once the assets are published:

./sign-windows-assets.sh

Which assets get signed

Release tagAsset
deepphe-visualizer-v2-7.1deepphe-visualizer-v2-win-x64.exe
dphe-data-api-7.1dphe-data-api-win-x64.exe
dphe-db-pipeline-7.1DeepPheVizDbCreator-windows-x86_64.exe

For each one the script: downloads the asset with gh, signs it with jsign (YubiKey + Sectigo timestamp), verifies the signature and chain with osslsigncode verify, then re-uploads it with gh release upload --clobber.

Prerequisites

brew install jsign osslsigncode

The YubiKey PIV PIN is read from the macOS keychain at runtime — it is not hard-coded. Store it once:

security add-generic-password -s yubikey-piv-pin -w '<PIN>'

The script retrieves it with security find-generic-password -s yubikey-piv-pin -w.

Finding the right alias

The script uses the alias X.509 Certificate for PIV Authentication (PIV slot 9a). If that is wrong for your key, run the jsign command without --alias and it prints the available aliases.

Before you trust the output

These .exe files are single-file bundles (~75–113 MB) that append a payload to the PE overlay:

  • the visualizer / data-api are JS-runtime bundles (pkg / Node SEA / Deno / Bun)
  • DeepPheVizDbCreator is a PyInstaller (Python) bundle

Authenticode adds its certificate table to that same overlay. This is usually fine but can occasionally break the embedded payload, so:

  1. Smoke-test each signed .exe on Windows — confirm it still launches. Once per tool; if it's clean, it stays clean.
  2. Keep the asset name identical. The installer downloads these by URL/name, so --clobber in place is correct — do not rename to …-signed.exe.
  3. Update any checksum the installer verifies. Signing changes the bytes; if a manifest or the install4j installer checks a hash, regenerate it or the download will be rejected.

For final release testing, run the full smoke-test matrix.

Why this is opt-in

Signing the release assets is a remote operation that mutates the public GitHub releases and needs physical access to the YubiKey. That is why it is gated behind --sign rather than running on every build.