コード署名

**コード署名**（コードしょめい、Code signing）または、**コードサイニング**とは、ソフトウェアの作者を確認し、署名されてからコードの同一性を保証するために、実行ファイルやスクリプトにデジタル署名を行うプロセスである。このプロセスでは、暗号学的ハッシュ関数を使用して、完全性 (Integrity)、信頼性 (Authenticity)、否認防止 (Non-repudiation)を検証する。1995年、コード署名はマイケル・ドイルによって、Eolas社のWebWishブラウザプラグインの一部として発明された。これにより、公開鍵暗号方式を利用して、ダウンロード可能なウェブアプリケーションのプログラムコードに秘密鍵で署名し、プラグインのコードインタプリタが対応する公開鍵を使用してコードを認証してからAPIへのアクセスを許可することが可能になった。

コード署名の最も一般的な用途は、ソフトウェアを配布する際のセキュリティを提供することである。一部のプログラミング言語では、名前空間の衝突を防ぐためにも使用できる。ほとんどすべてのコード署名の実装は、作者またはビルドシステムの身元を検証するための何らかのデジタル署名メカニズムと、オブジェクトが変更されていないことを検証するためのチェックサムを提供する。また、オブジェクトに関するバージョン情報を提供したり、オブジェクトに関する他のメタデータを保存したりするためにも使用できる。

ソフトウェアの認証メカニズムとしてのコード署名の有効性は、基盤となる署名鍵のセキュリティに依存する。他の公開鍵基盤 (PKI) 技術と同様に、システムの完全性は、発行者が秘密鍵を不正なアクセスから保護することにかかっている。汎用コンピュータ上のソフトウェアに保存された鍵は、漏洩の危険にさらされやすい。安全で改ざん防止機能のあるハードウェア・セキュリティ・モジュールに鍵を保存する方がより安全であるとされている。

## 概要
コード署名は、公開鍵暗号方式という技術的基盤の上に成り立っている。署名と検証のプロセスは、以下の通り。

# **ハッシュ化**: ソフトウェア開発者は、配布するコード（実行ファイルなど）から、ハッシュ関数を用いて一意の固定長データ（ハッシュ値またはメッセージダイジェスト）を生成する 。ハッシュ関数は一方向性であり、元のコードからハッシュ値を計算することは容易だが、ハッシュ値から元のコードを復元することは事実上不可能である。また、コードの内容が1ビットでも異なれば、生成されるハッシュ値は全く異なるものになる 。   
# **暗号化（署名）**: 開発者は、自身だけが厳重に管理する**秘密鍵**を使用して、生成したハッシュ値を暗号化する 。この「秘密鍵で暗号化されたハッシュ値」こそが、デジタル署名である。秘密鍵は開発者の手元から決して離れることはなく、これを持つ者だけが正規の署名を作成できる 。   
# **パッケージ化と配布**: 開発者は、元のコード、デジタル署名、そして自身の身元情報と公開鍵を含む**コードサイニング証明書**の3点をパッケージ化して、ユーザーに配布する 。   
# **検証**: ソフトウェアを受け取ったユーザーのコンピュータ（OS）は、以下の検証プロセスを自動的に実行する。
#* まず、パッケージからコードサイニング証明書を取り出し、その証明書が信頼できる認証局から発行された有効なものであるかを確認する 。   
#* 次に、コードサイニング証明書に含まれる**公開鍵**を使い、デジタル署名を復号する。これにより、開発者が暗号化する前の元のハッシュ値が復元される 。   
#* 同時に、パッケージに含まれるコード本体から、署名時と全く同じハッシュ関数を用いて、新たにハッシュ値を計算する 。   
#* 最後に、復号して得られたハッシュ値と、新たに計算したハッシュ値を比較する。両者が完全に一致すれば、そのソフトウェアは証明書に記載された発行元によって署名されたものであり、かつ署名されてから一切改ざんされていないことが数学的に証明される 。   
コード署名はソフトウェアの配布において不可欠な三つの価値を保証する。

* **完全性 (Integrity)**: ユーザーがダウンロードしたソフトウェアが、開発者が署名した時点から一瞬たりとも変更されていないことを保証する。前述のハッシュ値の比較メカニズムにより、輸送中のデータ破損や、悪意のある第三者によるマルウェアの混入といった、いかなる改ざんも即座に検出される 。これにより、ユーザーは意図しない有害なコードを実行するリスクから保護される 。   
* **信頼性 (Authenticity)**: ソフトウェアの発行元が誰であるかを明確に証明する。コードサイニング証明書には、認証局（CA）による厳格な審査を経て検証された組織名や開発者名が記載される 。ユーザーは、ソフトウェアのプロパティ画面などでこの情報を確認でき、信頼できる発行元からのものであることを確信できる 。これは、有名なソフトウェアになりすましてマルウェアを配布するような攻撃を効果的に防ぐ 。   
* **否認防止 (Non-repudiation)**: デジタル署名は、その署名を作成した秘密鍵の所有者でなければ生成不可能である。したがって、一度有効な署名がなされたソフトウェアについて、発行元が後から「これは自社が配布したものではない」と主張すること（否認）を防ぐ 。これにより、ソフトウェアの出所に関する責任の所在が明確になる。

## セキュリティ

多くのコード署名実装では、TLSやSSHで採用されているプロセスと同様に、公開鍵と秘密鍵のペアを含むシステムを使用してコードに署名する方法が提供される。たとえば、.NETの場合、開発者はビルドのたびに秘密鍵を使用してライブラリや実行可能ファイルに署名する。この鍵は、開発者やグループに固有のものであったり、アプリケーションやオブジェクトごとに異なる場合もある。開発者は、この鍵を自分で生成するか、信頼できる認証局 (CA) から取得することができる。

コード署名は、Javaアプレット、ActiveXコントロール、その他のアクティブなウェブおよびブラウザのスクリプトコードなど、特定のコードのソースがすぐには明らかでない分散環境において特に価値がある。もう一つの重要な用途は、既存のソフトウェアに更新やパッチを安全に提供することである。Windows、、およびほとんどのLinuxディストリビューションは、コード署名を使用して更新を提供し、第三者がパッチシステムを介して悪意のあるコードを配布できないようにしている。これにより、受信側のOSは、更新が第三者や物理メディア（ディスク）によって配信された場合でも、その更新が正当なものであることを検証できる。

コード署名は、WindowsおよびMac OS Xでソフトウェアの初回実行時に認証するために使用され、ソフトウェアが第三者の配布元やダウンロードサイトによって悪意を持って改ざんされていないことを保証する。この形式のコード署名は、Linuxでは使用されない。これは、Linuxプラットフォームが分散型の性質を持っていること、パッケージマネージャが（更新やパッチだけでなく）あらゆる形式のソフトウェアの主要な配布モードであること、そして必要であればオープンソースモデルによってソースコードを直接検査できることによるものである。DebianベースのLinuxディストリビューション（その他も含む）は、公開鍵暗号を使用してダウンロードされたパッケージを検証する。

### 認証局（CA）による信頼された識別

コード署名の認証に使用される公開鍵は、できれば安全な公開鍵基盤（PKI）を使用して、信頼できるルート認証局まで追跡可能でなければならない。これは、コード自体が信頼できることを保証するものではなく、それが記載されたソースから（より正確には、特定の秘密鍵から）来ていることのみを保証するものである。CAはルートレベルの信頼を提供し、代理で他者に信頼を割り当てることができる。ユーザーがCAを信頼している場合、そのユーザーは、そのCAまたはその代理によって生成された鍵で署名されたコードの正当性を信頼できると想定される。多くのオペレーティングシステムやフレームワークには、1つ以上の認証局に対する信頼が組み込まれている。また、大企業が組織内部でプライベートCAを実装することも一般的であり、これは公開CAと同じ機能を提供するが、組織内でのみ信頼される。

### EV（Extended Validation）コード署名

EV（Extended Validation）コード署名証明書は、追加の検証および技術的要件に従う。これらのガイドラインは、CA/B Forumのベースライン要件およびEVガイドラインに基づいている。EVに特有の検証要件に加えて、EVコード署名ガイドラインでは、「加入者の秘密鍵は、FIPS 140-2レベル2の要件を満たすかそれを超える暗号モジュールで生成、保存、使用される」と規定されている。

Windows 10のカーネルモードドライバへの署名など、特定のアプリケーションではEVコード署名証明書が必要である。さらに、MicrosoftのIEBlogによると、EVコード署名証明書で署名されたWindowsプログラムは、「そのファイルや発行者に事前の評価が存在しなくても、SmartScreenの評価サービスで即座に評価を確立できる」とされている。

#### EVコード署名証明書の例

これは、SSL.comがソフトウェアへの署名に使用したデコード済みEVコード署名証明書の例である。発行者のcommonNameとして`SSL.com EV Code Signing Intermediate CA RSA R3`が表示されており、これがEVコード署名証明書であることを示している。証明書の`Subject`フィールドは、SSL Corpを組織として記述している。`Code Signing`が唯一のX509v3拡張キー使用法として示されている。

```
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            59:4e:2d:88:5a:2c:b0:1a:5e:d6:4c:7b:df:35:59:7d
    Signature Algorithm: sha256WithRSAEncryption
        Issuer:
            commonName                = SSL.com EV Code Signing Intermediate CA RSA R3
            organizationName          = SSL Corp
            localityName              = Houston
            stateOrProvinceName       = Texas
            countryName               = US
        Validity
            Not Before: Aug 30 20:29:13 2019 GMT
            Not After : Nov 12 20:29:13 2022 GMT
        Subject:
            1.3.6.1.4.1.311.60.2.1.3 = US
            1.3.6.1.4.1.311.60.2.1.2 = Nevada
            streetAddress             = 3100 Richmond Ave Ste 503
            businessCategory          = Private Organization
            postalCode                = 77098
            commonName                = SSL Corp
            serialNumber              = NV20081614243
            organizationName          = SSL Corp
            localityName              = Houston
            stateOrProvinceName       = Texas
            countryName               = US
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:c3:e9:ae:be:d7:a2:6f:2f:24 ...
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Authority Key Identifier: 
                keyid:36:BD:49:FF:31:2C:EB:AF:6A:40:FE:99:C0:16:ED:BA:FC:48:DD:5F
            
            Authority Information Access: 
                CA Issuers - URI:http://www.ssl.com/repository/SSLcom-SubCA-EV-CodeSigning-RSA-4096-R3.crt
                OCSP - URI:http://ocsps.ssl.com
            
            X509v3 Certificate Policies: 
                Policy: 2.23.140.1.3
                Policy: 1.2.616.1.113527.2.5.1.7
                Policy: 1.3.6.1.4.1.38064.1.3.3.2
                  CPS: https://www.ssl.com/repository
                
            X509v3 Extended Key Usage: 
                Code Signing
            X509v3 CRL Distribution Points: 
            
                Full Name:
                  URI:http://crls.ssl.com/SSLcom-SubCA-EV-CodeSigning-RSA-4096-R3.crl
                
            X509v3 Subject Key Identifier: 
                EC:6A:64:06:26:A7:7A:69:E8:CC:06:D5:6F:FA:E1:C2:9A:29:79:DE
            X509v3 Key Usage: critical
                Digital Signature
    Signature Algorithm: sha256WithRSAEncryption
          17:d7:a1:26:58:31:14:2b:9f:3b ...
```


### CAの代替手段

もう一つのモデルは、初回使用時に信頼する (Trust on first use) モデルであり、開発者は自身で生成した鍵を提供することができる。このシナリオでは、ユーザーは通常、初回にオブジェクトが開発者本人からのものであることを確認するために、開発者から直接何らかの方法で公開鍵を入手する必要がある。多くのコード署名システムは、署名内に公開鍵を保存する。コードを実行する前に署名をチェックする一部のソフトウェアフレームワークやOSでは、初回実行後にその開発者を信頼することを選択できる。アプリケーション開発者は、インストーラに公開鍵を含めることで同様のシステムを提供できる。その鍵を使用して、アップグレード、プラグイン、または他のアプリケーションなど、後で実行する必要があるすべてのオブジェクトが同じ開発者からのものであることを確認できる。

### タイムスタンプ
タイムスタンプは、証明書の有効期限が切れた場合に表示される信頼の警告を回避するために設計された。事実上、タイムスタンプは証明書の有効期間を超えてコードの信頼性を拡張する。証明書が漏洩により失効しなければならない場合、漏洩イベントの特定の日時が失効記録の一部となる。この場合、タイムスタンプは、コードが証明書が漏洩する前か後かに署名されたかを判断するのに役立つ。
### [[Xcode]] におけるコード署名

開発者は、iOSおよびtvOSアプリを実機で実行したり、App Storeにアップロードしたりする前に、アプリに署名する必要がある。これは、開発者が有効なApple Developer IDを所有していることを証明するために必要である。アプリケーションがデバイス上で実行されるためには、有効なプロファイルまたは証明書が必要である。

### 問題点

他のセキュリティ対策と同様に、コード署名も破られる可能性がある。ユーザーは、署名されていないコードや、検証を拒否するコードを実行するように騙される可能性があり、システムは秘密鍵が秘密である限りにおいてのみ安全である。また、コード署名は、ソフトウェア作者による悪意のある活動や意図しないソフトウェアのバグからエンドユーザーを保護するものではないことにも注意が必要である。それは単に、ソフトウェアが作者以外の誰によっても変更されていないことを保証するだけである。時には、偽のタイムスタンプやRAMの過剰な使用により、サンドボックスシステムが証明書を受け入れないことがある。

## 実装

Microsoftは、Microsoftがテストしたドライバ用に提供されるコード署名の一形態（Authenticodeに基づく）を実装している。ドライバはカーネルで実行されるため、システムを不安定にしたり、システムのセキュリティホールを開いたりする可能性がある。このため、MicrosoftはWHQLプログラムに提出されたドライバをテストする。ドライバが合格すると、Microsoftはそのバージョンのドライバが安全であるとして署名する。32ビットシステムに限り、コードが署名されていないという警告プロンプトでインストールを許可することに同意した後、Microsoftによって検証されていないドライバをインストールすることが可能である。.NET（マネージド）コードには、証明書の代わりに公開/秘密鍵とSHA-1ハッシュを使用する厳密な名前署名と呼ばれる追加のメカニズムがある。しかし、MicrosoftはAuthenticodeの代替として厳密な名前署名に依存することを推奨していない。

CA/Browser Forumのコード署名ワーキンググループは、2023年6月1日以降、すべてのコード署名証明書（EV証明書だけでなく）について、秘密鍵をFIPS 140-2レベル2またはCommon Criteria EAL 4+以上に準拠するハードウェア暗号モジュールなどの物理メディアに保存することを義務付けることを決定した。その後、各認証局はこの決定への準拠に関する発表を行った。

## ゲーム機およびコンシューマ向けデバイスにおける未署名コード

ゲーム機などのコンシューマ向けデバイスの文脈では、「未署名コード」という用語は、ソフトウェアが受け入れられ実行されるために通常必要な暗号鍵で署名されていないアプリケーションを指すことが多い。ほとんどのコンソールゲームは、コンソールメーカーが設計した秘密鍵で署名されている必要があり、そうでないとゲームはコンソールでロードされない（これはベンダーロックインの強制とソフトウェアの海賊版対策の両方を目的としている）。未署名コードを実行させる方法には、ソフトウェアのエクスプロイト、MODチップの使用、スワップトリックとして知られるテクニック、またはSoftmodの実行など、いくつかの方法がある。

署名されたアプリケーションを単に別のDVDにコピーしても起動しない理由は、すぐには明らかではないかもしれない。Xboxの場合、その理由は、Xbox実行ファイル（XBE）にメディアタイプのフラグが含まれており、XBEが起動可能なメディアの種類を指定しているためである。ほとんどすべてのXboxソフトウェアでは、実行ファイルが工場で生産されたディスクからのみ起動するように設定されているため、実行ファイルを書き込み可能なメディアにコピーするだけで、ソフトウェアの実行が停止する。

しかし、実行ファイルは署名されているため、フラグの値を変更するだけでは不可能である。その理由は、実行ファイルの署名が変更され、チェック時に検証に失敗するためである。

## 関連項目

* デジタル署名
* 公開鍵証明書
* 公開鍵暗号方式
* 暗号学的ハッシュ関数
* 権限昇格
* Symbian OS#プラットフォームセキュリティのバイパス

## 脚注

## 外部リンク
*Appleコード署名ガイド
*Microsoftコード署名入門
*Debianセキュリティインフラストラクチャ
*Strong Distribution HOWTO