10% off every 3-year code signing certificate — Sectigo, Comodo & DigiCert. | Use Code: SAVE10 at Checkout.

Claim 10% off

How to Sign a Windows App: Step-by-Step Code Signing Guide

Short answer: Buy a code signing certificate from a trusted CA, pass identity validation, and get the private key onto a hardware token or cloud HSM. Then run SignTool with SHA-256 and an RFC 3161 timestamp. Check the result with signtool verify /pa, and sign your installer last.

Windows will run an unsigned .exe. It just won’t make it easy. Users see “Unknown publisher” in the UAC prompt, SmartScreen gets suspicious, and some managed corporate machines block the file outright.

A signature fixes the first problem and gives you a fighting chance on the other two. It does not switch SmartScreen warnings off on day one. We’ll cover that part honestly further down.

The steps below assume you’re signing a desktop app you distribute yourself: .exe, .dll, .msi, or an installer built with a tool like WiX, Inno Setup, or an Electron packager.

What code signing does (and what it doesn’t)

A signature does two things. It ties the file to a publisher whose identity a CA has verified, and it lets Windows detect any change made after signing.

Under the hood, SignTool hashes the file and encrypts that hash with your private key. Windows repeats the hash and checks it against the public key in your certificate. Change one byte after signing and the check fails.

It does not scan your software for malware. It does not vouch for the quality of your code. And it is not the same thing as .NET strong-name signing, which is an assembly identity feature and does nothing for Windows trust.

Before you start

Have these ready:

  • The final binary. Sign what you ship, not a debug build.
  • Company documents. For an organization certificate, that means your legal registration details and a phone number the CA can reach. Individual certificates use government ID instead.
  • A Windows machine with the Windows SDK. That is where SignTool lives.
  • A plan for the private key. You can’t skip this one anymore, and Step 2 explains why.

Step 1: Choose the right certificate

Two validation levels exist for Windows code signing: OV (Organization Validation) and EV (Extended Validation). Both put your verified name in the signature.

OV EV
Identity checks Standard business validation Stricter, more documents
Private key storage Certified hardware or cloud HSM Certified hardware or cloud HSM
SmartScreen reputation Builds over time Builds over time
Kernel-mode drivers Not accepted for Hardware Dev Center Required
Typical buyer Most app developers Driver vendors, some enterprise buyers

Read the SmartScreen row twice. For years, EV was the way to skip SmartScreen’s warm-up period. Microsoft removed that behavior in 2024, and its current developer documentation says EV no longer changes SmartScreen behavior.

So if your only reason for EV was to avoid the blue “Windows protected your PC” screen, that reason is gone. If you ship drivers, or a customer’s procurement team asks for EV by name, it still makes sense.

Step 2: Get validated and secure your key

Once you order, the CA verifies that your organization exists and that you are authorized to request the certificate.

Most delays come from small mismatches. The company name on your order differs from the name in the registry by a comma or an abbreviation. Or the verification call goes to a number nobody answers. Match the legal name character for character before you submit.

Since June 1, 2023, every publicly trusted code signing certificate, OV and EV alike, needs its private key on certified hardware. That means a FIPS 140-2 Level 2 or Common Criteria EAL 4+ device. The old habit of downloading a .pfx file and installing it on a build server no longer applies to new certificates.

You have three ways to meet that rule:

  • USB token. The CA ships it to you. It’s simple, but the token has to be plugged into the machine that signs.
  • Cloud signing or cloud HSM. The key stays in the provider’s hardware and your build calls it remotely. This is the practical choice for CI/CD and distributed teams.
  • Your own HSM. Suits organizations that already run one and want full control.

[Internal link: Cloud Code Signing vs. Hardware Tokens]

Step 3: Install SignTool

SignTool ships with the Windows SDK. In the SDK installer, select the signing tools for desktop apps. Visual Studio can install the same component.

After installation, you’ll find it here:

C:\Program Files (x86)\Windows Kits\10\bin\10.0.<build>\x64\signtool.exe

Add that folder to your PATH, or run the tool from the Developer Command Prompt. Then check it responds:

signtool /?

Step 4: Sign the file

Find your certificate first. With the token plugged in and unlocked, list code signing certificates in your store:

powershell
Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert

Copy the thumbprint, then sign:

signtool sign /sha1 <thumbprint> /fd SHA256 /tr http://timestamp.digicert.com /td SHA256 "C:\build\MyApp.exe"

Here’s what each flag does:

  • /sha1 picks the certificate by thumbprint. It’s more precise than /a, which lets SignTool guess.
  • /fd SHA256 sets the file digest algorithm. Leave it out and SignTool warns that it’s falling back to SHA-1.
  • /tr is the timestamp server URL.
  • /td SHA256 sets the timestamp digest algorithm. It pairs with /tr.

Use the timestamp URL your CA publishes. If you buy from a reseller, the order confirmation or knowledge base lists it.

You can pass several files in one command, including wildcards like *.dll. Sign your own binaries only. Don’t re-sign third-party DLLs you bundle.

If your certificate arrived as a .pfx file (older certificates and some software-key setups), swap the selector for /f cert.pfx /p <password>. Keep that password out of your scripts and repository.

Why the timestamp matters

Certificates expire. A signature made without a timestamp stops validating when the certificate does. A signature made with one stays valid, because it proves the file was signed while the certificate was still good.

Always use /tr with /td. The older /t switch uses a legacy SHA-1 timestamp. Also build a retry into scripts: a timestamp server that is briefly unreachable is one of the most common reasons a release build fails at the last step.

Step 5: Verify the signature

Run:

signtool verify /pa /v "C:\build\MyApp.exe"

The /pa flag matters. Without it, SignTool checks against a different policy and can report a failure on a perfectly good signature.

You can also right-click the file, open Properties, and look at the Digital Signatures tab. Or use PowerShell:

powershell
Get-AuthenticodeSignature "C:\build\MyApp.exe"

You want the status to read Valid. Check that the timestamp is listed too.

One more habit worth adopting: signing changes the file. If you publish checksums, calculate them after signing, not before.

Step 6: Sign installers and packages in the right order

Sign from the inside out. The order is:

  1. Sign your .exe and .dll files.
  2. Build the installer that packages them.
  3. Sign the installer itself.

If you sign the installer only, the app files inside it stay unsigned. Once installed, Windows and your customers’ security tools see unsigned binaries.

MSI installers: SignTool signs .msi files the same way as an .exe.

Installer builders (Inno Setup, NSIS, WiX): Most have a hook that calls SignTool for you. Some also generate an uninstaller stub that needs its own signature, so read the builder’s docs.

Electron apps: Both electron-builder and Electron Forge can sign at packaging time. When your key sits on a token or in the cloud, there’s no .pfx to point at. Use the tool’s custom signing hook to call SignTool yourself.

MSIX packages: The certificate subject must match the Publisher value in AppxManifest.xml exactly. A mismatch is the usual cause of error 0x8007000B.

Signing in a CI/CD pipeline

This is where the hardware rule bites. A hosted build runner can’t have a USB token plugged into it.

Three setups work in practice:

  • Cloud signing service. Your pipeline calls the provider’s signing tool or key provider, and SignTool uses it through the /csp and /kc parameters. Follow your CA’s exact syntax.
  • Self-hosted runner with the token attached. It works, but it ties releases to one physical machine.
  • A dedicated signing server. Builds send artifacts to it, and it signs and returns them.

A few habits keep this from turning into a security hole:

  • Sign at the release stage only, not on every commit.
  • Keep PINs and API credentials in your secrets manager, never in the repo.
  • Limit which branches and people can trigger the signing job.
  • Keep a log of what was signed, when, and by whom.

A signing key that any pull request can reach is a stolen key waiting to happen.

Why SmartScreen still warns after you sign

This is the complaint we hear most. The app is signed, verifies as valid, and users still get the SmartScreen prompt.

SmartScreen judges reputation, and reputation builds as people download and run your software without problems. Microsoft doesn’t publish the threshold. A signature makes you identifiable, which lets reputation attach to your name. It doesn’t hand you that reputation.

A brand-new build can start with little history, and so can a freshly issued or renewed certificate. Here’s what helps:

  • Sign every release with the same identity. Don’t switch publisher names between versions.
  • Serve downloads over HTTPS from one stable domain.
  • Avoid repackaging the same build again and again.
  • Report false positives through Microsoft’s file submission portal if a clean build gets flagged.

Apps distributed through the Microsoft Store are re-signed by Microsoft and don’t trigger SmartScreen warnings. That’s a real option if the Store fits your product.

Certificate validity in 2026: the 460-day rule

Since March 1, 2026, publicly trusted code signing certificates can’t be issued for more than 460 days, about 15 months. The old ceiling was 39 months. It covers OV and EV, and applies to anything issued or renewed on or after that date. Certificates issued earlier stay valid until their own expiry date.

What this means for your workflow:

  • Renew every year. Put the date in a calendar with a two-week warning, not the day before a release.
  • Expect a new thumbprint on renewal. A pipeline that selects the certificate with /sha1 breaks the day you renew. Selecting by subject name with /n survives, as long as your organization name stays the same.
  • Old releases keep working. Anything signed and timestamped while the certificate was valid stays valid after it expires.

Can I sign with a self-signed certificate?

You can, and for testing it’s fine. In PowerShell:

powershell
New-SelfSignedCertificate -Type CodeSigningCert -Subject "CN=MyApp Test" -CertStoreLocation Cert:\CurrentUser\My

Windows won’t trust it on other machines, and users will still see “Unknown publisher”. Inside a company, IT can push your certificate to managed machines through Group Policy. For software you give to customers, a self-signed certificate is not an option. Never ask customers to install your own root certificate to get around the warning.

Common SignTool errors and fixes

“No certificates were found that met all the given criteria.” The token isn’t plugged in or unlocked, the thumbprint is wrong, or the certificate isn’t in the store you’re searching. Check with the PowerShell command from Step 4.

“The specified timestamp server either could not be reached or returned an invalid response.” The server is down, or a proxy or firewall is blocking it. Retry, try another URL from your CA, and confirm you used /tr with /td.

“The signing certificate is not valid for the requested usage.” You picked a certificate without the code signing purpose, such as a TLS certificate.

Valid signature, but verification fails with a certificate chain error. The machine is missing an intermediate or root certificate, common on older or offline Windows installs. Also confirm you used /pa.

“No file digest algorithm specified. Defaulting to SHA1.” Add /fd SHA256.

FAQ

Is code signing required to run a Windows app?
No. Windows runs unsigned apps, with warnings. Kernel-mode drivers and MSIX packages do require signing.

Does signing remove SmartScreen warnings?
Not right away. It identifies you so reputation can build. EV no longer skips that step.

Can I keep the certificate as a file on my computer?
Not for a new publicly trusted certificate. The key has to live on certified hardware or in a cloud HSM.

Can I use one certificate on several build machines?
With a USB token, only where the token is plugged in. With cloud signing, several machines can call the same key. Check your CA’s license terms for how many signers or machines are allowed.

What happens to my signed app when the certificate expires?
If you timestamped it, the signature remains valid. If you didn’t, it stops validating at expiry.

Wrap-up

The process is short once the certificate and key are sorted: choose OV or EV, validate, get the key on hardware, run SignTool with /fd SHA256 and a timestamp, verify with /pa, and sign the installer last.

Most of the trouble comes from the key, not the command. Decide early where the key lives and how your pipeline reaches it. If you’re still picking a certificate, CodeSignCert lists OV and EV options from Sectigo, DigiCert, and Comodo.