The short answer
To sign a DLL so Windows can name its publisher, add an Authenticode signature with a code signing certificate: signtool sign /fd SHA256 /tr <timestamp URL> /td SHA256 /n "Your Company" MyLib.dll, then check it with signtool verify /pa /v MyLib.dll. Visual Studio's "Sign the assembly" option is strong naming, not Authenticode: in our test a strong-named .NET DLL carried no Authenticode signature at all. When you need both, apply the strong name first and Authenticode last.
On this page
- Which signature does a DLL need?
- What do you need before you sign?
- How do you sign a DLL with SignTool?
- How do you check that a DLL is signed?
- What happened when we signed a native and a .NET DLL?
- Why must strong naming come before Authenticode?
- Can you sign DLLs on Linux or in a pipeline?
- Which DLL signing mistakes cause trouble later?
- Frequently Asked Questions
Which signature does a DLL need?
A DLL that customers install needs an Authenticode signature, because that is the signature that carries a CA-issued certificate naming the publisher. A strong name is a separate .NET mechanism: Microsoft says to "not rely on strong names for security. They provide a unique identity only." Strong names exist only for .NET assemblies, so a native C or C++ DLL has Authenticode as its only option.
| Question | Strong name | Authenticode |
|---|---|---|
| What it proves | A unique identity for one .NET assembly | Who published the file, and that it has not changed since signing |
| Where the key comes from | A key pair you generate yourself; no CA involved | A code signing certificate from a public CA, key in certified hardware |
| Works on native (C/C++) DLLs | No, .NET assemblies only | Yes, any Windows PE file |
| Checked by the modern .NET runtime | No: .NET Core and .NET 5+ never validate it | Not by the runtime; Windows trust features such as Smart App Control check it |
| Smart App Control | Not a signature it uses | Lets an otherwise-blocked file run when the certificate is from a Trusted Root Program CA |
| App Control for Business | Not a signature it uses | Allowed when the organization's policy trusts the signer |
Strong naming still has a place in .NET Framework, where Microsoft lists it for libraries that strong-named assemblies must be able to reference and for assemblies installed in the global assembly cache. For .NET Core and .NET 5+, Microsoft's documentation says the runtime "never validates the strong-name signature, nor does it use the strong-name for assembly binding", and its library guidance recommends Authenticode and NuGet package signing when the publisher's identity matters.
What do you need before you sign?
To sign a DLL you need a code signing certificate whose private key sits in certified hardware, SignTool from the Windows SDK, and the finished build. Since 1 June 2023 the CA/Browser Forum's code signing requirements make CAs ensure the key is generated, stored and used in a hardware crypto module, so instructions that start from a PFX file only work with old or self-made certificates.
My-SSL sells Certum code signing certificates that sign through the SimplySign cloud, with no USB token to plug in. Before SignTool can see such a certificate, SimplySign Desktop has to be connected with a code from the SimplySign mobile app; the steps are in our SimplySign Desktop setup guide. With a hardware token, plug it in and install the token software first.
How do you sign a DLL with SignTool?
SignTool signs a DLL the same way it signs an EXE: one signtool sign command with a file digest, a certificate selector and an RFC 3161 timestamp. Run it from a Developer Command Prompt after the build, on the files you are about to package.
- Connect the key. Connect SimplySign Desktop or plug in the token so SignTool can see the certificate.
- Sign and timestamp in one call. Certum's signing manual uses
http://time.certum.plas its RFC 3161 server:
signtool sign /fd SHA256 /tr http://time.certum.pl /td SHA256 /n "Your Company" /v MyLib.dllEach option has a job. Microsoft states that "if the /fd option isn't specified while signing, the command generates an error", and recommends SHA256. Without /tr (or the legacy /t) "the signed file isn't time stamped", and /td sets the digest the timestamp server uses. /n picks the certificate by a substring of its subject name; when several certificates match, select one by its SHA-1 thumbprint with /sha1 instead.
- Sign every DLL in one pass. SignTool's syntax accepts more than one file name, so a release script can pass all of its DLLs and EXEs to a single command:
signtool sign /fd SHA256 /tr http://time.certum.pl /td SHA256 /n "Your Company" ^
bin\Release\MyApp.exe bin\Release\MyLib.dll bin\Release\MyLib.Native.dllThe EXE side of the same tool, including how to install it from the Windows SDK, is covered in how to sign an EXE with SignTool.
How do you check that a DLL is signed?
Check a signed DLL with signtool verify /pa /v MyLib.dll, which prints the certificate chain and the timestamp. The /pa option matters: Microsoft documents that it selects the Default Authentication Verification Policy, and that without it SignTool uses the Windows Driver Verification Policy, so add it when you check an application DLL.
signtool verify /pa /v MyLib.dllOn Linux or macOS, osslsigncode verify -in MyLib.dll does the same job, and it is what we used in the test below. Other ways to inspect a signature are in how to verify a code signature.
What happened when we signed a native and a .NET DLL?
We signed a native DLL and a strong-named .NET DLL on 20 October 2026 and verified each step with osslsigncode 2.8. The native DLL was built from C with MinGW-w64 GCC 13; the .NET 8 class library was built with .NET SDK 8.0.132 with strong naming switched on (<SignAssembly>true</SignAssembly> and a key file). The signing certificate came from a test root we made ourselves, with its key in a file, which no public CA may issue today. We did not run SignTool, SimplySign Desktop or Smart App Control in this test; the Windows commands above come from Microsoft's and Certum's documentation.
$ osslsigncode verify -in managed.dll # strong-named, CLI flag STRONGNAMESIGNED set
Unable to extract existing signature
Failed
$ osslsigncode sign -certs cs.crt -key cs.key -h sha256 \
-ts http://time.certum.pl -in managed.dll -out managed-signed.dll
Succeeded
$ osslsigncode verify -in managed-signed.dll -CAfile ca.crt -TSA-CAfile ca-certificates.crt
Current message digest : 7D3695209144263E115CE89E64F90A1E9148BE98E25A3D46BBAB9FFF70E25DDC
Calculated message digest : 7D3695209144263E115CE89E64F90A1E9148BE98E25A3D46BBAB9FFF70E25DDC
Timestamp time: Oct 20 08:55:02 2026 GMT
SucceededThree results are worth carrying into your own release process. The strong-named DLL had an empty Authenticode slot until we signed it, so a project that only ticks "Sign the assembly" ships unsigned binaries as far as Windows is concerned. The signed native DLL failed with "unable to get local issuer certificate" when we stopped trusting our test root, the same trust failure a customer's machine runs into with a self-signed or private-root certificate. And changing the strong-name bytes after Authenticode signing produced "MISMATCH".
Why must strong naming come before Authenticode?
Strong naming must come before Authenticode because the Authenticode hash covers the assembly's bytes, strong-name signature included. Microsoft's .NET security team gave the order as "1. Strong name the assembly 2. Authenticode sign the assembly", because Authenticode "needs to see the exact same bits during signing and verification".
That post dates from 2007, but our test shows the mechanism still holds: overwriting the 128-byte strong-name signature of an Authenticode-signed DLL made the calculated digest differ from the signed one. That is the change completing a delay-signed assembly makes, because the final strong-name step writes the signature into a space left empty at build time. If you use delay signing, run the final strong-name step, then SignTool, then package.
Can you sign DLLs on Linux or in a pipeline?
DLLs can be signed on Linux with osslsigncode, as in our test, when the key is reachable from that machine. Certum ships SimplySign Desktop for Windows, Linux and macOS, but its signing manual documents PKCS#11 library paths for Windows only, and it logs SimplySign Desktop in with a username and a code from the mobile app, with no unattended mode described.
So a pipeline either reaches a machine where someone has connected SimplySign Desktop (Windows is the route Certum's manual documents), or sends files to one signing host. The trade-offs are in signing Windows binaries on Linux and code signing in CI/CD.
Which DLL signing mistakes cause trouble later?
Most DLL signing problems show up months later, on a customer's machine or after the certificate expires, and come from one of five habits.
- Signing the EXE and skipping the DLLs. Smart App Control blocks "unknown, unsigned code" by default, and Microsoft's App Control guidance asks organizations to require all app binaries to be signed.
- Leaving out the timestamp. Microsoft states that without one the signature becomes invalid when the certificate expires and Windows treats the binary as unsigned. See code signing timestamping.
- Treating the strong name as the signature. It proves identity, not publisher, and modern .NET never checks it.
- Changing a file after signing it. Completing a delay-signed assembly, patching resources or any other step that rewrites the file after SignTool breaks the signature, as our mismatch test shows.
- Following PFX-file instructions. Guides that pass
/f MyCert.pfx /p passwordfollow the pre-June-2023 model of a key in a file; a current certificate is selected from the store with/nor/sha1.
Kernel-mode drivers are a separate case. Microsoft states that from Windows 10, version 1607, Windows will not load new kernel-mode drivers that are not signed by the Dev Portal, and registering for the Windows Hardware Developer Program requires an EV code signing certificate. The full route is in how to sign a Windows driver.
Frequently Asked Questions
Answers to common questions about certificates and our services.
Does Visual Studio's "Sign the assembly" option sign my DLL with my certificate?
No. Microsoft's Visual Studio documentation places "Sign the assembly" under Build > Strong naming: it gives the assembly a strong name, a unique identity, and it does not use your code signing certificate. To show a verified publisher you add an Authenticode signature with SignTool after the build.
Do I need to sign every DLL in my application, or only the EXE?
Sign every binary you ship. Microsoft's App Control for Business guidance tells organizations to require all app binaries and scripts to be code signed as part of app acceptance, and Smart App Control blocks unknown, unsigned code by default. An unsigned DLL next to a signed EXE can be the file a customer's policy stops.
Can I sign a DLL with a self-signed certificate?
You can, but only machines that trust your own root will accept it. In our test a DLL signed with a certificate from an untrusted test root failed verification with "unable to get local issuer certificate", and Microsoft says Smart App Control lets a file it would otherwise block run when it is signed with a certificate from a CA in Microsoft's Trusted Root Program.
Does the .NET runtime check the strong-name signature?
Not on modern .NET. Microsoft states that for .NET Core and .NET 5+ the runtime never validates the strong-name signature and does not use the strong name for assembly binding, and that strong names should not be relied on for security.
What happens to a signed DLL when the certificate expires?
If you added a timestamp, the signature stays valid. Microsoft states that without a timestamp the signature becomes invalid when the signing certificate expires and Windows treats the binary as unsigned, so always pass /tr and /td to SignTool.
If your DLLs still ship without an Authenticode signature, start with the certificate. Compare Standard and EV on our code signing certificate page; the Certum code signing certificates we sell are delivered through SimplySign, so the SignTool commands above apply once SimplySign Desktop is connected.