Signing Windows executables and Visual Studio Team Services

When you download a program from the internet and execute it, User Account Control warns you about the application you’re about going to start. When you start the Firefox installer, for example, you get a message like this:

Windows tells you who the publisher of this file is. In this case, it’s the Mozilla Corporation. In this way, it warns users who download a certain file, who the original publisher is. If the file has been tampered, the publisher will be reset into an “Unidentified Publisher”.

Visual Studio Team Services (VSTS) has build in tasks to sign iOS and Android applications, however there are no off the shelf solutions for signing Windows applications. Therefore I investigated a way for signing an application within VSTS using Continuous Integration.

Using secure files

VSTS has the ability to save files in a safe place under “Library->Secure Files”. This could be a nice place to store our key into. However, I found out it is only possible to get access to the secure files via a custom task. There are only a few extensions which actually support this secureFile input. There are default extensions for signing iOS and Android files. I found actually one in the marketplace that claimed to sign Windows executables, but didn’t tried this one.

Secret variables

Within each build you have also the possibility to have variables which are secret. The values of these attributes are hidden and stored securely on the server. They cannot be viewed by users after they are saved. They are received by the agent over a HTTPS connection and then decrypted. You can use these secret variables for example by providing them as arguments to a batch-file. This batch-file is then triggered during the build.

To create a secret variable, go within “Build and release” to variables. Now add a new variable under “process variables”, lets say codesign_pwd. As value, give the value of the key and make it secret by pressing on the lock right of the value. Add a Batch Script task and provide as an argument the just created codesign_pwd as follows:

$(codesignkey_pwd)

Also put the signtool under version control, and make sure it can be accessed from your build script. Since the pfx is password protected and you also need a password to access the repository, you need actually two passwords to get access to it. Put in your batch-file the command to sign your executable:

..\tools\signtool\signtool.exe sign /f "%solutiondir%\Build\PrivateKeys\mysigningkey.pfx" /p %1 /t http://timestamp.verisign.com/scripts/timstamp.dll "%solutiondir%\Build\Output\Installer\MyApplication_Setup.exe"

The main drawback of this solution is however, when you change the batch-file, you can actually print the password on screen.

In this example, I use a timestamp to sign the executable MyApplication_Setup.exe. Certificates have a certain time span when they’re valid. By using a timestamp, the signed application will still have a valid certification even when the time span of the certificate has passed.

Azure key vault

Didn’t have access to this, but it seems a secure way of storing your signing key when using VSTS. The key vault stores your key and only your build agent can access the key vault when signing is needed.

Running your agent locally

Besides using the Azure key vault, this is also a very secure way of storing your signing key. You install your private key into a build machine, which is executed by a local agent. You need to have access to the build server in order to get the private key. Although it requires either a Virtual Machine running within the cloud or having a physical build machine where your run the local agent upon.

Posted in DevOps by Bruno at October 24th, 2017.

Leave a Reply