Files
Kiwy-Signage/documentation/CODE_SIGNING_SMART_APP_CONTROL.md
T
ske087 5d9aa02c07 Add Windows card reader, code-signing helpers and playlist diagnostics
- windows/win_card_reader.py: Windows-native card reader via the Raw Input API
  with a low-level keyboard-hook fallback.
- windows/sign_exe.ps1: sign the built executable with a .pfx certificate.
- windows/create_self_signed_cert.ps1: generate a self-signed cert for local
  testing (not trusted by Smart App Control).
- windows/verify_sendinput_fix.py: verification helper for the SendInput
  foreground-unlock fix in run_win.py.
- documentation/CODE_SIGNING_SMART_APP_CONTROL.md: signing guidance.
- working_files/execute_playlist_retrieve.py,
  working_files/raw_server_playlist.json: playlist retrieval diagnostics.

Note: windows/archive_list.txt and windows/build_last.txt are build output and
were committed by request rather than by convention.
2026-09-10 16:44:12 +03:00

4.1 KiB
Raw Blame History

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-AuthenticodeSignatureNotSigned), 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 100300/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:

    # 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:

    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:

# 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

:: 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.)