How to Correctly do SHA-256 Code Signing:
The Real Scoop on Code Signing, SHA-256, and Windows 10

(by Chris Long, developer of SSE Setup)

Updated January 2020

Code signing used to be pretty simple. Most everyone had a SHA-1 certificate and signed their files with the SHA-1 algorithm. Then things got complicated. Ever since Microsoft announced in 2015/2016 that they were deprecating SHA-1 and making changes in regards to the trusting of files signed with SHA-1, there has been a lot of confusing and inaccurate information floating out there about what it all really means. And Microsoft themselves have changed their story on what it all means several times. This article seeks to give you the true, practical, bottom-line information you need to know as a software developer and give you good advice on how to sign your files.

The good news is that as of now in early 2020, it's gotten easier and less confusing than it was for several years.

Understanding the Basic Terminology

First, let's get our terminology straight. There are 3 major issues: what the algorithm of your certificate itself is, what signing algorithm you use ("digest algorithm"), and what the algorithm of the timestamper you use is. They can all be different. For instance, your certificate itself might be SHA-256, but you could sign your files with the SHA-1 algorithm and/or timestamp with SHA-1, etc.

Having the Right Certificate

If your code signing certificate was issued in the last 5 years (2014 or later), it probably is already a SHA-256 certificate or higher. So this isn't even a concern anymore for most people. You want to have a SHA-256 certificate or higher. Note that XP SP2 or lower and Vista SP1 or lower do NOT support SHA-256 certificates so unless you have some pressing need to release software for those old OS's, a SHA-256 or higher certificate is all you want.

The Problem

While your certificate itself might be SHA-256 or higher, it also matters what algorithm you use to sign your files (your "signing algorithm") as well as the algorithm used to timestamp the files. Historically, people have signed only with SHA-1. Then in the last few years it was common to do what's called dual-signing, where the same file is signed twice with both SHA-1 and SHA-256. Most recently, it is becoming increasingly common to only sign with SHA-256 or higher.

Files that are only signed with SHA-1 may not be trusted on newer OS's including Windows 10 and Windows 7 (with updates applied). Files that are only signed with SHA-256 or higher will not be trusted on old OS's prior to Windows 7, including Vista SP2 and XP SP3. And Windows 7 might require updates to correctly handle some files signed only with SHA-256.

There are numerous articles out there that claim XP and Vista support SHA-256, but when it comes to code-signed files signed (and timestamped) with SHA-256 or higher algorithms, they are flat wrong. This is why dual-signing with both SHA-1 and SHA-256 has been a popular option for a few years as it allowed developers to support XP SP3 and Vista SP2 as well as Windows 7 and newer.

The Answer

The thing is that SHA-1 is now considered insecure and in 2019 due to Microsoft's concerns about the increased feasibility of attacks on it, Microsoft has now begun even issuing their own security updates only signed with SHA-256 (whereas they had commonly been dual-signing for several years).

Thus, my advice to developers now is to sign only with SHA-256 and target Windows 7 or higher. If you must support XP SP3 and Vista SP2, you can dual-sign, but again, that may not be a wise move security-wise at this juncture. If you do decide to dual-sign, you can only actually do the signing on Windows 8 or higher (unless you use a workaround for Windows 7 - see below). Be advised also that dual-signing does not work for .MSI files so you might want to first wrap your MSI in an .EXE file (or use a non-MSI installer such as SSE Setup).

When signing, you want to also make sure that you are also having the files timestamped by a trusted timestamp CA server using the same or higher algorithm. Thus if you sign a file with SHA-256, you should also have it timestamped by a SHA-256 or higher timestamping server. If you are dual-signing, you will both sign and timestamp using SHA-1 and then sign and timestamp using SHA-256 (or higher).

How to Sign / The Best Way to Sign

The main signing tool that everyone talks about is SignTool (signtool.exe) and is provided by Microsoft. However, there is a much easier solution out there. SignTool is only generally available by downloading the Windows SDK, only operates via the command-line, and is NOT a redistributable file. Instructions for using SignTool are further below. However, an alternative is a small free and ultra-simple program called EZSignIt. EZSignIt is both a GUI and command-line program (works either way) and already knows several SHA-1 and SHA-256 timestamper URL's that you can choose from. You simply pick your file to sign, your certificate, and specify whether to sign as SHA-1, SHA-256, or to Dual-Sign, and it'll do it (using the same underlying signing mechanism SignTool uses). It also conveniently remembers most of your settings for future use, allows you to batch sign multiple files at once, and automatically verifies/validates files it signs. Basically it's just a whole lot easier than the SignTool approach. It also will detect if you are on Windows 7 and want to Dual-Sign and can provide you information on a pretty easy workaround to get dual-signing working on Windows 7! On top of that, it comes with a help file with full info on signing in general and how to sign.

Full disclosure: EZSignIt is my tool - It was originally developed as a part of the SSE Setup Installer Platform to provide signing for SSE Setup created installers since SignTool is not redistributable and there were no other suitable options available (10 years later and there still really aren't many options out there - let alone one that provides all that EZSignIt does!). While developed for, and included with, SSE Setup, the tool has been released as freeware to benefit the entire developer and codesigning community, and unlike SignTook, it is redistributable if you follow some conditions. Seriously, I doubt you are going to find a more straightforward and easy, yet functional way to do codesigning than EZSignIt and I'm not just saying that because I wrote it. :)

Plus, it can even still easily use SignTool to actually do the signing if you want (it knows SignTool's command-line and also allows you to customize it) so there's really no downsides and lots of upsides to using it (i.e. GUI interface in addition to command-line, easy batch signing, etc.) There are no catches to using it - it is safe and fully free software with no ads or anything like that. To download it, just go here

So I'm biased, but if you really want to muck around just with SignTool, have at it.

Using SignTool

See the section directly above this for my suggestion to NOT use SignTool directly. However, if you still do want to use it, here's what you need to know.

First, the command-line will be different depending on how you specify your certificate (i.e. whether it's in a .PFX/.P12 file or just in your local certificate store). The examples below assume it is a .PFX file. However, if that's not the case such as with Extended Validation/EV certificates, then you can substitute the /f and /p parameters for /n "IssuedTo Name on Certificate".

SHA-1 Sample SignTool line: SignTool.exe /f "C:\MyFolder\MyCert.pfx" /p "PFX Password" /t "http://timestamp.comodoca.com/authenticode" "C:\MyFolder\MyFile.exe"

SHA-256 Sample SignTool line (NOT dual signing): SignTool.exe /f "C:\MyFolder\MyCert.pfx" /p "PFX Password" /fd sha256 /tr "http://timestamp.comodoca.com?td=sha256" /td sha256 "C:\MyFolder\MyFile.exe"

SHA-256 Sample SignTool line (Dual signing): SignTool.exe /f "C:\MyFolder\MyCert.pfx" /p "PFX Password" /fd sha256 /tr "http://timestamp.comodoca.com?td=sha256" /td sha256 /as "C:\MyFolder\MyFile.exe"

If you are dual-signing, sign with SHA-1 first and then sign with SHA-256 per the related-example above. Note that dual-signing will require the version of SignTool from the Windows 8.1 SDK or higher, and signing with SHA-256 at all will at least require the Windows 7 SDK version of SignTool. If you try to use a version of SignTool that doesn't support SHA-256 or dual-signatures, it won't work.

Conclusion

The bottom line for most developers is: (1) get a SHA-256 certificate, (2) Sign and timestamp your files using SHA-256 or higher using the free EZSignIt tool or SignTool. The resulting signed files should work on Windows 7 and newer OS's.

[Disclaimer: The advice and opinions in this article are strictly my own and are based on lots of investigation and testing. I've tried to simplify it all down for you as much as possible. I shall not be liable in any way for any advice or opinions shared here. It is your responsibility to do your own research, make your own mind up, and choose your own course of action based on your specific needs.]


 
Copyright © by Chris Long 2016-2020. All rights reserved.