Automate code signing using signtool.exe, but without saving a certificate or password

I have a C # /. NET 4.5 x64 project in Visual Studio 2013. More than one developer works in this project, so the code is managed in Git. I am signing compiled .dll and .exe with signtool.exe . My company bought a code signing certificate, and if I sign it manually from the command line as follows:

 signtool.exe sign /f cert.p12 /p "password" "compiled.dll" 

... then it looks like everything is fine: I get a success message and the properties of the compiled DLL in Windows Explorer show that it is correctly signed. This way I have no problem with the actual signing process.

But the certificate and its password should not reside in Git . They will be provided out of range to all project developers. I can assume that every developer, when he builds the project, will have a certificate stored in a predefined location on his computer, and he will know the password for it.

So here is my question: how can I configure Visual Studio 2013 to automatically sign the compiled output without saving the certificate or its password in Git? I want it to be as simple as the developer has the certificate in a predefined path (either imported or something else), and based on the assumption that the developer knows the password for the certificate, clicking "Build" in Visual Studio 2013 simply builds and signs it, asked no questions.

If the signing process can be non-interactive (without a password), this is a bonus. In the end, it will be part of a continuous integration server (CI), which can also sign its output, and since it is automated, no one will be there to enter the password. However, I will take any decision for now.

My certificate is in PKCS # 12 format and is password protected. Windows claims that it is not marked for export.

+9
c # visual-studio-2013 code-signing signtool
source share
7 answers

The solution I used earlier is similar to @Mikko's answer, but it split into two parts:

  • A local uncontrolled script that simply sets an environment variable containing a password. This is the file that you give to each developer.

     @echo off set SIGNPASS=whatever 
  • Managed by a script source that invokes the previous script and performs the actual signing.

     @echo off setlocal call "C:\local\signing_password.bat" "C:\toolpath\signtool.exe" sign /f "c:\certpath\cert.p12" /p "%SIGNPASS%" "%1" endlocal 

The setlocal / endlocal ensures that the password does not endlocal into the environment if the script is started manually.

"%1" is the path to the executable file that is passed as the script parameter in the Post Build phase. ..

+13
source share

Another way is to import the certificate in each certificate store for each developer, and then use the fingerprint using the icon:

 signtool ... /sha1 'hex thumbprint' ... 

Then you only need the password during the initial import of the certificate, and not during the build.

+7
source share

You can add the batch file to the project directory, for example sign.bat .

 @echo off <path>\signtool.exe /f cert.p12 /p "password" "compiled.dll" echo Signed with certificate 

Add the file to your .gitignore , but do not add it to your Visual Studio project.

In the project properties, call batch as an event after the build.

enter image description here

+3
source share

As a newer alternative to these, I have created a code signing service that individuals and organizations can deploy in their Azure environments that can help automate code signing, while private keys never leave Key Vault HSM.

Details are on the project page: https://github.com/onovotny/SignService

+1
source share

The signtool call from VS2015 did not work for me when I provided the password in the form of "$(SIGNPASS)" , but it worked when you used the notation "%SIGNPASS%" .

Checking how the complete signtool command was generated in the VS output window, the commands look the same, but there is some difference under the hood.

Remember to use double quotation marks to protect yourself from paths that contain spaces.

0
source share

I cannot add to Daniel Schlesser's answer - which, in my opinion, is the best answer. After adding the certificate to the certificate store, the password and pfx are not needed for signing.

However, I wanted to add the following comments:

  1. The certificate must be installed correctly in the certificate store (I used .pfx and password)
  2. signtool.exe must support the command line option / sha1 (I use 10.0.16299)
  3. For my certificate, it took me a long time to understand that I need to use the / sm switch to specify "Computer Storage" instead of "User Storage"
  4. The fingerprint is on the Details tab in the certificate properties.
  5. . Despite the fact that I read another post, the hash fingerprint is not case sensitive

So here is my command line that works for SHA256 (the hash has been changed):

 signtool.exe sign /sm /debug /v /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 /sha1 65cc2e77dc52b99d46e7caae2377bb5d7d9384b2 "D:\app.msi" 
0
source share

save the certificate to the Windows certificate store and download it using signtool.exe / n ... https://docs.microsoft.com/en-us/windows/win32/seccrypto/using-signtool-to-sign-a-file

0
source share

All Articles