7

I have a VSTO program in Visual Studio 2017. In order to make the install process run more smoothly when I publish via ClickOnce and host the files on the web, I bought an EV Certificate from DigiCert.

This is what I bought - https://www.digicert.com/code-signing/ev-code-signing/

So I waited a couple days, got my USB token, set everything up and now when I sign the app with my fancy new certificate... the install flat-out fails.

The error the user gets is: Customized Functionality in this application will not work because the certificate used to sign the deployment manifest for AppName or its location is not trusted. Contact your administrator for further assistance.

I contacted DigiCert for tech support and they basically said that this is an error with Visual Studio 2017 and the Operating System.

I then called Entrust to see if they could confirm since they also have the EV Certificates: https://www.entrust.com/code-signing-certificates/#ev-code-signing-certificates

Turns out I guess until you buy one, they can't answer the question. They just kindof say "buy it and try it and if it doesn't work we'll give you your money back."

How is it possible that nobody knows how to sign an install from Visual Studio?

I would love to be able to sign this install and get it to work.

gotmike
  • 1,515
  • 4
  • 20
  • 44

2 Answers2

8

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.

gotmike
  • 1,515
  • 4
  • 20
  • 44
  • 1
    Having spoken with GlobalSign, they say: their EV certificates can only be issued under PKCS#11 format, which is incompatible with the .pfx file required by VS. Is it the problem you resolved? Or should I expect to have a different problem than yours right at the step 1 you mention above (or maybe step 7?)? – Ama Jul 29 '19 at 11:26
  • 1
    @Ama -- this was a couple years ago. i am not sure if they have changed anything, but i still use the same `.bat` file to deploy my code and i have updated the certs since then so other than changing the signatures and cert targets, the same logic still works (for me). – gotmike Aug 29 '19 at 10:28
  • 1
    Looks like the incompatibility between SHA2 signature and ClickOnce, whilst Authenticode requires SHA2 signatures was the reason you needed to sign the files separately, and via a .p12. Have you tried the procedure integrated in VS 2017/2019? it might just work fine by now.. – Ama Nov 01 '19 at 13:59
1

What to sign and why

  1. Visual Studio relies on SignTool to sign the Setup.exe of the App it builds. This is because Windows will run an integrity check when installing a new app. This is Authenticode technology, for any software run via Windows.
  2. However, because we are under the context of a VSTO, and because Microsoft Office verifies the integrity of COM Add-Ins each time they are called, you also need to sign your project DLL via the Manifest Generation and Editing Tool. This is Mage technology, specific for deployment manifests such as theses relied upon by ClickOnce.
  3. Because we are under the context of a ClickOnce deployment, you also need to sign the deployment manifest, which guarantees the link to the remote location which contains the installation files is legit. This is Mage technology.
  4. And Finally, ClickOnce also requires to sign the application manifest; that is, the listing of all the files included in the release (setup.exe / main DLL, and others requisites such as supporting DLLs). This is Mage technology.

Worth noting

In the past, in terms of security Authenticode stepped ahead faster than Mage: Authenticode required to sign SHA256 digests, whilst Mage only supported SHA1 digests. Hence the requirement to sometimes sign the same file twice. See full topic here.

This however, seems to be a problem of the past.


How to proceed

I am using an EV code signing dongle provided by Sectigo. All I have to do to sign and publish the solution via ClickOnce is:

  1. Run SafeNet Authentication Client Tools
  2. Plug the dongle and make sure it appears in the SafeNet client
  3. In Visual Studio (VS 2017 here), go to Project / Properties / Signing and choose [Select from Store...]
  4. Publish the solution (Publish Tab, click [Publish Now])
  5. SafeNet will ask you for the Signing Certificate password. Note sometime you may have to type your password twice, not sure why.
  6. The Solution is fully published and all relevant documents mentioned above are signed.
Community
  • 1
  • 1
Ama
  • 1,373
  • 10
  • 24
  • 1
    curious to hear how it goes. the `.bat` routine above is still working for me, but i do think it is overkill. i actually use two separate certs, one which is a `.p12` and one that is the EV on the USB dongle. u can see reference to both in the `.bat` routine. i think the `.p12` is unnecessary, but since it seems to work perfectly every time, i haven't wanted to poke the bear at the zoo. kudos to u for going down the rabbit hole! – gotmike Oct 17 '19 at 19:54
  • 1
    This post sounds promising, but won't be able to try it until next week I am afraid. https://www.codeproject.com/Tips/1225324/How-to-Sign-ClickOnce-Deployment-if-ClickOnce-Code – Ama Oct 18 '19 at 10:15
  • 1
    See my update. Which might be disappointing for you as in the end everything worked fine for me. However, I am soon going to include an obfuscation step in the mix, and get the feeling I might then have to manually sign the files through post build events. So I might come back and update this post again :D – Ama Nov 01 '19 at 13:54
  • i get the same "sometimes you have to type password twice" thing. i also don't know why it does this. post-build events weren't what i needed, i needed post-publish events which is how i ended up with the `.bat` file which signs the published files and preps for distribution. i don't understand why VS has post-build but not post-publish events. – gotmike Feb 10 '20 at 18:05
  • On top of my head, in post build events you can specify at what stage of the build you wish to execute your routine. So if you pick the end of the build, it's effectively a post-publish? – Ama Feb 10 '20 at 20:18
  • I guess the password is needed twice because the signing certificate is opened by SignTool, and then by Mage. – Ama Feb 10 '20 at 22:28