DSK-2Recommended
Sign every Windows file with a SHA-256 signature and a timestamp
Sign every .exe, .dll, .msi and .msix you hand out with Authenticode, using SHA-256 and an RFC 3161 timestamp. Sign each release with the same publisher identity.
How to do it
Windows SmartScreen blocks unsigned downloads hard, and enterprises often refuse them. Without a timestamp, the signature turns invalid when the certificate expires, and Windows treats the file as unsigned. Pass /fd SHA256 /tr <timestamp server> /td SHA256 to signtool. Since 2024, an EV certificate no longer skips SmartScreen's reputation check. An OV certificate or a cloud signing service such as Azure Artifact Signing does as well. Reputation builds per publisher, so keep one identity across releases. Keep the key as keep code signing keys in hardware or a signing service says. MSIX packages sold through the Microsoft Store are signed by Microsoft. Sign the files inside the installer too, not only the installer.
Examples
Plain text example
signtool sign /fd SHA256 /tr http://timestamp.example.com /td SHA256 /n "Example Tools AB" .\dist\Ledgerly.exe
signtool verify /pa /v .\dist\Ledgerly.exe
How to check
In CI, signtool verify /pa /v passes on every executable file in the release, and its output shows a timestamp. A test that sets the clock past the certificate's end date still finds a valid signature.
Sources
- Microsoft, Time stamping Authenticode signatures
- Microsoft, Code signing options for Windows app developers
Related rules
- DSK-3 Keep code signing keys in hardware or a signing service in Desktop apps, extensions and CLIs
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/desktop-apps/signing-and-notarisation/windows-authenticode">Agent Wranglers desktop apps, extensions and CLIs playbook</a>. In code you write, add a comment next to it with the same link.