Skip to main content

Code signing your .NET Core application

We stopped a long time signing our code of our backend applications however we still do it for the applications that are running on a local machine(desktop applications, console apps,...). This is because we whitelist what can be installed and executed on a local machine.

Code signing remains a valuable security practice that validates the authenticity and integrity of your .NET Core applications. When you sign your code, you're essentially providing a digital certificate that proves the software comes from you and hasn't been tampered with since it was signed.

Why sign your code?

Before diving into the how, let's understand why code signing matters:

  • Trust and Authenticity: Users can verify that your application comes from a legitimate source
  • Integrity Verification: The signature ensures the code hasn't been modified after signing
  • Windows SmartScreen: Signed applications are less likely to trigger security warnings
  • Enterprise Requirements: Many organizations require all software to be signed before deployment
  • Malware Protection: Code signing helps prevent malicious actors from distributing modified versions of your software

Reasons enough to still give it a try…

What you’ll need

To sign your .NET Core application, you'll need:

  1. A code signing certificate from a trusted Certificate Authority (CA) like DigiCert or GlobalSign
  2. The SignTool utility (included with the Windows SDK or Visual Studio ClickOnce tools)
  3. Your compiled .NET Core application files

Step 1: Obtaining a code signing certificate

You can purchase a code signing certificate from various certificate authorities. The process typically involves:

  • Verifying your identity or organization
  • Purchasing the certificate (prices vary by provider)
  • Downloading the certificate file (usually a .pfx or .p12 file)

For testing purposes, you can create a self-signed certificate, though this won't provide the same trust benefits as a certificate from a recognized CA.

# Create a self-signed certificate
$cert = New-SelfSignedCertificate -Type CodeSigningCert -Subject "CN=YourName" -CertStoreLocation Cert:\CurrentUser\My

# Export to PFX file
$password = ConvertTo-SecureString -String "YourPassword" -Force -AsPlainText
Export-PfxCertificate -Cert $cert -FilePath "TestCertificate.pfx" -Password $password

Step 2: Signing your application with SignTool

The SignTool utility is the standard tool for signing Windows applications. Here's how to use it:

signtool sign /f "path\to\certificate.pfx" /p "YourPassword" /tr http://timestamp.digicert.com /td sha256 /fd sha256 "path\to\your\application.exe"

Let's break down these parameters:

  • /f: Specifies the path to your certificate file
  • /p: The password for your certificate
  • /tr: Timestamp server URL (crucial for long-term validity)
  • /td: Timestamp digest algorithm
  • /fd: File digest algorithm
  • The final parameter is the path to your executable

If you need to sign multiple files (DLLs, executables, etc.):

signtool sign /f "certificate.pfx" /p "YourPassword" /tr http://timestamp.digicert.com /td sha256 /fd sha256 *.exe *.dll

Remark: If you cannot find the exe, have a look at C:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool

Step 3: Automating code signing in your build process

For continuous integration and deployment, you'll want to automate code signing.

Here is an example using Powershell in Azure Pipelines:


 - script: signtool.exe sign /f "$(SigningCertificate.secureFilePath)" /p $(CertificatePassword) /td sha256 /fd SHA256 /tr "http://timestamp.digicert.com/" "$(ApplicationExe)"

Step 4: Verifying your signature

After signing, verify that the signature is valid:

signtool verify /pa "path\to\your\application.exe"

You can also right-click the file in Windows Explorer, select Properties, and check the Digital Signatures tab.

Best practices

As you implement code signing, keep these practices in mind:

  • Protect Your Certificate: Store your certificate securely, preferably in a hardware security module (HSM) or secure key vault like Azure Key Vault. Never commit certificates to source control.
  • Always Use Timestamping: The timestamp ensures your signature remains valid even after your certificate expires. Use a reliable timestamp server from your CA or a service like DigiCert's.
  • Sign All Executables and DLLs: Don't just sign the main executable. Sign all components of your application to provide comprehensive verification.
  • Use Strong Algorithms: Always use SHA-256 or stronger algorithms. SHA-1 is deprecated and no longer trusted by modern systems.
  • Automate the Process: Integrate signing into your CI/CD pipeline to ensure every release is properly signed.

More information

Sign application and deployment manifests - Visual Studio (Windows) | Microsoft Learn

dotnet/sign: Code Signing CLI tool supporting Authenticode, NuGet, VSIX, and ClickOnce

SignTool - Win32 apps | Microsoft Learn

SignTool.exe (Sign Tool) - .NET Framework | Microsoft Learn

Popular posts from this blog

Azure DevOps/ GitHub emoji

I’m really bad at remembering emoji’s. So here is cheat sheet with all emoji’s that can be used in tools that support the github emoji markdown markup: All credits go to rcaviers who created this list.

.NET 8–Keyed/Named Services

A feature that a lot of IoC container libraries support but that was missing in the default DI container provided by Microsoft is the support for Keyed or Named Services. This feature allows you to register the same type multiple times using different names, allowing you to resolve a specific instance based on the circumstances. Although there is some controversy if supporting this feature is a good idea or not, it certainly can be handy. To support this feature a new interface IKeyedServiceProvider got introduced in .NET 8 providing 2 new methods on our ServiceProvider instance: object? GetKeyedService(Type serviceType, object? serviceKey); object GetRequiredKeyedService(Type serviceType, object? serviceKey); To use it, we need to register our service using one of the new extension methods: Resolving the service can be done either through the FromKeyedServices attribute: or by injecting the IKeyedServiceProvider interface and calling the GetRequiredKeyedServic...

Kubernetes–Limit your environmental impact

Reducing the carbon footprint and CO2 emission of our (cloud) workloads, is a responsibility of all of us. If you are running a Kubernetes cluster, have a look at Kube-Green . kube-green is a simple Kubernetes operator that automatically shuts down (some of) your pods when you don't need them. A single pod produces about 11 Kg CO2eq per year( here the calculation). Reason enough to give it a try! Installing kube-green in your cluster The easiest way to install the operator in your cluster is through kubectl. We first need to install a cert-manager: kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.5/cert-manager.yaml Remark: Wait a minute before you continue as it can take some time before the cert-manager is up & running inside your cluster. Now we can install the kube-green operator: kubectl apply -f https://github.com/kube-green/kube-green/releases/latest/download/kube-green.yaml Now in the namespace where we want t...