Last month, I noticed that my eToken USB code-signing key only supports SHA1 and not SHA256. I began hunting for a replacement that can sign using the stronger hash. Fortunately, I didn’t have to look far—the Yubico YubiKey 4 is $40 and supports SHA256, RSA 4096, and ECC p384. Beyond supporting stronger algorithms, it seems to integrate better with Windows – I don’t need to install third-party software to use it after loading my certificate with the YubiKey PIV Manager.
To take advantage of SHA256, I needed to update my scripts to use signtool.exe instead of the older signcode.exe, which only supports SHA1.
My script is simply:
signtool sign /d "Brotli [De]compressor" /du "https://github.com/google/brotli" /n "Eric Lawrence" /t http://timestamp.digicert.com /fd SHA1 brotli.exe
signtool sign /as /d "Brotli [De]compressor" /du "https://github.com/google/brotli" /n "Eric Lawrence" /tr http://timestamp.digicert.com /td SHA256 /fd SHA256 brotli.exe
Notably, we sign the file twice:
First, sign using a SHA1 digest (older Windows versions don’t support SHA256). Then add an additional signature (the /as argument) using the stronger SHA256 file digest (the /fd argument).
For the stronger signature, use /tr to specify the timestamp URL (SHA256 signatures should use RFC3161 timestamps) and request that the timestamping server use a SHA256 digest (the /td argument).
Both signtool invocations will prompt for your PIN to access the private key stored on the token:
I was somewhat annoyed that the YubiKey only supports an 8 character PIN/password; I later learned that I can use the same 10 character password my old token uses—the final two characters are silently ignored.
After you’ve signed the file, you should use Windows Explorer to verify that each of the signatures and timestamps is valid:
Interestingly, most public CAs will use SHA256 for the timestamp’s digest but not for the signature itself; you can see this if you look closely at the timestamp signature (“RSA”):
This is likely due to a limitation in OpenSSL, and isn’t seen in Microsoft’s signatures (“sha256RSA”):
A Few Caveats
- MSIs cannot be dual-signed, only executables. (Update: Possibly introduced in Windows 8? See comments below.)
- Not all timestamping servers support SHA256 and not all support RFC3161 from their default timestamp service. For GlobalSign, use
http://timestamp.globalsign.com. For Comodo, use
6 thoughts on “Authenticode in 2016”
Bare with me here Eric. So you are using a Yubikey to sign your SSL certificates instead of say openssl(1) ? If yes, what is the advantage of that ? If no – I don’t get it.
Hi, Alex– this post concerns using a YubiKey to apply an Authenticode-signature to code (specifically, Windows executables). The reason for using a hardware token is that it protects the private key, as described in this post: http://blogs.msdn.com/b/ieinternals/archive/2015/01/28/authenticode-in-2015-signcode-with-certificate-on-etoken.aspx
You mention in the blog post that MSIs can’t be dual-signed.
I’m confused, because we do this for Mumble.
See for example https://dl.mumble.info/mumble-1.2.16.msi
Super interesting! Apparently, support for this was added in Windows 8, although Microsoft’s own references don’t recognize that.
You say “older Windows versions don’t support SHA256” but it’s not clear which older versions don’t support it. Some research suggests that fully patched Windows XP supports SHA-256, but another source suggested that Windows 7 only has partial support for SHA-256 code signing.
Ad-hoc testing on Windows 7 shows that SHA-256 signed binaries seem to be properly validated – maybe SHA1 signing isn’t really needed anymore? For my own particular software distribution needs I don’t really care about anything before Windows 7 (maybe Vista, but not really) and typing my password twice seems unfortunate.
XP, fully patched, supported SHA256 for certificates only (not Authenticode) unless something very quietly changed in its last breaths.
Vista and Win7 (and even one insider build of Win10, iirc) had bugs with binaries signed only with SHA2, but I believe these are all fixed for Win7+ at any reasonable patch level, and pure SHA256 signing is now done by some (e.g. Brave browser). I suspect there’s probably some obscure Firewall or AV packages that don’t know how to handle it, but I doubt it’s a big problem.