- 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.
4.1 KiB
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
.exemust 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.exeis 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
-
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).
-
Sign the exe after each build. Place your pfx at
windows\kiwy_signing.pfx(or setKIWY_SIGN_PFXenv var) —build_win.batwill then auto-sign viasign_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 withwinget install Microsoft.WindowsSDK.10.0.26100if 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.
- locates
-
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.bathandles this. - Do not use UPX on the signed exe — it invalidates the signature and can
trigger false positives. (
upx=Truein the spec currently does nothing because UPX is not installed; if you ever install UPX, set it to False.)