1. なぜ署名なしの exe は止まるのか — 「誤検知」と「実行制御」は別問題
まず、日本語の解説記事でもっとも混ざっている点を分けます。自作 exe が配布先で止まる原因は 1 つではなく、性格の違う 3 つの門があり、どの門で止まったかによって打つ手がまったく変わります。
門 A はウイルス対策ソフトの検知です。PyInstaller 製 exe が「未知のプログラム」として警告され、最悪の場合は自動削除される現象で、主因は自分のコードではなく、世界中の PyInstaller 製 exe が同じブートローダを共有していることにあります(PyInstaller の記事の 6.2 節で扱っています)。
門 B は SmartScreen。許可リスト方式ではなく評判で判断し、信号は発行元の評判(署名の有無・発行元証明書が既知か)とファイルハッシュの評判(ダウンロード実績)の 2 つだと Microsoft は説明しています。門 C は実行制御——App Control for Business(旧 WDAC)とその上の Smart App Control です。門 B と決定的に違うのは、ダウンロードしたファイルに限らず、すべての実行可能ファイルに署名チェックが及ぶ点で、共有フォルダの exe でも USB メモリの exe でも判定されます。
ここが本記事の出発点です。「ウイルス対策の除外リストに入れてもらったのに、まだ動かない」は、門 A を開けたのに門 C が閉じている状態です。日本語の Q&A サイトには、この 2 つが混ざったまま「除外設定を追加してもらいましょう」で終わる回答が少なくありません。
| 症状 | 止めている門 | コード署名は効くか |
|---|---|---|
| exe がいつの間にか消えている/隔離された | 門 A(ウイルス対策) | 直接は効かない。除外登録が本筋 |
| 「Windows によって PC が保護されました」+「詳細情報」→「実行」で動く | 門 B(SmartScreen) | 公的証明書なら効く。ただし即効ではない |
| 「組織のポリシーによりブロックされました」で実行ボタンがない | 門 C(実行制御) | 条件付き。信頼されたルートの CA 発行証明書が必要 |
| ダブルクリックしても何も起きない/一瞬で閉じる | どれでもない(アプリ側の問題) | 効かない。起動しない原因の切り分けへ |
なお「組織のポリシーによりブロックされました」系の文言が出たからといって、会社が管理している端末とは限りません。Smart App Control は個人用 PC でも同系統の文言を出します。実際、本記事の検証に使った Windows 11 環境(会社支給の端末ではありません)でも同種のブロックが発生しています(5 章)。本記事では、この系統のブロック表示を「組織のポリシーによりブロックされました」と総称しています。実際の表示文言は機能や言語環境によって異なり、当サイトの検証環境で観測した表示は英語の「An Application Control policy has blocked this file」でした(5.1)。文言が違っても、実行ボタンがなく exe も削除されないなら門 C です。
2. 選択肢は 5 つ — 先に「どれを選ぶか」を決める
手を動かす前に選択肢を並べます。ここを飛ばして「とりあえず自己署名で」と進むと、解決しない問題に時間を溶かします。
いちばん誤解されているのが EV 証明書です。「EV を買えば SmartScreen 警告が即座に消える」という説明が日英とも大量に残っていますが、Microsoft は開発者向けドキュメントでこの挙動は 2024 年に廃止されたと明言し、「SmartScreen 警告を避けることだけを目的に EV の割増料金を払うことは正当化できない」という主旨まで書いています。EV を検討するなら、SmartScreen 以外の理由(カーネルモードドライバの署名要件など)があるかを先に確認してください。
もう 1 つの前提として、署名済みでも新しく作ったバイナリは評判が溜まるまで SmartScreen 警告が出ることがあると Microsoft は明記しています。社内数十台に配る現場ツールでは、評判が付くのに必要なダウンロード数を満たすこと自体が現実的ではありません。社内配布で「公的証明書を買って SmartScreen を黙らせる」戦略は、費用に対して効果が読めないということです。
もう 1 点、公的証明書(OV / EV)を買う前提は 2023 年と 2026 年の 2 回にわたって変わりました。秘密鍵を .pfx ファイルで持ち歩く運用は認められなくなり、最大有効期間も 39 か月から 460 日へ短縮されています。制度変更の中身と発効日、費用の相場、審査に要する日数、Azure Artifact Signing、タイムスタンプの扱いはコード署名証明書の費用と 2026 年の制度変更にまとめたので、まだ買う段階にない方は後回しで構いません。ここから先は、1 円も払わずに試せる範囲を実際に動かします。
3. Windows SDK なしで署名する — 自己署名証明書と PowerShell(実測手順)
この章と 5 章を実行する前に: 証明書ストアの操作は端末のセキュリティ設定に触れる行為です。会社支給の PC では、社内の IT 利用規程・情報システム部門の承認の範囲内で行ってください。実測は個人の Windows 11 環境で行ったもので、業務端末での実施を勧めるものではありません。
3.1 signtool は標準では入っていない
署名の解説記事はほぼ signtool.exe を前提に書かれています。ただし signtool は Windows SDK の一部で、Windows に最初から入っているものではありません。当サイトの検証環境でも、where signtool は該当なし、C:\Program Files と C:\Program Files (x86) を再帰検索しても 1 件も見つかりませんでした。
そこで本記事は、Windows に最初から入っている PowerShell だけで完結する経路を主軸にします。Set-AuthenticodeSignature は Windows 専用ですが、SIP(Subject Interface Package=その形式のどこに署名を埋め込み、どこを検証するかを Windows に教える仕組み)に対応していれば exe でも dll でも署名できます。開発ツールの導入申請が要らないぶん、現場では話が早いはずです。signtool は 6 章へ。
3.2 自己署名のコード署名証明書を作る
New-SelfSignedCertificate の公式ドキュメントの説明は「テスト目的で新しい自己署名証明書を作成する」です。この位置づけは最初に押さえてください。
$cert = New-SelfSignedCertificate `
-Type CodeSigningCert `
-Subject "CN=Genbapy Test Org" `
-CertStoreLocation "Cert:\CurrentUser\My" `
-KeyAlgorithm RSA -KeyLength 3072 `
-HashAlgorithm SHA256 `
-NotAfter (Get-Date).AddYears(1)
-Type CodeSigningCert は必須です。既定値は SSLServerAuthentication なので、忘れるとコード署名に使えない証明書ができます。作成した証明書を実測で確認した結果です。
| 項目 | 実測値(当サイト検証環境) | 備考 |
|---|---|---|
| 拡張キー使用法(EKU=この証明書を何の用途に使ってよいかの指定) | コード署名 1.3.6.1.5.5.7.3.3 | -Type CodeSigningCert の効果 |
| 鍵長 | 3072 bit | -KeyLength の指定どおり |
| Subject / Issuer | どちらも CN=Genbapy Test Org | 一致している=自己署名 |
| NotBefore | 作成時刻の 10 分前 | 公式ドキュメントの既定値どおり |
| NotAfter | 作成の 1 年後 | 既定も 1 年。-NotAfter で変更可 |
| 秘密鍵 | あり(HasPrivateKey = True) | これが無いと署名できない |
NotBefore が「作成の 10 分前」なのは、端末間の時刻ずれで直後の署名が無効判定されるのを防ぐためです。作成済みの証明書は次で一覧できます(秘密鍵を持つコード署名証明書だけが返ります)。
Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Select-Object Thumbprint, Subject, NotAfter
社内 PKI を意識するなら -Signer も覚えておいてください。既存の証明書で新しい証明書に署名できるので、社内ルート CA → 中間 CA → コード署名証明書のチェーンを自分で組み立てられます。情シスが既に社内 CA を運用しているなら、そこに乗せてもらうほうが配布の話は早く進みます。
3.3 署名する — Windows PowerShell 5.1 の既定は SHA-1 だった
署名はコマンド 1 行ですが、ここに現場で踏みやすい落とし穴があります。
# 実際に配布する exe には -TimestampServer http://timestamp.digicert.com も付ける
# (付けないと、証明書の期限が切れた時点で署名が無効と判定される)
Set-AuthenticodeSignature -FilePath .\SampleTool.exe -Certificate $cert -HashAlgorithm SHA256
-HashAlgorithm の既定値は公式ドキュメントによると PowerShell 7.3 以降は SHA256、それ以前は SHA1。Windows 11 に最初から入っているのは Windows PowerShell 5.1 なので、何も指定せずに実行すると SHA-1 で署名されます。
これを実測しました。同じ exe を 2 つコピーし、片方は -HashAlgorithm を指定せず、もう片方は SHA256 を指定して署名したうえで、PE ファイルの証明書テーブル(データディレクトリの 5 番目)を切り出し、SignedData に含まれるダイジェストアルゴリズムの OID を数えた結果です。
| 署名方法 | sha1 の OID (1.3.14.3.2.26) | sha256 の OID (2.16.840.1.101.3.4.2.1) | 証明書テーブルのサイズ |
|---|---|---|---|
-HashAlgorithm 省略 | 3 回出現 | 0 回 | 1,760 バイト |
-HashAlgorithm SHA256 | 0 回 | 3 回出現 | 1,800 バイト |
署名対象は最小構成の --onefile ビルド(7,284,710 バイト)。実測環境は記事末尾に記載。
SHA-1 は署名用ハッシュとしては退役した扱いで、Microsoft も signtool のドキュメントで SHA256 を推奨しています。PowerShell で署名するなら -HashAlgorithm SHA256 を毎回書く、が結論です。指定を忘れても例外は出ず見た目には署名済みになるので、気付かないまま SHA-1 署名の exe を配ってしまいます。なお署名するとファイルサイズは増え、実測では SHA-1 署名で +1,762 バイト、SHA-256 署名で +1,802 バイトでした。
4. 署名して何が変わったか — 署名前後の実測
ここからが本記事の中心です。署名した結果何が変わって何が変わらなかったのかを、検証環境で測った範囲で並べます。
4.1 署名の状態を読む — UnknownError は失敗ではない
Get-AuthenticodeSignature の Status は、慣れないと解釈を誤ります。実測で観測した 4 状態です。
| Status | SignatureType | 意味(実測時の状況) |
|---|---|---|
NotSigned | None | 署名されていない。ビルド直後の PyInstaller 製 exe はこれ |
UnknownError | Authenticode | 署名は付いているが、信頼されたルートに繋がらない。自己署名だとこうなる |
HashMismatch | Authenticode | 署名後にファイルが改変された |
Valid | Authenticode | 署名が有効で、信頼されたルートまで検証できた |
自己署名の場合、StatusMessage は「A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider」(信頼されていないルート証明書でチェーンが終わった)でした。署名処理そのものは成功しており、「この端末はこの発行元を信頼していない」と言われているだけです。ここを「署名に失敗した」と読むと、原因を延々と探すことになります。
HashMismatch も実測しました。SHA-256 署名した exe を 1 バイト書き換えると Status が HashMismatch に変わります。署名後にアイコンを差し替える、バージョン情報を書き換える、UPX で圧縮するといった後処理をすると署名は壊れます。署名は必ず最後の工程に置いてください。
4.2 署名した onefile の exe はちゃんと起動する
--onefile の exe には、末尾に PyInstaller の PKG アーカイブが追記されています。Authenticode の署名も PE の末尾に証明書テーブルとして追記されるので、末尾に追記するものが 2 つ重なって壊れるのではないかという懸念は当然出てきます。
実測では問題なく起動しました。署名前の exe が 7,284,710 バイト、証明書テーブルはオフセット 7,284,712(8 バイト境界)から 1,800 バイト。PKG アーカイブの後ろに証明書テーブルが付くので、ブートローダは自分のアーカイブを正しく展開できていました。署名済み exe でも sys._MEIPASS は設定され、通常どおり動作します。
onedir でビルドした exe も起動を確認できました。「署名すると PyInstaller の exe が壊れる」という心配は、検証環境では再現しませんでした。ただし別の onedir ビルドでは署名後の実行が拒否される事象も起きており、これは署名の破損ではなく 5.1 の実行制御によるブロックです(5.1 の集計には含めていません)。「署名したのに動かない」ときは、署名の破損か実行制御かを先に切り分けてください——前者なら Get-AuthenticodeSignature が HashMismatch を返し、後者なら署名状態は正常のまま実行だけが拒否されます。
4.3 期限切れ証明書では、署名が「静かに」書き込まれない
CI に組み込む人には、この実測がいちばん役に立つはずです。有効期限切れの自己署名証明書(NotAfter を作成日の前日に設定)で署名した結果です。
Set-AuthenticodeSignatureは例外を投げませんでした- 戻り値の
StatusはUnknownError、StatusMessageは「A certificate chain could not be built to a trusted root authority」 - その後
Get-AuthenticodeSignatureで確認するとNotSigned - PE を解析すると証明書テーブルのサイズは 0。ファイルサイズも 1 バイトも変わっていない
つまり署名は 1 バイトも書き込まれていないのに、スクリプトはエラーで止まりません。戻り値を捨てているビルドスクリプトからは、無署名の exe がそのまま配布物として出ていきます。対策は単純で、戻り値の Status を毎回検査することです。
$r = Set-AuthenticodeSignature -FilePath .\SampleTool.exe -Certificate $cert -HashAlgorithm SHA256
if ($r.Status -ne 'Valid' -and $r.Status -ne 'UnknownError') {
throw "署名に失敗しました: $($r.Status) / $($r.StatusMessage)"
}
if ((Get-AuthenticodeSignature .\SampleTool.exe).SignatureType -ne 'Authenticode') {
throw "署名が書き込まれていません"
}
if ($null -eq (Get-AuthenticodeSignature .\SampleTool.exe).TimeStamperCertificate) {
throw "タイムスタンプが付いていません" # 配布用ビルドでのみ有効にする
}
自己署名の間は UnknownError が正常系なので許容しています。公的証明書に切り替えたら Valid のみを成功とするのが本来の形です。最後の TimeStamperCertificate の検査は、-TimestampServer を付けて配布用に署名するビルドでだけ有効にしてください(本記事の検証は外部サービスへリクエストしない方針のため、タイムスタンプなしで署名しています)。
signtool 側にも似た罠があります。終了コードは 0(成功)・1(失敗)・2(警告付きで完了)の 3 種類で、タイムスタンプの取得に失敗しても警告止まりの 2 になります。CI に組み込むなら 0 のみを成功として扱ってください(当サイトでは未実測。公式ドキュメントに基づく整理です)。
5. 自己署名では解決しないこと — 実行制御と内部 DLL(実測)
ここが本記事でいちばん書きたかった章です。署名すれば止まらなくなる、という期待は実測で裏切られました。
5.1 実行制御のブロックは、自己署名では消えなかった
検証環境の状態を先に開示します。レジストリ HKLM\SYSTEM\CurrentControlSet\Control\CI\Policy の VerifiedAndReputablePolicyState は 1(強制モード)——Smart App Control が有効な状態でした(読み取りのみで変更はしていません)。
この環境で、内容の異なる PyInstaller 製 onefile exe を 9 本ビルドして無署名のまま実行し、うち 6 本は自己署名(SHA-256)して再実行し、署名前後を比較しました(残る 3 本は無署名の実行のみ。別に SHA-256 署名だけの 1 本と SHA-1 署名の 1 本があり、計 11 本)。署名するとハッシュが変わるので、無署名版と署名版は別ファイル扱いです。集計はすべて onefile ビルドが対象で、4.2 の onedir の事象は含めていません。
| 条件 | 試した exe の数 (すべて異なるハッシュ) | ブロックされた数 | 実行できた数 |
|---|---|---|---|
| 無署名 | 9 | 3 | 6 |
| 自己署名(SHA-256) | 7 | 3 | 4 |
| 自己署名(SHA-1) | 1 | 1 | 0 |
SHA-1 の行は 1 本しか試していないので、「SHA-1 だからブロックされた」とは言えません。件数の併記です。
ブロック時のメッセージは「An Application Control policy has blocked this file」。exe は削除されず実行だけが拒否されます。署名前後を試せた 6 本の変化は次のとおりです。
- 改善したもの 2 本: 無署名ではブロックされたのに、自己署名したら実行できた
- 悪化したもの 2 本: 無署名では実行できたのに、自己署名したらブロックされた
- 変化なし 2 本: 署名の前後とも実行できた 1 本と、前後ともブロックされた 1 本
- 同じハッシュに対する判定は再現しました(2 回繰り返して同じ結果)
読み取れる結論は「自己署名はこのブロックを解決しない」です。改善も悪化もあり、署名の有無と結果が対応していません。むしろ署名するとハッシュが変わるため判定はゼロからやり直しになる副作用のほうが、実務的な影響は大きいはずです。
この観測は Microsoft 公式の説明とも矛盾しません。Smart App Control のドキュメントは「app intelligence が予測できない場合、Trusted Root Program 内の CA が発行した証明書で署名されていれば実行を許可する」と書いており、自己署名はこの条件を満たしません。SmartScreen の比較表でも、自己署名は「無署名と同じ挙動」です。
この結果の限界を明示します。上記は 1 台の Windows 11 環境(Smart App Control が強制モード)での観測で、app intelligence はクラウド側のサービスですから、同じ exe でも時期や環境で結果は変わりえます。「Windows ではこうなる」と一般化できるデータではありません。言えるのは「自己署名すればブロックが消える、という期待には根拠がなかった」の 1 点だけです。
なお Microsoft の公式情報は食い違っています。開発者向けの Microsoft Learn は 2026 年 8 月 31 日時点でも「Smart App Control はクリーンインストール時にしか有効にできない」と書きますが、Microsoft Support の KB5079391(2026 年 3 月 26 日公開)は「クリーンインストールなしでオン/オフできる」と明記しています。ただし「困ったら切ればいい」という話ではありません。会社支給の PC で切るのは情シスの管轄です。自分の判断で無効化しないでください。
5.2 exe に署名しても、内部の DLL には署名が及ばない
PyInstaller には 2022 年 4 月に起票され、2026 年 8 月 31 日時点でまだ open の Issue #6747「Windows: Sign files for Smart App Control」があります。争点は--onefile の exe だけ署名すれば足りるのか、実行時に展開される内部 DLL も署名しなければならないのかで、結論は出ていません。
署名済みの onefile exe を実行し、展開先(sys._MEIPASS が指す %TEMP%\_MEIxxxxxx)の全ファイルの署名状態を調べた結果です(pywin32 を import するアプリ)。
| 展開されたファイル | 署名状態 | 署名者 |
|---|---|---|
python312.dll / libcrypto-3.dll | Valid | Python Software Foundation |
_socket.pyd / _hashlib.pyd など標準ライブラリの 7 ファイル | Valid | Python Software Foundation |
VCRUNTIME140.dll / VCRUNTIME140_1.dll | Valid | Microsoft Windows Software Compatibility Publisher |
pywintypes312.dll | NotSigned | (署名なし) |
win32api.pyd | NotSigned | (署名なし) |
base_library.zip | UnknownError | (Authenticode の対象形式ではない) |
読み取れることは 3 つ。
- exe に署名しても、展開される内部ファイルには署名は付きません。署名は exe 本体に対してだけ行われます
- CPython 由来の DLL / pyd には、PyInstaller が何もしなくても PSF の署名が付いています。Issue #6747 が心配した「内部が全部未署名」ではありません
- ただしサードパーティ製 wheel 由来のバイナリには未署名のものがあります。今回は
pywin32のpywintypes312.dllとwin32api.pydで、issue の投稿者が挙げたpywintypes310.dllのバージョン違いです
onedir の _internal フォルダでも同じ傾向で、標準ライブラリ由来はすべて Valid、base_library.zip のみ Authenticode の対象外でした。
実務上の含意はこうです。実行制御が厳しい環境に配るなら、「exe を 1 つ署名すれば配布物全体が署名済みになる」とは考えないでください。全部に署名するなら onedir でビルドして各ファイルに署名を回すことになります。その運用コストと、情シスに配置パスやハッシュで許可登録してもらうコストを比べて決めてください。当サイトの見立てでは、社内数十台規模なら後者のほうが早く終わります。
5.3 それでも自己署名には正当な使い道がある
ここまで否定的な結果が続きましたが、自己署名(および社内 PKI)が無意味なわけではありません。Microsoft の開発者向けドキュメントは適切な用途を 2 つ挙げています。
- ローカルでの開発・テスト
- 情報システム部門が Intune やグループポリシーで「信頼されたルート証明機関」として証明書を配る、企業内での配布(管理下の端末ならサイレントインストールも可能)
同じドキュメントは「自己署名証明書は Windows に既定で信頼されず、手動でルートに入れていないユーザーには強い SmartScreen ブロックを引き起こすため公開配布には不適」とも書いています。「社内の管理された端末に配る」条件が満たされて初めて成立する選択肢で、閉域網・情シス管理下で動く製造業の現場ツールは当てはまることが多いはずです。
ただし、この方式は端末のセキュリティ境界を広げる操作を伴います。ルートストアに入れるとは、その証明書で署名されたものを OS が無条件に信頼するということです。個人の判断で業務端末に入れる話ではなく、情シスが管理する仕組みとして設計すべきものです。当サイトも、登録後に Status が Valid へ変わることの確認は実施していません。端末の信頼設定を変える操作にあたるため、意図的に手を出していない領域です。
相談前に、鍵の管理者は誰か(退職時にどう引き継ぐか)、署名するのは誰か(個人 PC に鍵を置く運用は最初に否定されます)、鍵が漏れたときの失効手順の 3 点を決めてください。内製化の合意形成と同じで、技術より段取りの問題です。決めた内容はそのまま依頼文になります。次の 4 行を埋めて持ち込むと、情シス側は可否をその場で判断できます(ルートストアへの登録は当サイトで実施していないため、依頼が通ったあとの動作は未確認です)。
- この証明書(拇印= Thumbprint を添付します)を「信頼されたルート証明機関」ストアへ、Intune またはグループポリシーで配布してください
- 配布対象は ○○ 部の △ 台、対象アプリは □□(用途・実行頻度)です
- 証明書の有効期限は YYYY-MM-DD です。更新時は再配布が必要になります
- 鍵の保管者は □□、署名を行うのは □□、失効を依頼する連絡先は □□ です
6. signtool を使う場合(公式ドキュメント準拠・当サイト未実測)
この章の内容は当サイトでは実行していません(検証環境に signtool.exe が存在しなかったためです)。以下は Microsoft 公式ドキュメントと CA 公式手順の整理で、実測値ではありません。
6.1 /fd と /td は省略できない
ここが、古い日本語記事をそのまま実行すると詰まる箇所です。公式ドキュメントは SDK・HLK・WDK・ADK のビルド 20236 以降ではダイジェストアルゴリズムの指定が必要とし、sign には /fd、タイムスタンプには /td が要る(いずれも SHA256 推奨)と書いています。指定しない場合、当初は警告(終了コード 0)だったものが後のバージョンではエラーになる、とも書かれています。
これが効いてくるのが PyInstaller 公式 Wiki の「Recipe Win Code Signing」です。.spec から subprocess.call() で signtool を呼ぶ方式自体は今でも有効ですが、掲載コマンドは SIGNTOOL.EXE /F yourkey.pfx /P <password> /T <url> <file.exe> という形で /fd も /td も付いていません。.pfx に秘密鍵を持つ前提も、2023 年 6 月の HSM 必須化以降の公的証明書では成立しません(秘密鍵の HSM 必須化(2023 年 6 月)=費用記事の 1 章)。現行 SDK と現行の証明書でそのまま通るかは未検証ですが、コピーする前にコマンド形式を疑ってください。
6.2 検証時は /pa を付ける
signtool verify の /pa は「既定の認証検証ポリシーを使う」という意味で、指定しないと Windows ドライバ検証ポリシーで検証されます。一般的な exe には実質必須で、付けずに「検証に失敗する」と悩むパターンがあります。よく使うオプションを表にまとめました(出典は Microsoft Learn — SignTool)。
| オプション | 意味 |
|---|---|
/fd <alg> | ファイルダイジェストアルゴリズム(省略不可) |
/tr <URL> / /td <alg> | RFC 3161 タイムスタンプサーバーとそのダイジェストアルゴリズム。/t とは同時指定できない |
/f <file> / /p <pw> | PFX ファイルとそのパスワード(旧型証明書向け) |
/a / /n <SubjectName> | 証明書ストアから自動選択 / Subject 名で選択(トークン内証明書はこちら) |
/sm / /as | マシンストアを使う / 署名を追加する(デュアル署名) |
/dlib <DLL> | 外部 DLL に digest 署名を委譲する。Azure Artifact Signing はこの方式 |
verify /pa | 既定の認証検証ポリシーで検証する(一般 exe では実質必須) |
HSM 必須化後の証明書(USB トークンやクラウド HSM に鍵がある形)では、/f でファイルを指定せず、トークン内の証明書を /a /n "Common Name" で選びます。GMOグローバルサインの手順ページも、新型証明書と旧型証明書でコマンド例を分けています。
7. 現場配布の意思決定フロー — どの規模なら何を選ぶか
ここまでを、配る相手と管理体制から逆算する形にまとめます。
どのルートでも先にやることは同じです。署名より効果が読める順に並べます。
- 止めている門を、表示されたメッセージから確定させる(1 章の表)
- 更新のたびに許可を取り直す必要があるかを、作り込む前に情シスへ確認する
- PyInstaller を最新に保ち
--noupxを付け、ハッシュ・配置パス・用途を添えて申請する
この図の左半分(社内配布)では、証明書の購入は主戦場になりません。数十台に配るツールに証明書を買っても SmartScreen の評判は溜まらず、実行制御の許可登録は結局必要です。お金を払っても、情シスとの会話は省略できません。
逆に、証明書に投資する価値が出るのは次の 3 つです。複数拠点・複数アプリに継続的に配る場合——証明書単位で許可が出れば、アプリごと・更新ごとの申請が消えます。社外(取引先・顧客)に渡す場合——相手の情シスに許可登録を依頼できないので、署名以外に手がありません。ダウンロード配布する場合——Mark of the Web(Windows が付ける「出所」の印)で SmartScreen の対象になり、評判を積む母数が確保できるなら効果が出ます。当てはまるなら、証明書の費用相場と購入の段取りを確認してから稟議に進んでください。
常駐サービスも判断は同じです。Windows サービスとして動かす exe も署名の対象で、登録・起動に管理者権限が要るため、情シスとの調整はいずれにせよ必要です。
8. おわりに
コード署名は「やれば警告が消える魔法」ではありませんでした。実測で確定できたのは次のことです。
- Windows SDK が無くても、PowerShell だけで自己署名証明書の作成から署名・検証まで完結する
- Windows PowerShell 5.1 の
Set-AuthenticodeSignatureは、既定で SHA-1 署名になる。-HashAlgorithm SHA256は毎回書く - 署名済みの
--onefileexe は正常に起動する。ただし期限切れ証明書では例外も出ないまま署名が書き込まれないので、戻り値のStatusを必ず検査する - 自己署名では実行制御のブロックは解消しなかった。改善も悪化もあり、署名の有無と結果が対応していない
- exe に署名しても、展開される内部ファイルには署名が及ばない。CPython 由来の DLL は PSF 署名済みだが、サードパーティ wheel 由来には未署名のものがある
確認できていないことも明示します。signtool の挙動は検証環境に Windows SDK が無いためすべて未実測で、公式ドキュメントの記載として紹介しました。ルートストアへ登録した後に検証が通るかは、端末の信頼設定を変える操作なので実施していません。公開 TSA からのタイムスタンプ取得、SmartScreen 警告文言の署名前後比較、公的証明書と Azure Artifact Signing の実利用も未実施です。
現場に向けた結論はこうです。「配布先で止まった」と言われたら、まずメッセージを読んで、止めている門を確定させてください。門を取り違えたまま証明書を買っても、問題は動きません。社内配布でいちばん効くのは証明書ではなく、更新のたびに許可を取り直す必要があるかを、作り込む前に情シスと合意しておくことです。完成してから配れないと分かるのが、いちばん高くつきます。買う側の検討に進むなら、費用と段取りをコード署名証明書の費用と 2026 年の制度変更にまとめてあります。