Microsoft announced some time ago that windows 7 & higher would no longer trust anything that is code signed with an SHA1 (https://en.wikipedia.org/wiki/SHA-1 ) certificate as of 1st Jan 2016. The reason for this is well documented, SHA1 has become increasingly vulnerable and is no longer secure enough to be trusted.
What do I need to do?
First things first, check your code signing certificate. If it's current, and uses SHA1, contact your certificate issuer for a replacement SHA256 certificate. Most issuers have a formal process for this since this is something they have known about for a while and should not charge extra (KSoftware/Comodo do not charge). In our case, our certificate was renewed in Nov 2014 and was already an SHA256 certificate.
What if I need to support Windows XP/Server 2003?
Windows XP & Server 2003 do not support SHA256, so this deprecation of SHA1 does not apply to those versions of windows. If you sign with your SHA256 certificate using the SHA256 digest algorithm, you will find you code is not trusted on those versions of windows. The trick is to use the SHA1 digest algorithm.
So do I need separate installers for XP and Windows 7+ ?
Well that's one way to do it, but you can support XP and windows 7+ with a single installer or exe, by signing twice, with SHA1 and SHA256.
NOTE: If you are a long time FinalBuilder user and still using the Authenticode action, then don't, it's been deprecated for some time as it uses the deprecated capicom.dll api
. The only reason we haven't removed it is to avoid errors when you load your old projects. The correct actions to use for code signing are the SignTool actions.
Recent versions of Signtool.exe
include a switch (/as) to append a signature ( the default operation is to replace the primary signature). I believe the windows 8.1 sdk was the first version to include this option (and other related options).
In my experiments, I found that you need to sign with SHA1 first, then SHA256. The reason for this is that WinXP only looks at the first signature and would not recognise the timestamps from any RFC3161 timestamp servers that I tried. The signtool options that allow adding additional signatures (/as for signing, /tp for timestamping) only work with RFC3161 compliant timestamp servers, so the SHA1 signature and timestamp must be done first since we can't use /as or /tp with a non RFC3161 timestamp server.
Sign, then TimeStamp
Whilst signtool can sign and timestamp in a single operation (and the SignTool Sign
action in FinalBuilder can too), I prefer to do the timestamp step separately. The reason for this is that signing rarely fails (typically only when the certificate has expired or you get the password wrong!), but timestamping fails often, because the timestamp server may be unreachable or it just has some issue and doesn't respond correctly.
By doing the timestamp operation separately, we can retry if timestamping fails. Often, just a few seconds between retries is enough (unless your internet connection is down), and there is always the option of using a different timestamp server.
So the order of events is :
Sign SHA256 (with append signature /as).
Timestamp SHA1 - using older style authenticode timestamp server.
Timestamp SHA256 (/tp with index 1
) - using an RFC3161 compliant timestamp server.
Show me how!
I have created an examples repository on github : FinalBuilder Examples
- you can find a nice example there showing how to double (optionally) sign and then timestamp (with retries). This example requires FinalBuilder 220.127.116.110 or later (added support for /tp option on timestamp action).