ヘッダーをスキップ
Oracle® Fusion Middleware Oracle Security Developer Toolsリファレンス
11gリリース1 (11.1.1)
B61386-02
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

8 Oracle XML Security

XMLセキュリティとは、XML文書の標準セキュリティ要件(機密保持、整合性、メッセージの認証、否認防止など)を意味します。XML文書のためのデジタル署名暗号化の規格のニーズが高まったため、W3Cは、XML署名規格およびXML暗号化規格を提唱しています。

この章では、Oracle XML Securityの主要な機能と利点、およびOracle XML Securityを使用するための環境設定について説明します。

この章に含まれる内容は次のとおりです。


関連項目:

XMLおよびXML規格の詳細は、次のリソースを参照してください。
  • XML署名のW3C勧告

  • XML暗号化のW3C勧告

これらのリソースへのリンクは、付録A「リファレンス」を参照してください。


8.1 Oracle XML Securityの機能と利点

Oracleセキュリティ開発ツールでは、XML Signature仕様およびXML Encryption仕様の完全な実装が提供されます。

8.1.1 サポートされるアルゴリズム

Oracleセキュリティ開発ツールでは、XML Signature仕様およびXML Encryption仕様の完全な実装が提供され、次のアルゴリズムがサポートされています。

署名アルゴリズム

  • DSA-SHA1

  • RSA-SHA1

  • HMAC-SHA1

ダイジェスト・アルゴリズム

  • MD5

  • SHA1

  • SHA256

  • SHA512

変換

  • Canonicalization: Canonical XML 1.0、Canonical XML 1.1、Exclusive Canonical XML 1.0(すべての形式はコメントありおよびコメントなしでサポートされます)

  • XSLT

  • XPath Filter

  • XPath Filter 2.0

  • Base64 Decode

  • Enveloped Signature

  • Decrypt Transform

データ暗号化アルゴリズム

  • AES-128(CBCモード)

  • AES-192(CBCモード)

  • AES-256(CBCモード)

  • DES EDE(CBCモード)

鍵暗号化アルゴリズムと鍵ラップ・アルゴリズム

  • MGF1使用のRSAES-OAEP-ENCRYPT

  • RSAES-PKCS1-v1_5

  • AES-128鍵ラップ

  • AES-192鍵ラップ

  • AES-256鍵ラップ

  • DES-EDE鍵ラップ

これらの規格へのリンクは、付録A「リファレンス」を参照してください。

8.2 Oracle XML Securityの環境設定

Oracleセキュリティ開発ツールは、Oracle WebLogic ServerとともにORACLE_HOME/modules/oracle.osdt_11.1.1にインストールされます。

システム要件

Oracle XML Securityを使用するには、JDK 5以上が必要です。

CLASSPATH環境変数

次の項目をCLASSPATHに指定します。

8.3 データの署名方法

Oracleセキュリティ開発ツールのOracle XML Security APIを使用すると、XML文書、XML文書のフラグメントまたは一部のバイナリ・データに署名できます。この項では、データ署名の概念について説明します。

基本手順は次のとおりです。

  1. 署名対象と署名の配置場所を識別します。

  2. 署名鍵を決定します。


関連項目:

Oracle XML Security APIを使用したデータ署名の詳細は、8.8項から8.11項を参照してください。

8.3.1 署名対象の識別

最初の手順は、署名が必要なデータおよび署名の配置場所を識別することです。

署名の最も一般的な例は、文書の一部に署名している場合で、署名も同じ文書内に配置されます。この場合は、該当の部分を参照する方法を決定する必要があります。最も簡単な方法は、たとえば次のようにIDを使用することです。

<myDoc>
  <importantInfo  xml:id="foo1">
    ...
  </importantInfo>
  <dsig:Signature>
    ...
      <dsig:Reference URI="#foo1">
    ...
  </dsig:Signature>
</myDoc>

この例では、myDocが文書全体で、その中の<importantInfo>要素のみに署名し、署名は<importantInfo>要素の直後に配置されます。<importantInfo>には、xml:id属性があり、Signatureはこの部分を使用して参照します。

xml:idは、汎用の識別メカニズムです。

この属性を<importantInfo>要素に追加することがスキーマで許可されていない場合は、かわりにXpathを使用して参照できます。

8.3.1.1 署名エンベロープの決定

この例では、署名と署名対象の要素が完全に別個である非結合署名を使用します。

署名には、次の2つ正反対の方法があります。

  • エンベロープされる(署名要素が署名対象の要素の子/子孫)

  • エンベロープする(署名要素が署名対象の要素の親/祖先)

エンベロープされる署名の例

<myDoc>
  <importantInfo  xml:id="foo1">
    ...
    <dsig:Signature>
      ...
      <dsig:Reference URI="#foo1">
         ...
         <Transform Algorithm="...enveloped-signature">
         ...
      </dsig:Reference>
      ...
    </dsig:Signature>
    ...
  </importantInfo>
</myDoc>

エンベロープされる署名を使用する場合は、EnvelopedSignatureTransformを使用して、署名の計算から署名自身を除外する必要があります。除外しないと、署名を生成する処理によってimporttantInfo要素の内容が変更され、検証が失敗します。

8.3.1.2 バイナリ・データの署名方法の決定

バイナリ・データに署名することもできます。この場合は、バイナリ・データをURIで参照できるようにする必要があります。Oracle XML Securityでは、http:、file:およびzip:のURIなど、JDKで解決できるものであればどのようなURIでも使用できます。

Signature要素を含む別のXML文書を作成する必要があります。この署名は、このURIを使用してバイナリ・データを参照します。

URIでXMLデータにアクセスできる場合は、このメカニズムを使用してXMLデータに署名することもできます。ただし、XMLの場合は、バイナリ・データとして処理してバイナリ・データのまま署名するか、正規化を適用してXMLとして署名するかを決定します。正規化を適用するには、正規化変換を追加する必要があります。

バイナリ・データが、base64でエンコードされた文字列としてXML文書に存在する場合は、IDベースまたはXpathベースの参照を使用できます。データのデコードとバイナリの署名にはBase64DecodeTransformを使用できます。

<myDoc>
  <importantBinaryData  xml:id="foo1">
    XJELGHKLasNDE12KL=
  </importantBinaryData>
  <dsig:Signature>
    ...
      <dsig:Reference URI="#foo1">
         ...
         <Transform Algorithm="...base64">
         ...
      </dsig:Reference>
      ...
  </dsig:Signature>
</myDoc>

注意:

外部URI間接参照は、安全性が非常に低下する場合があります。たとえば、Oracleセキュリティ開発ツールのコードをサーバー内で実行しており、受信メッセージを検証するとします。このメッセージに外部URI参照が含まれていると、サーバーは基本的にファイルまたは外部のWebサイトから読み取ることになります。これは、サービス拒否攻撃やクロスサイト・スクリプティングにつながる場合があります。

デフォルトで外部URI間接参照が無効になっているのはこのためです。外部URI間接参照を許可するには、JVMプロパティosdt.allow.externalReferences(またはosdt.allow.all)を設定する必要があります。


8.3.1.3 1つの署名での複数XMLフラグメントの署名

同じ署名に複数のXMLフラグメントを含めることができます。たとえば、IDベースの参照が2つある場合に、両方の参照を同じ署名に含めることができます。また、複数のサブツリーに解決されるXpath式を使用することもできます。

ローカルIDベースの参照とリモートのURI参照を混在して一致させ、すべての参照を同じ署名に含めることもできます。

実際は、複数の部分を同じ署名に含め、暗号的に一緒にバインドするすることをお薦めします。たとえば、XML署名を使用して発注書の承認に署名する場合は、購入対象の品目、承認したユーザー、承認時刻をすべて同じ署名に含める必要があります。ユーザーを含めることを忘れると、第三者がこのメッセージを盗んでユーザー名を変更し、再送信することが可能になり、この場合も署名は検証されます。

8.3.1.4 署名からの要素の除外

サブツリー全体に署名するのではなく、一部のサブツリーを除外して署名する必要がある場合は、Xpath式を使用する必要があります。

8.3.2 署名鍵の決定

署名対象と参照方法を決定したら、署名鍵を決定する必要があります。オプションは次のとおりです。

  • X509Certificateを使用します。

    これは最も一般的なメカニズムです。秘密鍵を使用して署名し、対応する公開鍵を持つユーザーはその鍵で検証できます。

  • DSA、RSA、DH鍵などのRAW非対称署名鍵を使用します。

    X509certificateを使用して署名している場合は、実際は証明書に関連付けられたDSA/RSA/DH署名鍵で署名していることになります。証明書に関連付けられていないDSA/RSA/DH署名鍵を使用することもできますが、このような処理には意味がありません。

  • 対称鍵を使用します。

    対象鍵を使用してHMAC署名を行うこともできます。これは、署名した側と検証する側で対称鍵をすでに共有している場合に有効で、この場合、パスワードから導出された鍵や、対称鍵を使用するKerberosシステムから導出された鍵にすることができます。Oracleセキュリティ開発ツールのWS Security APIには、パスワードベースの鍵用とKerberos鍵用に明示的なAPIが用意されています。

8.3.2.1 鍵交換の設定

鍵交換は帯域外で処理する必要があります。たとえば、証明書を使用して署名している場合は、受信者側で証明書を検証できるように、トラスト・ポイントを使用して受信者が設定されている必要があります。また、対称鍵を使用して署名している場合は、受信者側でこの対称鍵を把握している必要があります。XML Signature仕様では、このような最初の鍵交換のメカニズムについては定義していません。

8.3.2.2 受信者ヒントの提供

署名の検証方法を把握できるように、受信者にヒントを提供する必要もあります。これは、<dsig:Signature>内の<dsig:KeyInfo>タグにあります。ヒントの提供は、次の方法で可能です。

  • ヒントを提供しないこともできます。鍵を受信者にすでに渡してある場合は、この方法でもまったく問題がなく、受信者側では、すべての署名がこの鍵で署名されることを前提としています。ただし、このような状況はあまりありません。

  • X509Certificateを使用して署名する場合は、次の中から1つ以上を提供できます。

    • X509Certificate全体。これが最も一般的な用法です。

    • 証明書のSubject DN。これは、受信者側でLDAPディレクトリにアクセスできる場合に有効で、受信者はDNに基づいて証明書を検索できます。

    • SubjectKeyIdentifierまたはIssuerDN/Serial番号ペア。これは、受信者側で証明書のセットから1つの署名を要求するだけの場合に有効です。受信者は、署名を検証する必要があるたびに、すべての証明書をループ処理して、一致するSKIまたはIssuerSerialを持つ証明書を検索できます。

  • RAW非対称鍵を使用して署名する場合は、RSA/DSA/DH公開鍵の実際の値を提供できます。これは、受信者側で鍵を検証できないためお薦めしませんが、かわりに、証明書を含んでいる場合は、受信者側でPKIX処理を実行して検証できます。つまり、受信者は証明書の妥当性をチェックしてOCSPまたはCRLと照合できます。

  • 対称鍵を使用して署名する場合は、鍵名を提供できます。これは、受信者側で対称鍵の取得/構成に使用できる情報を伝える文字列にすぎません。

8.4 データの検証方法

この項では、データ検証の概念について説明します。

署名の作成方法について理解したら、同様の手順を使用して署名を検証できます。基本手順は次のとおりです。

  1. 署名要素を検索し、署名された部分をチェック

    XML文書で署名要素を最初に検索します。この署名に含まれている要素をリスト表示するためのメソッド(リンクを挿入)がOracle XML Securityで提供されます。これらが署名対象の要素であることを確認します。

  2. 検証鍵をフェッチ

    次に、署名に使用された鍵を識別します。この場合は、<dsig:KeyInfo>を確認し、検証に使用する証明書、RAW公開鍵または対称鍵を識別します。


関連項目:

Oracle XML Security APIを使用したデータ検証の詳細は、次を参照してください。

8.5 データの暗号化方法

この項では、データの暗号化の概念について説明します。

Oracle XML Security APIを使用すると、XML文書、XML文書のフラグメントまたは一部のバイナリ・データに署名できます。基本手順は次のとおりです。


関連項目:

Oracle XML Security APIを使用したデータ暗号化の詳細は、8.10項「Oracle XML Security APIを使用したデータの暗号化方法」を参照してください。

8.5.1 暗号化対象の識別

最も一般的な暗号化のシナリオは、暗号化と置換です。文書の一部を暗号化すると、暗号化したバイトで文書が置換されます。

次に例を示します。

<myDoc>
  <importantInfo>
    ...
  </importantInfo>
</myDoc>

importantInfo要素を暗号化すると、次のようになります。

<myDoc>
  <xenc:EncryptedData>
    ...
  </xenc:EncryptedData>
</myDoc>

この場合は、<importantInfo>全体およびすべての内容が、EncryptedData要素によって置き換えられます。この要素は、基本的に暗号化された<importantInfo>要素のbase64エンコーディングであるbase64の大きな文字列を含みます。

このモードでは、<importantInfo>要素は完全に非表示になっており、受信者は復号化されるまで内容を知ることはできません。

8.5.1.1 コンテンツのみの暗号化モード

コンテンツのみの暗号化モードもあります。このモードでは、要素タグ自身は暗号化されませんが、すべての内容が暗号化されます。

<myDoc>
  <importantInfo>
    <xenc:EncryptedData>
      ...
    </xenc:EncryptedData>
  </importantInfo>
</myDoc>

コンテンツのみのモードを使用するのは、全員が<importantInfo>の存在を知っていることが適切な場合です。<importantInfo>要素の内容の復号化および確認方法を知るのは対象の相手のみになります。

8.5.1.2 バイナリ・データの暗号化

base64エンコード文字列として存在するバイナリ・データを暗号化する場合は、正規のXMLデータであるかのように暗号化できます。

ただし、外部のバイナリ・データ(XML文書の外部にあるデータ)を暗号化する場合は、暗号化したデータの格納場所に応じてオプションが異なります。

外部に格納する場合

1つのオプションは、暗号化したデータを外部にも格納する方法です。SOAP添付ファイルの場合は、添付ファイルの暗号化メカニズムと、暗号化したデータを添付ファイルとして格納するメカニズムについて指定している、WS Security SOAP Attachments (リンクを挿入)を参照してください。

暗号化したデータを外部に格納するには、xencEncryptedDataのサブ要素であるxenc:CipherReferenceを使用し、暗号化したバイトをURIを使用して参照するする必要があります。

内部に格納する場合

もう1つのオプションは、インプレースのXML暗号化と同様に、暗号化したバイトをEncryptedData内に格納する方法です。

8.5.2 暗号化鍵の決定

この方法は、非対称鍵を使用して直接暗号化を行わない点を除いて、署名鍵を決定するタスク(8.3.2項「署名鍵の決定」を参照)と非常に似ています。通常は次のようにします。

  • ランダムの対称鍵を選択します。

  • この鍵でデータを暗号化します。

  • 非対称鍵でランダムの対称鍵を暗号化します。

  • 暗号化したデータと暗号化した鍵の両方を受信者に送信します。

対称鍵を使用した場合も、次の方法を選択できます。

  • ランダムの対称鍵を生成します。

  • 対称鍵でランダムの対称鍵を暗号化します。

  • 暗号化したデータ鍵と暗号化した鍵の両方を受信者に送信します。

このような暗号化した鍵のメカニズムを使用するには、xenc:EncryptedKeyを文書内のどこに配置するかを決定する必要があります。

  • encryptedData要素が1つしかない場合は、EncryptedKeyEncryptedDataKeyInfoに配置します。

  • それ以外の場合は個別に配置し、一方がもう一方を参照するようにします。

EncryptedKeyの復号化に使用できる証明書、非対称鍵または鍵名を参照するには、EncryptedKey内で<dsig:KeyInfo>を使用します。

8.6 データの復号化方法

データの復号化では、データの暗号化と同じプロセスに従いますが、処理手順が逆です。基本手順は次のとおりです。

適切な位置に配置した単純な暗号化を使用してデータが暗号化されている場合は、EncryptedData要素を検索し、そのKeyInfoを参照します。

既知の対称鍵で直接暗号化されている場合は、その部分を復号化します。

ランダムの対称鍵で暗号化されている場合は、次のようにします。


関連項目:

Oracle XML Security APIを使用したデータ復号化の詳細は、次を参照してください。

8.7 Oracleセキュリティ開発ツールのXML APIの要素ラッパーについて

Oracle XML Security、Oracle Web Services Security、Oracle SAML、Oracle XKMS、Oracle Liberty SDKなどのXMLベースのOracleセキュリティ開発ツールAPIは、すべてラッパーの概念を使用しています。

各XML要素には、それぞれ対応するJavaラッパー・クラスがあります。たとえば、<dsig:Signature> XML要素はXSSignatureクラスに対応します。これらのラッパー・クラスはすべてXMLElementから継承され、対応するDOM要素のポインタであるデータ・メンバーを1つだけ含みます。

この項では、Oracleセキュリティ開発ツールAPIでラッパー・オブジェクトを処理する方法について説明します。

8.7.1 ラッパー・オブジェクトの構成

DOM要素からラッパー・オブジェクトを構成するには、コンストラクタを起動するだけです。

次に例を示します。

Element sigElem =  
   (Element)doc.getElementsByTagNameNS(XMLURI.ns_dsig, "Signature").item(0);
XSSignature sig = new XSSignature(sigElem);

DOM要素が存在しない場合にラッパー・オブジェクトを構成するには、次のいずれかを実行します。

  • DOM要素を作成し、前述のメソッドを使用します。

  • newInstanceメソッドを使用します。

XSSignature sig = XSSignature.newInstance(doc, null);

これにより、内部的には同じ結果になり、つまり、<dsig:Signature> DOM要素がどこにも追加されずに作成され、ラッパー・オブジェクトが要素の上に作成されます。この要素は、文書の任意の場所に追加する必要があります。

一部のラッパー・クラスでは、newInstanceメソッドがないため、文書オブジェクトを取得するコンストラクタをコールする必要があります。

XSSignedInfo sigInfo =  new XSSignedInfo(doc, null);

要素からラッパー・オブジェクトを作成するには、XMLUtils.getInstanceメソッドをコールする方法もあります。

XSSignature sig = (XSSignature)XMLUtils.getInstance(sigElem);

Oracleセキュリティ開発ツールAPIでは、要素名をラッパー・クラス名に関連付ける表が内部に保持されます。XMLUtils.getInstanceは、この表を使用して適切なコンストラクタを起動し、ラッパー・クラスのインスタンスを返します。

8.7.2 ラッパー・オブジェクトからのDOM要素の取得

基礎となるDOM要素は、すぐに利用できます。すべてのラッパー・クラスは、基礎となるDOM要素を取得できるように、メソッドXMLElement.getElement()を提供するXMLElementから拡張されています。

8.7.3 複合要素の解析

サブ要素の階層を含む複合要素がある場合は、同等のラッパー・オブジェクトの階層も常に存在します。たとえば、次のように署名を含む文書を受信するとします。

<dsig:Signature>
  <dsig:SignedInfo>
    <dsig:CanonicalizationMethod ... />
     ...
  <dsig:SignedInfo>
  <dsig:SignatureValue>..</dsig:SignatureValue>
  ...  
</dsig:Signature>

これらの要素の大部分には、対応するラッパー・クラス(dsig:Signature -> XSSignature、dsig:SignedInfo -> XSSignedInfo、dsig:SignatureValue -> XSSignatureValueなど)があります。

ただし、dsig:Signature DOM要素からXSSignedInfoオブジェクトを構成すると、子オブジェクトは構成されないため、子要素を見ることもありません。新しいXSSignature(sigElem)は、sigElemを指すデータ・メンバーでオブジェクトを作成するだけのクイック・コールです。子オブジェクトは毎回作成されます。このため、XSSignature.getSignedInfo()をコールすると、dsig:Signatureの子要素を検索してdsig:SignedInfo要素が特定され、その要素に対してラッパー・オブジェクトが構成されて返されます。

このラッパー・オブジェクトはどこにも格納されません。したがって、XSSignature.getSignedInfo()を再度起動しても同じ処理が実行され、SignedInfoオブジェクトの異なるインスタンスが返されますが、これらのオブジェクトは両方とも同じDOM要素を指すため、インスタンスが異なる場合でもまったく同じように動作します。


注意:

DOMは真のソースですが、ラッパー・オブジェクトは棄却型オブジェクトであることを忘れないでください。getメソッドでは、常に新しいラッパー・オブジェクトが作成されますが、基礎となるDOMを変更すると、ラッパー・オブジェクトには常に最新の変更が反映されます。

8.7.4 複合要素の構成

ここでは、前述と同じ例を検討しますが、受信文書に存在する署名ではなく、署名を含む文書を作成し、この文書を第三者に送信します。

<dsig:Signature>
  <dsig:SignedInfo>
     ...
  <dsig:SignedInfo>
  ...  
</dsig:Signature>

このような複合要素を構成するには、個別のラッパー・オブジェクトを作成し、setメソッドを使用してアセンブルする必要があります。

次に例を示します。

XSSignature sig = XSSignature.newInstance(doc, null);
XSSignedInfo sigInfo = new XSSignedInfo(doc, null);
sig.setSignedInfo(sigInfo);

DOMは常に真のソースであることを忘れないでください。setメソッドでは、渡されたラッパー・オブジェクトの格納やコピーは実行されません。基礎となるDOMを変更するだけです。

この場合、setSignedInfodsig:SignedInfo要素を取得し、dsig:Signature要素の子にします。したがって、setSignedInfo(sigInfo)を起動した後に、sigInfo = nullを実行しても、影響を受けるものはありません。

最後に、最上位レベルのオブジェクトをDOMの任意の場所に挿入する必要があります。

elem.appendChild(sig.getElement());

8.8 Oracle XML Security APIを使用したデータの署名方法

この項では、Oracle XML Security APIでデータに署名する技術について説明します。

8.8.1 デタッチされた署名を作成するための基本手順

デタッチされた署名を作成するには、次のようにします。

<myDoc>
  <importantInfo  xml:id="foo1">
    ...
  </importantInfo>
  <dsig:Signature>
    ...
      <dsig:Reference URI="#foo1">
    ...
  </dsig:Signature>
</myDoc>

次を実行する必要があります。

// assume you have your data set up in doc
Document doc = ...
Element impElem = ...
 
// Now put an ID on the importantInfo element
impElem.setAttributeNS(XMLURI.ns_xml, "xml:id", "foo1");
 
// Then get the signing key and certificate from 
// somewhere – e.g. you can load them from a keystore
PrivateKey signKey = ...
X509Certificate signCert = ...
 
// Create the Signature object
XSSignature sig = XSSignature.newInstance(doc, null);
 
// Create the SignedInfo object
// Normally you should use exclusive canonicalization
//    alg_exclusiveC14N
// Depending on the type of your private key DSA or RSA
//    use dsaWithSHA1 or rsaWithSHA1
XSSignedInfo sigInfo = sig.createSignedInfo(
  XMLURI.alg_exclusiveC14N, XMLURI.alg_rsaWithSHA1, null)
sig.setSignedInfo(sigInfo);
 
 
// Create a Reference object to the importantInfo element
// You need to specify the id which you set up earlier, 
//  and also a digestMethod
XSReference ref = sig.createReference(null, "#foo1", null, 
   XMLURI.alg_sha1);
sigInfo.addReference(ref);
// Create an exclusive c14n Transform object
// If you do not add this transform object, it will use 
// inclusive by default
XSAlgorithmIdentifier transform = 
  new XSAlgorithmIdentifier(doc, "Transform", 
  XMLURI.alg_exclusiveC14n);
ref.addTransform(transform);
 
 
// Create a KeyInfo object
XSKeyInfo keyInfo = sig.createKeyInfo();
sig.setKeyInfo(keyInfo);
 
// Create an X509Data element for your signingCert, inside
//  this keyingo
X509Data x509 = keyInfo.createX509Data(signingCert);
keyInfo.addKeyInfoData(x509);
 
// Everything is setup, now do the actual signing
// This will actually do all the canonicalization, 
// digesting, signing etc
sig.sign(signKey, null);
 
// Finally insert the signature somewhere in your document
doc.getDocumentElement().appendChild(sig.getElement());

注意:

子のラッパー・オブジェクトを作成したら、setメソッドまたはaddメソッドをコールして親に配置する必要があります。最上位レベルのSignatureオブジェクトを文書に挿入することも忘れないでください。

8.8.2 基本的な署名手順に対するバリエーション

基本的な署名手順に対するバリエーションには、複数の参照、エンベロープされた署名、XPath式、証明書ヒントおよびHMAC鍵署名があります。

8.8.2.1 複数の参照

署名に複数の参照を含めるには、XSReferenceオブジェクトをXSSignedInfoオブジェクトに追加するだけです。各XSReferenceオブジェクトには、独自の変換リストが必要です。

8.8.2.2 エンベロープされた署名

エンベロープされた署名を使用するには、エンベロープされた署名変換を参照に追加します。つまり、排他変換を追加するコードの直前に次のコードを挿入します。

XSAlgorithmIdentifier transform1 = 
  new XSAlgorithmIdentifier(doc, "Transform", 
  XMLURI.alg_envelopedSignature);
ref.addTransform(transform1);

8.8.2.3 XPath式

IDベースの参照のかわりにXPath式を使用するには、createReferenceのURIパラメータに、#foo1ではなく空の文字列を渡し、最初の変換としてXPath変換をReferenceに追加します。

String xpathExpr = "ancestor-or-self:importantInfo";
Element xpathElem = doc.createElementNS(XMLURI.ns_dsig, 
 "dsig:XPath");
xpathElem.appendChild(doc.createTextNode(xpathExpr);
XSAlgorithmIdentifier transform2 = 
  new XSAlgorithmIdentifier(doc, "Transform", 
  XMLURI.alg_xpath);
transform2.addParameter(xpathElem);
ref.addTransform(transform2);

8.8.2.4 証明書ヒント

鍵情報に証明書全体を含めず、証明書のヒントのみを含める場合は、引数なしの形式のXSKeyInfo.createX509Data()を使用し、メソッドX509Data.addIssuerSerialaddSubjectNameまたはaddSubjectKeyIDのいずれかをコールします。

8.8.2.5 HMAC鍵を使用した署名

RSAまたはDSAの秘密鍵ではなく、HMAC鍵を使用して署名するには、XSSignature.sign(byte[] secret, String sigValueId)メソッドを使用し、最初の引数としてHMAC鍵を渡します。

また、XSKeyInfo.createKeyNameをコールすることにより、KeyNameなどの異なる種類のKeyInfoを使用します。

8.9 Oracle XML Security APIを使用した署名の検証方法

この項では、Oracle XML Security APIを使用して署名を検証する方法について説明します。

8.9.1 署名対象をチェックするための基本手順

署名を検証するには、最初に文書内の<dsig:Signature>要素を検索し、この要素を使用してXSSignatureラッパー・オブジェクトを構成します。

Element sigElem = …
XSSignature sig = new XSSignature(sigElem);

次に、署名のKeyInfoをフェッチし、鍵を調べて署名者が信頼できるかどうかを判断します。KeyInfoを処理するには、次のような様々な方法があります。

  • 非常に単純な場合は、検証鍵が事前にわかっている場合があるため、KeyInfoを確認する必要はありません。

  • これに対し、ほとんどの場合では、KeyInfoを確認する必要があります。1つの方法はコールバックを設定することであるため、XSSignature.verify()をコールする場合は、検証鍵なしてコールします。内部的に、Oracleセキュリティ開発ツールでは、KeyInfoを確認し、コールバックを起動して鍵をフェッチするかどうかを判断します。

  • その他のオプションには、KeyInfoを事前に確認して、鍵を自身で判断する方法があります。

8.9.2 コールバックの設定

KeyInfoに署名証明書が含まれている場合

KeyInfoに署名証明書が含まれていることが想定される場合で、この証明書をまだ取得しておらず、トラスト・ポイントを設定している場合は、証明書バリデータのコールバックを設定するだけで済みます。

// Create your certificate validator
CertificateValidator myValidator 
  = new CertificateValidator() {
  public void validateCert(CertPath cp) {
     // Code to validate the certificate
  }
};
KeyRetriever.setCertificateValidator(myValidator);

Oracleセキュリティ開発ツールAPIでは、証明書をKeyInfoから取得して、コールバックを起動します。コールバックがtrueを返す場合は、その証明書で検証されます。

KeyInfoにヒントが含まれている場合

KeyInfoに署名証明書のヒント(subjectDN、発行者のSerialまたはサブジェクト・キー識別子)しか含まれていないことが想定される場合は、KeyRetrieverを記述して、このヒントに指定された証明書ストアから証明書をフェッチします。

証明書ストアがキーストア、PKCS12ウォレットまたはPKCS8ファイルの場合は、これらのタイプの組込みの取得機能のいずれかを使用します。これらの取得機能では、キーストアまたはOracleウォレット内のすべての証明書を反復処理し、指定したsubjectDN/issuerSerialまたはSubjectKeyに一致する証明書を検索します。


注意:

KeyInfoに証明書全体が含まれている場合、このメカニズムを使用することもできます。この場合は、鍵の取得機能で証明書全体を一致させるだけです。

// Load your keystore
KeyStore ks = 
// Set up a callback against this KeyStore
KeyRetriever.addKeyRetriever(
  new KeyStoreKeyRetriever(ks, passwd));

8.9.3 カスタムの鍵取得機能の記述

これらの組込みの取得機能が適切でない場合は、カスタムのKeyRetrieverKeyRetrieverクラスから導出して記述できます。これは、たとえばKeyInfosubjectDNが含まれていることが想定され、LDAPディレクトリを参照してそのDNの証明書を検索する場合に可能です。

KeyRetriever myRetriever = new KeyRetriever() {
   X509Certificate retrieveCertificate (KeyInfoData keyInfo) {
       // write code to fetch the certificate from 
       // the certificate store based on keyInfo
   }
 
   PublicKey retrieveCertificate (KeyInfoData keyInfo) {
       // write code to fetch the PublicKey from 
       // the certificate store based on keyInfo
   }
};
KeyRetriever.addKeyRetriever(myRetriever);

署名で対称鍵が使用されており、その鍵の名前がKeyInfoに含まれている場合は、この鍵名に基づいて対称鍵をフェッチできるカスタムの鍵取得機能を記述します。

8.9.4 署名対象のチェック

次の手順では、この署名で署名対象を実際に署名するかどうかをチェックします。Oracleセキュリティ開発ツールには、次の情報を返すAPIが用意されています。

// XSSignature has be created as mentioned before
XSSignature sig = ...
 
// at first locate the element that are expecting 
// to be signed
Element impElem = ...
 
// Now check if the signature really signs this
List signedObjects = XMLUtils.resolveReferences(sig);
if (signedObjects.size() != 1 ||
   signedObjects.get(0) != impElem {
   // something is wrong – impElem is not signed by
   // this signature
}

8.9.5 署名の検証

最後の手順では、署名を実際に検証します。

8.9.5.1 コールバックが設定されている場合

コールバックを設定したら、次のようにコールを実行します。

boolean result = sig.verify();

次のように、失敗した結果と例外の両方をチェックする必要があります。

  • 署名形式が正しいが参照ダイジェストのいずれかが一致していない場合や、署名が検証されない場合、sig.verify()falseを返します。

  • 署名の構成に問題がある場合、たとえば、アルゴリズム名に問題がある場合や署名のバイトが正しいサイズでない場合、sig.verify()は例外をスローします。

8.9.5.2 コールバックが設定されていない場合

コールバックを設定しておらず、鍵を自身で判断した場合は、次をコールする必要があります。

  • sig.verify(byte[])(HMAC鍵の場合)

  • sig.verify(PublicKey)(DSA/RSA鍵の場合)

8.9.5.3 検証のデバッグ

特定の署名が検証されない理由を特定できない場合は、デバッグし、JVMプロパティ–Dxml.debug.verify=1を設定する必要があります。このフラグは、Oracleセキュリティ開発ツールに、失敗した署名のstderrに診断結果を出力するように指示します。

8.10 Oracle XML Security APIを使用したデータの暗号化方法

この項では、Oracle XML Securityを使用したデータ暗号化の各種のオプションについて説明します。

8.10.1 共有対称鍵を使用した暗号化

次の<importantInfo>要素を暗号化して置き換えるには、次のようにします。

<myDoc>
  <importantInfo>
    ...
  </importantInfo>
</myDoc>

次の手順に従う必要があります。

// Assuming there is a shared symmetric key
SecretKey dataEncKey = ...
 
// Create a new XEEncryptedData instance 
// use either obj_Element or obj_Content depending
// on whether you want to encrypt the whole element
// or content only
XEEncryptedData ed = XEEncryptedData
    .newInstance(doc, null, XMLURI.obj_Element);
 
// Specify the data encryption method
XEEncryptionMethod em =   
   ed.createEncryptionMethod(XMLURI.alg_aes128_CBC);
ed.setEncryptionMethod(em);
 
// Create a Keyinfo with a hint to the symmetric key
XEKeyInfo ki= ed.createKeyInfo();
ki.addKeyInfoData(ki.createKeyName("MyKey"));
ed.setKeyInfo(ki);
 
// Locate the importantInfo element
Element impElem = ...
 
// Encrypt the importantInfo element and replace
// it with the EncryptedData element
XEEncrytedData.encryptAndReplace(impElem, dataEncKey, 
   null, ed);

暗号化のユーティティ・メソッド

次のすべての手順を実行するユーティリティ・メソッドが用意されています。

XEncUtils.encryptElement(
  impElem,  // element to be encrypted
  false,    // true = contentOnly, false = entire element
  XMLURI.alg_aes128_CBC, // data encryption alg
  "MyKey" // hint to data key
);

8.10.2 ランダムの対称鍵を使用した暗号化

8.10.1項「共有対称鍵を使用した暗号化」で紹介した例では、共有対称鍵があると想定した場合を簡素化していました。実際は、ランダムの対称鍵を生成してその鍵で暗号化し、このランダム対称鍵を受信者の公開鍵で暗号化するのが一般的です。この方法は次のとおりです。

// Load up the encryption certificate of the reciever
X509Certificate encCert = ...
 
// Get the reciever's public key from the cert
PublicKey keyEncKey = encCert.getPublicKey();
 
// Then generate a random symmetric key
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey dataEncKey = keyGen.generateKey();
 
// Now create an EncryptedKey object
XEEncryptedKey = new XEEncryptedKey(doc);
 
// set up the key encryption algorithm
XEEncryptionMethod em =   
  ek.createEncryptionMethod(XMLURI.alg_rsaOAEP_MGF1);
em.setDigestMethod(XMLURI.alg_sha1);
ek.setEncryptionMethod(em);
 
// encrypt the random symmetric key with public key
byte[] cipherValue = ek.encrypt(dataEncKey, keyEncKey);
 
// store this cipherValue into ek
XECipherData cd = ek.createCipherData();
cd.setCipherValue(cipherValue);
ek.setCipherData(cd);
 
 
// decide on how you would let the receiver know the
// the key encryption key. We are putting in the 
// entire reciever's certificate
XEKeyInfo kki = ek.createKeyInfo();
kki.addKeyInfoData(kki.createX509Data(encCert);
 
// Now the encrypted key has been set up, let us
// do the data encryption as before
XEncUtils.encryptElement(
  impElem,  // element to be encrypted
  false,    // true = contentOnly, false = entire element
  XMLURI.alg_aes128_CBC, // data encryption alg
  null // No hint to data key
);
 
// Finally we need to put the EncryptedKey inside the
// KeyInfo of the EncryptedData
ed.addKeyInfoData(ek);

暗号化のユーティティ・メソッド

次のすべての手順を実行するユーティリティ・メソッドが用意されています。

XEncUtils.encryptElement (
  impElem,  // element to be encrypted
  false,    // true = contentOnly, false = entire element
  XMLURI.alg_aes128_CBC, // data encryption alg
  dataEncKey, // the random symmetric key that we generated
  XMLURI.alg_rsaOAEP_MGF1, // key encryption alg
  KeyEncKey, // public key that we got from cert
  "RecieverCert" // A hint to the certificate
);

このユーティリティ・メソッドでは、KeyNameをEncryptedKeyのKeyInfoに配置する点に注意してください。このかわりにX509Dataを渡す場合は、keyEncKeyNameにnullを渡し、X509Dataを手動で追加します。

// use utility method to create EncrytedData
XEEncryptedData ed = XEncUtils...
 
// no extract EncryptedKey from it
XEEncryptedKey ek = (XEEncryptedKey)ed.getKeyInfo()
 .getEncryptedKeys().elementAt(0);
 
// Set the keyInfo of the ek
XEKeyInfo kki = ek.createKeyInfo();
kki.addKeyInfoData(kki.createX509Data(encCert);

8.11 Oracle XML Security APIを使用したデータの復号化方法

復号化技術は、共有対称鍵が存在するか、ランダムの対称鍵を使用するかによって異なります。

8.11.1 共有対称鍵を使用した復号化

共有対称鍵がある場合は、次のようにします。

// search for the EncryptedData element
Element edElem = ...
 
// decrypt the data
SecretKey dataDecKey = ...
XEEncrytedData.decryptAndReplace(dataDecKey, edElem, true);

8.11.2 ランダムの対称鍵を使用した復号化

ランダムの対称鍵を使用する場合は、次のようにします。

// search for the EncryptedData element
Element edElem = ...
 
// decrypt the data
PrivateKey keyDecKey = ...
XEEncUtils.decryptElement(edElem, keyDecKey);

8.12 サポート・クラスとインタフェース

この項では、Oracle XML Security APIのその他のクラスとインタフェースについて説明します。

8.12.1 oracle.security.xmlsec.util.XMLURIインタフェース

このインタフェースは、アルゴリズム、ネームスペースおよびオブジェクトのURI文字列定数を定義します。次のネーミング規則が使用されます。

  • アルゴリズムのURIはalg_で始まります。

  • ネームスペースのURIはns_で始まります。

  • オブジェクト・タイプのURIはobj_で始まります。

8.12.2 oracle.security.xmlsec.util.XMLUtilsクラス

このクラスには、XMLおよびXML-DSIGの静的ユーティリティ・メソッドが含まれます。アプリケーションで頻繁に使用されるメソッドには、createDocBuilder()createDocument()toBytesXML()およびtoStringXML()メソッドがあります。

8.13 XMLセキュリティに関する一般的な質問

この項では、XMLセキュリティやOracle XML Securityの使用に関してよくある質問に回答します。内容は次のとおりです。

DER形式とはなんですか。PEM形式とはなんですか。これらの形式はどのように使用しますか。

DERは、ASN.1 Distinguished Encoding Rules(特殊エンコーディング規則)の略称です。DERは、証明書と秘密鍵のエンコードに使用されるバイナリ形式です。Oracle XML Security SDKでは、証明書と秘密鍵を使用するほとんどの市販製品と同様に、ネイティブ形式としてDERを使用しています。

証明書と秘密鍵のエンコーディングに使用される形式は、PEM、PKCS #7およびPKCS #12など他にも多くありますが、これらはDERエンコーディングが変化したものです。たとえば、プライバシ強化メール(PEM)はテキスト形式ですが、DERバイナリ形式のBase 64エンコーディングです。PEM形式では、エンコードされるコンテンツのタイプを指定する、BEGINおよびENDテキスト行の使用も指定されます。

テキスト形式の電子メールで証明書を受信しました。意味不明と思われるテキスト文字が数行あります。Oracle XML Securityで使用可能な形式に変換するにはどうすればよいですか。

電子メールで証明書を受信した場合、証明書はPEM形式になっています。証明書をプライバシ強化メール(PEM)形式からASN.1特殊エンコーディング規則(DER)形式に変換する必要があります。

ブラウザでエクスポートした証明書はどのように使用すればよいですか。

ブラウザで証明書をエクスポートした際、多くの場合は、証明書はPKCS #12形式(*.p12または*.pfx)になります。PKCS #12オブジェクトを解析してコンポーネント部に分ける必要があります。

8.14 ベスト・プラクティス

XML署名仕様の実装者およびユーザーのベスト・プラクティスについては、次のサイトを参照してください。

http://www.w3.org/TR/xmldsig-bestpractices/

8.15 Oracle XML SecurityのJava APIリファレンス

Oracle XML SecurityのAPIリファレンス(Javadoc)は次のドキュメントで参照できます。

『Oracle Fusion Middleware XML Security Java API Reference for Oracle Security Developer Tools』