特集
次世代XML Webサービスを試す Part 2

5.SOAPメッセージの秘匿性

インフォテリア株式会社
吉松 史彰
2003/01/29

Page1 Page2 Page3 Page4 Page5

SOAPメッセージの秘匿性

 WS-Securityが取り扱うもう1つのセキュリティ領域に、「メッセージの秘匿性」がある。メッセージの秘匿性とは、端的にはメッセージが転送の途中でのぞき見されないことを保証することだ。そのために有効な手段として暗号化がある。WS-Security仕様には、W3Cから発表されているXML暗号化仕様を利用して、SOAPメッセージを暗号化する手順が示されている。

 WSEでは、X.509v3証明書を使った非対称鍵による暗号化と、System.Security.Cryptography.SymmetricAlgorithmクラスから派生した対称鍵による暗号化をサポートしている。また、ユーザー定義のアルゴリズムを利用することも可能だ。ここでは、証明書を使って証明書に含まれる公開鍵で暗号化したデータを送信する手順と、3DES(Triple-DES)を使った暗号化方法を解説する。

■証明書を利用した暗号化
 証明書を利用する手順やコードは、ほとんど前述のデジタル署名の手順やコードと同じだ。まずサーバ側が、暗号化/復号化に利用する正しい証明書を用意する。サーバ側は、この証明書に対応する秘密鍵も持っていなければならない。この証明書は、ほとんどの場合Windowsの証明書ストアにインストールしておくことになる。通常、サーバで利用する証明書は、(ユーザーではなく)コンピュータの証明書ストアに配置されていなければならない。ASP.NETのXML Webサービスは、デフォルトではコンピュータの証明書ストアにはアクセスできないので、WSEのドキュメントの「Managing Applications Created with the Web Services Enhancements」の項をよく読んで、正しい設定をしておく必要がある。

 サーバ側は、証明書ストアに正しい証明書をインストールしたら、それをエクスポートしてクライアントに渡さなければならない。WindowsのMMCコンソールで証明書を扱っている場合は、インストールされている証明書を選択して「エクスポート」すればよい。このエクスポートした証明書は、クライアントに渡されるので、秘密鍵を含んではいけない。後々、コードで扱いやすくすることも考慮して、デフォルトで選択されている.cerファイルとしてエクスポートすればいいだろう。

 最後にもう1つサーバ側でしなければならないことがある。XML Webサービスが使っているWeb.configファイルに次のようなエントリを追加する作業だ。<microsoft.web.services>要素と<configSections>要素は、前回のPart 1でも解説したとおり<configuration>要素の直下に配置する。これによって、WSEが証明書を扱うときに「ローカル・コンピュータのストアから証明書を探して、信頼の検証を行う」という設定ができる。

<configSections>
  <section name="microsoft.web.services" type="Microsoft.Web.Services.Configuration.WebServicesConfiguration, Microsoft.Web.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<microsoft.web.services>
  <security>
    <x509 storeLocation="LocalMachine"
        verifyTrust="true" allowTestRoot="false" />
  </security>
</microsoft.wev.services>
ローカル・コンピュータのストアから証明書を探して、信頼の検証を行うために必要なWeb.configファイルの<microsoft.web.services>要素

 サーバ側では、前述のデジタル署名と同様に、[WebMethod]の中で暗号の解除などを行う必要はまったくない。暗号の処理はすべてWSEが行ってくれるので、[WebMethod]では本来の処理だけを記述すればよい。

 クライアント側では、やはりデジタル署名のときのようにいくらかのコードを書く必要がある。といっても、証明書を取り出してSOAPコンテキストに追加するだけなので、それほど難しいコードではない。次のようなコードで、ファイルから証明書の内容を取得し、その中に含まれる公開鍵でSOAPのBody以下を暗号化して送信できる。ここで指定しているファイルは、上記の手順でサーバ側からエクスポートされた証明書のファイルである。

localhost.Service1 svc = new localhost.Service1();

Microsoft.Web.Services.SoapContext ctx = svc.RequestSoapContext;
Microsoft.Web.Services.Security.X509.X509Certificate cert =
    Microsoft.Web.Services.Security.X509.X509Certificate.
    CreateCertFromFile(@C:\Temp\ServerCert.cer");
Microsoft.Web.Services.Security.X509SecurityToken x509 =
  new Microsoft.Web.Services.Security.X509SecurityToken(cert);

Microsoft.Web.Services.Security.EncryptedData enc =
  new Microsoft.Web.Services.Security.EncryptedData(x509);
ctx.Security.Elements.Add(enc);

string ret = svc.GetData();
Webサービス・クライアントで、証明書ファイルに含まれる公開鍵によりSOAPメッセージを暗号化して送信するためのコード例
は、実際のコードでは改行しないで次行に続いていることを示しています)

 下から5行目を除いて、証明書をセキュリティ・トークンに使うときのコードと同じコードになっている。下から5行目では、X509SecurityTokenから暗号化データを作成して、最後の行でそれをSOAPメッセージに含める操作をしている。このコードで送信されるSOAPメッセージは次のようになる。これまた目が回りそうな内容だが、これを手で書いたり、目で見たりして理解する必要はない。

上記のコードで送信される、証明書を利用して暗号化されたSOAPメッセージ例(IEで表示)

 このメッセージを受け取ったサーバ側では、Bodyの暗号を解くためにHeader/Security/EncryptedKey/KeyInfo要素を参照して、これがX.509v3証明書による暗号であることを認識し、証明書ストアにアクセスしてIDが一致する証明書を入手して、暗号の解読を行う。なお、この場合に利用する証明書には、証明書のキー使用法として「Key Encipherment」が含まれていなければならない。含まれていない場合、クライアント側でSOAPメッセージを暗号化しようとしたときに例外が発生する。

■対称鍵を利用した暗号
 対称鍵を利用する場合の注意点は、鍵情報をあらかじめクライアントとサーバの間で交換しておかなくてはならないということだ。例えば、サービス提供の契約を交わすときに、鍵を交換してもいいだろう。あるいは非対称鍵暗号方式を使って、対象鍵をまず暗号化して電子的に交換し、次からはその鍵を利用する方法も考えられる。

 .NET Frameworkには、最初から3DESでデータの暗号化を行うクラスが用意されている。このクラスは、WSEからでも利用できる。クライアント側では、次のようなコードにより3DESでSOAPメッセージのBodyを暗号化して送信できる。珍妙なバイト列を扱っているところに注意してほしい。この情報が、クライアントとサーバの間で共有されていなければならないのだ。もちろん下記のコードはあくまでも例であり、この例のようなキーでは安全性が低いのはいうまでもない。

localhost.Service1 svc = new localhost.Service1();

Microsoft.Web.Services.SoapContext ctx = svc.RequestSoapContext;
System.Security.Cryptography.SymmetricAlgorithm sma = new
  System.Security.Cryptography.TripleDESCryptoServiceProvider();
byte[] bkey = new byte[]
  {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
sma.Key = bkey;
sma.IV = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};
Microsoft.Web.Services.Security.EncryptionKey key = new
  Microsoft.Web.Services.Security.SymmetricEncryptionKey(sma, bkey);
Microsoft.Web.Services.Security.EncryptedData enc
  = new Microsoft.Web.Services.Security.EncryptedData(key);
ctx.Security.Elements.Add(enc);

string ret = svc.GetData();
Webサービス・クライアントで、3DESによりSOAPメッセージを暗号化して送信するためのコード例

 このコードで送信されるSOAPメッセージは次のようになる。またまた目が回りそうな内容だが、やはりこれを手で書いたり、目で見たりして理解する必要はない。

上記のコードで送信される、3DESにより暗号化されたSOAPメッセージ例(IEで表示)

 このメッセージを受け取ったサーバ側では、Bodyの暗号を解くためにMicrosoft.Web.Services.Security.IDecryptionKeyProviderインターフェイスの実装をロードし、そのGetDecryptionKeyメソッドを呼び出して解読用の鍵を入手する。IDecryptionKeyProviderインターフェイスの実装は開発者が用意しなければならない。このインターフェイスには、GetDecryptionKeyメソッドが1つだけ定義されている。例えば次のような実装で、上記のコードで暗号化されたSOAPメッセージを復号できる。上記のコードで利用したのと同じ内容のSystem.Security.Cryptography.TripleDESCryptoServiceProviderクラスのインスタンスを作成して、それを基にMicrosoft.Web.Services.Security.SymmetricDecryptionKeyクラスのインスタンスを返しているだけだ。

public Microsoft.Web.Services.Security.DecryptionKey
    GetDecryptionKey(string algorithmUri,
      System.Security.Cryptography.Xml.KeyInfo keyInfo) {
  System.Security.Cryptography.SymmetricAlgorithm sma = new
    System.Security.Cryptography.TripleDESCryptoServiceProvider();
  byte[] bkey = new byte[]
    {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
  sma.Key = bkey;
  sma.IV = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};

  return new Microsoft.Web.Services.Security.SymmetricDecryptionKey
              (sma, bkey);
}
SOAPメッセージを復号するための鍵を返すGetDecryptionKeyメソッドの実装例

 このメソッドを実装したIDecryptionKeyProviderインターフェイスの実装クラスは、Web.configファイルに設定しなければならない。設定方法はPasswordProviderクラスと同じ要領だ。これによってWSEがこのクラスを探せるようになる。

<configSections>
  <section name="microsoft.web.services" type="Microsoft.Web.Services.Configuration.WebServicesConfiguration, Microsoft.Web.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<microsoft.web.services>
  <security>
    <decryptionKeyProvider type="WSE1.DecryptionProvider1, WSE1" />
  </security>
</microsoft.web.services>
IDecryptionKeyProviderインターフェイスを実装したクラスを指定するためのWeb.configの記述例

 これまで同様、[WebMethod]の中で暗号化や復号について心配する必要はない。WSEが面倒を見てくれる。

今回のまとめ

 今回は、WSEが持つWS-Security仕様の実装を一通り網羅して解説した。WS-SecurityはOASISで標準化作業が始まったばかりだし、WSEも初期リリースで足りない機能も多いが、それでもだいぶ以前からの懸案だったXML Webサービスのセキュリティについて、Microsoftやほかの有力ベンダがどの方向に進もうとしているのかを、開発者の視点で確認できるだろう。

 次回はWSEのそのほかの機能である、添付ファイルの処理とルーティングを取り上げる。End of Article

 

 INDEX
  特集 次世代XML Webサービスを試す Part 2
  WS-Security詳細解説
    1.WS-SecurityとWeb Services Enhancements
    2.セキュリティ・トークンと認証
    3.セキュリティ・トークンとしてのX.509v3証明書
    4.SOAPメッセージの完全性
  5.SOAPメッセージの秘匿性
 
 「特集:次世代XML Webサービスを試す」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間