67
15 情経第 1516 号 セキュリティ API に関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004 年 2 月 独立行政法人 情報処理推進機構

セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

15 情経第 1516 号

セキュリティ APIに関する技術調査

- Part 3 -

.NET Crypto API:機能と利用法

2004 年 2 月 独立行政法人 情報処理推進機構

Page 2: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

登録商標

Microsoft、Windows、Internet Explorer、Outlook、Visual C++は、米国およびその他の国における米国

Microsoft Corp.の登録商標である。

その他、記載されている会社名、製品名などは、一般に各社の商標または登録商標である。

本書では、™、©、®などを記載しない。

Page 3: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

i

― 目 次 ―

1 はじめに .....................................................................................................................................1 2 Microsoft .NET Crypto APIの構造 ............................................................................................1 2.1 概要.....................................................................................................................................1 2.2 .NET Framework クラスライブラリ .................................................................................2 3 Microsoft .NETフレームワークにおける Crypto API ...............................................................4 3.1 APIの分類 ...........................................................................................................................4 3.2 証明書ストアと構造体 ........................................................................................................5 3.3 証明書信頼リスト CTL(Certificate Trust List) ............................................................7 3.4 セキュリティ関連のツールについて...................................................................................8 3.4.1 証明書作成ツール Makecert.exe................................................................................9 3.4.2 証明書マネージャ ツール Certmgr.exe .....................................................................9 3.4.3 証明書検査ツール Chktrust.exe ..............................................................................10 3.4.4 コードアクセス・セキュリティポリシーツール Caspol.exe.................................... 11 3.4.5 ファイル署名ツール Signcode.exe ...........................................................................12 3.4.6 アクセス許可表示ツール Permview.exe ..................................................................12 3.4.7 PEVerify ツール PEverify.exe .................................................................................12 3.4.8 Secutil ツール Secutil.exe .......................................................................................12 3.4.9 レジストリ設定ツール Setreg.exe............................................................................13 3.4.10 ソフトウェア発行元証明書テスト ツール Cert2spc.exe .......................................13 3.4.11 厳密名ツール Sn.exe ..............................................................................................13

4 CryptoAPIを利用したアプリケーション .................................................................................14 4.1 暗号化、復号、ハッシュ計算 ...........................................................................................15 4.1.1 CSPについて.............................................................................................................15 4.1.2 CSPを使ったプログラム...........................................................................................18 4.2 証明書ストア ....................................................................................................................22 4.2.1 関連する関数の解説 ..................................................................................................22 4.2.2 証明書ストアを扱うプログラム ................................................................................23 4.2.3 証明書コンテキストを扱うプログラム......................................................................24 4.3 証明書の検証 ....................................................................................................................25 4.3.1 Certificate Verification Functionsを使った証明書パス検証....................................25 4.3.2 CertVerifyRevocationによる証明書ステータスの取得 .............................................33 4.4 デジタル署名とデジタル署名の検証.................................................................................37 4.4.1 関連する関数の解説 ..................................................................................................37 4.4.2 デジタル署名を行うサンプルプログラム ..................................................................37 4.4.3 デジタル署名の検証行うサンプルプログラム ...........................................................39

Page 4: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

ii

4.5 証明書および秘密鍵のインポート/エクスポート ...........................................................41 4.5.1 関連する関数の解説 ..................................................................................................41 4.5.2 証明書および秘密鍵のインポートを行うサンプルプログラム ..................................41 4.5.3 証明書および秘密鍵のエクスポートを行うサンプルプログラム ..............................43

5 CryptoAPIのプロバイダの実装................................................................................................45 5.1 Crypto Service Provider ...................................................................................................45 5.1.1 開発手順 ....................................................................................................................45 5.1.2 単純な換字暗号を実装した CSPのサンプルプログラムの解説 ................................49 5.2 Revocation Providerの実装..............................................................................................53 5.2.1 関連する関数の解説 ..................................................................................................53 5.2.2 証明書の有効/無効を通知する Revocation Providerサンプルプログラムの解説 ..56 5.3 その他の拡張可能な関数...................................................................................................57 6 まとめ .......................................................................................................................................59 7 参考文献 ...................................................................................................................................60 8 用語(参考) ............................................................................................................................61

Page 5: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

iii

― 図 目 次 ―

図 2-1 MICROSOFT .NETの構成 .............................................................................................................. 2 図 3-1 CRYPTOAPIの構造 ...................................................................................................................... 4 図 3-2 「証明書」スナップインを追加した管理コンソール ................................................................. 5 図 3-3 CTL作成ツール(MAKECTL)のウィザード画面 ..................................................................... 8 図 3-4 CERMGRの画面 ......................................................................................................................... 10 図 3-5 CHKTRUSTの図面 ...................................................................................................................... 11 図 4-1 アプリケーションと CSP.......................................................................................................... 15 図 4-2 CSPを管理しているレジストリ................................................................................................ 16 図 4-3 CSPを使ったハッシュの例 ....................................................................................................... 19 図 4-4 ブロック暗号による暗号化の例 ................................................................................................ 21 図 4-5 暗号文の復号の例...................................................................................................................... 21 図 4-6 証明書ストアから証明書コンテキストを獲得する例 ............................................................... 23 図 4-7 X.509証明書ファイルから証明書コンテキストを作成する例 .................................................. 24 図 4-8 CERT_CHAIN_ENGINE_CONFIGの内容............................................................................. 26 図 4-9 CERTIFICATE VERIFICATION FUNCTIONSを使った証明書パス検証の例 ................................... 29 図 4-10 パス検証結果を格納する構造体 .............................................................................................. 31 図 4-11 CRYPTOAPIでの証明書パス検証の処理フロー ....................................................................... 31 図 4-12 CERTVERIFYREVOCATIONを使った失効ステータス取得の例................................................. 35 図 4-13 CMS SIGNEDDATAを作成する例 ............................................................................................. 39 図 4-14 CMS SIGNEDDATAから署名者の証明書コンテキストを得る例 .............................................. 40 図 4-15 PKCS #12ファイルから秘密鍵をインポートする例 .............................................................. 42 図 4-16 PKCS #12ファイルへ秘密鍵と証明書をエクスポートする例................................................ 44 図 5-1 CSPのリソースファイル........................................................................................................... 48 図 5-2 レジストリへの登録/削除の関数 ............................................................................................ 49 図 5-3 CSPの暗号化のサンプルプログラム......................................................................................... 52 図 5-4 REVOCATION PROVIDERでエクスポートする関数 ..................................................................... 55 図 5-5 サンプルの REVOCATION PROVIDERが呼ばれたところ ............................................................ 56 図 5-6 レジストリの拡張関数に関する情報......................................................................................... 58

Page 6: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

iv

― 表 目 次 ―

表 3-1 CRYPTOAPIの関数の分類............................................................................................................ 4 表 3-2 CRYPTOAPIで扱う証明書ストアの種類...................................................................................... 6 表 3-3 CRYPTOAPIの構造体の例 ........................................................................................................... 7 表 3-4 CERTIFICATE TRUST LISTのフォーマット................................................................................... 7 表 3-5 .NET FRAMEWORK SDKのセキュリティツール .......................................................................... 9 表 4-1 サンプルプログラムの一覧 ....................................................................................................... 14 表 4-2 標準提供される PROVIDER TYPE(一部) ................................................................................ 16 表 4-3標準で提供される CSP(一部) ................................................................................................ 16 表 4-4 PROV_RSA_FULL の 3つの CSPでサポートされる鍵長の比較 ........................................... 17 表 4-5 ブロック暗号のモード .............................................................................................................. 18 表 4-6 ハッシュ、暗号化、復号を行うプログラムが使う関数............................................................ 18 表 4-7 証明書ストア、証明書、CRL、CTLを扱う主な関数 .............................................................. 22 表 4-8 パス検証の初期パラメータ ....................................................................................................... 25 表 4-9 CRYPTOAPIにおけるパス検証の診断値 .................................................................................... 32 表 4-10 公開鍵証明書を使ったデジタル署名を扱う関数..................................................................... 37 表 4-11 PKCS #12を扱う関数 ............................................................................................................. 41 表 5-1 CSPDK(CRYPTOGRAPHIC SERVICE PROVIDER DEVELOPER'S TOOLKIT)の内容......................... 46 表 5-2 テスト用署名ツール CSPSIGNのオプション............................................................................. 48 表 5-3 CRYPTOAPIの拡張可能な関数 .................................................................................................. 57

Page 7: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

1

1. はじめに

このパートでは、以下の項目について調査を行いMicrosoft社の.NET Crypto APIについての分析を行う。そして、その結果を踏まえ、.NET CryptoAPIを利用してアプリケーションを実装する上での留意点に関して、必要であればサンプルプログラムを例示しながら、解説する。

Microsoft .NET Crypto APIの構造 Microsoft .NETフレームワークにおける Crypto API CryptoAPIを利用したアプリケーション CryptoAPIのプロバイダの実装

サンプルプログラムとしては以下の 7種類のカテゴリに分けてプログラムを実装し、各々に関

して解説をする。また、これらを通してWindows .NET Crypto APIのフレームワーク、開発者がアプリケーションへ固有の暗号機能を付与する際の、拡張方法に対しての分析を行う。

暗号化/復号/ハッシュ計算のプログラム 証明書リポジトリィを扱うプログラム 証明書の検証を行うプログラム デジタル署名/デジタル署名の検証を行うプログラム 証明書および秘密鍵のインポート/エクスポートを行うプログラム 単純な換字暗号を実装した Crypto Service Providerの実装 証明書の有効/無効を通知する Revocation Providerの実装

なお、サンプルプログラムの開発は以下の環境で行った。 コンパイラ : Microsoft Visual C++ V6.0 SP5 ライブラリ: Microsoft Platform Software Development Kit (SDK) CryptoAPIのライブラリやヘッダファイルはMicrosoft Platform Software Development Kit

(SDK)に含まれる。この SDKはMicrosoft社のWebサイトよりダウンロード可能である。以下のサイトにアクセスし、「Core SDK」を選択しダウンロードする。

http://www.microsoft.com/msdownload/platformsdk/sdkupdate/default.htm

2. Microsoft .NET Crypto APIの構造

(1) 概要

Microsoft .NET とは、インターネットを利用したWebサービスなどの分散アプリケーションの稼動環境である。.NETは図 2-1のように分類されるサービスにより実現される。

Page 8: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

2

アプリケーション

オーケストレーション

.Net Framework.Net EnterpriseServer

ビルディングブロックサービス

図 2-1 Microsoft .Net の構成

アプリケーションの開発及び稼働環境である.Net Framework、サーバソフトウェア(BizTalk Server、Commerce Server、SQL Serverなど)である.Net Enterprise Server、ビジネスロジックを実現したサービスのコンポーネントであるビルディングブロックサービスのコンポーネント

を、オーケストレーションという形で組みあせてアプリケーションを提供するのが、

Microsoft .NETの目的である。 アプリケーション開発環境としての.Net Frameworkは、共通言語ランタイム(CLR : Common

Language Runtime)と.NET Framework クラス ライブラリに分類される。 .Net Framework対応のアプリケーションを開発するためには、.NET Framework SDKを用いる。.NET Framework SDKは、.NET対応プログラムを開発するためのコンパイラやクラスライブラリ、プログラム実行環境、各種開発ツール、ドキュメントなどが含んでおり、Microsoft社のWebサイトよりダウンロード可能である。ただし、グラフィカルユーザーインターフェースを持つアプリケーションの開発には、Microsoft社の統合開発環境である Visual Studio.NETが必要となる。

Microsoft .NET Framework 1.1 SDK は以下のサイトにアクセスし、セットアッププログラムをダウンロードしてインストーラを行う。 「.NET Framework 1.1 再頒布パッケージ」と「Microsoft .NET Framework Version 1.1 日

本語 Language Pack」のインストールも必要である。 http://www.microsoft.com/japan/msdn/netframework/

(2) .NET Framework クラスライブラリ

.NET Framework クラスライブラリは、Microsoft .NET Framework SDK に含まれるクラス、インターフェイス、および値型のライブラリである。このライブラリは、システム機能へのアク

セスを提供する.NET Framework のアプリケーション、コンポーネント、及び、コントロールを作成する場合の基礎となるように設計されている。クラスライブラリは機能によって名前空間

を持ち、名前空間にクラスが定義されている。これらのうちセキュリティに関連した名前空間を

以下に示す。 System.Security アクセス許可のための基本クラスなど、.NET Frameworkのセキュリティ システムの基になる構造が用意されている。

System.Security.Cryptography

Page 9: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

3

データの安全なエンコーディングおよびデコーディングの他、ハッシュ処理、乱数生成、

メッセージ認証などの多数の操作を含む暗号サービスを提供している。 System.Security.Cryptography.X509Certificates 共通言語ランタイムによる Authenticode X.509 v.3 証明書の実装が含まれている。この証明書は、証明書の所有者を一意に、そして確実に識別する秘密キーで署名される。

System.Security.Cryptography.Xml XML デジタル署名の作成と検証をサポートするためのクラスが含まれている。この名前空間に含まれるクラスは、W3C(World Wide Web Consortium)による勧告『XML-Signature Syntax and Processing』を実装している。この勧告は http://www.w3.org/TR/xmldsig-core/ で公開されている。

System.Security.Permissions 操作とリソースへのアクセスをポリシーに基づいて制御するクラスを定義している。

System.Security.Policy コードグループ、メンバシップ条件、及び、証拠の各クラスを含む。これら 3 種類のクラスは、.NET Framework のセキュリティポリシーシステムによって適用される規則を作成するために使用される。証拠クラスはセキュリティポリシーへの入力であり、メンバ

シップ条件はスイッチである。これら 2 つのクラスの両方によって、ポリシーステートメントが作成され、与えられるアクセス許可セットが決定される。ポリシーレベルとコー

ドグループは、ポリシーの階層構造を形成する。コードグループは規則をカプセル化した

もので、ポリシーレベルに階層的に配置される。

System.Security.Principal コードが実行されているセキュリティコンテキストを表すプリンシパルオブジェクトを

定義する。

System.ServiceProcess Windows サービスアプリケーションを実装、インストール、および制御するためのクラスが用意されている。サービスは、ユーザーインターフェイスを表示せずに長時間にわた

って動作する実行可能ファイルである。サービスの実装の手順には、ServiceBaseクラスから継承し、開始、停止、一時中断、続行の各コマンドが渡されたときの特定を定義し、

さらにシステムがシャットダウンするときのカスタムの動作およびアクションを定義す

る手順が含まれている。

.Net Frameworkにおけるセキュリティ関連のクラスライブラリはWindowsのコアとなるモジュールである CryptoAPIをラップしている。以降の節では、この.NETにおけるセキュリティ機能の中核をなす CryptoAPIについて解説する。

Page 10: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

4

3. Microsoft .NETフレームワークにおけるCrypto API

(1) APIの分類

CryptoAPIの構造を次図に示す。図 3-1では、左側が証明書の関連する関数群、右側は暗号メッセージつまり、CMS(PKCS #7)に関連する関数群、下側が暗号プリミティブを提供する関数群となっている。

Message FunctionsCertificate and Certificate Store Functions

アプリケーション

CryptoAPI インターフェース

Certificate StoreFunctions

CertificateEncode DecodeFunctions

Low Level MessageFunctions

Simple MessageFunctions

Cryptographic FunctionsBase Cryptography Functions CSP Functions

Cryptographic Service Provider(CSP)

鍵 データベース

標準のCSPとしては、

・Microsoft Base Cryptographic Provider

・Microsoft Enhanced Cryptographic Provider

・Microsoft DSS Cryptographic Provider

などがある。

SmartCard Service Provider(CSP)

鍵 データベース

Certificate VerificationFunctions

Certificate ServicesBackup and Restore

Functions

Callback Functions

Auxiliary Functions

証明書ストア

図 3-1 CryptoAPI の構造

これらの関数群はさらに以下のように分類することができる。

表 3-1 CryptoAPI の関数の分類

分類名 説明 Base Cryptography Functions 暗号アルゴリズムを利用するための関数 Certificate and Certificate Store Functions

証明書ストアにアクセスする関数

Certificate Verification Functions 証明書パスの獲得、検証の関数 Message Functions CMSの生成、解析する関数 Auxiliary Functions 関連するデータを扱うにあたって、補足的な関

数 CSP Functions CryptoServiceProviderとの I/F関数 Certificate Services Backup and Restore Functions

証明書ストアのバックアップ関係の関数

Callback Functions 証明書ストアに関するコールバック関数

Page 11: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

5

なお、CryptoAPI では、PKCS #7に関して、上位互換を持つ後継仕様である CMS (Cryptographic Message Syntax)を前提として処理を行っている。そのため、本章では、PKCS #7ではなく、CMSと表記する。

(2) 証明書ストアと構造体

Windowsシステムでは、PKIで扱う公開鍵証明書や CRLのリポジトリは「証明書ストア」と呼ばれる。システムで標準に持つ「証明書ストア」はローカルディスクのファイルやレジストリ

を用いて保管されている。また、システムが標準で持つ「証明書ストア」は、「カレントユーザ」

のものと「ローカルコンピュータ」のものに分けられる。それぞれは、以下のように証明書の種

類ごとに分類されている。 「個人」:秘密鍵とペアになった証明書 「ほかの人」:他の EE証明書 「中間証明機関」:中間 CA証明書 「信頼されたルート証明期間」:トラストポイントとなるルート CA証明書 「Microsoft 管理コンソール」では、図 3-2のように「証明書」スナップインを追加してこれらの証明書ストアを管理することができる。

図 3-2 「証明書」スナップインを追加した管理コンソール

CryptoAPIで扱う証明書ストアは物理的な格納場所として、以下の4つに分類できる。 レジストリ 証明書ストアをシリアライズしたファイル CMS LDAPサーバー

Page 12: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

6

これらは、プログラミングの観点からは、さらに細かく分けられて、表 3-2のように定義されている。

表 3-2 CryptoAPI で扱う証明書ストアの種類

定義値 説明 CERT_STORE_PROV_MEMORY メモリを使った証明書ストア CERT_STORE_PROV_FILE 証明書ストアをシリアライズして保持す

るファイルのファイルハンドル CERT_STORE_PROV_FILENAME 証明書ストアをシリアライズして保持す

るファイルのファイル名 CERT_STORE_PROV_COLLECTION 開いた証明書ストアのコレクション CERT_STORE_PROV_REG 開いたレジストリキーを使う CERT_STORE_PROV_SYSTEM システムの標準の証明書ストア CERT_STORE_PROV_SYSTEM_REGISTRY システムの標準のレジストリの証明書ス

トア CERT_STORE_PROV_PHYSICAL レジストリの証明書ストア CERT_STORE_PROV_MSG CMS を オ ー プ ン す る 関 数

CryptMsgOpenToDecode で得たハンドル

CERT_STORE_PROV_PKCS7 CMSのバイナリデータ CERT_STORE_PROV_SERIALIZED 証明書ストアをシリアライズしたバイナ

リデータ CERT_STORE_PROV_LDAP LDAP URL

Page 13: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

7

PKIの主な要素である、X.509証明書、CRL、CTLを CryptoAPIで扱う場合の構造体を表 3-3

に示す。 それぞれについて、xxx_INFOは解析された内容を保持し、xxx_CONTEXTは処理中の識別子であり、その中には、バイナリのデータと xxx_INFOも含む。

表 3-3 CryptoAPI の構造体の例

構造体 役割 CERT_INFO 解析された証明書の各フィールドの情報を持つ CERT_CONTEXT 証明書コンテキスト、証明書のバイナリデータと CERT_INFOを持つ CRL_INFO 解析された CRLの各フィールドの情報を持つ CRL_CONTEXT CRLコンテキスト、CRLのバイナリデータと CRL_INFOを持つ CTL_INFO 解析された CTLの各フィールドの情報を持つ CTL_CONTEXT CTLコンテキスト、CTLのバイナリデータと CTL_INFOを持つ

(3) 証明書信頼リスト CTL(Certificate Trust List)

信頼の基点であるルート証明書の配布は、PKIの運用にあたって重要な用件である。CryptoAPIでは、ルート証明書の配布に独自仕様である Certificate Trust List(CTL)という方法を採用している。CTLは、CMSをベースに自己署名の証明書とその使用目的に対してデジタル署名が可能なフォーマットとなっている。これを利用者に配布することで、利用者は署名を検証し、その配

布された証明書の信頼性を確認できる。CTLは表 3-4のような CMSの SignedData形式を採用している。

contentTypeの ObjectIDはMicrosoft社のプライベートな IDで certTrustListを指す。対応する contentは表に示す様な内容を持つ独自に定義されたフォーマットになっている。certTrustListには CTLの有効期限や証明書の用途、信頼する証明書のハッシュ値などを含ませる事が出来る。certTrustList自体にはデジタル署名が存在しない。つまり signerInfosがなくても CTLとして成立する。ただし、署名し signerInfosを付与したのちに配布し、署名を検証してから受容するという運用が想定されている。

表 3-4 Certificate Trust List のフォーマット

フィールド 内容 SignedData encapContentInfo contentType 1.3.6.1.4.1.311.10.1 content 使用目的(複数) サーバー認証

クライアント認証 など

識別名 CTLの識別名(オプション) 開始有効期日 終了有効期日 (オプション)

Page 14: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

8

フィールド 内容 ハッシュ関数の ID 拇印アルゴリズム(SHA1) 信頼する証明書の拇印(複数)

certificates 信頼する証明書(オプション) signerInfos CTL自体の規定に含まれない(オプシ

ョン) Platform SDKには、CTLを作成するためのツールMakeCTL.exeがバンドルされている。 このコマンドに適切なパラメータを与えることで、CTLを作成することが可能である。パラメータを指定せずに起動すると図 3-3のようなウィザード画面が表示される。

図 3-3 CTL 作成ツール(MakeCTL)のウィザード画面

(4) セキュリティ関連のツールについて

Net Framework SDKには開発者向けに用意されたセキュリティ関連のツールの一覧を表 3-5に示す。

Page 15: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

9

表 3-5 .Net Framework SDK のセキュリティツール

ツールの名前 プログラム a 証明書作成ツール Makecert.exe b 証明書マネージャ ツール Certmgr.exe c 証明書検査ツール Chktrust.exe d コードアクセス セキュリティポリシーツール Caspol.exe e ファイル署名ツール Signcode.exe f アクセス許可表示ツール Permview.exe g PEVerifyツール PEverify.exe h Secutilツール Secutil.exe i レジストリ設定ツール Setreg.exe j ソフトウェア発行元証明書テスト ツール Cert2spc.exe k 厳密名ツール Sn.exe

次にこれら.Net Framework SDKのセキュリティ関連のツールの詳細を解説する。

1.1.1 証明書作成ツール Makecert.exe

証明書作成ツールは、テスト目的専用の X.509 証明書を生成する。このツールは、デジタル署名用の公開鍵と秘密キーのペアを作成し、証明書ファイルの中に格納する。また、このキーペ

アと指定された発行元の名前を関連づけて、ユーザー指定の名前とキーペアの公開部分を結びつ

ける X.509 証明書を作成する。 Makecert.exe には基本オプションと拡張オプションがあり、証明書の作成に最も一般的に使用されるのは基本オプションである。拡張オプションを使用すると、証明書をより柔軟に設定で

きる。

1.1.2 証明書マネージャ ツール Certmgr.exe

証明書マネージャ ツールは、証明書、証明書信頼リスト(CTL: Certificate Trust List)、および証明書失効リスト(CRL: Certificate Revocation List)の 2種類のデータを管理する。 具体的には、Certmgr.exe は次の基本的な機能を実行する。 証明書、CTL、および CRL をコンソールに表示する。 証明書、CTL、および CRL を証明書ストアに追加する。 証明書、CTL、および CRL を証明書ストアから削除する。

証明書ストアに含まれている X.509 証明書、CTL、または CRL をファイルに保存する。 Certmgr.exeは、StoreFileとシステムストアという 2種類の証明書ストアに対して機能する。

StoreFile証明書ストアの種類を指定する必要はなく、Certmgr.exeがストアの種類を識別し、適切な操作が実行される。

Page 16: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

10

オプションを何も指定せずに Certmgr.exeを実行すると、図 3-4のような証明書の管理タスクの実行時に役立つ GUIが起動する。この GUIには、証明書、CTL、および CRLをディスクから証明書ストアへとコピーする、インポート ウィザードが用意されている。

図 3-4 CerMgr の画面

1.1.3 証明書検査ツール Chktrust.exe

証明書検査ツールは、Authenticode 証明書による署名が付いたファイルの有効性をチェックする。有効性のチェックは次の手順で行われる。

1. ファイルから PKCS #7署名付きデータオブジェクトを抽出する。 2. PKCS #7署名付きデータオブジェクトから X.509 証明書を抽出する。 3. このファイルの新しいハッシュを計算し、それを PKCS #7 オブジェクトに含まれる署名付きハッシュと比較する。

4. ハッシュが一致する場合、Chktrust.exe は、署名者の X.509 証明書が信頼できるルート証明書に由来する証明書かどうかを検査する。

すべての手順が成功した場合に、ファイルは改ざんされていないと判定する。したがって、フ

ァイルの署名に使われた証明書は、信頼できるルート機関から発行されている必要がある。

Page 17: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

11

-q オプションを指定しないで有効な Authenticode署名を持たないファイルを引数に指定すると、図 2-1のようなセキュリティ警告のダイアログボックスが表示される。このダイアログを使用すると、Authenticode署名がない場合でも、PEファイルをインストールして実行できる。ソフトウェアや発行者について十分な情報がないなどの理由で、そのファイルをインストールして

も安全であることが認できない場合は、[いいえ]を選択する。 [いいえ]ボタンを選択すると、ファイルのインストールも実行も行われずに、チェックが異常

終了したことが報告される。 [はい]ボタンをクリックすると、そのファイルがインストール、実行されて、チェックが正常終了したことが報告される。

図 3-5 ChkTrust の図面

1.1.4 コードアクセス・セキュリティポリシーツール Caspol.exe

ユーザーと管理者は、コードアクセス・セキュリティポリシーツールを使用して、マシンポリ

シーレベル、ユーザーポリシーレベル、およびエンタープライズポリシーレベルのセキュリティ

ポリシーを変更できる。 セキュリティポリシーは 3種類のポリシーレベル、つまりマシンポリシー、ユーザ

ーポリシー、エンタープライズポリシーによって表現される。アセンブリが受信するアクセス許

可のセットは、これらの 3種類のポリシーレベルで許可されるアクセス許可セットの AND集合によって決定される。 それぞれのポリシーレベルは、コード グループの階層構造で表現されている。すべてのコード グループは、どのコードをそのグループのメンバとするのかを決定するためのメンバシップ条件

を持っている。名前付きアクセス許可セットも、各コード グループと関連づけられる。このアクセス許可セットは、メンバシップ条件を満たすコードに対してランタイムから与えられるアクセ

Page 18: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

12

ス許可を指定する。コードグループの階層構造、および関連する名前付きアクセス許可セットに

よって、各レベルのセキュリティポリシーの定義と保守が行われる。コマンドラインのオプショ

ンを使用して、セキュリティポリシーのレベルが設定できる。

1.1.5 ファイル署名ツール Signcode.exe

ファイル署名ツールは、Authenticode用証明書を使用して、ポータブル実行可能(PE)ファイル(.dllファイルまたは.exeファイル)に署名する。マルチファイル アセンブリに含まれているアセンブリ、あるいは個別のファイルに署名する。アセンブリを配布する場合は、個別のファ

イルではなく、アセンブリに署名する必要がある。オプションを指定せずに Signcode.exeを実行すると、署名を支援するウィザードが起動する。

1.1.6 アクセス許可表示ツール Permview.exe

アセンブリによって要求された最小のアクセス許可セット、オプションのアクセス許可セット、

および拒否されたアクセス許可セットを表示するす。このツールを使用して、アセンブリによっ

て使用されるすべての宣言セキュリティを表示することもできる。 開発者は、Permview.exeを使用して、作成したコードに対してアクセス許可要求を正しく適用したかどうかを検査できる。また、作成したコードの利用者は、Permview.exeを実行して、アセンブリが動作するために必要なアクセス許可を確認できる。これにより、たとえば、マネー

ジ実行可能ファイルを実行して、

System.Security.Policy.PolicyException:必要なアクセス許可を取得できません

というようなエラーが発生した場合に、Permview.exeを使用して、実行可能ファイルに含まれるコードを実行する前に得る必要のあるアクセス許可を確認できる。

1.1.7 PEVerify ツール PEverify.exe

PEVerify ツールは、Microsoft Intermediate Language (MSIL) を生成する開発者(コンパイラの作成者、スクリプトエンジンの開発者など)が、生成する MSIL コードと関連メタデータがタイプセーフ要件を満たしているかどうかを確認するために使う。 一部のコンパイラでは、特定の言語構成を使用しなかった場合にだけ、検査可能でタイプセー

フなコードが生成される。このようなコンパイラを使用している場合、生成したコードがタイプ

セーフかどうかの確認を必要となったような場合などに、ファイルに対して PEVerifyツールを実行し、MSILとメタデータを検査できる。

1.1.8 Secutil ツール Secutil.exe

Secutilツールは、厳密な名前情報または X.509証明書用の公開鍵をアセンブリから抽出し、

Page 19: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

13

この情報をコードに組み込むことができる形式に変換する。 .NET Frameworkにおけるセキュリティ・システムには、関連づけられている証拠に基づいてプログラムのアクションを制限するための機構が用意されている。厳密な名前と Authenticode発行元という 2種類の証拠は、暗号鍵とデジタル署名の技術に基づいている。 これらの形式の証拠を必須の IDアクセス許可チェックで使用するためには、かなり長いバイ

ナリデータのシーケンス(厳密な名前の場合は公開鍵の値、Authenticode 発行元の場合は X.509証明書)を参照する必要がある。チェックする証拠を保持するアセンブリファイルの名前を指定

して、Secutil.exeを実行すと、Secutil.exeからの出力データを定数定義の形式でコードに貼り付けることができる。その後、この定数値を使用して、チェック対象の正確な IDアクセス許可を構築できる。

1.1.9 レジストリ設定ツール Setreg.exe

レジストリ設定ツールを使用すると、公開鍵の暗号化に関するレジストリの設定を変更できる。

これらのレジストリの設定は、ソフトウェア発行状態キーと呼ばれ、証明書の検査処理を制御し

ている。 以下の項目について、レジストリ設定を指定する。それぞれについて true または false を指

定することができる。 MakeCertで作ったテスト用ルートを信頼する。 証明書の有効期限を使用する。 失効リストを確認する。 オフライン失効サーバーOK。trueの場合は、個人用証明書をオフラインで承認できる。 オフライン失効サーバーOK。trueの場合は、商用証明書をオフラインで承認できる。 X.509証明書バージョン 1による署名付きオブジェクトを無効化する。 Time Stamp Signerの失効リストを確認する。 Trustデータベース内で見つかった項目だけを信頼する。trueの場合は、Personal Trust

Databaseに含まれる発行者からのダウンロードが許可される。

1.1.10 ソフトウェア発行元証明書テスト ツール Cert2spc.exe

ソフトウェア発行元証明書テストツールは、1つ以上の X.509証明書からテスト用のソフトウェア発行元証明書(SPC: Software Publisher's Certificate)を作成する。Cert2spc.exeはテスト専用のツールで、有効な SPC は、VeriSignや Thawteなどの証明書発行機関から入手する必要がある。

1.1.11 厳密名ツール Sn.exe

厳密名ツールは、証明書/プライベート鍵の鍵ぺアに基づく厳密な名前と呼ばれる識別符を使

Page 20: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

14

用し、アセンブリと呼ばれる、.NET Framework アプリケーションにおける機能単位をなすモジュールに署名をする。Sn.exeには、キーの管理、署名の生成、署名の検査に関するオプションが用意されている。 各コマンドのパラメータなどの詳細な情報は以下の URLを参照してほしい。

http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/m

sdn/library/ja/cptools/html/cpconnetframeworktools.asp?frame=true

なお、Platform SDKにも、同様のセキュリティ関連のツールがバンドルされている。(3) に示したMakeCTL以外に 6個ある。詳細は以下の URLを参照してほしい。

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sec

urity/security/cryptoapi_tools_reference.asp

4. CryptoAPIを利用したアプリケーション

以下では、CryptoAPIを利用したアプリケーションを例示する。 それぞれのアプリケーションにはサンプルプログラムが与えられる。サンプルプログラムは、

ワークスペース“cpkismpl”に全て含まれている。“cpkismpl”に含まれるプロジェクトの一覧を表 4-1に示す。

表 4-1 サンプルプログラムの一覧

プロジェクト 説明 cpkicdec 復号のサンプル cpkicenc 暗号化のサンプル cpkicexp 証明書および PKCS #12のエクスポートのサンプル cpkichsh ハッシュのサンプル cpkicimp 証明書および PKCS #12のインポートのサンプル cpkicrp Revocation Providerのサンプル cpkicsps Crypto Service providerのサンプル cpkicval 署名検証のサンプル cspinst CSPのセットアッププログラムのサンプル Csptest CSPのテストを兼ねた、CSP利用のプログラムのサンプル

Page 21: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

15

(1) 暗号化、復号、ハッシュ計算

1.1.12 CSPについて

(1) CSPの役割

CryptoAPIでは、暗号や、デジタル署名のアルゴリズム自体の実装は Cryptographic Service Provider(CSP)としてモジュール化されている。つまり、暗号エンジンは独立したモジュールとして、プラグイン可能な構造となっている。したがって、暗号アルゴリズムの実装者は CSPを開発することになる。また、アプリケーションは、図 4-1に示すように、CryptoAPIを通して、CSPを選択し、間接的に CSPに実装されているアルゴリズムを利用する。

Windowsアプリケーション A Windowsアプリケーション B Windowsアプリケーション C

(エクスポートされた)関数群CryptoAPI (advapi32.dll、crypt32.dll)

CSP #1 CSP #2 CSP #3

CryptoAPI

CryptoSPI

アプリケーション

OS

サービス・プロバイダ

図 4-1 アプリケーションと CSP

アプリケーションが呼び出すのは、advapi32.dll、crypt32.dllがエクスポートしている関数である。次に、呼び出されたこれらモジュールは、対応する CSPがエクスポートしている関数を呼び出している。

CSPがエクスポートすべき関数群は CryptoSPIとして規定されており、CryptoAPIの関数に1対 1で対応している。CryptoAPIでの暗号の関数名は「Crypt」で始まるが、CryptoSPIでは「CP」で始まる。 このような仕組みにより、暗号アルゴリズムを実装し、暗号の鍵を保持するスマートカードも、

アプリケーションからは CSPの 1つとして利用可能となる。

(2) Provider Typeと Provider Name

CSPは Provider Nameという名前を持つ。また、CSPはサポートするアルゴリズムによってProvider Typeに分類される。各 CSPはいずれか1つの Provider Typeとなる。標準で定義されている Provider Typeが複数あるが、任意の Provider Typeを定義して導入することも可能である。各 Provider Typeにはデフォルトの CSPが設定されている。この関係はレジストリで確認できる。レジストリでは、図 4-2のように

Page 22: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

16

HKEY_LOCAL_MACHINE¥SOFTWARE¥Microsoft¥Cryptography¥Defaults

をキーとして、これらの情報が保存されている。

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults

Provider Types

Provider

Type 001 Name = Microsoft Strong Cryptographic ProviderTypeName = RSA Full (Signature and Key Exchange)

Type 003 Name = Microsoft Base DSS Cryptographic ProviderTypeName = DSS Signature

Microsoft Strong Cryptographic Provider

Microsoft Base DSS Cryptographic Provider

Image Path = CSPの実態 DLLファイルのパスSigInFile = CSPの署名に関する情報Type = Provider Type (この場合は 1)

Image Path = ・・・・・・・・・・SigInFile = ・・・・・・・・・・Type = 3

プロバイダのタイプが登録されている

個々のCSPが登録されている

タイプごとのデフォルト

・・・・・・・

・・・・・・・

図 4-2 CSP を管理しているレジストリ

(3) 標準の CSP

Microsoft社が提供している標準の CSPを解説する。規定の Provider Typeとサポートするアルゴリズムを表 4-2に示す。表 4-3には、標準で提供される CSPと、その Provider Typeを示す。

表 4-2 標準提供される Provider Type(一部)

Provider Type 定義値 鍵交換 署名 共通鍵暗号 ハッシュ

PROV_RSA_FULL 1 RSA RSA RC2,RC4 MD5,SHA PROV_RSA_SIG 2 - RSA - MD5,SHA PROV_DSS 3 - DSS - MD5,SHA PROV_FORTEZZA 4 KEA DSS Skipjack SHA PROV_MS_EXCHANGE 5 RSA RSA CAST MD5 PROV_SSL 6 RSA RSA 多種 多種 PROV_RSA_SCHANNEL 12 RSA RSA RC4、DES、

トリプル DES MD5,SHA

PROV_DSS_DH 13 DH DSS CYLINK MEK MD5,SHA PROV_RSA_AES 24 RSA RSA RC2,RC4,AES MD5,SHA

表 4-3標準で提供される CSP(一部)

Page 23: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

17

Provider Name 定義値 対 応 す る Provider Type

Microsoft Base Cryptographic Provider

MS_DEF_PROV PROV_RSA_FULL

Microsoft Strong Cryptographic Provider

MS_STRONG_PROV PROV_RSA_FULL

Microsoft Enhanced Cryptographic Provider

MS_ENHANCED_PROV PROV_RSA_FULL

Microsoft DSS Cryptographic Provider

MS_DEF_DSS_PROV PROV_DSS

Microsoft Base DSS and Diffie-Hellman Cryptographic Provider

MS_DEF_DSS_DH_PROV PROV_DSS_DH

Microsoft DH SChannel Cryptographic Provider

MS_DEF_DH_SCHANNEL_PROV

PROV_DH_SCHANNEL

Microsoft RSA/Schannel Cryptographic Provider

MS_DEF_RSA_SCHANNEL_PROV

PROV_RSA_SCHANNEL

Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)

MS_ENH_RSA_AES_PROV PROV_RSA_AES

上記の CSPのうち、Provider Type が PROV_RSA_FULLのものは 3つあるが、サポートし

ているアルゴリズムやその鍵長が異なる。 それらの相違点を表 4-4に示す。

表 4-4 PROV_RSA_FULL の 3 つの CSP でサポートされる鍵長の比較

アルゴリズム MS_DEF_PROV MS_STRONG_PROV MS_ENHANCED_PROV

RSA署名 512 ~1024 ~1024 RSA鍵交換 512 ~1024 ~1024 RC2 40 ~128 ~128 ソルト指定可能 RC4 40 ~128 ~128 ソルト指定可能 DES 56 56 56 トリプルDES(2キー)

サポートせず 112 112

トリプルDES(3キー)

サポートせず 168 168

表 4-5はこれらの CSPがサポートするブロック暗号のモードを与える。

Page 24: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

18

表 4-5 ブロック暗号のモード

モード 定義値 Cipher Block Chaining CRYPT_MODE_CBC Cipher Feedback 8bits CRYPT_MODE_CFB Electronic Codebook CRYPT_MODE_ECB Output Feedback CRYPT_MODE_OFB

パディングは PKCS #5 V1.5の仕様をサポートしている。

1.1.13 CSPを使ったプログラム

(1) CSPを使ったハッシュ、暗号化、復号のための関数

CSPを使って、ハッシュ、暗号化、復号を行うプログラムが使う CryptoAPIの関数を表 4-6に示す。

表 4-6 ハッシュ、暗号化、復号を行うプログラムが使う関数

関数 説明 CryptEnumProviders CSPを列挙する。 CryptAcquireContext CSPのインスタンスを生成し、ハンドルを獲得する。 CryptDeriveKey 暗号鍵を得る。 CryptEncrypt 暗号化する。 CryptDecrypt 復号する。 CryptCreateHash ハッシュのインスタンスを生成し、ハンドルを獲得する CryptGetHashParam ハッシュ値を得る。 CryptHashData ハッシュの入力を与える。

(2) ハッシュのサンプルプログラム

図 4-3に CSPを使ったハッシュの例を示す。プログラムの全体は付録の cpkichsh.cppを参照のこと。

Page 25: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

19

HCRYPTPROV hCryptProv;

HCRYPTKEY hKey;

BYTE *pbBuffer; // ハッシュする入力データ

DWORD dwBufLen; // ハッシュする入力データの長さ

BYTE *pbHash // ハッシュ値の格納バッファ

BYTE *dwHashLen // ハッシュ値の長さ

// CSPのハンドルの獲得

::CryptAcquireContext(&hCryptProv, NULL,

MS_ENHANCED_PROV, // CSPの名前

PROV_RSA_FULL, // CSPのタイプ

0);

// SHA1ハッシュ関数のハンドルを獲得

::CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash);

::CryptHashData(hHash, pbBuffer, dwBufLen, 0))

::CryptGetHashParam(hHash, HP_HASHVAL, NULL, &dwHashLen, 0);

pbHash = (BYTE*)malloc(dwHashLen))

::CryptGetHashParam(hHash, HP_HASHVAL, pbHash, &dwHashLen, 0);

printf("The hash is: ");

for(i = 0 ; i < dwHashLen ; i++) {

printf("%2.2x ",pbHash[i]); // ハッシュ値の出力

}

printf("¥n");

図 4-3 CSP を使ったハッシュの例

Page 26: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

20

(3) 共通鍵暗号による暗号化のサンプルプログラム

図 4-4に標準の CSPを使って、パスワードのハッシュ値を鍵とした、ブロック暗号による暗号化を行う例を示す。プログラムの全体は付録の cpkicenc.cppを参照のこと。

HCRYPTPROV hCryptProv;

HCRYPTKEY hKey;

HCRYPTKEY hXchgKey;

HCRYPTHASH hHash;

char *szPassword = “password”;

BYTE *pbBuffer; // 暗号化対象データと暗号化データのバッファ

DWORD dwBufferLen; // 暗号化対象データの長さ

DWORD dwCount; // 暗号化データのバッファの長さ

/*暗号化データのバッファ ブロック暗号ブロック長と入力データから判断した出力バッファのサイ

ズを決める。*/

// CSPのハンドルの獲得

::CryptAcquireContext(&hCryptProv, NULL,

MS_ENHANCED_PROV, // CSPの名前

PROV_RSA_FULL, // CSPのタイプ

0);

// MD5ハッシュ関数のハンドルを獲得

::CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash);

// パスワードをハッシュ

::CryptHashData(hHash, (BYTE *)szPassword, strlen(szPassword), 0);

//鍵ハンドルの獲得

::CryptDeriveKey(

hCryptProv,

CALG_3DES, // アルゴリズム

hHash, //ハッシュ関数のハンドル

KEYLENGTH_3DES | CRYPT_EXPORTABLE | CRYPT_NO_SALT, //鍵長

Page 27: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

21

&hKey); //鍵ハンドル

::CryptEncrypt(hKey,

0,

TRUE, //データはこれで最後

0,

pbBuffer, // [in/out]暗号化対象データと暗号化データのバッファ

&dwCount, //暗号化対象データの長さ

dwBufferLen); // pbBufferの長さ

::CryptDestroyKey(hKey); //鍵ハンドルの破棄

::CryptDestroyHash(hHash); //ハッシュハンドルの破棄

::CryptReleaseContext(hCryptProv, 0);// CSPハンドルの破棄

図 4-4 ブロック暗号による暗号化の例

(4) 共通鍵暗号による復号のサンプルプログラム

図 4-5にパスワードのハッシュ値を鍵とした、ブロック暗号によて暗号化されたデータの復号を行う例を示す。鍵ハンドルである hKeyの獲得までの処理は暗号化の場合と同様であるため、省略している。プログラムの全体は付録の cpkicdec.cppを参照のこと。

BYTE *pbBuffer; // 複号対象データと複号結果データのバッファ

DWORD dwCount; //複号対象データの長さ

::CryptDecrypt(hKey, 0, TRUE, 0, pbBuffer, &dwCount);

図 4-5 暗号文の復号の例

Page 28: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

22

(2) 証明書ストア

1.1.14 関連する関数の解説

証明書ストア、証明書、CRL、CTLを扱う主要な関数を表 4-7に示す。

表 4-7 証明書ストア、証明書、CRL、CTL を扱う主な関数

関数 説明 CertEnumSystemStore システム証明書ストアを列挙する。 CertOpenStore 任意の証明書ストアをオープンする。 CertOpenSystemStore システム証明書ストアを開く。 CertSaveStore 証明書ストアを保存する。 CertCloseStore 証明書ストアを閉じる。 CertAddCertificateContextToStore 証明書ストアへ証明書を証明書コンテキストか

ら追加する。 CertAddEncodedCertificateToStore 証明書ストアへ証明書をバイナリデータから追

加する。 CertCreateCertificateContext バイナリデータから証明書コンテキストを作成

する。 CertEnumCertificatesInStore 証明書ストアから証明書コンテキストをを列挙

して得る。 CertFreeCertificateContext 証明書コンテキストを開放する。 CertAddCRLContextToStore 証明書ストアへ CRLを CRLコンテキストから

追加する。 CertAddEncodedCRLToStore 証明書ストアへ CRL をバイナリデータから追

加する。 CertCreateCRLContext バイナリデータから CRL コンテキストを作成

する。 CertEnumCRLsInStore 証明書ストアから CRL コンテキストを列挙し

て得る。 CertFreeCRLContext CRLコンテキストを開放する。 CertAddCTLContextToStore 証明書ストアへ CTL をCTL コンテキストから

追加する。 CertAddEncodedCTLToStore 証明書ストアへCTLをバイナリデータから追加

する。 CertCreateCTLContext バイナリデータからCTLコンテキストを作成す

る。 CertEnumCTLsInStore 証明書ストアからCTLコンテキストを列挙して

得る。 CertFreeCTLContext CTLコンテキストを開放する。 CertEnumCertificateContextProperties 証明書コンテキストから証明書の属性の識別子

を列挙する。 CertGetCertificateContextProperty 証明書コンテキストから証明書の属性を得る。 CertSetCertificateContextProperty 証明書コンテキストから証明書の属性をセット

する。 CRLと CTLについても上記3関数と同様の関数が用意されている。

Page 29: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

23

1.1.15 証明書ストアを扱うプログラム

図 4-6に証明書ストアから証明書コンテキストを獲得する例を示す。 この例では、

5. カレントユーザのシステム証明書ストアのうち中間証明機関の証明書ストアを開く。 6. 証明書コンテキストを得て、サブジェクトの DNを標準出力に出力する。 7. CertOpenSystemStoreの 2番目の引数に以下の文字列を指定し、対象の証明書ストアハンドルを得る。

処理を行なっている。 「個人」:”MY” 「ほかのひと」:”ADDRESSBOOK” 「中間証明機関」:”CA” 「信頼された証明機関」:”ROOT” 「信頼された発行元」:”SPC”

HCERTSTORE hCertStore; /*証明書ストアハンドル*/

PCCERT_CONTEXT pCertContext /*証明書コンテキスト*/

hCertStore = ::CertOpenSystemStore(NULL, “CA”);

while(pCertContext = ::CertEnumCertificatesInStore(hCertStore,

pCertContext)) {

char szNameString[256];

::CertGetNameString(pCertContext,

CERT_NAME_RDN_TYPE,

0, /* CERT_NAME_ISSUER_FLAG だと発行元*/

NULL, szNameString, 256);

printf(“subject : %s¥n”, szNameString);

}

::CertFreeCertificateContext(pCertContext);

::CertCloseStore(hCertStore, CERT_CLOSE_STORE_CHECK_FLAG);

図 4-6 証明書ストアから証明書コンテキストを獲得する例

Page 30: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

24

1.1.16 証明書コンテキストを扱うプログラム

図 4-7に DERエンコードされた X.509証明書ファイルを読み込み、証明書コンテキストを作成する例を示す。

PCCERT_CONTEXT pCertContext; /*証明書コンテキスト*/

CFile file(szCertFile, CFile::modeRead);

BYTE *pszBuf = new BYTE[file.GetLength()];

file.Read(pszBuf, file.GetLength());

pCertContext = ::CertCreateCertificateContext(

X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,

pszBuf,

file.GetLength());

file.Close();

delete(pszBuf);

if (pCertContext == NULL) {

DWORD dwErr = ::GetLastError();

}

図 4-7 X.509 証明書ファイルから証明書コンテキストを作成する例

Page 31: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

25

(3) 証明書の検証

CryptoAPIの標準の機能では、証明書パス検証に関して RFC 3280で規定されているパス検証の初期パラメータ(表 4-8)を指定した検証はできない。 この問題への解決手法については「6. まとめ」で触れる。 証明書の検証を扱うサンプルプログラムは付録の cpkicval.cppで示す。

表 4-8 パス検証の初期パラメータ

パラメータ 定義 user-initial-policy-set 受け入れ可能なポリシーIDのセット Initial-policy-mapping-inhibit ポリシーマッピングを許可/非許可 Initial-explicit-policy 検証結果に user-initial-policy-set のいずれかを含める

ことの要求/非要求 Initial-any-policy-inhibit 証明書パス中の ANYポリシーの許可/非許可

1.1.17 Certificate Verification Functionsを使った証明書パス検証

CryptoAPIを使った証明書パスの獲得と、パスの失効検証は、通常、「Certificate Verification Functions」にある一連の関数を使って行う。 「証明書パスエンジン」を作成し、対象の証明書を検証する。図 4-11に処理フローを示す。

(1) 証明書パスエンジン(CertCreateCertificateChainEngine)

パス構築、パス検証には「証明書パスエンジン」を作成し、「証明書パスエンジン」を指定し

て、証明書ストアから証明書パス上の証明書を獲得し、失効の検証を行う。 「証明書パスエンジン」には、検証のパラメータを CERT_CHAIN_ENGINE_CONFIGという構造体を入力として与える。これにより、システムのルート証明書ストアのサブセットを

一時的な証明書ストアとして作成し、トラストポイントの証明書を限定することが可能である。 また、中間 CAの証明書については、システムの中間 CA証明書ストアとは別に一時的な証

明書ストアを作成して、証明書、CRLを格納しておくことにより、パス構築処理の際に追加、あるいは限定的に参照させることも可能である。また、拡張鍵使用法、CTLの使用法など検証方法を指定できる。 CERT_CHAIN_ENGINE_CONFIGの内容については図 4-8に示す。

typedef struct _CERT_CHAIN_ENGINE_CONFIG {

DWORD cbSize;

HCERTSTORE hRestrictedRoot;

HCERTSTORE hRestrictedTrust;

HCERTSTORE hRestrictedOther;

Page 32: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

26

DWORD cAdditionalStore;

HCERTSTORE* rghAdditionalStore;

DWORD dwFlags;

DWORD dwUrlRetrievalTimeout;

DWORD MaximumCachedCertificates;

DWORD CycleDetectionModulus;

} CERT_CHAIN_ENGINE_CONFIG, *PCERT_CHAIN_ENGINE_CONFIG;

図 4-8 CERT_CHAIN_ENGINE_CONFIG の内容

cbSize:本構造体のサイズをセット hRestrictedRoot:参照するルート証明書の格納された証明書の証明書ストアハンド

ルを指定する。システムのルート証明書ストアのサブセットとなる。 hRestrictedTrust:参照する CTLの格納された証明書の証明書ストアハンドルを指定する。

hRestrictedOther:中間 CAの証明書、および、CRL、ARLの格納された証明書ストアハンドルを指定する。

cAdditionalStore : 他 に 参 照 す べ き 証 明 書 ス ト ア ハ ン ド ル の 配 列

rghAdditionalStoreの要素数 rghAdditionalStore:他に参照すべき証明書ストアハンドルの配列 dwFlags:以下の定義値が指定可能

CERT_CHAIN_CACHE_END_CERT:EE証明書もキャッシュする。 CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL:URL 参照があったらキャッシュのものを使う。

CERT_CHAIN_USE_LOCAL_MACHINE_STORE:カレントユーザではなく、ローカ

ルマシンの証明書ストアを参照する。 dwUrlRetrievalTimeout:URL参照のタイムアウト値、0はシステムのデフォルト値を使用。0を指定

MaximumCachedCertificates:パス構築時にキャッシュする上限サイズを指定する。

0はシステムのデフォルト値を使用。 CycleDetectionModulus:同一の証明書のパス上での出現回数の制限値を指定する。

(2) 検証処理(CertGetCertificateChain)

検証時のパラメータとしては、EE証明書の失効検証の有無、パス上の証明書の失効検証の有無や、キャッシュの使用法、日時を特定しての検証が可能である。 パス検証の失効検証では、内部で関数 CertverifyRevocationが呼ばれて、登録されている

RevocationProviderが働く。 図 4-9に Certificate Verification Functionsを使った証明書パス検証の例を示す。プログラム

Page 33: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

27

の全体は付録の cpkicval.cppを参照のこと。

PCCERT_CONTEXT pCertContext; // 検証対象の証明書コンテキスト

HCERTCHAINENGINE hChainEngine; //パス検証エンジンのハンドル

PCCERT_CHAIN_CONTEXT pChainContext; // パス検証結果コンテキスト

CERT_CHAIN_ENGINE_CONFIG ChainConfig; //パス検証エンジンの設定

ChainConfig.cbSize = sizeof(CERT_CHAIN_ENGINE_CONFIG);

ChainConfig.hRestrictedRoot= NULL;

ChainConfig.hRestrictedTrust= NULL;

ChainConfig.hRestrictedOther= NULL;

ChainConfig.cAdditionalStore= 0 ;

ChainConfig.rghAdditionalStore = NULL;

ChainConfig.dwFlags = CERT_CHAIN_CACHE_END_CERT;

ChainConfig.dwUrlRetrievalTimeout= 0 ;

ChainConfig.MaximumCachedCertificates=0 ;

ChainConfig.CycleDetectionModulus = 0;

if (!::CertCreateCertificateChainEngine(&ChainConfig, &hChainEngine))

{

cerr << "検証エンジンの作成に失敗しました。" << endl;

DWORD dwErr = ::GetLastError();

return;

}

CERT_ENHKEY_USAGE EnhkeyUsage;

CERT_USAGE_MATCH CertUsage;

CERT_CHAIN_PARA ChainPara;

EnhkeyUsage.cUsageIdentifier = 0;

EnhkeyUsage.rgpszUsageIdentifier=NULL;

CertUsage.dwType = USAGE_MATCH_TYPE_AND;

CertUsage.Usage = EnhkeyUsage;

ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);

ChainPara.RequestedUsage=CertUsage;

if (::CertGetCertificateChain(

Page 34: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

28

hChainEngine,

pCertContext,

NULL,

NULL,

&ChainPara,

CERT_CHAIN_REVOCATION_CHECK_END_CERT|

CERT_CHAIN_REVOCATION_CHECK_CHAIN|

CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS,

NULL,

&pChainContext))

{

char szNameString[256];

CString strStatus;

const char* pCodeName = NULL;

const char* pText = NULL;

cout << "パス上の個々の証明書に関する情報" << endl;

for (int i=0; i < pChainContext->cChain; ++i) {

PCERT_SIMPLE_CHAIN pChain = pChainContext->rgpChain[i];

for (int j = 0; j < pChain->cElement; ++j) {

PCERT_CHAIN_ELEMENT pElemet = pChain->rgpElement[j];

if (::CertGetNameString(

pElemet->pCertContext,

CERT_NAME_RDN_TYPE,

0,

NULL,

szNameString,

256)) {

cout << szNameString << endl;

}

if (pElemet->TrustStatus.dwErrorStatus == 0) {

cout << "有効な証明書です。" << endl;

} else {

cout << "無効な証明書です。ステータスコード : " <<

pElemet->TrustStatus.dwErrorStatus << endl;

}

if (pElemet->TrustStatus.dwInfoStatus) {

Page 35: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

29

cout << " 参照情報コード : " <<

pElemet->TrustStatus.dwInfoStatus << endl;

}

cout << "統合した情報" << endl;

if (pChainContext->TrustStatus.dwErrorStatus == 0) {

cout << "有効な証明書です。" << endl;

} else {

cout << "無効な証明書です。ステータスコード : " <<

pChainContext->TrustStatus.dwErrorStatus << endl;

}

if (pChainContext->TrustStatus.dwInfoStatus) {

cout << " 参照情報コード : " <<

pChainContext->TrustStatus.dwInfoStatus << endl;

} else {

DWORD dwErr = ::GetLastError();

}

if (pChainContext)

::CertFreeCertificateChain(pChainContext);

if (pCertContext)

::CertFreeCertificateContext(pCertContext);

if (hChainEngine)

::CertFreeCertificateChainEngine(hChainEngine);

図 4-9 Certificate Verification Functions を使った証明書パス検証の例

Page 36: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

30

パス検証結果を格納する構造体について図 4-10に示す。 PCCERT_CHAIN_CONTEXTの変数から、次のように、パス上の証明書に関する証明書コンテキストとステータス情報が得ることができる。 rgpChain[0]-> rgpElement[0]-> pCertContext //証明書コンテキスト

rgpChain[0]-> rgpElement[0]-> TrustStatus //ステータス情報

typedef struct _CERT_CHAIN_CONTEXT {

DWORD cbSize; // 構造体のサイズ

CERT_TRUST_STATUS TrustStatus; // パス検証結果コード

DWORD cChain; // rgpChainの配列の要素数

PCERT_SIMPLE_CHAIN* rgpChain; // パス上の証明書に関するステータス

DWORD cLowerQualityChainContext; // 次の配列の要素数

PCCERT_CHAIN_CONTEXT* rgpLowerQualityChainContext;

// CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS情報

BOOL fHasRevocationFreshnessTime; // TRUE:次の値がある

DWORD dwRevocationFreshnessTime; // CRLの ThisUpdateからの差異

} CERT_CHAIN_CONTEXT, *PCERT_CHAIN_CONTEXT;

typedef struct _CERT_SIMPLE_CHAIN {

DWORD cbSize; // 構造体のサイズ

CERT_TRUST_STATUS TrustStatus; // パス検証結果コード

DWORD cElement; // rgpElementの配列の要素数

PCERT_CHAIN_ELEMENT* rgpElement;

PCERT_TRUST_LIST_INFO pTrustListInfo;

BOOL fHasRevocationFreshnessTime;

DWORD dwRevocationFreshnessTime;

} CERT_SIMPLE_CHAIN, *PCERT_SIMPLE_CHAIN;

typedef struct _CERT_CHAIN_ELEMENT {

DWORD cbSize; // 構造体のサイズ

PCCERT_CONTEXT pCertContext; // 証明書コンテキスト

CERT_TRUST_STATUS TrustStatus; // パス検証結果コード

PCERT_REVOCATION_INFO pRevocationInfo; // 失効情報

Page 37: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

31

PCERT_ENHKEY_USAGE pIssuanceUsage; // 発行元付与の拡張鍵用途

PCERT_ENHKEY_USAGE pApplicationUsage; // 個別の拡張鍵用途

} CERT_CHAIN_ELEMENT, *PCERT_CHAIN_ELEMENT;

図 4-10 パス検証結果を格納する構造体

認証パスエンジン作成CertCreateCertificateChainEngine

検証対象の証明書を入力とし、認証パスと検証結果を獲得

CertGetCertificateChain

入力・システムの証明書ストアの利用を制限、あるいは補足するために作成した一時証明書ストアのハンドル・証明書、CRLのキャッシュの使い方、上限値・URLによる参照時のタイムアウト値・パス上の同一証明書の出現回数の上限値出力・認証パスエンジンのハンドル

入力・認証パスエンジンのハンドル・検証対象の証明書コンテキスト・検証する拡張鍵使用法・失効検証の仕方(EEのみ、パスを含むなど)出力・証明書チェーンコンテキスト

証明書チェーンコンテキストの開放CertFreeCertificateChain

認証パス、検証結果の表示

一時証明書ストアの作成(トラストポイント用、中間CA用の2つ)

認証パスエンジンのハンドルの開放CertFreeCertificateChainEngine

証明書コンテキストの開放

中間CAの証明書とCRL、ARLを一時証明書ストアに追加

トラストポイントの証明書からCTLを作成し、証明書とともに、一時証明書ストアに

追加

システムの証明書ストアをそのまま利用しない場合、検証に利用する以下のデータを持つ一時的な証明書ストアを作成する。・ルート証明書ストアを制限するため トラストポイントの証明書 トラストポイントCTL・中間CA証明書ストアを補足するため 中間CAの証明書 中間CA発行のCRL

一時的なCA証明書ストア

関数内部ではCertVerifyRevocationなどを呼び出し検証

検証対象の証明書コンテキストの作成

一時証明書ストアの開放

一時的なルート証明書ストア

トラストポイントの証明書をルート証明書ストアへ追加

通常の処理

図 4-11 CryptoAPI での証明書パス検証の処理フロー

Page 38: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

32

処理の結果として証明書パスとともに、証明書の信頼情報として、以下のようなエラーステー

タスと参照情報が獲得される。

表 4-9 CryptoAPI におけるパス検証の診断値

エラーコードの定義値 # 意味

検証対象の証明書または証明書パスに関するエラー CERT_TRUST_NO_ERROR 1 証明書およびパスに問題はない。 CERT_TRUST_IS_NOT_TIME_VALID 2 検証対象の証明書かパス上の証明書で有効期限が妥当ではないものがある。 CERT_TRUST_IS_NOT_TIME_NESTED 3 パス上の証明書で有効期限の関連が適切ではない CERT_TRUST_IS_REVOKED 4 トラストポイントの証明書かパス上の証明書で失効しているものがある。 CERT_TRUST_IS_NOT_SIGNATURE_VALID 5 検証対象の証明書かパス上の証明書で有効な署名でないものがある。 CERT_TRUST_IS_NOT_VALID_FOR_USAGE 6 検証対象の証明書かパス上の証明書で指定された鍵使用法と合致しないものがある。 CERT_TRUST_IS_UNTRUSTED_ROOT 7 証明書パスが信頼されないルート認証局に基づいている。 CERT_TRUST_REVOCATION_STATUS_UNKNOWN 8 検証対象の証明書かパス上の証明書で、失効状態が不明なものがある。 CERT_TRUST_IS_CYCLIC 9 証明書パスが循環している。 CERT_TRUST_INVALID_EXTENSION 10 無効な拡張がある。 CERT_TRUST_INVALID_POLICY_CONSTRAINTS 11 検証対象の証明書かパス上の証明書で、ポリシー制約拡張を持つものがあり、プリシマ

ッピングが禁止されているか、ポリシーが要求されているのにない証明書がある。 CERT_TRUST_INVALID_BASIC_CONSTRAINTS 12 検証対象の証明書かパス上の証明書で、基本制約拡張を持つものがあり、CA 制約かパス長制約に反する証明書がある。 CERT_TRUST_INVALID_NAME_CONSTRAINTS 13 検証対象の証明書かパス上の証明書で、無効な名前制約拡張がある CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT 14 検証対象の証明書かパス上の証明書で、サポートしていないフィールドを持つ名前制約

拡張を持つものがある。minimum フィールドと maximum フィールドはサポートしていない。したがって、minimum値は常に 0として、maximum値はあってはいけない。otherName としては MicrosoftUPN(1.3.6.1.4.1.311.20.2.3)がサポートされている。x400Address、ediPartyName、registeredIDはサポートされていない。 CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT 15 検証対象の証明書かパス上の証明書で、名前制約拡張があるが、証明書の名前に使われ

ているフィールドに関する制約がない。 CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT 16 検証対象の証明書かパス上の証明書で、名前制約拡張を持つものがあり

permittedSubtreesフィールドがあるが、許可されていない名前を持つ証明書がある。

Page 39: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

33

エラーコードの定義値 # 意味 CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT 17 検証対象の証明書かパス上の証明書で、名前制約拡張を持つものがあり、

excludedSubtreesフィールドがあるが、受け付けられない名前を持つ証明書がある。 CERT_TRUST_IS_OFFLINE_REVOCATION 18 検証対象の証明書かパス上の証明書に関する失効情報は、オフラインでものであるか古

い。 CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY 19 ポリシー制約拡張でポリシーが要求されているが、要求されたポリシーを満たさないも

のがある。 証明書パスに関するエラー

CERT_TRUST_IS_PARTIAL_CHAIN 20 証明書パスが完結していない。 CERT_TRUST_CTL_IS_NOT_TIME_VALID 21 この証明書パスを構築するために使った CTLが古い。 CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID 22 この証明書パスを構築するために使った CTLに有効な署名がない。 CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE 23 この証明書パスを構築するために使った CTLの使用法は適切ではない。

参照情報(エラーではない) CERT_TRUST_HAS_EXACT_MATCH_ISSUER 24 適切な発行元の証明書が存在する。 CERT_TRUST_HAS_KEY_MATCH_ISSUER 25 適切な鍵を持つ発行元の証明書が存在する。 CERT_TRUST_HAS_NAME_MATCH_ISSUER 26 適切な名前を持つ発行元の証明書が存在する。 CERT_TRUST_IS_SELF_SIGNED 27 自己署名の証明書である。 CERT_TRUST_IS_COMPLEX_CHAIN 28 証明書パスは複数ある。 CERT_TRUST_HAS_PREFERRED_ISSUER 29 適切な発行元を持つ。 CERT_TRUST_HAS_ISSUANCE_CHAIN_POLICY 30 ポリシーを持つ。 CERT_TRUST_HAS_VALID_NAME_CONSTRAINTS 31 有効な名前制約を持つ。

1.1.18 CertVerifyRevocationによる証明書ステータスの取得

「Auxiliary Functions」に分類される関数 CertVerifyRevocationを使って、証明書のステータスを確認できる。前述の「Certificate Verification Functions」の関数が証明書パスに対する処理を行うのに対し、この関数では、個々の証明書コンテキストを入力とし、単一の証明書のス

テータスを取得するのが目的である。 この関数の特筆すべき点は、任意の失効検証ルーチンを開発し Revocation Providersとしてシステムに登録しておくと、関数内部で、登録されている失効検証ルーチンを呼び出すことだ。こ

Page 40: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

34

れにより、開発者は、CryptoAPI標準の失効検証ルーチン以外の失効検証ルーチンを提供することが可能となる。Revocation Providersの実装については、「5. (2) Revocation Providerの実装」で解説する。

(1) CertVerifyRevocationを使った失効検証

CertGetCertificateChain と異なり、CertVerifyRevocationでは複数の証明書コンテキストを配列にして渡すことができる。図 4-12 に CertVerifyRevocationを使った失効ステータスの取得の例を示す。プログラムの全体は付録の cpkicval.cppを参照のこと。 引数で使われる CERT_REVOCATION_PARA構造体の詳細は図 5-4に示した。

// 検証のパラメータをセットします。

DWORD dwFlags = 0;

dwFlags |= CERT_VERIFY_REV_CHAIN_FLAG;

dwFlags |= CERT_VERIFY_CACHE_ONLY_BASED_REVOCATION;

dwFlags |= CERT_VERIFY_REV_ACCUMULATIVE_TIMEOUT_FLAG;

dwFlags = 0;

pPara = (CERT_REVOCATION_PARA )

malloc(sizeof(CERT_REVOCATION_PARA));

memset(pPara, 0x00, sizeof(CERT_REVOCATION_PARA));

pStatus = (CERT_REVOCATION_STATUS)

malloc(sizeof(CERT_REVOCATION_STATUS));

memset(pStatus, 0x00, sizeof(CERT_REVOCATION_STATUS));

pStatus->cbSize = sizeof(CERT_REVOCATION_STATUS);

BOOL bRet = ::CertVerifyRevocation(

X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,

CERT_CONTEXT_REVOCATION_TYPE, /*固定値*/

1, /*証明書コンテキスト配列の数*/

(void **)pCertContext, /*検証する証明書コンテキスト配列*/

dwFlags,

pPara,

pStatus);

if (bRet) {

cout << "有効な証明書です。" << endl;

} else {

Page 41: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

35

cout << "無効な証明書です。" << endl;

cout << “ステータス : ”<< pStatus ->dwError << endl;

cout << “失効理由: ”<< pStatus -> dwReason << endl;

}

図 4-12 CertVerifyRevocation を使った失効ステータス取得の例

(2) 既存のアプリケーションについて

一般的な CryptoAPIを使ったアプリケーションでも、CertVerifyRevocationを使った失効検証を行っている。その場合、アプリケーションでの設定が必要となる場合がある。以下に設定に

ついて記す。

(a) Outlook Express の設定

ツール」メニューの「オプション」の「セキュリティ」タブで「セキュリティの詳細設定」を

開く。そこで、「デジタル IDが取り消されているか確認する」の「オンラインのときのみ」をチェックする。

(b) Internet Explorer の設定

インターネットオプションの「詳細設定」で「サーバー証明書の取り消しを確認する」をチェ

ックする。

(c) IPsec/ISAKMPでの PKI利用時の設定

IPsec/ISAKMPでのネゴシエーションに公開鍵証明書を利用する場合、CRL-DPを元に CRLを取得し失効検証をさせるためには設定が必要である。レジストリにキー

HKEY_LOCAL_MACHINE¥SYSTEM¥CurrentControlSet¥Services¥PolicyAgent¥Oak

ley

を追加して、 DWORD値の値「StrongCrlCheck」を追加 StrongCrlCheck が 0 の場合、CRLによる検証を行わない。 StrongCrlCheck が 1 の場合、CRLによる検証を行う。 StrongCrlCheck が 2 の場合、CRLによる検証を行い、かつ、適正な CRLが取得できないよ

うな場合、無効な証明書として扱う。 値を追加、変更した後は、コマンドプロンプトから

Page 42: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

36

>net stop policyagent

>net start policyagent

を実行すると、設定が有効となる。

(3) CRLのキャッシュ

標準の cryptnet.dllでは、取得した CRLをキャッシュする。キャッシュに使う場所は、Internet Explorerの Temporary Internet Filesなどである。

Page 43: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

37

(4) デジタル署名とデジタル署名の検証

1.1.19 関連する関数の解説

公開鍵証明書を使ったデジタル署名に関連する関数を表 4-10に示す。この関数を使ってsignedDataを contentとしてもつ CMSを処理する。

表 4-10 公開鍵証明書を使ったデジタル署名を扱う関数

関数 説明 CryptSignMessage デジタル署名をする。 CryptVerifyMessageSignature デジタル署名の検証をする。

1.1.20 デジタル署名を行うサンプルプログラム

図 4-13に公開鍵証明書による CMSのデジタル署名を行う例を示す。

CRYPT_SIGN_MESSAGE_PARA SigParams;

PCCERT_CONTEXT *m_pSignerCert; //署名者の証明書コンテキスト

BYTE *pbIn // 署名対象のデータ

DWORD cbIn // 署名対象のデータのサイズ

BYTE* pbOut; // 処理結果の CMS

DWORD cbOut; // 処理結果の CMSのサイズ

const BYTE* MessageArray[1];

DWORD MessageSizeArray[1];

MessageArray[0] = pbIn;

MessageSizeArray[0] = cbIn;

//-- CRYPT_SIGN_MESSAGE_PARA を作る

SigParams.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);

SigParams.dwMsgEncodingType =

PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;

SigParams.pSigningCert = m_pSignerCert;

SigParams.HashAlgorithm.pszObjId = szOID_OIWSEC_sha1; // SHA1 を指定

SigParams.HashAlgorithm.Parameters.cbData = NULL;

SigParams.pvHashAuxInfo = NULL;

Page 44: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

38

// 署名者の証明書のみ証明書を添付

SigParams.cMsgCert = 1;

SigParams.rgpMsgCert = &m_pSignerCert;

// 署名付属性の署名時刻を指定

pAttr = new CRYPT_ATTRIBUTE[1];

pBlob = new CRYPT_ATTR_BLOB[1];

FILETIME time;

::GetSystemTimeAsFileTime(&time);

::GetEncodedObject(szOID_RSA_signingTime,

&time, (void **)&(pBlob[0].pbData), &(pBlob[0].cbData));

pAttr[0].pszObjId = szOID_RSA_signingTime;

pAttr[0].cValue = 1;

pAttr[0].rgValue = &pBlob[0];

SigParams.cAuthAttr = 1;

SigParams.rgAuthAttr = pAttr;

SigParams.cUnauthAttr = 0;

SigParams.rgUnauthAttr = NULL;

SigParams.dwFlags = 0;

SigParams.dwInnerContentType = 0;

if (!::CryptSignMessage(

&SigParams,

FALSE, //オペイク署名を指定

1, // メッセージ配列の数

MessageArray,

MessageSizeArray,

NULL,

&cbOut)) { // バッファのサイズ

DWORD dwErr = ::GetLastError();

return;

}

if(!(pbOut =

(BYTE*)malloc(cbOut))) {

return;

Page 45: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

39

}

if (!::CryptSignMessage(

&SigParams,

FALSE, //オペイク署名を指定

1,

MessageArray,

MessageSizeArray,

pbOut,

&cbOut)) {

DWORD dwErr = ::GetLastError();

return;

}

図 4-13 CMS signedData を作成する例

1.1.21 デジタル署名の検証行うサンプルプログラム

図 4-14に CMSのデジタル署名を検証し、署名者の証明書コンテキストを得る例を示す。

BYTE *pbIn // 署名データ

DWORD cbIn // 署名データのサイズ

BYTE* pbOut; // オペイク署名の場合の署名対象データ

DWORD cbOut; // オペイク署名の場合の署名対象データのサイズ

PCCERT_CONTEXT * pSignerCert=NULL;//署名者の証明書コンテキストを得る

CRYPT_VERIFY_MESSAGE_PARA VerifyParams;

VerifyParams.cbSize = sizeof(CRYPT_VERIFY_MESSAGE_PARA);

VerifyParams.dwMsgAndCertEncodingType =

PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;

VerifyParams.hCryptProv = 0;

/* 次は、 証明書が添付されていない signedDataの場合には、署名者の証明書コンテキストを

得るためのコールバック関数を指定する。*/

VerifyParams.pfnGetSignerCertificate = NULL;

/*コールバック関数に渡す構造体*/

VerifyParams.pvGetArg = NULL;

if (!::CryptVerifyMessageSignature(

Page 46: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

40

&VerifyParams,

0,

pbIn, cbIn, NULL, &cbOut,

NULL)) {

DWORD dwErr = ::GetLastError();

return;

}

if(!(pbOut = (BYTE*)malloc(cbDecodedMessageBlob))) {

return;

}

if (!::CryptVerifyMessageSignature(

&VerifyParams,

0,

pbIn, cbIn, pbOut, &cbOut,

&pSignerCert)) {

DWORD dwErr = ::GetLastError();

return;

}

図 4-14 CMS signedData から署名者の証明書コンテキストを得る例

Page 47: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

41

(5) 証明書および秘密鍵のインポート/エクスポート

1.1.22 関連する関数の解説

証明書のインポートは、証明書ファイルから、証明書コンテキストを作成し、証明書ストアへ

追加する。エクスポートは証明書ストアから取得した証明書コンテキストからデータ部分をファ

イルに格納する。これらは「(2) 証明書ストア」で解説しているので、ここでは省略する。 秘密鍵を含めたインポート/エクスポートでつかわれる PKCS #12フォーマットについては、表 4-11で示すような関数が用意されている。

表 4-11 PKCS #12 を扱う関数

関数 説明 PFXExportCertStoreEx 引数に指定された証明書ストアにある証明書と関連する秘密

鍵を、引数に指定されたパスワードで保護して PKCS #12フォーマットで取り出す。

PFXImportCertStore 引数に指定されたPKCS #12フォーマットのデータとパスワードからから関連する秘密鍵を取り出し、内部の証明について

は、戻り値の証明書ストアハンドルで参照可能とする。 PFXIsPFXBlob PKCS #12フォーマットのデータかチェックする。 PFXVerifyPassword PKCS #12のパスワードであるかチェックする。

1.1.23 証明書および秘密鍵のインポートを行うサンプルプログラム

図 4-15に PKCS #12ファイルから秘密鍵をインポートする例を示す。PFXImportCertStoreの戻り値として得た証明書ストアハンドルから、PKCS #12ファイルに入っている証明書が獲得できるので、これを適切な証明書ストアに追加する。プログラムの全体は付録の cpkicimp.cppを参照のこと。

CFile file;

file.Open(szPkcs12, CFile::modeRead);

pfx.cbData = file.GetLength();

pfx.pbData = (BYTE *)calloc(pfx.cbData, sizeof(BYTE));

file.Read(pfx.pbData, pfx.cbData);

file.Close();

int len = strlen(szPassword);

wPsw = (wchar_t *)calloc(len+1, sizeof(wchar_t));

mbstowcs(wPsw, szPassword, len);

// PKCS #12 フォーマットのチェック

Page 48: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

42

if (!::PFXIsPFXBlob(&pfx)) {

cerr << szPkcs12<< " は PKCS #12 ファイルではありません。" << endl;

return;

}

// パスワードのチェック

if (!::PFXVerifyPassword(&pfx, wPsw, 0)) {

cerr << "PKCS #12 ファイルのパスワードが違います。" << endl;

return;

}

HCERTSTORE hP12CertStore = NULL;

// 秘密鍵は適切に保管され PKCS #12にある証明書について証明書ストアとして参照可能にな

る。

hP12CertStore = ::PFXImportCertStore(

&pfx,

wPsw,

CRYPT_EXPORTABLE|CRYPT_USER_KEYSET);

if (hP12CertStore == NULL) {

cerr << " PKCS #12 ファイルのインポートに失敗しました。" << endl;

DWORD dwErr = ::GetLastError();

return;

}

図 4-15 PKCS #12 ファイルから秘密鍵をインポートする例

Page 49: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

43

1.1.24 証明書および秘密鍵のエクスポートを行うサンプルプログラム

図 4-16に PKCS #12ファイルへ秘密鍵と証明書をエクスポートする例を示す。ファイルを一時的な証明書ストアとして使い、そこに対象の証明書コンテキストを追加する。その証明書スト

アハンドルを PFXExportCertStoreの引数とすることで、PKCS #12のデータが作成される。プログラムの全体は付録の cpkicexp.cppを参照のこと。

HANDLE hFile;

HCERTSTORE hFileStore;

TCHAR szTempFile[_MAX_PATH];

::GetTempFileName(".", "sto", 1, szTempFile);

hFile = ::CreateFile(

szTempFile,

GENERIC_READ|GENERIC_WRITE,

0, // 共有モード

NULL, // セキュリティ

OPEN_ALWAYS,

FILE_ATTRIBUTE_NORMAL,

NULL);

// ファイルを一時証明書ストアとして開く

hFileStore = ::CertOpenStore(CERT_STORE_PROV_FILE,

0, // エンコードタイプは指定なし

NULL, // デフォルトのプロバイダを使う。

CERT_STORE_READONLY_FLAG,

hFile );

// 秘密鍵をエクスポートしたい対象の証明書コンテキストをストアに追加

::CertAddCertificateContextToStore(hFileStore,

pCertContext,

CERT_STORE_ADD_ALWAYS,

NULL);

// パスワード

int len = strlen(szPassword);

wPsw = (wchar_t *)calloc(len+1, sizeof(wchar_t));

mbstowcs(wPsw, szPassword, len);

Page 50: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

44

// PKCS #12へ

// サイズを獲得

pfx.pbData = NULL;

if (!::PFXExportCertStore(hFileStore,

&pfx,

wPsw,

EXPORT_PRIVATE_KEYS))

{

cerr << "PKCS #12の作成に失敗しました。" << endl;

DWORD dwErr = ::GetLastError();

return;

}

pfx.pbData = (BYTE*)malloc(pfx.cbData);

::PFXExportCertStore(hFileStore,

&pfx,

wPsw,

EXPORT_PRIVATE_KEYS))

// ファイルへ保存

CFile file;

file.Open(szPkcs12File, CFile::modeCreate|CFile::modeWrite);

file.Write(pfx.pbData, pfx.cbData);

file.Close();

// 証明書ストアを閉じる

CertCloseStore(

hFileStore,

CERT_CLOSE_STORE_CHECK_FLAG);

//証明書ストアに使ったファイルを閉じる

CloseHandle(hFile);

CFile::Remove(szTempFile);

cout << pszNameString << endl;

cout << " 証明書を秘密鍵とともにエクスポートしました。" << endl;

図 4-16 PKCS #12 ファイルへ秘密鍵と証明書をエクスポートする例

Page 51: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

45

5. CryptoAPIのプロバイダの実装

本節では CryptoAPIにおいて、開発者が組み込み可能なサービスプロバイダとして、以下の2つを取り上げる。 Crypto Service Provider Revocation Provider

(1) Crypto Service Provider

CSPを開発する上で重要なポイントとなるのが CSPの署名である。 これは AuthentiCodeや CodeSigningのような PKIに枠組みの中で、権限を証明書の保持者が署名し実行時に検証されるものではなく、開発者が米国のMicrosoft社に申請し、CSPに署名を施されるものである。OSではアプリケーションが CSPをロードする際にその署名の正当性を検証している。 署名は独自の形式であり、Microsoft社で所定の手順に則り付与されている。そのため、CSPの開発者は CSPの開発キット”CSPDK(Cryptographic Service Provider Developer's Toolkit)”を入手し、正式な署名を獲得するまでは、この開発キットに含まれるツールを用いて署名検証の

プロセスを代替することなる。以下にこの CSPDKを用いた開発の手順を示す。

1.1.25 開発手順

CSPの開発手順は以下のステップを踏む。 8. CryptoSPIを持った CSPを開発する。 9. CSPのセットアッププログラムを開発する 10. テスト用の署名を生成する。 11. CSPをテストする。 12. Microsoft社から CSPに署名を得る。 13. 署名された CSPをテストする。

このうち、8から10の手順について次に解説する。

(1) CSPDK(Cryptographic Service Provider Developer's Toolkit)のダウンロードと動作確認

(a) ダウンロードと展開

以下のMicrosoft社の開発者向けのダウンロードサイトでキーワードに”CSPDK”と入力して検索して示されるリンク先より CSPDKをダウンロードする。

http://msdn.microsoft.com/downloads/ ダウンロードした圧縮ファイル cspdk.exeを解凍すると、表 5-1のようなディレクトリ構成に

なっている。

Page 52: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

46

表 5-1 CSPDK(Cryptographic Service Provider Developer's Toolkit)の内容

ディレクトリ ファイル 説明 ¥ readme.txt cspSign.exe CSPのテスト用署名清々ツール csp.dll サンプルの CSP csp.sig サンプルの CSPの署名ファイル testcsp.exe サンプルの CSPを利用するテストプログラム cspinstl.exe サンプルの CSPをセットアップするプログラム ¥csp サンプルの CSPのソースコード ¥testcsp テストプログラム testcsp.exeのソースコード ¥cspinstl セットアッププログラム cspinstl.exeのソースコード ¥sdkinc C言語のヘッダファイル ¥doc Windows 2000 ログイン画面に関するドキュメント OS ごとのディレクトリ

advapi32.dl_ 圧縮された advapi32.dll

(b) advapi32.dllの置換とテストプログラムの実行

プログラムは CSPを利用するにあたって、advapi32.dllでエクスポートされている関数CryptAcquireContext を呼び出す。このとき CryptAcquireContextの内部では、CSPをロードする際に、その署名を検証している。CSPDKに同梱された advapi32.dllはこの署名検証をcspSign.exeで生成されたテスト用の署名を有効と判断するものである。CSP開発者は、Microsoft社の署名を受ける前に、通常の advapi32.dllを置き換えてテスト用の署名を使い開発する。 ここで注意しなければならないのは、同梱されている advapi32.dllは英語版のWindowsの各バージョンに対応したものだ。確認した範囲では日本語のWindowsで利用可能な advapi32.dllはWindows NT4.0とWindows98のものである。

Windows98では起動後にシステム関連のファイルを置換できるが、Windows NT4.0では、起動中はシステムのファイルを置換出来ないので、PCのリムーバブルメディアを使って他の OSで起動して、対象の OSのシステムディレクトリにコピーする。同梱されているテストプログラムを稼動させるまでの手順は以下のようになる。

1. expandコマンドを使って、advapi32.dl_を伸張し advapi32.dllを作る。 2. %systemroot%¥system32(Windows98では、windows¥system)の advapi32.dllをバックア

ップし、用意した advapi32.dllと置き換える。 3. csp.dllを%systemroot%¥system32にコピーする。 4. csp.sigを cspsignにリネームする。 これは cspinstl.exeが署名ファイルとして参照するが、cspinstl.exeのソースコードではファ

イル名が cspsignとしてコーディングされているためである。

Page 53: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

47

5. cspinstl.exeを実行する。

これにより、レジストリに以下のようなキーと値が登録される。

HKEY_LOCAL_MACHINE¥SOFTWARE¥Microsoft¥Cryptography¥Defaults¥Provider

¥CSP Provider

文字列の値 Image Path:csp.dll

バイナリの値 Signature:(署名データである cspsignの内容 136バイト)

DWORDの値 Type:0x00000384(900) Provider Type

1. コマンドプロンプトでテストプログラム testcsp.exeを実行する

CSPとして csp.dllをロードし一連の CryptoSPIの各関数の呼び出しのテストを行い、結果を

表示する。

Calling CryptAcquireContext - CryptAcquireConext returned error 80090019

FAILED

などと表示された場合は、csp.dllのセットアップが正しく行われていない。 以上で、動作確認は終了である。次に開発した CSPをテストするために署名とセットアップについて解説する。

(2) CSPの署名とセットアップ

Windows 2000以前の OSでは、前述の例のように、署名データはレジストリにバイナリの値“Signature”として格納していた。

Windows 2000からは署名データを dllファイルにリソースとして保持することが可能となっている。dllファイルにリソース IDが 0x29A(666)のリソースがあった場合、署名データとして扱われる。リソースとして署名データを持つ場合、レジストリには“Signature”のかわりにDWORD値の”SigInFile”で値のデータを“0”とする。署名データの操作は同梱されているcspSign.exeによって行う。

cspSign.exeの使用方法を次に示す。

Page 54: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

48

(a) cspSign.exeによるテスト用署名の生成

CSPの署名データは、表 5-2のようにして生成する。

cspSign <オプション> <CSP ファイル> [<署名ファイル>]

表 5-2 テスト用署名ツール cspSign のオプション

オプション 説明 C <CSPファイル>を指定して実行する。署名データをリソースに格納する。 S <CSP ファイル>と[<署名ファイル>]を指定して実行する。署名データがファイ

ルに格納される。 D <CSP ファイル>を指定して実行する。リソースの署名データから署名検証を行

う。 V <CSP ファイル>と[<署名ファイル>]を指定して実行する。署名ファイルの署名

データから署名検証を行う。 リソースタイプの署名を使うためには、開発する CSPのリソースファイルは図

5-1のようにする。 ここで、署名データの大きさ 144バイトに相当するダミーのファイル(csp.sig)を用意する。次のようにコマンドを実行することによって、この 144バイトのリソースが適切な署名データに置き換わる。

> cspSign -c <CSP ファイル>

2 TEXTINCLUDE DISCARDABLE

BEGIN

"#include ""cspdk.h""¥0"

END

CRYPT_SIG_RESOURCE_NUMBER RCDATA DISCARDABLE "csp.sig"

図 5-1 CSP のリソースファイル

(b) セットアップ

開発した CSPをレジストリに登録するために、CSPには、CryptoSPIの関数以外に、図 5-2のように DllRegisterServerと DllUnregisterServerの 2つの関数を記述しエクスポートする。

DllRegisterServerでは、レジストリに Provider Nameをキーとして、ImagePath、Provider Type、Signatureまたは SigInFileがセットする。DllUnregisterServerではレジストリから自身の Provider Nameのキーを削除する。これにより、以下のコマンドを実行するとそれぞれの

Page 55: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

49

関数が呼び出され、レジストリへの操作が行われる。

(c) レジストリへの登録コマンド

> regsvr32 CSP ファイル

(d) レジストリからの削除コマンド

regsvr32 /u CSP ファイル

void DllRegisterServer (void)

{

レジストリに値を登録

}

void DllUnregisterServer (void)

{

レジストリの値を削除

}

図 5-2 レジストリへの登録/削除の関数

これとは別に、cspinstl.exeのように、セットアッププログラムが必要なキーと値を直接レジストリに書く込むことも可能である。 その場合、Windows NT4などの署名データをリソースとしてではなく、レジストリに登録する必要がある OSを考慮して、cspinstl.exeでは、署名データのファイルを読み込んで、レジストリに登録することもあわせて行っている。

1.1.26 単純な換字暗号を実装した CSPのサンプルプログラムの解説

付録に CSPのサンプルプログラム cpkicsps.cを添付した。サンプルのなかから、暗号化部分について図 5-3に示す。

// アルゴリズムのパラメータを保持する構造体

typedef struct tagMyAlgorithmParam {

BYTE *m_pData;

DWORD m_nDataLen;

} MyAlgorithmParam;

Page 56: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

50

// 処理中のデータを保持する構造体

typedef struct tagMyKeyParam {

BYTE m_nBits; // 暗号鍵

void *m_pOption; // 未使用

} MyKeyParam;

MyAlgorithmParam *g_pParam = NULL;

MyKeyParam *g_pKey = NULL;

// CrypotSPI 初期化

BOOL WINAPI CPAcquireContext(

OUT HCRYPTPROV *phProv,

IN LPCSTR szContainer,

IN DWORD dwFlags,

IN PVTableProvStruc pVTable) {

g_pParam = (MyAlgorithmParam *)malloc(sizeof(MyAlgorithmParam));

*phProv = (HCRYPTPROV)g_pParam;

g_pParam->m_pData = NULL;

g_pParam->m_nDataLen = 0;

return TRUE;

}

// CrypotSPI 開放

BOOL WINAPI CPReleaseContext(

IN HCRYPTPROV hProv,

IN DWORD dwFlags)

{

free((MyAlgorithmParam *)hProv);

return TRUE;

}

// CrypotSPI 鍵生成

BOOL WINAPI CPGenKey(

IN HCRYPTPROV hProv,

Page 57: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

51

IN ALG_ID Algid,

IN DWORD dwFlags,

OUT HCRYPTKEY *phKey)

{

g_pKey = (MyKeyParam *)malloc(sizeof(MyKeyParam));

g_pKey->m_nBits = (BYTE)(BASE_ADDITION + (dwFlags & 0xff));

g_pKey->m_pOption = NULL;

*phKey = (HCRYPTKEY)g_pKey; // Replace NULL with your own

structure.

return TRUE;

}

// CrypotSPI 暗号化

BOOL WINAPI CPEncrypt(

IN HCRYPTPROV hProv,

IN HCRYPTKEY hKey,

IN HCRYPTHASH hHash,

IN BOOL fFinal,

IN DWORD dwFlags,

IN OUT LPBYTE pbData,

IN OUT LPDWORD pcbDataLen,

IN DWORD cbBufLen)

{

BYTE *pBuf = NULL;

DWORD dwPrevLen = 0;

DWORD dwLen = 0;

DWORD n;

BYTE bAddition;

// 初期化済みか確認

if (hProv == NULL)

return FALSE;

if (pbData == NULL) {

// 暗号化した結果のデータの長さを通知する。

*pcbDataLen = ((MyAlgorithmParam *)hProv)->m_nDataLen;

return TRUE;

}

dwPrevLen = ((MyAlgorithmParam *)hProv)->m_nDataLen;

Page 58: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

52

dwLen = dwPrevLen + cbBufLen;

pBuf = realloc(((MyAlgorithmParam *)hProv)->m_pData,

dwLen);

memcpy(pBuf+dwPrevLen, pbData, cbBufLen);

((MyAlgorithmParam *)hProv)->m_pData = pBuf;

((MyAlgorithmParam *)hProv)->m_nDataLen = dwLen;

// 最終データでなければ戻る。

if (!fFinal)

return TRUE;

bAddition = ((MyKeyParam *)hKey)->m_nBits;

// 最終データなので、暗号化して戻る。

for (n = 0; n < dwLen; ++n) {

pBuf[n] += bAddition;

}

*pcbDataLen = *pcbDataLen >= dwLen ? *pcbDataLen : dwLen;

memcpy(pbData, pBuf, *pcbDataLen);

return TRUE;

}

図 5-3 CSP の暗号化のサンプルプログラム

Page 59: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

53

(2) Revocation Providerの実装

CryptoAPIでは証明書の検証のための機能をプロバイダとして、追加や置換することが可能である。この証明書の検証のためのプログラムを Revocation Providerと呼ぶ。

1.1.27 関連する関数の解説

Revocation Providerは図 5-4に示す関数を実装してエクスポートする。 BOOL WINAPI CertDllVerifyRevocation(

DWORD dwEncodingType,

DWORD dwRevType,

DWORD cContext,

PVOID rgpvContext[ ],

DWORD dwFlags,

PCERT_REVOCATION_PARA pRevPara,

PCERT_REVOCATION_STATUS pRevStatus

)

戻り値:TRUE:有効な証明書。FALSE:無効な証明書

引数:

dwEncodingType

[入力]引き渡したデータのフォーマットを示す。以下の定義値をセットされている。

X509_ASN_ENCODING | PKCS_7_ASN_ENCODING

dwRevType

[入力]rgpvContextにて引き渡すデータの種別を示す。以下の定義値がセットされている。

CERT_CONTEXT_REVOCATION_TYPE

cContext

[入力]rgpvContext配列の数。

rgpvContext

[入力]検証対象の証明書を CERT_CONTEXT構造体の配列として渡す。

dwFlags

[入力]検証処理の動作フラグとして以下の定義位置がセットされている。

CERT_VERIFY_REV_CHAIN_FLAG : 0番目の証明書から順に発行元からと仮定してよい。

CERT_VERIFY_CACHE_ONLY_BASED_REVOCATION:キャッシュのみを使う。

CERT_VERIFY_REV_ACCUMULATIVE_TIMEOUT_FLAG:dwUrlRetrievalTimeout タイム

アウト値を参照する。

Page 60: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

54

pRevPara

[入力]CERT_REVOCATION_PARA構造体を使い、パス構築に必要なCTL、証明書、CRLを格納し

た証明書ストアのハンドルを渡すために使う。rgCertStore に証明書ストアハンドルの配列を指

定し、cCertStoreには配列の数を指定する。

typedef struct _CERT_REVOCATION_PARA {

DWORD cbSize; 本構造体のサイズをセット

PCCERT_CONTEXT pIssuerCert; 発行元証明書

DWORD cCertStore; 参照すべき証明書ストアの数

HCERTSTORE *rgCertStore; 参照すべき証明書ストア

HCERTSTORE hCrlStore; 参照すべき CRLストア

LPFILETIME pftTimeToUse; 検証時刻として使う。

DWORD dwUrlRetrievalTimeout; URLへのタイムアウト値

BOOL fCheckFreshnessTime; dwFreshnessTime を使う

DWORD dwFreshnessTime;

LPFILETIME pftCurrentTime; 検証時刻として使う。

PCERT_REVOCATION_CRL_INFO pCrlInfo;ベース CRL とデルダ CRL

} CERT_REVOCATION_PARA, *PCERT_REVOCATION_PARA;

dwFreshnessTime の使い方:

ThisUpdate >= (CurrentTime - dwFreshnessTime) の場合に CRLを探す。

pRevStatus

[入力/出力]以下の構造体のポインタが渡され、終了時に処理結果をセットする。

typedef struct _CERT_REVOCATION_STATUS {

DWORD cbSize; 本構造体のサイズをセット

DWORD dwIndex;

DWORD dwError;

DWORD dwReason;

BOOL fHasFreshnessTime;

DWORD dwFreshnessTime;

} CERT_REVOCATION_STATUS;

dwIndex:検証した証明書の rgpvContextでの順番

dwError:以下の定義値をセットする。

ERROR_SUCCESS 有効な証明書である。

CRYPT_E_NO_REVOCATION_CHECK:検証完了しなかった

Page 61: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

55

CRYPT_E_REVOKED:無効な証明書である。

dwReason:証明書が失効していた場合、以下のような失効理由をセットする。

CRL_REASON_UNSPECIFIED 理由なし

CRL_REASON_KEY_COMPROMISE 鍵の危殆化

CRL_REASON_CA_COMPROMISE CAの危殆化

CRL_REASON_AFFILIATION_CHANGED 属性変更

CRL_REASON_SUPERSEDED 更新されている

CRL_REASON_CESSATION_OF_OPERATION 使われなくなった

CRL_REASON_CERTIFICATE_HOLD 保留中

図 5-4 Revocation Provider でエクスポートする関数

Revocation Providerでは関数 CertDllVerifyRevocation 以外に、CSPと同様にセットアップ用の関数として、DllRegisterServerと DllUnregisterServerの 2つの関数を記述しエクスポートする。これにより、CSPと同様、regsvr32コマンドを使い、図 5-6に示すようなレジストリへの登録/削除の処理が行われる。

OSの標準では cryptnet.dll、mscrlrev.dll などがあらかじめ登録されている。

Page 62: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

56

1.1.28 証明書の有効/無効を通知する Revocation Providerサンプルプログラムの解説

付録に証明書の有効/無効を UIにより指定し、通知するサンプルプログラム(cpkicrp.dll)のソースを添付する。 サンプルの証明書検証プログラム(cpkicval.exe)を次のようにコマンドプロンプトで実行す

ると、図 5-5のような画面が表示されマニュアルで失効情報を指定することが可能である。

> cpkicval. -r 証明書ファイル

図 5-5 サンプルの Revocation Provider が呼ばれたところ

Page 63: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

57

(3) その他の拡張可能な関数

Revocation Provider以外にも CryptoAPIの関数を置換することが可能である。表 5-3に想定されている関数を示す。これらも、Revocation Providerと同様にレジストリに登録すると、プログラムでは標準の関数を呼び出すと Crypt32.dllがレジストリを参照し適切に処理する。

表 5-3 CryptoAPI の拡張可能な関数

CryptoAPI の関数 プロバイダでエクスポートす

る関数

説明

CryptEncodeObject CryptDllEncodeObject X.509や PKCSなどで規定されているデータ型のエンコードを行う。未

サポートのデータ型を使う場合など

に置換する。 CryptEncodeObjectEx CryptDllEncodeObjectEx CryptEncodeObjectの関数ないでの

メモリアロケーション機能付版

(Windows 2000、XP) CryptDecodeObject CryptDllDEcodeObject エンコードされた規定のデータを解

析し構造体に格納する。 CryptDecodeObjectEx CryptDllDEcodeObjectEx CryptDecodeObjectの関数ないでの

メモリアロケーション機能付版

(Windows 2000、XP) CertOpenStore CertDllOpenStoreProv 証明書ストアをオープンする。置換

することで、未サポートの証明書ス

トア形式を利用可能となる。 CertVerifyCTLUsage CertDllVerifyCTLUsage CTLの用途に関して検証する。検証

手順を拡張する場合に置換する。 これらの拡張関数のレジストリでの登録状態を図 5-6に示す。ロードされる dllファイルと関

数によっては呼び出す関数も指定できることが分かる。例えば、「RFC 2634 Enhanced Security Services for S/MIME」で定義されている署名つき受領通知はオブジェクト IDが1.2.840.113549.1.9.16.1.1であるが、inetcomm.dllでエクスポートされている関数EssReceiptEncodeExを呼び出すことがわかる。

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 1

CertDllVerifyCTLUsage

DEFAULT

CertDllVerifyRevocation

DEFAULT

Dll = cryptnet.dll

CryptDllDecodeObject

CryptDllDecodeObjectEx

CryptDllEncodeObject

CryptDllEncodeObjectEx

1.2.840.113549.1.9.16.1.1

Dll = cryptnet.dll

・・・・・・・

CryptDllFormatObject

Dll = inetcomm.dllFuncName = EssReceiptEncodeEx

Page 64: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

58

図 5-6 レジストリの拡張関数に関する情報

Page 65: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

59

6. まとめ

「4. (3) 証明書の検証」で述べたように、CryptoAPIの標準の機能では、証明書パス検証に関して RFC 3280で規定されているパス検証の初期パラメータ(表 4-8)を指定した検証はできない。 この問題に対処するためには、「5. (2) Revocation Providerの実装」で示すようなプラグイン可能な独自の失効検証ルーチンにパス構築/パス検証の機能を組み込みことが考えられる。ただ

し、Revocation Providerは名の示すとおり、本来は証明書の失効を確認することを主目的として用意されているインターフェイスであるため、受け渡し可能な引数には RFC 3280の初期パラメータは想定されていない。ファイルやレジストリなどを使った独自の手段を用いて渡す工夫が

必要となるであろう。

Page 66: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

60

7. 参考文献

[CAPIRV] Revocation Provider, http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsecure/html/rpcrypto.asp

[CAPITOOLS] CryptoAPIツール, http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/cryptoapi_tools_reference.asp

[CAPIVAL] CryptoAPIの証明書検証, http://www.microsoft.com/technet/treeview/default.asp?url=/technet/security/prodtech/dbsql/tshtcrl.asp

[DSS] DIGITAL SIGNATURE STANDARD (DSS), http://www.itl.nist.gov/fipspubs/fip186.htm

[NETFWTOOLS] NET Frameworkツール http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cptools/html/cpconnetframeworktools.asp?frame=true

[PKCS] Public-Key Cryptography Standards, http://www.rsasecurity.com/rsalabs/pkcs/

[RFC3280] RFC 3280 - Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile, htp://www.ietf.org/rfc/rfc3280.txt

Page 67: セキュリティ API に関する技術調査...15情経第1516号 セキュリティAPIに関する技術調査 - Part 3 - .NET Crypto API:機能と利用法 2004年2月 独立行政法人

61

8. 用語(参考)

Authenticode Microsoft社独自のプログラムへの署名スキームである。

CMS (Cryptographic Message Syntax) PKCS #7の後継の仕様であり、S/MIMEバージョン 3とともに IETFで議論され開発された。PKCS #7が公開鍵アルゴリズムとして、主として RSAを前提としていたのに対し、Diffie-Hellmanや DSAを取り入れている点などが異なる。PKCS #7に対しては下位互換性を持つ。 RFC 2630「Cryptographic Message Syntax」 RFC 2633「S/MIME Version 3 Message Specification」

MSIL(Microsoft Intermediate Language) .NETにおいては、プログラムの実行ファイルは従来の形式とことなり、MSILと呼ばれる CPU非依存のバイトコードと実行時に必要となる型情報などメタ情報によって構成されている。このバイトコードがネイティブコードに変換されてから実行される。 開発者はソースコードを.NET用のコンパイラでコンパイルすることによりMSILを作成することができる。

PEファイル コンパイラはソースコードからMSILの他に実行時に必要となる型情報などのメタデータも一緒に生成し、Portable Executable (PE)フォーマットと呼ばれるフォーマットで一つのファイルにまとめる。コンパイラによって生成された PEフォーマットファイルは、.exeや.dllといった拡張子を持つが従来の.exeファイルや.dllファイルとは異なる。 従来の.exeファイルはすでにそれ自体がネイティブコードであるが、.NET環境での.exeファイルは一度ネイティブコード変換されてから実行される。

PKCS #7 (Public Key Cryptography Standard #7) RSA Laboratoriesが開発したデジタル署名や暗号のデータフォーマットであり、後にRFCとなった。S/MIMEバージョン 2まではこのフォーマットを用いていた。 RFC 2315 「PKCS #7: Cryptographic Message Syntax Version 1.5」 RFC 2311 「S/MIME Version 2 Message Specification」

コンテキストハンドル コンテキストハンドルはオペレーティングシステムで使用するリソースに対する識別

IDである。実際のメモリアドレスを格納したポインタではない。