User Tools

Site Tools


kb:common:code-signing

Code Signing

This page contains information on signing code, more specifically builds like .exe files. This can reduce issues with antivirus programs, especially Windows Defender and SmartScreen, as well as helping prove the authenticity and integrity of the code. To sign code, either a certificate from a trusted certificate authority (CA) or a self-signed certificate is needed; more information on different types of certificates below.

Nowadays (since 2024) SmartScreen will always flag applications distributed outside the MS Store before their publisher's certificate has gained enough reputation through repeated installs without issues (cf. SmartScreen Documentation). Thus, programs will need to be installed often enough after code signing has been implemented in order for it to take effect. This process takes around “several weeks and hundreds of clean installs” until the warning will consistently be suppressed (SmartScreen Documentation). Furthermore, since reputation is built on a per certificate basis, it is likely for the warning to reappear after certificate renewal (cf. Microsoft Q&A)

Types of Certificates

One alternative to signing code manually is the use of Microsoft Store Signing. Software distributed this way gets resigned by Microsoft themselves. However, this only works for MSIX packages. If EXE or MSI are used, an additional certificate by a CA included in Microsoft's Trusted Root Program is necessary. Either way, MS Store (Re-)Signing is the only possible way to remove the SmartScreen warning immediately. For more information see Better Practices.

  • Organization validation (OV) certificates are the cheapest possibility to get rid of the SmartScreen warning long-term and are superior for proving authenticity than self signed ones. They should be purchased from a member of Microsoft's Trusted Root Program
  • Self signed certificates will not work to suppress the warning and behave as if no certificate were in place

Note: Since 2026, certificates can't be valid for more than 460 days, so CAs will usually just allow free renewals upon purchase of certificates for a longer period of time


Hardware Encryption Modules

Publicly trusted code-signing certificates require the private signing key to be generated, stored, and used in an approved hardware encryption module. This can be a physical token - an on-premises hardware security module (HSM) - or a managed cloud signing service. There are different types of HSMs available, each with their own benefits and drawbacks.

  • Cloud HSMs outsource the cryptographic functions to modules in the cloud allowing for easy integration with CI/CD and virtual build servers
  • Hardware tokens are physical modules stored on site and can be bought separately or in a subscription from the CA. Integration with virtual build servers is possible, (cf. NitroKey example) e.g. via USB passthrough, but may be tedious

Certificate Authorities

A Certificate Authority (CA) issues certificates and establishes the certificate’s chain of trust. A signing service then stores or accesses the private key and performs the signing operation.

Prices are per year and certificate for cloud signing. Hardware token subscriptions are mostly only cheaper when using just a single hardware token. Buying and maintaining a hardware token yourself is cheaper still, but comes with risks like possible future increases of hardware requirements. Nonetheless, prices for these cases are also added in parentheses if available. Information accurate as of: 06/07/2026 (DD/MM/YYYY), prices converted from USD to EUR for comparison

  • Microsoft Store Signing: free except for store fees; limitations: only MSIX supported
  • Azure Artifact Signing (Microsoft themselves; formerly Trusted Signing): ≈105€/year; limitations: 5000 signatures/month; no hardware token support
  • digicert: ≈852€/year (720€/year; 600€/year); very reputable
  • Certum: ≈140-209€/year (145-200€/year; 120-140€/year)
  • Sectigo: ≈466-621€/year; limitations: no cloud signing
  • SSL.com: ≈270€/year (115€/year + 330€ one-time; 115€/year + 500€ one-time)

Signing using SignTool.exe

SignTool.exe is part of the Windows SDK and can sign, timestamp, and verify Windows binaries. Install the required SDK version explicitly:

# SignTool.exe — explicit Windows SDK version required
winget install --exact --id Microsoft.WindowsSDK.10.0.28000

Note: The package version must be specified because several Windows SDK packages and versions are available through WinGet.

Azure Artifact Signing

The following instructions describe signing with Azure Artifact Signing.

Prerequisites

Before signing, the following Azure resources must exist:

  • an Artifact Signing account
  • a completed identity validation
  • a certificate profile
  • an identity with the Artifact Signing Certificate Profile Signer role

Assign the role at certificate-profile scope where practical, following the Microsoft instructions.

Installation

Install the Artifact Signing Client Tools:

# Azure Artifact Signing Dlib and client components
winget install --exact --id Microsoft.Azure.ArtifactSigningClientTools

The package installs the Artifact Signing Dlib plugin, the required .NET runtime, and their dependencies. Restart PowerShell after installation if the tools cannot immediately be found.

The install location is needed when doing the signing. If in doubt, run the following command to find it:

Get-ChildItem C:\ -Filter Azure.CodeSigning.Dlib.dll -Recurse -Force -ErrorAction SilentlyContinue |
    Select-Object -ExpandProperty FullName

Metadata

Create a azure-metadata.json file:

{
  "Endpoint": "https://<region>.codesigning.azure.net",
  "CodeSigningAccountName": "<Artifact Signing account name>",
  "CertificateProfileName": "<Certificate profile name>",
  "CorrelationId": "<optional build or workflow identifier>",
  "ExcludeCredentials": [
    "ManagedIdentityCredential",
    "WorkloadIdentityCredential",
    "SharedTokenCacheCredential",
    "VisualStudioCredential",
    "VisualStudioCodeCredential",
    "AzureCliCredential",
    "AzurePowerShellCredential",
    "AzureDeveloperCliCredential",
    "InteractiveBrowserCredential"
  ]
}

The endpoint must match the region of the Artifact Signing account. For example, the endpoint for North Europe is:

https://neu.codesigning.azure.net

CorrelationId is optional and can be omitted. It can be used to associate signing requests with builds, pipelines, or machines.

The ExcludeCredentials list makes authentication use the environment variables described below. Adjust or remove the list when using a different authentication method, such as Azure CLI authentication.

Unattended Authentication

For unattended signing, create a Microsoft Entra application and service principal and assign it the Artifact Signing Certificate Profile Signer role.

Provide its credentials through the environment variables expected by EnvironmentCredential:

AZURE_TENANT_ID     = "<tenant ID>"
AZURE_CLIENT_ID     = "<application/client ID>"
AZURE_CLIENT_SECRET = "<client secret>"

You can set these environment variables manually in PowerShell using the $env:VARIABLE=“VALUE” notation. In GitLab CI/CD, define these as masked and protected CI/CD variables instead of storing credentials in the repository.

Treat the client secret like a password. Limit its lifetime and permissions, rotate it regularly, and never write it to logs or commit it to the repository.

Interactive Authentication

For interactive local testing, Azure CLI authentication can be used instead. Install the Azure CLI:

# Azure CLI — required only for interactive AzureCliCredential authentication
winget install --exact --id Microsoft.AzureCLI

Restart PowerShell after installation. Remove AzureCliCredential from ExcludeCredentials, then authenticate:

az login

Signing

Sign and timestamp the artifact:

& 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.28000.0\x64\signtool.exe' sign /v /fd SHA256 /tr http://timestamp.acs.microsoft.com /td SHA256 /dlib "$env:LOCALAPPDATA\Microsoft\MicrosoftArtifactSigningClientTools\Azure.CodeSigning.Dlib.dll" /dmdf "C:\path\to\azure-metadata.json" "C:\path\to\application.exe"

The & call operator is required to execute the quoted path. Adjust the paths to signtool.exe, the metadata file and the artefact according to your needs.

Depending on how and where the Azure DLL was installed, the /dlib parameter needs to be adjusted accordingly, eg:

  • “$env:LOCALAPPDATA\Microsoft\MicrosoftArtifactSigningClientTools\Azure.CodeSigning.Dlib.dll”
  • “$env:userprofile\Microsoft.ArtifactSigning.Client.1.0.128\bin\x64\Azure.CodeSigning.Dlib.dll”

Note:

  • Sign nested binaries such as DLLs and EXEs before signing the enclosing installer or package.
  • Do not modify an artefact after signing it.

Verification

Verify every signed artifact before publishing it:

& 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.28000.0\x64\signtool.exe' verify /pa /v "C:\path\to\application.exe"

Verification confirms the publisher identity, signature integrity, certificate chain, and timestamp. It does not establish that the signed software is secure or free of defects.

For details of the HSE configuration and CI/CD implementation, refer to the internal DokuWiki entry.


Signing in LabVIEW

On signing a LabVIEW installer, refer to ni Knowledge or DMC: Digitally Signing a LabVIEW Installer. Note that information on EV certificates providing instantaneous SmartScreen bypass and certificate extraction being possible is outdated. To use a certificate for signing a LabVIEW installer, a Microsoft Authenticode certificate is needed.


FAQ

Wrong certificates selected

Possible reasons for seeing output like the following:

  The following certificates have been found to be suitable for signing:
      Issued to: Adobe Intermediate CA 10-3
      Issued by: Adobe Root CA 10-3
      Expires:   Sat Aug 04 19:37:58 2068
      SHA1 hash: D1DF7F06B769BCCB3F4479041EC1F06E9CD3CB1A
  
  SignTool Error: Multiple certificates were found that meet all the given
      criteria. Use the /a option to allow SignTool to choose the best
      certificate automatically or use the /sha1 option with the hash of the
      desired certificate.
  • Wrong bitness for the signtool.exe path selected: Most signing services are 64bit. Do not call the signtool.exe from the /x86/ path
  • Wrong path to the Azure Code Signing DLL: Use the Get-ChildItem call to find the correct location
kb/common/code-signing.txt · Last modified: 2026/08/05 07:51 by joerg.hampel