前回の投稿では、電子証明書と電子署名について投稿しました。今回は電子署名をする方法について投稿します。
モジュールの電子署名
電子証明書、電子署名、モジュールへの電子署名、コードサイニング証明書(通常の証明書、EV証明書)などについては、前回の投稿で説明しましたので、そちらを参照してください。
今回の投稿では、実際のモジュールへの署名方法についてです。
モジュールへの電子署名に必要なもの
実際にモジュールへ電子署名するには何が必要なのでしょうか?
Windows上での電子署名では以下のものが必要となります。
- コードサイニング用電子証明書 (署名者を証明するもの)
signtool.exe
(電子署名するためのツール)- タイプスタンプサーバー (タイムスタンプ副署名をするため)
それぞれについて説明します。
コードサイニング用電子証明書
コードサイニング証明書については、入手方法も含めて前回の投稿で説明しました。
モジュールファイルに電子署名をするためには、入手した電子証明書を使える状態にする必要があります。
まずは、署名処理を実行しようとするWindows PCに電子証明書(秘密鍵付)をセットアップします。
ハードウェアトークンに電子証明書がある場合は、ハードウェアトークンをUSBポートに接続します。
ファイルとして電子証明書がある場合は、PCにファイルをコピーするか、PCに証明書をインストールします。電子証明書をファイルとしてPC上に保持すると、流出などの問題が発生することがあります。そのため、電子証明書はファイルとしてはPC上に残さない方がよいです。電子証明書はPCにエクスポートできない形でPCにインストールすることをお勧めします。
電子証明書のPCへのインストールは、証明書ファイル(pfxファイル)をダブルクリックでインストールできます。
インストール時に表示されるウィザードの途中(上記の画面)で、エクスポートできない設定をする(「このキーをエクスポート可能にする」をチェックしない)ことにより、エクスポートできないようにインストールが可能です。
また、電子証明書の秘密キーを使うとき(電子署名のときは秘密キーを使います)に、人間による許可を必要とするように設定する(「秘密キーの保護を強力にする」をチェックする)と、悪意のあるプログラムなどが、勝手に電子証明書を使って電子署名されること防ぐことができます。
signtool.exe
signtool.exe
は、電子証明書を使って、モジュールファイルに電子署名をするマイクロソフト社製のツールです。signtool.exe
は、Windows SDKに含まれています。利用するにはWindows SDKをインストールします。なお、signtool.exe
は、実行時にはWindows SDK全体は必要とせず、単体で動作します。そのため、一度Windows SDKをインストールすれば、Windows SDKのインストールフォルダーからそのExeファイルをコピーして利用することもできます。
signtool.exe
は、多くの形式のファイルに署名できますが、2021年1月時点では、nugetパッケージには電子署名できません。そのため、nugetパッケージに電子署名するときは、別のツールを利用します。
タイムスタンプサーバー
モジュールファイルに電子署名をするときは、タイムスタンプ副署名を必ず付与します。これにより、電子署名は将来にわたって有効と判断されます。タイムスタンプ副署名を付与しない場合は、電子署名は、署名時に使用した電子証明書の有効期間でのみ有効と判断されます。
電子署名されたモジュールファイルは、電子証明書の有効期間だけでなく、そのソフトウェアが使われている間は、ずっと使われるものです。電子署名に使用した電子証明書の有効期間でしか電子署名が有効と判断されない場合、電子証明書の有効期間が切れるたびに、モジュールファイルに再署名して再配布する必要があります。電子署名されたモジュールファイルを使う側も、その都度、再配布されたものを再取得して、更新が必要になります。このような状況は、署名する側も、署名されたもモジュールを使う側も避けたいです。
タイムスタンプ副署名を付与することにより、電子署名に使用した電子証明書が電子署名をした時に有効であったことが副署名に記録されます。その結果、電子証明書の有効期間を過ぎても、電子署名は有効と判断されるようになります。
このような理由から、モジュールファイルに電子署名をするときは、必ずタイムスタンプ副署名を付与します。
タイムスタンプ副署名を付与するためには、タイムスタンプサーバーが必要となります。タイムスタンプサーバーは各自で用意するものではなく、電子証明書の認証局で用意されます。
古くから使われていたタイムスタンプサーバーは、以下のVeriSign / Symantecのタイムスタンプサーバーとなります。
TSAタイプ | タイムスタンプサーバーURL |
---|---|
Authenticode | http://timestamp.verisign.com/scripts/timstamp.dll |
RFC 3161 sha1 | http://sha1timestamp.ws.symantec.com/sha1/timestamp |
RFC 3161 sha256 | http://sha256timestamp.ws.symantec.com/sha256/timestamp |
2020年までは、これらのURLを使用して、電子署名時にタイムスタンプ副署名を付与することができました。
ただし、今年(2021年)に入ってから、上記のタイムスタンプサーバーで問題が起きました。そのため以下の新しいサーバーを使う必要があります。詳細は次回の投稿で記載します。
TSAタイプ | タイムスタンプサーバーURL |
---|---|
Authenticode | http://timestamp.digicert.com/?alg=sha1 |
RFC 3161 sha1 | http://timestamp.digicert.com/?alg=sha1 |
RFC 3161 sha256 | http://timestamp.digicert.com/?alg=sha256 |
署名方法
signtool.exeを使った電子署名方法について説明します。
説明を簡素化するために、ここでの説明では、まず、必要なパラメータを環境変数に設定します。その後、その環境変数を使ってsigntool.exeで署名します。実際の署名では、環境変数を経由する必要はなく、signtool.exeの引数として、パラメーターを直接設定することができます。
事前の設定
署名をするモジュールの設定
署名するモジュールの設定をします。
SET SIGN_FILES="c:\test1.exe" "c:\test2.dll"
SET SIGN_DESC=test module
SIGN_FILES
には、電子署名するファイル群を設定します。
SIGN_DESC
には、「署名の説明(モジュールの説明)」を設定します。多くの場合は、アプリ名を設定します。
電子署名するときに「署名の説明」を付与しない方が多くいますが、なるべく付与しましょう。Windows上でも、「署名の説明」が正しく設定されていると、それが利用されることがあるからです。その例の一つが、ユーザーアクセス制御(UAC)の実行の許可をする確認画面です。
上記のファイルプロパティを持つEXEファイルに電子署名したとします。
そのEXEファイルを管理者で実行すると、下記のようなユーザーアクセス制御(UAC)画面(実行の許可を確認する画面)が表示されます。
この絵を見てわかるように、左側の「署名の説明」を署名に付与していない場合は、ユーザーアカウント制御画面には、ファイルのプロパティの「ファイルの説明」、または、「ファイル名」が表示されます。
右側の「署名の説明」を署名に付与している場合は、ユーザーアカウント制御画面には「署名の説明」が表示されます。
そのため、署名時には、「署名の説明」を付与し、また、「署名の説明」にはアプリ名を設定した方がよいと考えます。
使用する電子証明書の設定
署名に使用する電子署名の設定をします。電子証明書をシステムにインストールした場合とファイルとしてコピーした場合で方法が異なります。
システムにインストールした証明書を利用
下記のように使用する電子証明書を設定します。
SET CER_SUBJECT_NAME=nishy software
SET CER_ISSUER_SUBJECT_NAME=COMODO RSA Code Signing CA
SET SELECTED_CERT=/a /n "%CER_SUBJECT_NAME%" /i "%CER_ISSUER_SUBJECT_NAME%"
システムに複数の証明書がインストールされている場合、電子署名時にどれを使えばよいかを判断するための情報を設定します。
CER_SUBJECT_NAME
には、使用する電子証明書のサブジェクト名(CommonName
)を設定します。
CER_ISSUER_SUBJECT_NAME
には、使用する電子証明書の発行者名を設定します。
SELECTED_CERT
には、上記の例のように設定します。上記の設定は、システムにインストールされている電子証明書を自動的に選択する設定です。その選択時の条件として、証明書のサブジェクト名と発行者名を指定しています。
ファイルの証明書を利用
下記のように使用する電子証明書のファイルを設定します。
SET PFX_FILE=c:\abcdef.pfx
SET PWD=abcdef
SET SELECTED_CERT=/f "%PFX_FILE%" /p %PWD%
PFX_FILE
には、証明書ファイルへのファイルパスを設定します。
PWD
には、証明書ファイルを使うときのパスワードを設定します。
SELECTED_CERT
には、上記の例のように設定します。上記の設定は、指定した電子証明書のファイルを指定のパスワードで使用する設定です。
タイムスタンプサーバーの設定
タイムスタンプサーバーは、ハッシュアルゴリズムがSHA1(160ビット)のときと、SHA2-256ビットのときで異なります。
REM 2020年まで利用できたタイムスタンプサーバー
SET TSA_URL=http://timestamp.verisign.com/scripts/timstamp.dll
SET TSA_RFC3161_URL=http://sha256timestamp.ws.symantec.com/sha256/timestamp
上記は、2020年末まで利用できたタイムスタンプサーバーの設定となります。2021年以降は使わないでください。
REM 2019年秋以降から利用できるタイムスタンプサーバー
SET TSA_URL=http://timestamp.digicert.com/?alg=sha1
SET TSA_RFC3161_URL=http://timestamp.digicert.com/?alg=sha256
上記は、2019年秋以降から利用できる(2021年以降も利用可能)タイムスタンプサーバーの設定となります。
電子署名の実行
電子署名では、署名するときに使用するハッシュアルゴリズムを指定します。以前はSHA1(160ビット)が使われていましたが、現在ではSHA2-256ビットを使うことが多いです。
以下に、SHA1での署名方法、SHA2-256ビットでの署名方法、SHA1/SHA2-256ビットの二つを付与した署名方法の例を示します。この署名方法の例は、先に述べた「事前の設定」(環境変数の設定)が終わっていることが前提です。
電子署名(SHA1)
アルゴリズムの指定(/fd
)をsha1
にします。
signtool.exe sign /fd sha1 /t %TSA_URL% %SELECTED_CERT% /d "%SIGN_DESC%" %SIGN_FILES%
電子署名(SHA256)
SHA1の場合と異なるのは、アルゴリズムの指定とタイムスタンプサーバーの指定です。アルゴリズムの指定(/fd
)はsha256
に変更します。また、タイムスタンプサーバーの指定はRFC3161用(/tr)にします。
signtool.exe sign /as /fd sha256 /tr %TSA_RFC3161_URL% %SELECTED_CERT% /d "%SIGN_DESC%" %SIGN_FILES%
電子署名(SHA1/SHA256)
二つのアルゴリズムの署名を一つのモジュールファイルに署名する場合は、下記のように2回署名します。1回目はビット数が小さい方(SHA1)にします。2回目は/as
オプションを追加して署名します。
signtool.exe sign /fd sha1 /t %TSA_URL% %SELECTED_CERT% /d "%SIGN_DESC%" %SIGN_FILES%
signtool.exe sign /as /fd sha256 /tr %TSA_RFC3161_URL% %SELECTED_CERT% /d "%SIGN_DESC%" %SIGN_FILES%
一つのモジュールファイルに二つの署名を付与するのは、過去のWindowsをサポートしたい場合に必須となります。古いWindowsでは、SHA2の電子署名をサポートしておらず、SHA1の署名のみをサポートしていました。これらの古いWindowsでは、二つの署名があった場合、一つ目の署名のみ認識します。その一つ目の署名がSHA1であれば、正しく認識できることになります。
モジュールが対象とするWindowsが、Windows 8.1やWindows 10などの最近のWindowsであれば、SHA2の署名を認識できるため、SHA2のみの署名でも問題ありません。
今回の投稿では、Windows上でsigntool.exeを使った電子署名の実行方法の投稿でした。