Signing VSTO Code with EV Certificate on Visual Studio 2017

After a lot of time spent on the phone with support at DigiCert, we finally figured out a process that works.

What is not immediately obvious in this case is that you end up doing a LOT of signing of code.

So when you build a VSTO application, you sign the code with the EV certificate. Then, when you want to publish (using ClickOnce) you will have to sign again.

But even after that, you have to then re-sign the setup file TWO MORE TIMES to get this all to work!

After spending a ton of time on this, I now have a batch file that does the final steps, including syncing the setup files up to Amazon S3 for deployment.

So here's how I do it:

  1. Once you have the USB dongle installed, you setup the "Signing" section of your app in Visual Studio to reference the correct certificate.
  2. Right-click your project and click Build (or Rebuild to be safe) and you will have to sign using the dongle.
  3. Now, right-click the project and pick Properties
  4. Inside Properties go to Signing and confirm you have the correct certificate selected. If you skip this step, the app won't install.
  5. Still inside Properties go to Publish and make sure to set your publishing location and installation folders. I use Amazon S3 for the installation folder.
  6. Click Publish Now. It will ask you to sign again.

Now, you would think at this point you'd be done... but you aren't.

  1. So what you need next is a .p12 certificate. I contacted DigiCert support and they were able to give me one for free (prob just for a year) since I was having so many problems. This is different than the EV certificate.
  2. After you have the .p12 certificate AND the EV, I run the following batch routine, which signs the setup.exe file TWICE (once with .p12 and then again with the EV) and also pushes up to Amazon S3.

Here's my SignDeploy.bat file:

echo off
cls
echo Signing setup.exe with .p12 Certificate File
"C:\Program Files (x86)\Windows Kits\10\bin\x64\signtool.exe" sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 /f [LOCATION OF P12 FILE] /p [PASSWORD] [LOCATION OF SETUP.EXE]
pause
echo Signing setup.exe with EV Certificate from Store
"C:\Program Files (x86)\Windows Kits\10\bin\x64\signtool.exe" sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 /sha1 [EV HASH FROM DIGICERT] [LOCATION OF SETUP.EXE]
pause
echo Dry run on syncing files up to S3
aws s3 sync [LOCAL DEPLOYMENT FOLDER] [S3 BUCKET AND FOLDER LOCATION] --acl public-read --dryrun
echo  
echo If that worked, it's time to send them up for real.
echo Control-C to stop now, or...
pause
aws s3 sync [LOCAL DEPLOYMENT FOLDER] [S3 BUCKET AND FOLDER LOCATION] --acl public-read
pause

After all this (I think you end up typing your EV certificate password 3 times total) a user who downloads setup.exe from the specified location (must be the same as indicated in your app) will be able to install and run your VSTO application.

There are other problems we have run into along the way with the installation process on the client side, but using the above process solves the issue with signing.

I won't pretend to understand why this needs signed so many times, nor does it make sense that this doesn't all work smoothly from inside Visual Studio. DigiCert tried to have me use Build Events to do this, but it doesn't work b/c those processes run on either side of the BUILD not the PUBLISH. What we'd need are Publish Events which I don't think exist.

I have explored the idea of a longer more involved command-line process using MsBuild.exe, but it's difficult to do the Automatically increment revision with each release part that way.

Maybe someone here has an idea how to set that up. My process is still a bit manual, but it seems to work reliably at this point so I'm not inclined to mess with it too much.