「第1回 Webサービスのセキュリティ概要」は、Webサービス・セキュリティのフレームワークの概要を述べた。今回はWebサービス・セキュリティの最も基本となるXMLデジタル署名とXML暗号について述べる。XMLデジタル署名とXML暗号は従来のASN.1で定義されたCMS署名フォーマットやCMS暗号フォーマット*1に比べてXML文書との親和性が高く、柔軟な署名や暗号化が可能となる。
*1 CMS
暗号メッセージ構文(Cryptographic Message Syntax:RFC2630)を定めた標準でASN.1で定義されデジタル署名や暗号メッセージの構文を規定している。
W3CはXMLにデジタル署名を埋め込むための標準化作業をIETFとのジョイントで行い、XML Digital Signature標準のRFC3075*2を定めた。XMLデジタル署名は、署名アルゴリズム、証明書や署名のタグを定め、任意のデータに対する署名のほか、XML文書の指定したエレメントやコンテントに対して署名を付けることを可能にしている。
XMLデジタル署名には、以下の特徴がある。
- 署名対象、署名アルゴリズムや署名値および証明書などをXMLの文法で統一して表現できる。
- デジタル署名がXMLタグ付き言語であり、ASN.1構文に比べて分かりやすい。
- 任意のデータファイルやXML文書の全体だけではなく、XML文書の一部に対しても署名を付けることができ、部分署名や多重署名などの複雑な要件に対応できる。
- XML署名で参照する暗号アルゴリズムなどのオブジェクトの識別子は、ASN.1がOID(Object Identifier)を指定するのに対して、W3Cなどで定めているURIを参照する。
XML署名は、指定した署名対象に対するデジタル署名である。まず、署名対象のダイジェスト値(ハッシュ値)を求め、ダイジェスト値を子要素としてXML署名情報要素に入れ、さらにその署名情報要素に対してダイジェスト値と署名値を計算し挿入する。参照URIで指定される署名対象のデータがXML文書であった場合、ダイジェスト値を計算する前にそのXML文書の正規化(Canonicalization:C14N)を行う必要がある。それはXML文書では内容が同じであってもXML構文に挿入された空白文字や改行などが任意に加わると表現が異なり、結果としてダイジェスト値が変わり、署名値が異なってしまうからである。XML文書の正規化処理はW3Cのデジタル署名ワークグループ(WG)とIETFで標準化を行っている(RFC3076)。
XML署名には鍵情報(KeyInfo)要素を指定することができ、ここに必要なら署名検証鍵を指定し、その公開鍵証明書としてX.509証明書などを示すことができる。
XMLデジタル署名は下記のようにSignature要素として記述される。
ここで、“?”は0または1、“+”は1または1以上、“*”は0または0以上を意味し、<!--xxx-->の部分は各要素のコメントである。
<Signature ID?> <!--
XML署名要素 -->
<SignedInfo> <!--署名情報要素>
<CanonicalizationMethod/> <!--署名対象正規化アルゴリズム要素-->
<SignatureMethod/> <!--署名アルゴリズム要素-->
(<Reference (URI=)? > <!--参照要素(URIは署名対象の識別子)-->
(<Transforms>)? <!--正規化変換プロセス要素-->
<DigestMethod> <!--ダイジェスト計算アルゴリズム要素-->
<DigestValue>
<!--署名対象のダイジェスト値要素-->
</Reference>)+ <!-- 1つ以上の参照要素-->
</SignedInfo>
<SignatureValue> <!--署名値要素-->
(<KeyInfo>
<!--鍵情報要素:オプション-->
<KeyValue> <!--検証鍵要素-->
<X.509Data>
<!-- X.509証明書要素-->
</KeyInfo>)?
(<Object ID?>)* <!--
XML署名対象要素>:オプション-->
</Signature> |
|
図1 XML署名の構文 |
XML署名にはURIで示す署名対象の指定方法の違いで以下のような3つの署名形式がある。
- Detached署名
署名対象要素と署名要素が独立した署名形式(sibling elements)である。
Detached署名は、署名対象データに任意の電子ファイル(Word、Excel、MPEG画像データ、XML文書など)を指定して、署名対象データをXML署名部分とは独立させ外部ネットワークやローカルファイルに置くことができる。またXML文書内にXML署名要素とXML署名対象要素を並列に配置させることもできる。
- Enveloped署名
署名要素が署名対象要素の子要素となる署名形式である。
Enveloped署名は同じ文書に複数人の署名を付けるなどの用途に適している。
- Enveloping署名
署名要素が署名対象要素の親要素となる署名形式である。
Enveloping署名は署名対象要素を包含した形式で、医療のカルテのように初めの医師が署名したカルテに、次の医師が新しく書き添えた部分のみに署名を加えていくような用途に適している。
図2 XML署名の種別
- オリジナルの署名対象に対して、XML変換プロセス要素(Transforms element:正規化変換)を適用して、署名対象を生成する。
- 署名対象のダイジェスト値を計算する。
- 参照要素(Reference element)を生成する。参照要素は署名対象識別子URI(オプション)、XML正規化変換プロセス要素(オプション)、ダイジェストアルゴリズム要素とダイジェスト値要素を含む。
- 署名アルゴリズム(SignatureMethod)、正規化アルゴリズム(CanonicalizationMethod)、参照要素(Reference element)を指定して、署名情報要素(SignedInfo element)を生成する。
- 正規化アルゴリズムによる正規化を行った後、署名アルゴリズムに基づいて、署名情報要素に対する署名値(SignatureValue)を計算する。
- オプションとして署名検証のために鍵情報要素(KeyInfo)を加える。これには署名検証用の公開鍵をBase64でエンコードした値と、X.509証明書などの情報を加えることができる。
- オプションとして被署名データオブジェクトとなるオブジェクト要素を指定できる。オブジェクトとしては画像データなどバイナリをBase64でエンコードしたものやMIMEオブジェクトなどのデータ属性を指定する。
- 署名要素(Signature element)を構成する。
XML署名の検証処理には、参照要素検証と署名検証の2つのステップが含まれる。参照要素検証では、署名情報要素内の各参照要素のダイジェスト値を検証する。署名検証では、署名情報要素に対して計算された暗号化署名値を検証する。
注意すべきなのは、XML署名は正確に記述されている場合でも、一部の署名検証アプリケーションでは検証できないことである。署名はXMLデジタル署名仕様のオプション部分があり、特殊なアルゴリズムが含まれ、または特別な識別子(URI)を参照する場合、署名検証アプリケーションはその署名に対応できないことがある。
- 署名情報要素(SignedInfo)に記載される正規化変換や署名方法で参照要素URIにより指定された被署名データと署名値が検証対象になる。
- 署名情報要素内の各参照要素に対して、下記の参照要素検証を行う。
- 署名対象を特定する。例えば、参照要素内の署名対象識別子URIを参照し、オリジナル署名対象を取得する。オリジナル署名に対して、XML正規化変換プロセス要素Transforms elementを適用した結果が署名検証対象になる。
- 参照要素内に記述されるダイジェストアルゴリズム(DigestMethod)を用いて、署名対象のダイジェスト値を計算する。
- 計算結果と署名情報要素(SignedInfo element)内に記述されるダイジェスト値を比較する。もし、一致しなければ、検証は失敗となる。
- KeyInfo elementまたは外部リソースから鍵情報を取得する。
- 鍵情報要素(KeyInfo)にある、または、そのほかの方法で取得した公開鍵証明書の有効性を検証する。
- 署名アルゴリズムと鍵情報の有効な公開鍵を使って、署名値を復号しダイジェスト値を求める。
- 求めたダイジェスト値と署名文書のダイジェスト値を比較し、署名を検証する。
以下にDetached署名の例を示す。正規化アルゴリズム、署名アルゴリズム、参照要素(ダイジェストアルゴリズム、ダイジェスト値)、署名値および鍵情報などの要素の使用方法が示されている。
[s01] <Signature
Id="MyFirstSignature"
xmlns="http://www.w3.org/2000/09/xmldsig#">
[s02] <SignedInfo> <!--署名情報-->
[s03] <CanonicalizationMethod Algorithm= <!--正規化アルゴリズム-->
"http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
[s04] <SignatureMethod <!--署名アルゴリズム DSA-SHA-1-->
Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/>
[s05] <Reference <!--署名対象文書を下記のURIを参照-->
URI="http://www.w3.org/TR/2000/REC-xhtml1-20000126/">
[s06] <Transforms>
[s07] <Transform Algorithm= <!--正規化アルゴリズム-->
"http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
[s08] </Transforms>
[s09] <DigestMethod <!--ダイジェストアルゴリズム-->
Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
[s10] <DigestValue> <!--署名対象のダイジェスト値-->
j6lwx3rvEPO0vKtMup4NbeVu8nk=
</DigestValue>
[s11] </Reference>
[s12] </SignedInfo>
[s13] <SignatureValue> MC0CFFr... </SignatureValue> <!--署名値-->
[s14] <KeyInfo> <!--署名検証鍵情報-->
[s15a] <KeyValue> <!--公開鍵の値-->
<RSA KeyValue>x5fd8jKn</RSA KeyValue>
</KeyValue>
[s15b] <X.509Data> <!--X.509証明書を添付-->
[s15c] <X.509SubjectName>cn=Suzuki,o=Entrust,c=JP</X.509SubjectName>
[s15d] <X.509Certificate>hy56Fd9XjKKu93m</X.509Certificate>
[s15e] </X.509Data>
[s16] </KeyInfo>
[s17] </Signature> |
|
図3 XML署名の例 |
- [s02〜12]:実際の署名対象となる署名情報要素(SignedInfo element)。
署名検証には署名情報要素に対する署名値の検証、署名情報要素内の各参照要素ダイジェスト値の検証という2つの検証プロセスが必要である。署名値そのものは署名情報要素外に存在するのに対して、署名値を計算するためのアルゴリズムは署名情報要素に含まれる。
- [s03]:署名情報要素の正規化に用いられるアルゴリズムを記述する正規化メソッド要素(CanonicalizationMethod element)。
署名情報要素のダイジェスト値を計算する前に、この正規化アルゴリズムを使って、署名情報要素(SignedInfo element)を正規化する。
- [s04]:正規化された署名情報要素(SignedInfo element)から署名値を計算するのに用いられるアルゴリズムを記述する署名メソッド要素(SignatureMethod element)。
アルゴリズムはダイジェストアルゴリズム、鍵依存アルゴリズムおよびそのほかのアルゴリズム(例RSA-SHA1)の集合である。アプリケーションの互換性を高めるために、W3CはXML署名アプリケーションの実装に必須なアルゴリズム、推薦アルゴリズム、オプションのアルゴリズムおよびユーザー策定アルゴリズムの仕様を規定している。
- [s05〜11]:署名対象の参照、ダイジェストアルゴリズムとダイジェスト値を記述する参照要素(Reference element)。
- [s05]:参照要素のURI属性(オプション)として、署名対象の参照URIを記述する。
- [s06〜08]:署名対象のダイジェスト値を計算する前に、オリジナルの署名対象の処理プロセスを記述する変換プロセス要素(オプション)。
オリジナルの署名対象の正規化、エンコード/デコード、XSLT、XPathなどのオペレーション仕様は変換プロセス要素内に記述される。この要素を記述しない場合、オリジナルの署名対象に対して直接ダイジェスト値を計算することになる。
- [s09]:署名対象の変換プロセス要素の適用後に、ダイジェスト値を計算するアルゴリズムを記述する要素(DigestMethod element)。
- [s10]:ダイジェストアルゴリズムに基づいて計算される署名対象のダイジェスト値を記述する要素(DigestValue element)
- [s14〜16]:署名を検証する際に使われる鍵の情報を記述する要素(KeyInfo elment)。
鍵の名前、鍵の値、X.509証明書などの記述が鍵情報内に含まれる。
XML暗号はW3C*3で最終的な勧告としてまとめられているものである。XML暗号はXML署名と同様にASN.1のファイルベースの暗号化に比べて柔軟な利用が可能である。XML暗号の暗号化対象は任意のデータ(非XMLも含む)の暗号化ばかりではなく、任意のXMLの要素やコンテントの暗号化も可能である。ファイルベースの暗号化の場合には、復号を行わなければ内容に何が書かれているか分からないが、XMLの要素レベルの暗号化によって文書の中の本当に秘匿すべき部分のみを暗号化することが可能で、そのほかの部分は可読性を維持できる。これは例えば、注文書などで本当にプライバシーの保護が必要なクレジット番号の入力要素部分のみを秘匿するなどの利用が可能になる。
XML暗号は、XML署名と同様に以下の特徴がある。
- 暗号対象、暗号アルゴリズムや署名値および証明書などをXMLの文法で統一して表現できる。
- 暗号構文がXMLタグ付きであり、ASN.1構文に比べて分かりやすい。
- 任意のデータファイルやXML文書の全体だけではなく、XML文書の一部に対しての暗号化もでき、多様な形式の暗号文書の作成に柔軟に対応できる。
- XML暗号で参照する暗号アルゴリズムなどのオブジェクトの識別子は、ASN.1がOID(Object Identifier)を指定するのに対して、W3Cなどで定めているURIを参照する。
XML暗号の構文は図4に示すようにEncryptedDataで指定される。
- EncryptionMethodは暗号方式を指定するもので、3DES-CBCやAES128-CBCなどの共通鍵アルゴリズムを指定する。
- ds:KeyInfoはXML署名で定めた鍵情報を指定するもので、子要素にEncryptedKeyで共通鍵を公開鍵で暗号化した鍵データを指定する。そして鍵の名称(鍵の所有者名)を指定する。
- CipherData要素では共通鍵で暗号化したデータをCipherValue要素にbase64でエンコードした値が置かれる。
<EncryptedData Id? Type?> <!--暗号データ要素-->
<EncryptionMethod/>? <!--暗号方式、3DESやAESなどを指定-->
(<ds:KeyInfo> <!--XML署名(ds)と同じ鍵情報要素-->
<EncryptedKey>? <!--公開鍵で暗号化した共通鍵要素-->
<ds:KeyName>? <!--鍵の名称(鍵の所有者名)-->
<ds:RetrievalMethod>? <!--鍵情報の検索方法要素-->
</ds:KeyInfo>)? <!--鍵情報要素:オプション-->
<CipherData> <!--暗号化データ要素-->
<CipherValue>? <!--暗号化されたデータ値-->
</CipherData>
</EncryptedData> |
|
図4 XML暗号構文 |
ここで示したXML暗号構文は要点を示したもので、実際は鍵情報の内容や暗号データなどを間接参照させる方法もある。
ここではオリジナルのXML文書がどのように暗号化されるかを見てみよう。図5にクレジットカードを使った支払いデータのXML文書を示す。黄色の部分がCreditCard要素である。
<?xml version='1.0'?>
<PaymentInfo xmlns='http://example.org/paymentv2'>
<Name>鈴木 優一</Name>
<CreditCard Limit='500,000' Currency='\'>
<Number>4019 2445 0277 5567</Number>
<Expiration>04/02</Expiration>
<Issuer>ABC銀行</Issuer>
</CreditCard>
</PaymentInfo> |
|
図5 オリジナルのXML文書 |
暗号化したい部分はクレジットカードのデータで、CreditCard要素全体をXML暗号化プロセッサで暗号化した結果は図6のようになる。ここではCreditCard要素がEncryptedData要素に置き換えられ、暗号化されたデータがCipherData要素のCipherValueにBase64でエンコードされることになる。
この例はCreditCard要素全体を暗号化したものだが、クレジットカードの番号(コンテント)のみを暗号化することもできる。
<?xml version='1.0'?>
<PaymentInfo xmlns='http://example.org/paymentv2'>
<Name>鈴木優一</Name>
<EncryptedData Type='http://www.w3.org/2001/04/xmlenc#Element'
xmlns='http://www.w3.org/2001/04/xmlenc#'>
<CipherData>
<CipherValue>A23B45C56</CipherValue>
</CipherData>
</EncryptedData>
</PaymentInfo> |
|
図6 XML暗号化の例 |
この例では暗号化鍵の情報<KeyInfo>を含めていないので、文書を暗号化するための共通鍵のアルゴリズムや鍵の値はあらかじめ知っていることとしている。
もし、PKIの環境で宛先、山田太郎の公開鍵を使って文書の暗号化のための共通鍵を暗号化してXML暗号文に添付する場合は、図7のようにEncryptedData要素の子要素に文書暗号化のための共通鍵のアルゴリズム<EncriptionMethod>の指定と、<KeyInfo>に宛先の公開鍵情報を指定することになる。
<EncryptedData
Id='ED' xmlns='http://www.w3.org/2001/04/xmlenc#'>
<EncryptionMethod <!--共通鍵3DES-CBCを指定-->
Algorithm='http://www.w3.org/2001/04/xmlenc#3DES-cbc'/>
<!--共通鍵3DES鍵を公開鍵RSAで暗号化-->
<EncryptedKey Id='EK' xmlns='http://www.w3.org/2001/04/xmlenc#'>
<EncryptionMethod
<!--公開鍵RSA-PKCSv1.5を指定-->
Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
<ReferenceList>
<DataReference URI='#ED'/>
<!--共通鍵で暗号化したデータへの参照-->
</ReferenceList>
<ds:KeyInfo xmlns:ds='http://www.w3.org/2000/09/xmldsig#'>
<ds:KeyName>山田太郎</ds:KeyName> <!--公開鍵の所有者名-->
</ds:KeyInfo>
<CipherData>
<CipherValue>xyzabc</CipherValue> <!--3DES鍵を公開鍵で暗号化-->
</CipherData>
</EncryptedKey>
<ds:KeyInfo>
<xenc:EncKeyReference URI='#EK'/> <!--鍵暗号への参照-->
</ds:KeyInfo>
<CipherData>
<CipherValue>DEADBEEF</CipherValue> <!--文書を暗号化した値-->
</CipherData>
</EncryptedData> |
|
図7 XML暗号文書に公開鍵で共通鍵を暗号化した鍵情報を添付 |
ここでは以下の用語を用いることにする。
Application:XML暗号化(復号)要求を行うアプリケーション
Encryptor:XML暗号化処理を行うモジュール
Decryptor:XML暗号化処理されたXMLデータを復号するモジュール
EncryptedDataまたはEncryptedKey要素を構成するためにEncryptorは以下の処理を行う。
- データ暗号化のアルゴリズムを選択する
- 鍵を取得し(鍵名称、URIなどから)、ds:KeyInfoを適切に構成する
もし鍵自体を暗号化するときには、ds:KeyInfo 要素の子要素としてEncryptedKey要素を適切に構成する
- データを暗号化する
暗号化対象の要素(エレメント)または内容(コンテント)を直列化(シリアライズ)し、オクテッド列を得て、選択したアルゴリズムと取得した鍵でこのオクテッドを暗号化する
- EncryptedType(EncryptedDataまたはEncryptedKey)構文を構成する
暗号化されたデータはCypherData要素のCypherValue要素にbase64でエンコードして格納する。もし暗号データを外部に置く場合はURIで参照させるようにする
- EncryptedDataの処理
暗号化対象がエレメントまたはコンテントの場合、EncryptorはEncryptedData要素をApplicationに返し、Applicationがこれを新しいXML文書のトップレベルとして使うか、ほかのXML文書に挿入できるようにする
Applicationがエレメントまたはコンテントを指定して暗号化を要求する場合には、Encryptorは指定されたエレメントまたはコンテントを削除しEncryptedData要素で置換する
暗号化対象がエレメントまたはコンテントでない場合、EncryptorはEncryptedData要素をApplicationに返し、Applicationがこれを新しいXML文書のトップレベルとして使うか、ほかのXML文書に挿入できるようにする
EncryptedDataまたはEncryptedKey要素の暗号化されたデータを復号するためにDecryptorは以下の処理を行う。
- EncryptedDataまたはEncryptedKey要素を処理し、アルゴリズムをKeyInfoの鍵情報から得る
- ds:KeyInfoからデータ暗号化鍵を得る。もしデータ暗号化鍵が暗号化されていた場合、対応する鍵を復号して得る
- CypherData要素のCypherValueにあるテキストをbase64でデコードし、暗号データを得てデータ暗号化鍵で復号する。
- 復号したエレメントまたはコンテントを処理する
Decryptorは復号したType(エレメントまたはコンテント)の値をApplicatioに返すか、もしApplicationから指定されたらEncryptedData要素を復号したエレメントまたはコンテントで置換する。
- Typeが指定されていないか、エレメントやコンテントでない場合の処理
復号したデータをApplicationに返し、Applicationが整形処理を行う。
W3CのXML暗号の仕様には以下のようなアルゴリズムが必須として指定されている。
- データ暗号(ブロック暗号)
3DES-CBC、AES128-CBC、AES256-CBC
- 鍵配布アルゴリズム(公開鍵)
RSA-PKCSv1.5、RSA-OAEP
- 鍵ラップ
CMS 3DES Key Wrap、AES Key Wrap
- メッセージ・ダイジェスト(ハッシュ関数)
SHA-1、SHA256、SHA512
W3CのXML暗号仕様にはデータ暗号化鍵を配布するために用いる公開鍵については、これが正しい公開鍵であることを前提にしている。従ってXML暗号の利用者は、この公開鍵があて先の正しい公開鍵であることを事前に調べておかなければならない。すなわち、公開鍵証明書の有効性検証を別途行っておく必要がある。このような検証はXML暗号処理を行うアプリケーション自身で行うか次回に述べるXKMSなどに処理させることが必要である。
オリジナルのXML文書を処理してXML署名やXML暗号を生成するためには、JavaプログラムのアプリケーションなどでXML署名、XML暗号を生成できるツールキットが必要である。このようなツールキットはIBMやEntrustなどが提供している。これらのツールキットは署名生成、暗号生成ばかりでなく、PKIの環境と連動させた署名検証や暗号の復号を行う機能も含まれている。
今回はWebサービス・セキュリティの基本となるXMLデジタル署名とXML暗号について述べた。次回はWebサービスのメッセージングに必須なSOAPとXMLセキュリティで鍵管理を外部サーバに任せるXKMSについて解説することにする。