コマンドだけ先に見たい方へ(検証の度合いが 2 段階あります。下の PowerShell 3 行は当サイトの検証環境で実行して出力を確認したもの、末尾の signtool 2 行は検証環境に signtool.exe が存在せず未実行で、Microsoft 公式ドキュメントに沿って組み立てたコマンドです)

1. テスト用の自己署名コード署名証明書を作る(組織名は記事用のダミー。3 章)

$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)

2. exe に署名する(-HashAlgorithm SHA256 を省略しないでください。Windows PowerShell 5.1 の既定は SHA-1 になることを実測しました。3.3)。実際に配る exe なら -TimestampServer http://timestamp.digicert.com も必ず足してください——付けないと、証明書の期限が切れた時点で署名が無効と判定されるのが Authenticode の考え方です(この検証挙動も公開 TSA からの取得も、外部サービスへリクエストしない方針のため未実測です。詳細はタイムスタンプの付け忘れと期限切れの扱い=費用記事の 4 章)

Set-AuthenticodeSignature -FilePath .\SampleTool.exe -Certificate $cert -HashAlgorithm SHA256

3. 署名状態を確認する(自己署名なら Status は UnknownError。失敗ではなく「信頼されたルートに繋がらない」という意味です。4 章)

Get-AuthenticodeSignature .\SampleTool.exe | Format-List Status, StatusMessage, SignatureType

4. Windows SDK を入れて signtool を使う場合(当サイトでは未実行。/fd /td は現行 SDK では省略できません。6 章)

signtool sign /fd SHA256 /a /n "Genbapy Test Org" /tr http://timestamp.digicert.com /td SHA256 /v SampleTool.exe
signtool verify /pa /v SampleTool.exe

先に結論だけ知りたい方へ: 自己署名は SmartScreen 警告を消しません(Microsoft 公式が「無署名と同じ挙動」と明記)。当サイトの実測でも、自己署名した exe が実行制御にブロックされる事象は消えませんでした(5 章)。それでも自己署名には正当な使い道があり、情報システム部門が信頼ルートを配れる社内配布がそれです(5.3)。すでに情シスへ相談する段階なら、7 章末の情シス相談チェックリストから読んでも構いません。

この記事の目次

費用相場・審査の所要日数・有効期間 460 日化・Azure Artifact Signing・タイムスタンプは、コード署名証明書の費用と 2026 年の制度変更に分けました。

1. なぜ署名なしの exe は止まるのか — 「誤検知」と「実行制御」は別問題

まず、日本語の解説記事でもっとも混ざっている点を分けます。自作 exe が配布先で止まる原因は 1 つではなく、性格の違う 3 つの門があり、どの門で止まったかによって打つ手がまったく変わります。

コード署名のパイプラインと、配布先 PC にある 3 つの門 証明書を用意し、署名ツールでタイムスタンプ付きの署名を付け、配布する。配布先 PC ではウイルス対策ソフトの検知、SmartScreen の評判判定、App Control の実行制御という 3 つの門がそれぞれ独立に判断する。 図 1: 署名のパイプラインと、配布先 PC にある 3 つの門 1. 証明書を用意 自己署名 / OV / EV / クラウド署名サービス 2. 署名する signtool sign /fd SHA256 + タイムスタンプ /tr /td 3. 配布する 共有フォルダ / メール / 社内配信ツール 署名しても変わらない部分 ビルドのたびにハッシュは 変わる(評判は積み直し) 配布先 PC で 3 つの門が独立に判断する 門 A: ウイルス対策ソフト 「ウイルスを検出しました」 exe が削除・隔離されることがある 署名の効果: 直接は効かない 対処: 情シスに除外登録を依頼 /PyInstaller を最新に保つ 門 B: SmartScreen(評判) 「Windows によって PC が保護されました」 「実行」を押せば動く(企業設定次第で不可) 署名の効果: 公的証明書なら効く ただし即時ではなく評判の蓄積が要る 自己署名は無署名と同じ扱い 門 C: 実行制御(App Control) 「組織のポリシーによりブロックされました」 exe は消えない。実行だけが拒否される 署名の効果: 条件付き 信頼されたルートの CA 発行証明書のみ 対処: 情シスでの許可登録 見分け方(メッセージで判断する) 「ウイルスを検出」= 門 A /「PC が保護されました・実行ボタンがある」= 門 B /「ポリシーによりブロック・実行ボタンがない」= 門 C 門 A にウイルス対策の除外設定を足しても、門 B・門 C は開かない。逆もまた同じ。
図 1: 署名のパイプラインと、配布先 PC にある 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 つ — 先に「どれを選ぶか」を決める

手を動かす前に選択肢を並べます。ここを飛ばして「とりあえず自己署名で」と進むと、解決しない問題に時間を溶かします。

コード署名の選択マップ 配布範囲と管理体制から、自己署名・社内 PKI、OV 証明書、EV 証明書、Azure Artifact Signing、署名しないの 5 つの選択肢を選び分けるマップ。SmartScreen への効果と費用感を併記している。Azure Artifact Signing の対象国は Microsoft 公式ドキュメントの中で記載が食い違っており、日本の法人が対象かどうかは申し込み前の確認を要する。 図 2: 証明書の選択マップ(配布範囲と管理体制で決まる) 誰に配るのか? これが最初の分岐点 社内だけ(情シスが端末を管理している) 社外・不特定多数(取引先・一般公開) 自己署名 / 社内 PKI 費用: 無料 HSM: 不要 SmartScreen: 効果なし 条件: 情シスが Intune / GPO で信頼ルートを配る 公開配布には使えない 署名しない 費用: 無料 HSM: 不要 SmartScreen: 警告が出る 条件: ハッシュや配置パス で許可登録してもらう 更新のたびに再申請 OV 証明書 目安 $150〜300/年 HSM: 必須 SmartScreen: 評判が溜まれば効く 法人の実在確認あり トークン費用は別 EV 証明書 目安 $400+/年 HSM: 必須 SmartScreen: OV と同じ扱い 即時バイパスは 2024 年に廃止済み Azure Artifact Signing 約 $9.99/月から HSM: 不要(内蔵) SmartScreen: OV と同じ 日本の法人は対象(要確認) 個人は米加のみ 3 つの共通事項 (1) どの証明書でも SmartScreen 警告は即座には消えない (2) 署名するとハッシュが変わる (3) 2023 年 6 月以降の公的証明書は秘密鍵をハードウェアに置く必要がある 中小製造業の現場ツールなら まず「社内だけ」に該当するはず。その場合の主戦場は証明書の購入ではなく、情シスとの許可登録の合意形成になる。
図 2: 証明書の選択マップ。費用は Microsoft Learn の比較表に載る 2026 年 8 月 31 日時点の目安(米ドル建て)で、CA や代理店によって変わります。Azure Artifact Signing に(要確認)と付けたのは、Microsoft 公式ドキュメント内で対象国の記載が食い違っているためです(コード署名証明書の費用と 2026 年の制度変更の 3 章)。

いちばん誤解されているのが 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 SHA2560 回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 状態です。

StatusSignatureType意味(実測時の状況)
NotSignedNone署名されていない。ビルド直後の PyInstaller 製 exe はこれ
UnknownErrorAuthenticode署名は付いているが、信頼されたルートに繋がらない。自己署名だとこうなる
HashMismatchAuthenticode署名後にファイルが改変された
ValidAuthenticode署名が有効で、信頼されたルートまで検証できた

自己署名の場合、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 の数
(すべて異なるハッシュ)
ブロックされた数実行できた数
無署名936
自己署名(SHA-256)734
自己署名(SHA-1)110

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.dllValidPython Software Foundation
_socket.pyd / _hashlib.pyd など標準ライブラリの 7 ファイルValidPython Software Foundation
VCRUNTIME140.dll / VCRUNTIME140_1.dllValidMicrosoft Windows Software Compatibility Publisher
pywintypes312.dllNotSigned(署名なし)
win32api.pydNotSigned(署名なし)
base_library.zipUnknownError(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 行を埋めて持ち込むと、情シス側は可否をその場で判断できます(ルートストアへの登録は当サイトで実施していないため、依頼が通ったあとの動作は未確認です)。

  1. この証明書(拇印= Thumbprint を添付します)を「信頼されたルート証明機関」ストアへ、Intune またはグループポリシーで配布してください
  2. 配布対象は ○○ 部の △ 台、対象アプリは □□(用途・実行頻度)です
  3. 証明書の有効期限は YYYY-MM-DD です。更新時は再配布が必要になります
  4. 鍵の保管者は □□、署名を行うのは □□、失効を依頼する連絡先は □□ です

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. 現場配布の意思決定フロー — どの規模なら何を選ぶか

ここまでを、配る相手と管理体制から逆算する形にまとめます。

現場配布の意思決定フロー 配布先が社内の管理端末か社外かを判定し、社内なら情シスとの許可登録を優先し、社外に配るなら Azure Artifact Signing か OV 証明書を選ぶ意思決定フロー。どのルートでも先にやることは図の直後に本文で挙げている。 図 3: 現場配布の意思決定フロー Q1. 配布先は情シスが管理する社内端末か? はい いいえ Q2. 情シスは許可登録に応じてくれるか? Q3. 継続的に配るか、単発か? 応じる 難しい 継続 単発 署名しないで進める 配置パス or ハッシュで 許可登録してもらう 最短で現場が動く 更新のたびに再申請 社内 PKI を提案する 情シスが信頼ルートを Intune / GPO で配布 証明書単位で許可でき 更新のたびの申請が不要 Azure Artifact Signing 法人なら日本も対象(要確認) トークン管理が不要 CI/CD に組み込みやすい 身元確認に 1〜20 営業日 OV 証明書 CA を選んで購入 HSM / トークンが必須 460 日ごとに更新作業 EV は SmartScreen 目的なら不要
図 3: 現場配布の意思決定フロー。社内配布では、証明書を買うことより情シスとの合意形成のほうが先に効きます。

どのルートでも先にやることは同じです。署名より効果が読める順に並べます。

  1. 止めている門を、表示されたメッセージから確定させる(1 章の表)
  2. 更新のたびに許可を取り直す必要があるかを、作り込む前に情シスへ確認する
  3. PyInstaller を最新に保ち --noupx を付け、ハッシュ・配置パス・用途を添えて申請する

この図の左半分(社内配布)では、証明書の購入は主戦場になりません。数十台に配るツールに証明書を買っても SmartScreen の評判は溜まらず、実行制御の許可登録は結局必要です。お金を払っても、情シスとの会話は省略できません。

逆に、証明書に投資する価値が出るのは次の 3 つです。複数拠点・複数アプリに継続的に配る場合——証明書単位で許可が出れば、アプリごと・更新ごとの申請が消えます。社外(取引先・顧客)に渡す場合——相手の情シスに許可登録を依頼できないので、署名以外に手がありません。ダウンロード配布する場合——Mark of the Web(Windows が付ける「出所」の印)で SmartScreen の対象になり、評判を積む母数が確保できるなら効果が出ます。当てはまるなら、証明書の費用相場と購入の段取りを確認してから稟議に進んでください。

常駐サービスも判断は同じです。Windows サービスとして動かす exe も署名の対象で、登録・起動に管理者権限が要るため、情シスとの調整はいずれにせよ必要です。

情シス相談チェックリスト(そのまま持ち込める 1 枚)

相談に必要な項目を 1 か所に。埋まらない欄が残っているうちは、まだ相談の時期ではありません。

  • 症状: 配布先の表示文言をそのまま書き、どの門か(門 A / B / C)を 1 章の表で確定させる
  • 選んだ方式と理由: 署名しない(許可登録)/社内 PKI/Azure Artifact Signing/OV 証明書のどれか(図 3)。自己署名で実行制御のブロックが消えるとは限らないこと(5.1 の実測)も添えます
  • 配布物の情報: ファイル名・SHA-256 ハッシュ・配置パス・用途・台数。許可登録はこの 5 点で申請します
  • 更新の扱い: 更新のたびに許可を取り直す必要があるか。必要なら想定頻度(月 1 回か年 1 回か)
  • 鍵と失効: 鍵の管理者・署名を行う人・失効依頼の連絡先。社内 PKI を提案するなら、5.3 の依頼テンプレ 4 行をそのまま添付する
  • 工程への織り込み: 購入やサービス利用なら、身元確認の 1〜20 営業日と、最長 460 日ごとの更新を日程に入れる(審査に要する日数と 460 日ごとの更新)

8. おわりに

コード署名は「やれば警告が消える魔法」ではありませんでした。実測で確定できたのは次のことです。

  • Windows SDK が無くても、PowerShell だけで自己署名証明書の作成から署名・検証まで完結する
  • Windows PowerShell 5.1 の Set-AuthenticodeSignature は、既定で SHA-1 署名になる。-HashAlgorithm SHA256 は毎回書く
  • 署名済みの --onefile exe は正常に起動する。ただし期限切れ証明書では例外も出ないまま署名が書き込まれないので、戻り値の Status を必ず検査する
  • 自己署名では実行制御のブロックは解消しなかった。改善も悪化もあり、署名の有無と結果が対応していない
  • exe に署名しても、展開される内部ファイルには署名が及ばない。CPython 由来の DLL は PSF 署名済みだが、サードパーティ wheel 由来には未署名のものがある

確認できていないことも明示します。signtool の挙動は検証環境に Windows SDK が無いためすべて未実測で、公式ドキュメントの記載として紹介しました。ルートストアへ登録した後に検証が通るかは、端末の信頼設定を変える操作なので実施していません。公開 TSA からのタイムスタンプ取得、SmartScreen 警告文言の署名前後比較、公的証明書と Azure Artifact Signing の実利用も未実施です。

現場に向けた結論はこうです。「配布先で止まった」と言われたら、まずメッセージを読んで、止めている門を確定させてください。門を取り違えたまま証明書を買っても、問題は動きません。社内配布でいちばん効くのは証明書ではなく、更新のたびに許可を取り直す必要があるかを、作り込む前に情シスと合意しておくことです。完成してから配れないと分かるのが、いちばん高くつきます。買う側の検討に進むなら、費用と段取りをコード署名証明書の費用と 2026 年の制度変更にまとめてあります。

参考文献・一次情報

一覧の冒頭 3 件(Code signing options / Ballot CSC-31 / DigiCert)は制度・費用の一次情報です。制度・費用の詳細はコード署名証明書の費用と 2026 年の制度変更にまとめてあり、残りの一次情報(Ballot CSC-13 / CSC-17・Azure Artifact Signing・GMOグローバルサインの価格ページ)もその末尾に載せています。一次情報の参照日はいずれも 2026 年 8 月 31 日。実測環境は Windows 11 Pro 25H2(ビルド 26200.9168)/ Windows PowerShell 5.1.26100.9168 / Python 3.12.10 / PyInstaller 6.22.2 / pywin32 312 で、他の環境で同じ結果になることは保証しません。アプリ名・組織名(SampleTool / Genbapy Test Org)は記事用のダミーです。

関連記事