Java Web サービス: クライアント証明書を使用しない WS-Security

WS-Security の対称暗号化を使用して、クライアント証明書を使わずにセキュアなメッセージ交換を行う方法を学ぶ

クライアントとサーバーの間でクライアント証明書を使わなくてもセキュアなメッセージ交換を行えるようにする WS-Security の対称暗号化は、Web サービス構成を単純化すると同時に、パフォーマンスにもメリットをもたらします。この暗号化手法はそのまま使用することも、WS-SecureConversation メッセージ交換のブートストラップで使用することもできます。この記事では、Axis2、Metro、CXF という代表的な 3 つのオープンソースの Java™ Web サービス・スタックを例に、対称暗号化を構成して使用する方法を説明します。さらに、基本的な WS-Security 対称暗号化のパフォーマンスを WS-SecureConversation のパフォーマンスと比較します。

Dennis Sosnoski, Architecture Consultant and Trainer, Sosnoski Software Solutions, Inc.

Author photoDennis Sosnoski は Java ベースの XML および Web サービスを専門とするコンサルタント兼トレーナーです。専門家としてのソフトウェア開発経験は 30 年以上に渡り、この 10 年間はサーバー・サイドの XML 技術や Java 技術に注力しています。オープンソースのJiBX XML Data Binding フレームワークや、それに関連した JiBX/WS Web サービス・フレームワークの開発リーダーを務め、さらに Apache Axis2 Web サービス・フレームワークのコミッターでもあります。彼は JAX-WS 2.0 および JAXB 2.0 仕様のエキスパート・グループの一員でもありました。



2010年 8月 03日

この連載について

Web サービスは、エンタープライズ・コンピューティングにおいて Java 技術が担う重大な役割の一部です。この連載では、XML および Web サービスのコンサルタントである Dennis Sosnoski が、Web サービスを使用する Java 開発者にとって重要になる主要なフレームワークと技術について説明します。この連載から、現場での最新の開発情報を入手して、それらを皆さんのプログラミング・プロジェクトにどのように利用できるかを知っておいてください。

多くの WS-Security 構成では、クライアントとサーバーの両方が公開鍵と秘密鍵のペアを使用し、X.509 証明書で公開鍵の所有権を保証することが必要となります。おそらくこれは、WS-Security でメッセージに署名を付けたり、メッセージを暗号化するために最も広く使われている手法であり、確かに利点もあります。具体的に言うと、クライアント証明書はリクエストのクライアント ID を厳格に検証する手段にも、リクエストに付けられた署名を強力に保証する手段にもなるという利点です。けれどもクライアント証明書には欠点もあります。それは、非対称暗号化によってパフォーマンス・オーバーヘッドがもたらされること、そしてクライアントごとに証明書を取得して維持しなければならないという管理上の悩みの種です。

WS-SecureConversation のパフォーマンス」では、WS-SecureConversation は (クライアント証明書を使用する場合でも) 対称暗号化を使用することによって、クライアントとサーバーとの間で進行中のメッセージ交換のパフォーマンス・オーバーヘッドを減少させる仕組みを説明しました。今回の記事ではさらに一歩踏み込んで、基本的な WS-Security と WS-SecureConversation の両方のメッセージ交換でクライアント証明書のしがらみから抜け出る方法を紹介します。

クライアント証明書を使用しない暗号化と署名付与

公開鍵と秘密鍵のペアを使ってメッセージに署名を付け、暗号化する非対称暗号化を使用するのは、(少なくとも概念上は) 単純なことです。「Axis2 WS-Security による署名および暗号化」で説明したように、メッセージの署名には秘密鍵を使用し、メッセージの暗号化にはメッセージの受け取り側の公開鍵を使用します。秘密鍵を使って生成された署名は、その秘密鍵に対応する公開鍵 (通常は、X.509 証明書という形の認証のレイヤーの中にラップされます) にアクセスできる誰もが検証することができますが、公開鍵で暗号化されたメッセージを復号できるのは、その公開鍵に対応する秘密鍵の所有者だけです。

クライアントが公開鍵と秘密鍵のペアを持っていなければ、完全な非対称暗号化を使用することはできません。その代りの方法となるのは対称暗号化ですが、対称暗号化では、メッセージを交換する 2 者間だけが知っている秘密鍵 (共有秘密鍵) が必要です。では、そのような共有秘密鍵を用意するにはどうしたらよいのでしょうか?

WS-Security で採用されている方法は、クライアントに共有秘密鍵の値を生成させ、その値をサーバーの公開鍵による非対称暗号化を使って暗号化した上で、リクエスト・メッセージの <xenc:EncryptedKey> トークンに組み込むという方法です。こうすれば、クライアントはこの共有秘密鍵 (あるいはセキュリティーを強化するために、この共有秘密鍵から派生させた別の鍵) を使用してリクエスト・メッセージの暗号化または署名付与、あるいはその両方を行うことができます。サーバーも同じく、共有秘密鍵を使ってレスポンス・メッセージを暗号化したり、署名を付与したりすることができます。クライアントにはすでに共有秘密鍵があるため、サーバーからクライアントに共有秘密鍵を送り返す必要はありません。


WS-SecurityPolicy 構成

クライアントが生成した鍵を使用して対称暗号化を行うための WS-Policy/WS-SecurityPolicy 構成は単純です。リスト 1 に、この記事で使用するバージョンを記載します。このポリシーは、双方向での送信メッセージ本文の暗号化に、クライアントが生成した共有秘密鍵を使用することを指定しています。

リスト 1. すべてのメッセージ本文を暗号化する WS-Policy
<wsp:Policy wsu:Id="SymmEncr"
    xmlns:wsu="http://.../oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
    xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
    xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
  <wsp:ExactlyOne>
    <wsp:All>
      <sp:SymmetricBinding>
        <wsp:Policy>
          <sp:ProtectionToken>
            <wsp:Policy>
              <sp:X509Token sp:IncludeToken=".../IncludeToken/Never">
                <wsp:Policy>
                  <sp:RequireDerivedKeys/>
                  <sp:RequireThumbprintReference/>
                  <sp:WssX509V3Token10/>
                </wsp:Policy>
              </sp:X509Token>
            </wsp:Policy>
          </sp:ProtectionToken>
          <sp:AlgorithmSuite>
            <wsp:Policy>
              <sp:Basic128Rsa15/>
            </wsp:Policy>
          </sp:AlgorithmSuite>
          <sp:Layout>
            <wsp:Policy>
              <sp:Strict/>
            </wsp:Policy>
          </sp:Layout>
        </wsp:Policy>
      </sp:SymmetricBinding>
      <sp:Wss11>
        <wsp:Policy>
          <sp:MustSupportRefKeyIdentifier/>
          <sp:MustSupportRefThumbprint/>
          <sp:MustSupportRefEncryptedKey/>
        </wsp:Policy>
      </sp:Wss11>
      <sp:EncryptedParts>
        <sp:Body/>
      </sp:EncryptedParts>
    </wsp:All>
  </wsp:ExactlyOne>
</wsp:Policy>

リスト 1 のポリシーに含まれる <sp:SymmetricBinding> アサーションが、共有秘密鍵による対称暗号化の使用法を構成します。このアサーションに組み込まれている <sp:X509Token> アサーションは、X.509 証明書を使用して共有秘密鍵の送信を保護すること (つまり、送信する共有秘密鍵を暗号化すること)、そして証明書の識別にはサムプリント参照 (基本的にはハッシュ値) を使用することを指定しています。クライアントが共有秘密鍵を生成するということに関しては、<sp:X509Token> 保護トークンを指定した <sp:SymmetricBinding> アサーションを使用しているところに暗黙的に示されています。他のポリシー・アサーションによって暗号化アルゴリズムと必要な機能の詳細が指定され、最後に <sp:EncryptedParts> アサーションで、共有秘密鍵による暗号化の対象として SOAP Body が指定されています。

以前の記事でも説明したように、セキュリティー操作のためのランタイム・パラメーター (鍵ストアとパスワードなど) は、それぞれの実装に合わせて定義する必要があります。この例の場合のパラメーターは単純です。クライアント・サイドはサーバー証明書が含まれるトラスト・ストアにアクセスするようにし、サーバー・サイドは証明書の公開鍵に対応する秘密鍵が含まれる鍵ストアにアクセスするようにすればよいのです。それぞれのスタックでパラメーターが渡される方法についての詳細は、この連載の以前の記事を参照してください。


クライアント証明書を使用しない WS-SecureConversation

WS-SecureConversation を使用する場合でも、クライアントと STS (Security Token Service) との間のメッセージ交換にクライアント証明書を使用しない上記の手法を適用することができます (WS-SecureConversation についての詳細は、「WS-Trust と WS-SecureConversation」および「WS-SecureConversation のパフォーマンス」を参照してください)。この手法を使用するには、基本的にリスト 1 のポリシーをセキュアな対話のための <sp:BootstrapPolicy> に置き換えます。リスト 2 に、その方法を示します。このリストの中では、太字で示されている <sp:SymmetricBinding> によって、「WS-SecureConversation のパフォーマンス」で使用した <sp:AsymmetricBinding> が置き換わっています。

リスト 2. クライアント証明書を使用しない WS-SecureConversation の WS-Policy
 <wsp:Policy wsu:Id="SecureConv"
  xmlns:wsu=".../oasis-200401-wss-wssecurity-utility-1.0.xsd"
  xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
  xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
 <wsp:ExactlyOne>
  <wsp:All>
   <sp:SymmetricBinding>
    <wsp:Policy>
     <sp:ProtectionToken>
      <wsp:Policy>
       <sp:SecureConversationToken
         sp:IncludeToken=".../IncludeToken/AlwaysToRecipient">
        <wsp:Policy>
         <sp:BootstrapPolicy>
          <wsp:Policy>
<sp:SymmetricBinding>
            <wsp:Policy>
             <sp:ProtectionToken>
              <wsp:Policy>
               <sp:X509Token sp:IncludeToken=".../IncludeToken/Never">
                <wsp:Policy>
                 <sp:RequireDerivedKeys/>
                 <sp:RequireThumbprintReference/>
                 <sp:WssX509V3Token10/>
                </wsp:Policy>
               </sp:X509Token>
              </wsp:Policy>
             </sp:ProtectionToken>
             <sp:AlgorithmSuite>
              <wsp:Policy>
               <sp:Basic128Rsa15/>
              </wsp:Policy>
             </sp:AlgorithmSuite>
             <sp:Layout>
              <wsp:Policy>
               <sp:Strict/>
              </wsp:Policy>
             </sp:Layout>
            </wsp:Policy>
           </sp:SymmetricBinding>
           <sp:Wss11>
            <wsp:Policy>
             <sp:MustSupportRefKeyIdentifier/>
             <sp:MustSupportRefThumbprint/>
             <sp:MustSupportRefEncryptedKey/>
            </wsp:Policy>
           </sp:Wss11>
           <sp:EncryptedParts>
            <sp:Body/>
           </sp:EncryptedParts>
          </wsp:Policy>
         </sp:BootstrapPolicy>
        </wsp:Policy>
       </sp:SecureConversationToken>
      </wsp:Policy>
     </sp:ProtectionToken>
     <sp:AlgorithmSuite>
      <wsp:Policy>
       <sp:Basic128Rsa15/>
      </wsp:Policy>
     </sp:AlgorithmSuite>
     <sp:Layout>
      <wsp:Policy>
       <sp:Strict/>
      </wsp:Policy>
     </sp:Layout>
    </wsp:Policy>
   </sp:SymmetricBinding>
   <sp:EncryptedParts>
    <sp:Body/>
   </sp:EncryptedParts>
  </wsp:All>
 </wsp:ExactlyOne>
</wsp:Policy>

リスト 2 のポリシーが「WS-SecureConversation のパフォーマンス」で使用したポリシーと異なる点は、STS とのメッセージ交換にクライアントが生成する鍵を使用することだけでなく、<wsap:UsingAddressing> アサーションを削除していることです。

理論上、このポリシーは WS-Security と WS-SecureConversation のあらゆる実装で機能します。しかし実際にこの構成を 3 つの主なオープンソースの Java Web サービス・スタックで試してみると、いくつかの問題が持ち上がりました。このポリシーのままで機能したスタックは、CXF だけです。Axis2 はまったく機能せず、STS レスポンス・メッセージを処理する際に、クライアント・サイドの例外によって失敗しました。そこで、ブートストラップ・ポリシーを非対称暗号化に戻したところ、Axis2 は機能するようになりましたが、すべてのメッセージで WS-Addressing が使用されています。Metro も同じく失敗しましたが、<wsap:UsingAddressing> を元に戻すと、STS メッセージ交換での対称暗号化にクライアントが生成する鍵を使って機能するようになりました。


パフォーマンスの比較

この記事でのパフォーマンスの比較では、以前の記事と同じ地震データ検索サービスのテスト・コードを使用します。このサービスが使用するデータベースには、1 年間に世界各地で起こった 93,000 件を超える地震のデータが保管されています。サービスに対するリクエストで地震が発生した時刻および場所 (緯度、経度) の範囲を指定すると、その範囲内で発生したすべての地震データが返されます。このテスト・アプリケーションの詳細、そしてリクエストとそれに対するレスポンス・メッセージのサンプルについては、「(WS-)Security に伴う高コスト」を参照してください。

以前の記事と同様、パフォーマンス・テストには 2 つのリクエスト・シーケンスを使用します。最初のシーケンスで使用する 1,000 のリクエストでは、地震データベース全体のほんの一部とだけ一致するようにクエリー・パラメーターを調整してあります (1,000 のリクエストに対する一致結果として、816 件の地震データが返されます)。2 番目のシーケンスでは、それよりも多くの件数と一致するように調整した 100 のリクエストを使用します (100 のリクエストに対する一致結果として、176,745 件の地震データが返されます)。この 2 つのリクエスト・シーケンスにより、Web サービス・スタックのパフォーマンス特性の違いが顕著に現れてくることになります。最初のシーケンスによって明らかになるのは、スタックがデータ量の少ないリクエストを処理する場合の速度、そして 2 番目のシーケンスによって明らかになるのは、大量のデータを処理する場合の速度です。それぞれのリクエスト・シーケンスを異なるセキュリティー構成で何度か実行し、構成ごとの最短処理時間だけを結果に残しました。今回テストしたのは、以下の 2 つのセキュリティー構成だけです。

  • すべてのリクエスト/レスポンスのメッセージ本文を SymmetricBinding で暗号化する WS-Security 構成 (direct)
  • すべてのリクエスト/レスポンスのメッセージ本文を暗号化する WS-SecureConversation 構成(securconv)

securconv 構成は、「WS-SecureConversation のパフォーマンス」で使用した構成と基本的に同じですが、唯一の違いとして、クライアントと Metro および CXF での STS との間のメッセージ交換には SymmetricBinding を使用します。テストした SymmetricBinding STS ポリシーは Axis2 では機能しなかったため、この実行時間の測定テストに使用した Axis2 構成は、以前の記事で使用したものと同じです。STS ポリシーに SymmetricBinding を使用するように変更しているのは、パフォーマンスに顕著な影響を与えるためというよりは、デモンストレーションを目的としたものなので、この違いは結果に重要な意味を持ちません。

テストは Turion X2 ZM-85 プロセッサーと 3GB の RAM を搭載したノート・パソコンに Mandriva 2009.1 32-bit Linux® システムをインストールした環境で、Sun (Oracle) Java 1.6.0_10 32-bit JVM を使用して実行しました (以前の記事でパフォーマンス・テストに使用したシステムとは異なることに注意してください)。サーバー・コードは Tomcat 6.0.20 上で実行され、1,024MB のヒープを使用するように構成されています。一方、クライアント・コードが使用するヒープは 512MB です。テストした各 Web サービス・スタックのバージョンは以下のとおりです。

  • Rampart 1.5 リリースを適用した Axis2 1.5.1
  • Metro 2.0
  • CXF 2.1.8

お使いのハードウェアと JVM でこのテストを試すには、「ダウンロード」セクションからサンプル・コードをダウンロードしてください。

パフォーマンスの結果

図 1 に、少数のレスポンスを返すテストで測定した実行時間を示します。「WS-SecureConversation のパフォーマンス」での結果と同じく、WS-SecureConversation を使用したテストでは、Metro の速度が CXF をやや上回ります (10 パーセント程度)。WS-Security で direct 構成の対称暗号化を使用した場合には、Metro はさらに良い結果となり、処理速度は約 30 パーセント程度速くなっています (この記事に記載するグラフでは、いずれも棒の長さが時間の長さを示すため、棒が短ければパフォーマンスに優れていることになります)。

図 1. 少数のレスポンスで測定した実行時間
少数のレスポンスで測定した実行時間

図 1 に Axis2 の結果が示されていないのは、テストの途中でバグが見つかったためです。Axis2 のテストは、出だしは妥当な速度でしたが、繰り返しを重ねるにつれて徐々に速度が落ちてきました。Axis2 でのこのテストの合計実行時間は Metro の値の 40 倍を上回る結果となりました。このような漸進的な速度低下は、コードの実行時に保管される値をすべて参照する、といったような問題が存在していることを表しているのが通常です。この場合、Axis2 による対称暗号化のセキュリティー処理の中で (リクエストごとに新しい共有秘密鍵が生成されるため、このクライアントが生成する鍵を処理することで) この問題が発生しています。

図 2 に、今度は多数のレスポンスを返すテストで測定した実行時間を示します。このテストでも、3 つのスタックのなかで最も速度に優れているのは Metro ですが、CXF もそれに迫る勢いです。Metro と CXF の差は、わずか 10 パーセントほどしかありません。Axis2 は他の 2 つに比べ、かなり処理速度が低下しています。これは、前の記事で記載した WS-Security と WS-SecureConversation のテスト結果と同じです。

図 2. 多数のレスポンスで測定した実行時間
多数のレスポンスで測定した実行時間

どのようなセキュリティー処理が行われているかを考えれば、以上の結果 (Axis2 を除く) は期待したとおりのはずです。両方のセキュリティー構成ではどちらも、クライアントとサービスとの間のメッセージ交換に対称暗号化が使用されています。この 2 つの構成の大きな違いは、WS-Security の対称暗号化構成では、リクエストおよびレスポンスのメッセージ・ペアごとにクライアントが新しく生成する共有秘密鍵を使用するという点です。新しく生成された共有秘密鍵に対しては、サーバーの公開鍵を使って非対称暗号化による暗号化を行ってから、リクエスト・メッセージの一部として送信しなければなりません。その一方、WS-SecureConversation では多数のメッセージ・ペアで共通して 1 つの共有秘密鍵を使用します。したがって、WS-Security 構成はリクエストごとに多大なオーバーヘッドを追加することになります。このオーバーヘッドが主として図 1 の測定時間に現れているというわけです。

これらのスタックでは、メッセージを暗号化するためだけに WS-Security の非対称暗号化を使用することはできません。暗号化と併せて、署名も付与する必要があります。そのため、パフォーマンスを直接比較することは困難ですが、上記の 2 つのグラフを前回の「WS-SecureConversation のパフォーマンス」に記載されているグラフと比較してみると、パフォーマンスの違いについて把握できるはずです。前回の記事では、WS-SecureConversation の対称暗号化のパフォーマンスは WS-Security の非対称暗号化よりも大幅に優れていることを明らかにしました。これは、メッセージを暗号化する場合は尚更のことです。上記の結果には、クライアントが生成する鍵を使用した WS-Security の対称暗号化は、WS-SecureConversation に匹敵する速さであることが示されており、このことは多数のメッセージを処理する場合は尚更のことです。


まとめ

この記事では、クライアントが生成する共有秘密鍵を使用した対称暗号化によって、クライアント証明書を使用せずにセキュアなメッセージ交換を行う方法を説明しました。この方法は、メッセージの数が比較的多い場合には、WS-SecureConversation に匹敵するほどの優れたパフォーマンスでのメッセージ交換を可能にします。クライアントとサーバーの間で交換されるメッセージがほんの少しであれば、クライアントが生成する共有秘密鍵によって、WS-SecureConversation の共有秘密鍵を超えるパフォーマンスを実現することができます (WS-SecureConversation には、クライアントと STS との間でのメッセージ交換も必要なためです)。

クライアントが生成する共有秘密鍵は、メッセージの署名付与にも使えます。この記事では説明しませんでしたが、クライアントが生成する共有秘密鍵を使用して署名を付与する方法は、「WS-SecureConversation のパフォーマンス」で説明した WS-SecureConversation の署名付与の例と基本的には同じです。共有秘密鍵での署名付与は、本質的には秘密鍵で署名を付与する場合よりも信頼性の保証が弱くなります。しかしそれでも、メッセージが送信中に改ざんされていないことを確実にするために利用できることには変わりありません。

この連載ではこれまで複数の記事にわたって、さまざまな形の WS-Security および WS-SecureConversation による Web サービスのセキュリティーについて、3 つの主要な Java Web サービス・スタックのパフォーマンスの比較をまじえて説明してきました。今後の記事では WS-Security の機能のなかでも専門的な機能を取り上げる予定ですが、ここでひとまず、セキュリティー・パフォーマンスの話題について要約すべき段階が来ました。連載の次回の記事では、3 つの主要な Java Web サービス・スタックに伴うパフォーマンスと相互運用性の問題をまとめ、これらのスタックをベースに Web サービスのセキュリティーを使用する最善の方法についてのガイドラインを紹介します。組織の中でセキュアな Web サービスを使用しているとしたら、次回の記事は見逃せないはずです。


ダウンロード

内容ファイル名サイズ
Sample code for this articlej-jws17.zip5.29MB

参考文献

学ぶために

議論するために

  • My developerWorks コミュニティーに加わってください。ここでは他の developerWorks ユーザーとのつながりを持てる他、開発者が主導するブログ、フォーラム、グループ、ウィキを調べることができます。

コメント

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=Java technology, SOA and web services, Open source
ArticleID=516672
ArticleTitle=Java Web サービス: クライアント証明書を使用しない WS-Security
publish-date=08032010