# Kiwy Signage Player — Code Signing & Smart App Control (Production) > **TL;DR:** If production PCs have **Smart App Control (SAC) ON** and you > cannot disable it, the player `.exe` **must be signed by a certificate from a > reputable public CA**. There is no other way — SAC blocks unsigned binaries at > the kernel level (no "Run anyway" button). Self-signed certs and Defender > exclusions do **not** satisfy SAC. --- ## 1. Why Smart App Control blocks the app - SAC (Windows 11 22H2+, "Smart App Control" in **Windows Security → App & browser control**) only runs apps that are **signed by a reputable publisher**. - Your locally-built `KiwySignagePlayer.exe` is **unsigned** (`Get-AuthenticodeSignature` → `NotSigned`), so SAC refuses to launch it and shows "An Application Control policy has blocked this file." - Unlike classic SmartScreen, SAC has **no "Run anyway" button** and cannot be bypassed per-file. Disabling SAC is **permanent** and only possible with admin rights — so it is not viable for locked-down production PCs. --- ## 2. The solution for production: a real code-signing certificate 1. **Buy an OV code-signing certificate** from a reputable CA, e.g.: - Sectigo Code Signing - SSL.com Code Signing - DigiCert Code Signing - GlobalSign Code Signing OV is sufficient for SAC; EV gives the highest trust level. Cost is roughly USD 100–300/yr. The CA will issue a `.pfx`/`.p12` (or `.cer`+key). 2. **Sign the exe** after each build. Place your pfx at `windows\kiwy_signing.pfx` (or set `KIWY_SIGN_PFX` env var) — `build_win.bat` will then auto-sign via `sign_exe.ps1`: ```powershell # One-off, from the windows\ folder: .\sign_exe.ps1 -CertPath "C:\certs\mycodesign.pfx" -CertPassword "yourpwd" ``` The script: - locates `signtool.exe` (Windows SDK) — install with `winget install Microsoft.WindowsSDK.10.0.26100` if missing, - signs with **SHA256** + **RFC3161 timestamp** (required for SAC and to keep the signature valid after the cert expires), - verifies the result with `Get-AuthenticodeSignature`. 3. **Test** — confirm on one production PC: ```powershell Get-AuthenticodeSignature "dist\KiwySignagePlayer\KiwySignagePlayer.exe" # Status must be: Valid ``` --- ## 3. Dev / test machines (where you have admin rights) If a test PC has SAC **off**, you can make the app trusted locally without buying a cert: ```powershell # Run as Administrator .\create_self_signed_cert.ps1 ``` This creates a self-signed code-signing cert, exports `kiwy_dev_signing.pfx`, and installs it into **Trusted Root + Trusted Publisher + Trusted People** for the current user, so the player runs without SmartScreen/Defender prompts on that dev PC. ⚠️ **This does NOT satisfy SAC.** It is only for machines where SAC is off or where you have admin rights. --- ## 4. Build → sign → verify workflow ```bat :: 1. Build (produces dist\KiwySignagePlayer\KiwySignagePlayer.exe) cd windows venv\Scripts\python.exe -m PyInstaller build.spec --clean --noconfirm :: 2. Sign (auto if kiwy_signing.pfx present, else manual) .\sign_exe.ps1 -CertPath "C:\certs\mycodesign.pfx" -CertPassword "..." :: 3. Verify Get-AuthenticodeSignature "dist\KiwySignagePlayer\KiwySignagePlayer.exe" ``` `build_win.bat` now does step 1 + step 2 automatically when a pfx is present. --- ## 5. Important caveats - **Timestamping is mandatory.** The sign script timestamps by default (`http://timestamp.digicert.com`). Without a timestamp, the signature becomes invalid once the certificate expires and SAC will block the app. - **SAC reputation takes time.** Even a validly signed exe from a brand-new certificate may be blocked until the CA's reputation builds. EV certificates and well-known CAs (DigiCert, Sectigo, SSL.com) pass immediately. - **Re-sign after every build.** PyInstaller creates a new exe each time; the old signature is lost. The auto-sign step in `build_win.bat` handles this. - **Do not use UPX** on the signed exe — it invalidates the signature and can trigger false positives. (`upx=True` in the spec currently does nothing because UPX is not installed; if you ever install UPX, set it to False.)