XML暗号化の方法を探る:第1回

構造化データを安全に交換する方法のデモ

XML暗号化は、構造化データを安全に交換する必要のあるアプリケーションのために、エンドツーエンドのセキュリティーを提供します。XMLはデータ構造化のテクノロジーとして最も広く使用されているものであり、XMLベースの暗号化は、データ交換アプリケーションでの複雑なセキュリティー要件を処理する自然な方法と言えます。この記事は2回にわたるシリーズの第1回です。Bilal氏が、W3CのXML暗号化のワーキング・ドラフトを踏まえて、XMLとセキュリティーの問題をどう処理できるかを説明します。

Bilal Siddiqui (wap_monster@yahoo.com), CEO, WAP Monster

Bilal SiddiquiはXMLのコンサルタントです。パキスタン、ラホールのUniversity of Engineering and Technologyで電子工学を学んだのち、1995年に産業制御システム向けのソフトウェア・ソリューションの設計を始めました。その後XMLに転向し、C++ のプログラミング経験を生かしてWebおよびWAPベースのXML処理ツール、サーバー・サイド構文解析ソリューション、およびサービス・アプリケーションの構築を行うようになりました。この記事に含まれているコード・ファイルの作業用コピーをご希望の方は、wap_monster@yahoo.com のBilalまで電子メールで連絡してください。



2002年 3月 01日

ゾーン・リーダーのコメント

この記事はW3C XML Encryptionの古いワーキングドラフトに基づいています。最新の仕様では、いくつかの点で重要な変更があります。最新の情報を得るには、W3Cの公式サイトhttp://www.w3.org/Encryption/2001/ を参照してください。

現在のところ、トランスポート層セキュリティー (TLS) が、インターネットにおける保護通信のデ・ファクト・スタンダードとなっています。TLSは、よく知られたSecure Socket Layer (SSL) に準拠したエンドツーエンドのセキュリティー・プロトコルです。SSLは、もともとNetscapeで設計されたものであり、そのバージョン3.0に対して、TLSを設計中のInternet Engineering Task Force (IETF) が後に手を加えたものです。これは、非常に安全性と信頼性の高いプロトコルであり、2者間のエンドツーエンド・セキュリティー・セッションを提供します。XML暗号化は、SSL/TLSを置き換えることを意図したものではありません。むしろ、SSLではカバーし切れないセキュリティー要件のためのメカニズムを提供するためのものです。SSLで対応できないこととして、以下に示す2つの重要な点があります。

  • 交換するデータの一部を暗号化すること
  • 2者以上での保護セッション

XML暗号化を使用した場合、どの通信者も、他者との間で保護状態または無保護状態を保つことができます。1つの文書の中で、保護データと無保護データの両方を交換できます。たとえば、ある保護機能付きチャット・アプリケーションがあるとします。それには、複数のチャット・ルームが含まれており、各チャット・ルームには複数の人が関係しています。チャット・パートナー相互の間ではXML暗号化ファイルを交換できますが、あるチャット・ルームのデータは、それ以外のチャット・ルームからは見えないようになっています。

XML暗号化では、XMLデータと非XMLデータ (バイナリー・データなど) を処理できます。以下に、XML暗号化によって保護された簡単なデータ交換の例を示します。セキュリティー要件を少しずつ複雑にしながら、XML暗号化スキーマとそのさまざまな要素の使い方について説明します。

XMLデータを安全に交換する簡単な例

リスト1 に示すXMLファイルを、ある出版会社に送るとします。このファイルには、購入したい本についての詳細なデータが含まれています。さらに、支払いに使用するクレジット・カードの情報も含まれています。当然、このような個人情報には保護通信を使用したいと思うことでしょう。1つの方法は、通信の全体を保護するSSLを使用することです。別の方法は、XML暗号化を使用することです。すでに述べたように、XML暗号化はSSL/TLSに代わるものではありません。通信の全体を保護する必要のあるアプリケーションなら、SSLを使用することでしょう。しかし、保護通信と無保護通信を組み合わせる (データの一部は保護した状態で交換し、それ以外の部分は元のまま交換する) ことの必要なアプリケーションの場合は、XML暗号化が最善です。

リスト1. 暗号化するサンプルXMLファイル
<purchaseOrder>
	<Order>
		<Item>book</Item>
		<Id>123-958-74598</Id>
		<Quantity>12</Quantity>
	</Order>
	<Payment>
		<CardId>123654-8988889-9996874</CardId>
		<CardName>visa</CardName>
		<ValidDate>12-10-2004</ValidDate>
	</Payment>
</purchaseOrder>

注:リスト1 のXMLファイルは、意図的に簡単なものにしてあります。それにより、暗号化の問題に注意を集中できます。共同コマースやWeb Servicesでの実際のXMLファイルは、構造としては似たようなものですが、もっと冗長です。WSDL (Webサービス記述言語) およびSOAP (Simple Object Access Protocol) は、B2B統合でしばしば使用されるXMLベースの文法です。WSDLでもSOAPでも、XML暗号化を使用することによって、企業全体にわたる保護通信を提供できます。詳細については、W3Cのサイトをご覧ください (参考文献を参照)。

XML暗号化による文書全体の暗号化

XML暗号化には、さまざまなオプションがあります。リスト2リスト3、およびリスト4 に、それぞれ異なる暗号化の結果を示します。1つずつ詳しく見てみましょう。

リスト2 は、リスト1 のXML文書全体を暗号化した場合のXML暗号化ファイルです。<CipherData><CipherValue> のタグに注目してください。<CipherValue> タグの内容が、実際の暗号化データです。CipherData 要素は、EncryptedData 要素の中に含まれています。EncryptedData 要素には、暗号化に使用されるXML名前空間が含まれています。たとえば、暗号化前の元のデータはXMLであり、Internet Assigned Numbers Authority (IANA) によるXMLの公式の型定義は、http://www.isi.edu/in-notes/iana/assignments/media-types/text/xmlです。このことは、Type 属性の値に示されています。XML暗号化では、RTF、PDF、JPGなど、広く使用されているさまざまなデータ形式に関して、IANAによる型定義が使用されます。詳しくは、対応するWebサイトをご覧ください (参考文献を参照)。特別なアプリケーション・データ型 (各企業のコンテンツ・マネージメント・システムに属する独自のDTDやXSDなど) の場合は、それをEncryptedData 要素のType 属性に指定できます。もう1つの属性xmlnsは、XMLデータの暗号化に使用したXML暗号化名前空間を指定します。

XML暗号化による単一要素の暗号化

リスト1 のうち、1つの要素 (たとえばPayment 要素) だけを暗号化したいと思うかもしれません。その結果を、リスト3 に示します。リスト2リスト3 を比較すると、次のような違いがあります。

  1. リスト2 に含まれるのはXML暗号化のスキーマだけですが、リスト3 にはXML暗号化とリスト1 の元データの要素とが混在しています。リスト3 の場合、XML暗号化データはユーザーのXMLの内部に埋め込まれています。
  2. リスト3 でも、<EncryptedData>Type 属性が指定されていますが、その値はhttp://www.w3.org/2001/04/xmlenc#Elementです。IANA型は使用されていません。その代わり、XML暗号化で指定される型が使用されています。
  3. 特に末尾の #Elementに注目してください。これは、EncryptedDataが1つの要素を表すことを意味しています。

要素の内容の暗号化

リスト4 は、リスト1 に含まれる1つの要素CardId の内容だけを暗号化した結果です。この場合、Type 属性値にはhttp://www.w3.org/2001/04/xmlenc#Contentを使用しています。内容だけを暗号化する場合には、この値を使用します。

非XMLデータの暗号化

では、JPEGファイルなどをXML暗号化によって送信する場合は、どうなるのでしょうか? その典型的な例を、リスト5 に示します。JPEGファイルは、そのバイト・シーケンスを暗号化した上で、CipherValue 要素の内容として含められています。リスト2リスト5 の違いは、1つしかありません。それは、EncryptedData 要素のType 属性です。リスト5 には、JPEG形式に対応するIANA型が示されています。同じような方法でIANAの値を指定することによって、任意の形式を暗号化できます。IANAのWebサイトをご覧ください (参考文献を参照)。


XML暗号化の鍵

リスト1~5は暗号化の例ですが、鍵がなくては使い物になりません (この後のコラム「公開鍵、私有鍵、および共通鍵」を参照)。XML暗号化で鍵に関連する問題は、次の2つの部分に分けられます。

  • 鍵の交換 (非対称暗号化)
  • 以前に交換された鍵の使用 (対称暗号化)

こうしてユーザーは鍵を交換し、その後それを使用できます。

共通鍵の交換のための非対称鍵

このシナリオでは、通信の一方の側がその公開鍵を相手に送ります。相手は、その公開鍵を使用して、自分の共通鍵を暗号化します。このデータ交換の様子をリスト6 (要求) とリスト7 (応答) に示します。通信の一方の側がImranで、相手がAliであるとしましょう。Imranは、公開鍵交換要求を初期化し、その公開鍵をKeyValueという要素に入れて送ります。属性CarriedKeyName は、送信する鍵の名前を表します。この構造のルート要素はEncryptedKey であり、それにはds:KeyInfo 要素とds:KeyValue 要素が含まれます。 ds:KeyInfo 要素とds:KeyValue 要素は、XMLディジタル・シグニチャー (ds:) 名前空間に属しています。XML暗号化は、鍵の交換に関してはXMLディジタル・シグニチャーの仕様に完全に依存しています。そのため、<ds:EncryptedKey><ds:KeyValue> は、いずれもXMLディジタル・シグニチャー名前空間に属しています。リスト7 は、Aliが送る応答です。リスト7 の中のCipherValue 要素の内容は、新たに生成された共通鍵をImranの公開鍵によって暗したものです。 リスト6とリスト7をよく見ると、要求と応答の両方にEncryptedKey 要素が含まれていることがわかります。EncryptedKey 要素の中のds:KeyInfo 要素とds:KeyValue 要素によって、公開鍵が送信されます (リスト6)。一方、EncryptedKey 要素の中のCipherData 要素とCipherValue 要素 (リスト7) によって、共通鍵 (を暗号化したもの) が送信されます。さらに、EncryptedKey 要素には、常にCarriedKeyName 属性が含まれており、送信され名前がそれによって指定されます。

過去に交換した鍵の使用

前のセクションでは、共通鍵を交換しました。ここでは、その鍵を使用してデータを暗号化します。Imranがリスト7 への応答としてXMLメッセージ (リスト8) を送信するとします (リスト7 には、"Imran Ali" という名前の暗号化された共通鍵が含まれていることに注意)。Imranは、自分の (Imranの) 私有鍵を使ってこの共通鍵を暗号化解除します (Aliは共通鍵をImranの公開鍵を使って暗号化しました)。Imranは、この共通鍵を使用し、 リスト8CipherValue 要素中にそれを入れることによって、Aliに送りたいデータを暗号化することができます。

リスト8ds:KeyInfo 要素の中には、KeyName 要素が含まれています。この組み合わせにより、データ暗号化のためにImranが使用した鍵の名前が参照されます。

図1に、保護データ交換でのXMLファイル交換の様子を示します。

図1. XML暗号化による鍵およびデータの交換のシーケンス
図1. XML暗号化による鍵およびデータの交換のシーケンス

XML暗号化ファイルから外部暗号化データを参照する

リスト5 および7 において、CipherData 要素はEncryptedData 要素またはEncryptedKey 要素の中に指定できます。 CipherData 要素は、暗号化されたデータ (EncryptedData 要素の中に指定した場合) または暗号化された鍵 (EncryptedKey 要素の中に指定した場合) を参照するために使用しています。リスト5 とリスト7 の両方において、CipherData 要素の中に、実際の暗号化データを含むCipherValue 子要素が含まれています。

さらには、外部の暗号化データまたは暗号化鍵も参照できます。つまり、実際の暗号化データまたは暗号化鍵が、XML暗号化ファイルの中ではなく、どこか別の場所 (おそらくインターネット上のどこか) にあるという場合です。その場合には、CipherData の中でCipherValue 子要素の代わりにCipherReference を使用します。実際の暗号化データは、URIによって参照します。リスト9 をご覧ください。

外部XMLファイルの特定の要素を参照する

リスト10 は、外部XMLファイルを参照する別の方法を示すものです。ここでは、URIの指す外部ファイルの一部分だけを参照しています。 CipherReference 要素の中にTransforms 子要素が含まれています。このTransforms 要素には、それぞれ単一のXPath要素を内容とするTransform 要素をいくつか含めることができます。このXPath要素には、外部XML文書の特定のノードを参照するXPath式を指定します。


API (案) のDOM構造

ここまでで、XML暗号化ファイルを作成し、暗号化データを交換する方法を見てきました。次に、XML暗号化のためのJava APIの案と、その実装例を示します。そのために、DOMを使用することにします。

このDOM実装は、一群のクラスで構成されます (リスト11~16)。XmlEncryptionクラス (リスト11) は、それ以外のクラスのラッパーであり、APIのユーザーが実際に必要とするのはこのクラスだけです。その内部では、その他のクラスの機能が使用されています。

リスト11 は、XML暗号化ファイル全体を生成するラッパー・クラスです。

リスト12 は、EncryptedData 要素を作成します。

リスト13 は、EncryptionMethod 要素を作成します。

リスト14 は、KeyInfo 要素を作成します。

リスト15 は、CipherData要素を作成します。

リスト16 には、アルゴリズムの名前 (静的整数) とそれに対応する名前空間 (ストリング) が含まれています。

XmlEncryption クラス (リスト11) には、さまざまなpublic get/setメソッドが含まれています。ユーザーは、setメソッドを呼び出すことによって、次のような暗号化パラメーターを指定します。

  1. 暗号化するファイルの名前
  2. 結果出力先のXML暗号化ファイルの名前
  3. 暗号化のアルゴリズムの名前
  4. 暗号化のために使用する鍵の名前
  5. <EncryptedData> 構造の識別用ID

main () メソッドでXmlEncryption クラスを使う方法については、すでに示しました (リスト11)。main () メソッドでは、このクラスのインスタンスを作成します。そのコンストラクターではDOMのインスタンスを生成し、基本となるクラスのすべてが同じオブジェクトを使用するようにします。

この記事の中で、鍵に関連した3種類の技術用語、つまり「公開鍵」、「私有鍵」、そして「共通鍵」が使用されています。これらの用語は、エンドツーエンド・セキュリティーを扱う開発者にとってはおなじみの語ですが、XMLの開発者にとっては、あまりなじみがないかもしれません。これらの用語について説明しておきましょう。

公開鍵と私有鍵: これらの用語は対で使用されます。アルゴリズムによっては、公開鍵と私有鍵の対を生成するものがあります。暗号化データを交換したい相手に対しては、まず公開鍵を送ります。その公開鍵によって暗号化できるデータは、サイズが限られています。通信の相手は、こちらが送った公開鍵を使用してデータを暗号化し、その結果を送り返しますそれを受け取ったなら、私有鍵を使ってそのデータを暗号化解除します。これは非対称暗号化です。

共通鍵: 共通鍵の交換には公開鍵と私有鍵を使用します。通常、共通鍵はランダムに生成されます。非対称暗号化によって共通鍵を相手と交換したなら、それ以降は、両方の側でその鍵を使用してデータを暗号化します。これは対称暗号化です。

この実装でサポートされているのは、リスト2 の場合のようなファイル全体の暗号化だけです。これはEncryptCompleteXmlFile () メソッドによって実行されます。そのメソッドの中では、次のメソッドが順に呼び出されます。

  1. GetEncryptedDataDoc()EncryptedData クラス (リスト12) のオブジェクトを戻します。それには、EncryptedData 要素の構造が含まれます。
  2. GetEncryptionMethodDoc() が、EncryptionMethod 要素に対応するXML構造を含むDocumentオブジェクトを戻します。GetEncryptionMethodDoc() は、EncryptionMethod クラス (リスト13) を使用してXMLを作成します。
  3. GetKeyInfoDoc() が、Document オブジェクトを戻します。それには、KeyInfo要素に対応するXML構造が含まれます。GetKeyInfoDoc() は、GenericKeyInfo クラス (リスト14) のオブジェクトを使用してXMLを作成します。このクラスには、最低限必要な機能しかありません (KeyName 要素とKeyValue 要素のサポート)。それで、機能全体を提供するため、GenericKeyInfo クラスから継承することになります。それには、X509証明書、PGPデータなどのサポートが含まれています。
  4. ReadFile() によって、暗号化するデータ (XMLファイル全体) を取り出します。
  5. 今のところ、GetEncryptedData() は何もしません。このメソッドは、このシリーズの第2回の記事で実装します。これは、ステップ4で取り出したXMLデータの暗号化形式を作成するためにサポートされています。使用する暗号化ストラテジーについては、最後のセクション (「Java Cryptographic Architecture」) で簡単に説明します。
  6. GetCipherDataDoc() は、暗号化データを引き数とし、CipherData 要素を含むDocumentオブジェクトを戻します。GetCipherDataDoc() は、CipherData クラス (リスト12) のオブジェクトを使用することによってXMLを作成します。
  7. 最後に、EncryptedData (リスト15) のオブジェクトのaddChild() メソッドを3回呼び出しています。それぞれステップ2、3、および6のDocumentオブジェクトを引き数に指定し、それらをその親である<EncryptedData> 構造に追加します。
  8. SaveEncryptedFile() によって、XML暗号化ファイル全体を保存します。

AlgoNames (リスト16) は、XML暗号化で必要な名前空間宣言を指定するだけのヘルパー・クラスです。

XmlEncryption クラス (リスト11) は、サーバー・サイド・コンポーネントとしても使用できます。このシリーズの第2回では、内部で独立して使用する方法とサーバー・サイド・アプリケーションとして使用する方法を示します。

ここで開発したクラスは、DOMベースのXMLオーサリングを実行するだけです。実際には、暗号化機能の実装も必要になります。ここで、暗号化サポートのためのストラテジーを構成することにします。そのためには、Java Cryptographic Architecture (JCA) について調べる必要があります。


Java Cryptographic Architecture (JCA)

Javaには、完全に揃った暗号化のサポートが含まれています。J2SEの中には、そのためのパッケージがいくつか含まれており、それによって、アクセス制御、シグニチャー、証明書、鍵ペア、鍵の保管、およびメッセージ・ダイジェストなど、セキュリティー・アーキテクチャーの主要な機能のすべてがカバーされています。

JCA設計の主要な原則となっているのは、暗号の概念とアルゴリズムの実装を切り離すことにより、JCAフレームワーク内で、異なるベンダーがそれぞれのツールを提供できるようにすることです。

JCAエンジン・クラス

JCAでは、それぞれが暗号化機能を提供する一連のエンジン・クラスが定義されています。たとえば、MD (メッセージ・ダイジェスト) アルゴリズムの複数の異なる標準規格があります。実装の点でそれらの標準規格はすべて異なっていますが、エンジンAPIのレベルではすべて同じです。異なるベンダーが、それぞれ特定のアルゴリズムの実装を提供することが可能です。

Java Cryptographic Extension (JCE)

暗号アルゴリズムの独立した (サード・パーティー) ベンダー実装は、Java Cryptographic Extension (JCE) と呼ばれます。Sun Microsystemsも、JCEの実装を提供しています。JCEを使用する場合には、それをJCAによって構成する必要があります。そのためには、次のことをする必要があります。

1.CLASSPATH 環境変数の中に、プロバイダーを構成するためのjarファイルのアドレスを追加する (JCE実装はすべてプロバイダーと呼ばれます)。

2. java.securityファイルを編集することによって、承認済みプロバイダーのリストの中でプロバイダーを構成する。このファイルは、JavaHome/jre/lib/securityフォルダーにあります。優先順位指定のための構文は、security.provider.<n>=<masterClassName> というものです。ここで、nは優先順位番号 (1、2、3、など) です。MasterClassName は、特定のアルゴリズム実装のためにエンジン・クラスが呼び出すマスター・クラスの名前です。マスター・クラスの名前は、プロバイダーのドキュメンテーションで指定されます。たとえば、java.securityファイルの中の次の項目について考慮してみましょう。

  • security.provider.1=sun.security.provider.Sun
  • security.provider.2=com.sun.rsajca.Provider
  • security.provider.3=com.sun.net.ssl.internal.ssl.Provider

これらの項目は、エンジン・クラスがアルゴリズム実装を上記の順序で検索する、ということを示しています。最初に見つかった実装が実行されます。これらの簡単なステップを実行したなら、XML暗号化アプリケーションの中でJCA/JCEを使用することになります。

XML暗号化実装例でJCAおよびJCEを使う

JCA/JCEに関連したすべての処理を実行する場所は、ラッパー・クラスXmlEncryption (リスト11) のGetEncryptedData() 関数です。今のところ、このメソッドは "This is Cipher Data" というストリングを戻すだけです。JCA/JCE関連のクラスは、まだ作成していません。このメソッドは、暗号化前のデータを引き数とし、それを暗号化したストリングを戻します。JCA/JCEのラッパー・クラスの作成後、アルゴリズムや鍵に関連したことは、すべてこのメソッドの中で処理することになります。

次回: このシリーズの第2回では、暗号化の詳細を検討し、それを実装します。暗号化および暗号化解除のクラスの動作や解析ロジックとの対話について示し、さらに、Web ServicesにおけるXML暗号化の応用について紹介します。

参考文献

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML
ArticleID=297341
ArticleTitle=XML暗号化の方法を探る:第1回
publish-date=03012002