There are many sites that explain how to run signtool.exe
on a .pfx
certificate file, which boil down to:
signtool.exe sign /f mycert.pfx /p mypassword /t http://timestamp.server.com \
/d "My description" file1.exe file2.exe
I have a continuous integration CI process setup (using TeamCity) which like most CI processes, does everything: checks out source, compiles, signs all .exes, packages into an installer, and signs the installer .exe. There are currently 3 build agents, running identical VMs, and any of them can run this process.
Insecure implementation
To accomplish this today, I do a couple Bad Things(TM) as far as security is concerned: the .pfx file is in source control, and the password for it is in the build script (also in source control). This means that any developers with access to source code repository can take the pfx file and do whatever nefarious things they'd like with. (We're a relatively small dev shop and trust everyone with access, but clearly this still isn't good).
The ultimate secure implementation
All I can find about doing this "correctly", is that you:
- Keep the pfx and password on some secure medium (like an encrypted USB drive with finger-based unlock), and probably not together
- Designate only a couple of people to have access to sign files
- Only sign final builds on a non-connected, dedicated machine that's kept in a locked-up vault until you need to bring it out for this code-signing ceremony.
While I can see merit in the security of this.. it is a very heavy process, and expensive in terms of time (running through this process, securely keeping backups of certificates, ensuring the code-signing machine is in a working state, etc).
I'm sure some people skip steps and just manually sign files with the certificate stored on their personal system, but that's still not great.
It also isn't compatible with signing files that are then used within the installer (which is also built by the build server) -- and this is important when you have an installed .exe that has a UAC prompt to get admin access.
Middle ground?
I am far more concerned with not presenting a scary "untrusted application" UAC prompt to users than proving it is my company. At the same time, storing the private key AND password in the source code repository that every developer (plus QA and high-tier tech support) have access to is clearly not a good security practice.
What I'd like is for the CI server to still sign during the build process like it does today, but without the password (or private key portion of the certificate) to be accessible to everyone with access to the source code repository.
Is there a way to keep the password out of the build or secure somehow? Should I be telling signtool to use a certificate store (and how do I do that, with 3 build agents and the build running as a non-interactive user account)? Something else?