How I code signed an Electron app on Windows
Published: 2021-12-14 17:33:17


So you want to distribute your Electron app to Windows users, but when people run it they get a nasty warning “Microsoft Defender SmartScreen prevented an unrecognized app from running” and it shows “Unknown publisher.”

[One way to immediately get rid of this warning is to purchase an Extended Validation (EV) Code Signing certificate](https://stackoverflow.com/a/66582477/1917537). I opted instead for a normal, non-EV Code Signing certificate. A normal Code Signing cert will show the publisher name in the warning instead of “unknown publisher.” However, SmartScreen will still need time to begin trusting my app before it will stop showing the warning altogether. I made that tradeoff to reduce the cost and validation time for my small app.

So here’s how I used electron-builder to sign my Electron app on Windows with a Code Signing certificate. It took three steps:

1. Obtain the certificate
2. Download the certificate
3. Configure electron-builder

## 1. Obtain the certificate

I purchased a Microsoft Authenticode Code Signing Certificate from Sectigo on this website: https://codesigncert.com/codesigning/authenti-codesigning.

To issue the certificate, the certificate vendor needs to either validate you as an individual or validate your business. I opted for business validation. For business validation, your business must be listed in public records that the vendor can look up. Your business phone number has to be listed as well. If the info is not listed, the validation process gets longer and more complicated.

After I purchased the certificate, [codesigncert.com](http://codesigncert.com/) gave me some instructions to kick off the validation process.

1. It had me create a Certificate Signing Request (CSR) with [DigiCert Certificate Utility](https://www.digicert.com/support/tools/certificate-utility-for-windows).
2. I uploaded that CSR (which is just a bunch of text) to the [codesigncert.com](http://codesigncert.com/) website. The info entered into the form on the website has to match what you inputted in the DigiCert tool.
3. Now the certificate vendor will begin the validation process. In my case, it was Sectigo.

[Codesigncert.com](http://codesigncert.com/) provides some info on the validation requirements — address, phone number, public listing, etc. To make my business info plus phone number visible before starting validation, I updated my business profile on [dnb.com](http://dnb.com/). Their customer support crew sent me a couple messages during validation that they needed to validate my business phone number. I called them and directed the operator to my [dnb.com](http://dnb.com/) listing. The operator was then able to validate and issue the certificate. All-in-all the purchase and validation process took a couple weeks.

## 2. Download the certificate

After the certificate is issued, I had to download it *with Internet Explorer* (IE11). Yes, it’s strange, but the certificate only downloads in the correct form with IE. At first I downloaded it with Chrome (my usual browser) but the downloaded file didn’t contain the private key. That tripped me up for a couple hours. Eventually I found that IE is a requirement. Then I followed [the Sectigo tutorial to export the certificate to pfx](https://sectigo.com/knowledge-base/detail/How-to-Export-Your-Code-Signing-Certificate-Windows/kA01N000000zFK0), which electron-builder needs.

## 3. Configure electron-builder

First set the environment variables CSC_LINK and CSC_KEY_PASSWORD.

* CSC_LINK — This should contain the path of the .pfx file you downloaded.
* CSC_PASSWORD — This should have the .pfx password you configured while downloading from IE.

Electron builder will pick those env vars up and sign all the executables in your bundle (including third-part executables in asar.unpacked). I set those in my dot-env file (`.env`) and used the package [dotenv-cli](https://github.com/entropitor/dotenv-cli) to load them in package.json scripts. Here is the package.json script that builds and signs: `dotenv -- cross-env NODE_ENV=production npm run test && npm run prod-build && electron-builder`

And this script builds, signs, and publishes to my Github releases: `dotenv -- electron-builder -p always`

Here’s the relevant electron-builder config that I used:

```
win:
  target:
    - nsis
  signingHashAlgorithms: [ 'sha256' ]
  publisherName: (YOUR BUSINESS NAME HERE)
  signAndEditExecutable: true
  verifyUpdateCodeSignature: true
```

After electron-builder has built and signed your executable, you can verify the signing with DigiCert Util if you want (press the “Check Signature” button).

## Summary

Windows now shows my business name as the publisher in the SmartScreen warning when users run the app. It’s nice to know that my app cannot be tampered with and faulty copies sent to users. According to online materials I’ve seen, the warning should go away altogether once enough people download and run it.

I also code signed the app for MacOS. That was a separate process, and I couldn’t use the cert I bought for Windows. See [How I Sign and Notarize my Electron App on MacOS](https://dev.to/awohletz/how-i-sign-and-notarize-my-electron-app-on-macos-59bb) for details.