[Electron] Windows用アプリにコード署名を行う

Electronで作成したWindows用アプリをインターネット経由で配布した場合に、悪い人に改ざんされておらず安全であることを証明するためにコード署名を付加します。

ここではelectron-builderを使った例になります。macOS用アプリの場合と比べれば、環境変数を設定するだけで終わるので非常に楽ちんです。

コード署名をするとどうなるの?

悪い人にファイルの内容が改ざんされていないかインストール前にOS等がチェックするのが一番の目的ではありますが、macOSの場合は署名がされていないとそもそも起動できない制約がありました。そのあたりWindowsではどうなってるかと言うと、(EVではない)お安いコード署名証明書の場合はぶっちゃけそれほど変わりませんw

厳密にはダウンロードしたインストーラーを起動しようとすると、証明書の内容がユーザへ表示されるようになります。

署名なし

インターネットからファイルをダウンロードしようとしたり、実行しようとするとWindows本体やDefenderが警告を出してくるわけですが、このときのダイアログの「発行元」の欄が「不明」と表示されるため、そこはかとなく怪しい雰囲気を醸し出しています。

保存前実行前

署名あり

ところがコード署名を行うと、証明書内に記載されている情報が表示されるようになります。

保存前実行前

見た目の変化は以上です。

……え、そんだけ?とツッコみたくなりますが、一定数以上インストールされれば表示されなくなるようです。マイクロソフト側で証明書単位でインストール数をカウントし信頼性をチェックしているとのこと。

準備

コード署名証明書

P12(PFX)形式のファイルを用意します。これが無いとはじまりません。この作業で最大の山場はこの証明書の取得です。ここだけめっちゃ面倒ですw

取得までの道のりは以下のページをご覧ください。海外サイトで購入した場合めんどくさいですが99ドル/年で取得できます。 blog.katsubemakito.net

こんな苦労したくないという方は日本語でサポートしてもらえるセクティゴジャパンから2.1万円/年で取得することもできます。日本国内だと恐らくこれが一番お手軽価格だと思われます。

package.jsonに追記

electron-builderの設定を行っているpackage.json内に、コード証明書に記載されている署名者の名前をpublisherNameに追加します。これを書いておかないとビルド時にエラーメッセージが表示されます(ビルド自体は停止しません)

"build": {
  "win": {
    "publisherName": "WINNING SECTION",
    "target": "nsis"
  },

コード署名する

Windowsの場合

作業としては環境変数を設定するだけです。後はelectron-builderさんが自動的に署名してくれます。

環境変数の設定

PowerShellの場合は以下の2つの環境変数を設定します。

PS C:\> $ENV:CSC_LINK="C:\Users\katsube\cert\mycompany.p12"
PS C:\> $ENV:CSC_KEY_PASSWORD="password"
CSC_LINK
コード署名証明書のファイルが置いてあるパス。P12(PFX)形式のファイルを用意。
CSC_KEY_PASSWORD
CSC_LINKで指定した証明書のパスワード

定常的に利用する場合は、タスクバーの検索窓に「環境変数」と入力し「環境変数の編集」から直接登録します。

ビルドしてみる

環境変数の設定が終わったら、あとは何も考えずにいつも通りビルドするだけです。ビルド時のメッセージにsigning関連の行が追加されているのが確認できますね。

PS C:\electron-sample> npx electron-builder --win --x64

> electron-sample-i18n@1.0.0 build-win C:\electron-sample
> electron-builder --win --x64

  • electron-builder  version=22.9.1 os=10.0.18363
  • loaded configuration  file=package.json ("build" field)
  • writing effective config  file=dist\builder-effective-config.yaml
  • packaging       platform=win32 arch=x64 electron=11.1.1 appOutDir=dist\win-unpackeddefault Electron icon is used  reason=application icon is not set
  • signing         file=dist\win-unpacked\electron-sample.exe certificateFile=C:\Users\katsube\cert\mycompany.p12
  • building        target=nsis file=dist\electron-sample Setup 1.0.0.exe archs=x64 oneClick=false perMachine=false
  • signing         file=dist\win-unpacked\resources\elevate.exe certificateFile=C:\Users\katsube\cert\mycompany.p12
  •   Signing NSIS uninstaller  file=dist\__uninstaller-nsis-electron-sample.exe certificateFile=C:\Users\katsube\cert\mycompany.p12
  • signing         file=dist\electron-sample Setup 1.0.0.exe certificateFile=C:\Users\katsube\cert\mycompany.p12
  • building block map  blockMapFile=dist\electron-sample Setup 1.0.0.exe.blockmap

生成されたインストーラーを右クリック→プロパティを開くと「デジタル署名」のタブが追加され、SHA1とSHA256の署名が付加されているのがわかります。

macOSの場合

macOS上でもWindows用アプリにコード署名を付加できます。作業的にもWindowsと同様に環境変数を設定するだけ。こちらもelectron-builderさんが自動的に裏側でやってくれます。

環境変数の設定

Terminal上で以下のコマンドを実行するか、.bashrc.zshrcなどに追記します。変数名の先頭にWIN_を追加するところだけWindowsと違いますね。

$ export WIN_CSC_LINK=~/cert/mycompany.p12 
$ export WIN_CSC_KEY_PASSWORD=password   
WIN_CSC_LINK
コード署名証明書のファイルが置いてあるパス。P12(PFX)形式のファイルを用意。
WIN_CSC_KEY_PASSWORD
WIN_CSC_LINKで指定した証明書のパスワード

ビルドしてみる

環境変数の設定が終わったら、こちらもWindowsと同様にいつも通りビルドするだけです。ここでもビルド時のメッセージにsigning関連の行が追加されているのが確認できます。

$ npx electron-builder --win --x64

> electron-sample@1.0.0 build-win /Users/katsube/electron-sample
> electron-builder --win --x64

  • electron-builder  version=22.9.1 os=19.6.0
  • loaded configuration  file=package.json ("build" field)
  • writing effective config  file=dist/builder-effective-config.yaml
  • packaging       platform=win32 arch=x64 electron=11.1.1 appOutDir=dist/win-unpacked
  • default Electron icon is used  reason=application icon is not set
  • signing         file=dist/win-unpacked/electron-sample.exe certificateFile=/Users/katsube/cert/mycompany.p12
  • building        target=nsis file=dist/electron-sample Setup 1.0.0.exe archs=x64 oneClick=false perMachine=false
  • signing         file=dist/win-unpacked/resources/elevate.exe certificateFile=/Users/katsube/cert/mycompany.p12
  •   Signing NSIS uninstaller  file=dist/__uninstaller-nsis-electron-sample.exe certificateFile=/Users/katsube/cert/mycompany.p12
  • signing         file=dist/electron-sample Setup 1.0.0.exe certificateFile=/Users/katsube/cert/mycompany.p12
  • building block map  blockMapFile=dist/electron-sample Setup 1.0.0.exe.blockmap

トラブルシューティング

SignTool Error: The file is being used by another process.

ビルド中にコード署名の処理に差し掛かったあたりで以下のエラーで強制終了することがあります。

SignTool Error: The file is being used by another process.
SignTool Error: An error occurred while attempting to sign: C:\Users\katsube\Documents\electron-sample-i18n\dist\xxxx.exe

このエラーが出たら試しにWindows DefenderをOFFにしてた状態でもう一度ビルドを実行してください。大抵の場合はこれで解決します。

Defenderを一時的に無効にする

Windows Defenderのリアルタイム保護の機能をOFFにして実行して成功、ONにして失敗すればこいつが犯人です。 support.microsoft.com

Defenderのチェック対象から特定のファイル・フォルダを除外する

ビルド後のファイルが生成されるフォルダをチェック対象から外す手もあります。ただウイルスが紛れ込んだ時のことを考えると最善手とは言い難いかもしれません。 support.microsoft.com

Cannot extract publisher name from code signing certificate

ビルド中に以下のエラーメッセージが出た場合は、冒頭にも書きましたがpackage.jsonにpublisherNameを追記すると出なくなります。

Cannot extract publisher name from code signing certificate: pkcs12: error reading P12 data: asn1: syntax error: indefinite length found (not DER)

こちらはelectron-builderのIssueで以下の通り報告されていました。

It seems to be fixed by setting publisherName in package.json under the win property: "win": { "publisherName": "Click Here Digital Ltd", "target": [ { "target": "nsis", "arch": [ "x64", "ia32" ] } ] }, The publisherName MUST match the common name set in your code signing cert i believe. it seems this is required actually and should have been there before.

※electron-builderのIssueより

参考ページ