Oracle® Fusion Middleware Oracle Security Developer Toolsによるアプリケーションの開発 12c (12.2.1) E72521-01 |
|
前 |
次 |
XMLセキュリティとは、XML文書の標準セキュリティ要件(機密保持、整合性、メッセージの認証、否認防止など)を意味します。XML文書のためのデジタル署名と暗号化の規格のニーズが高まったため、W3Cは、XML署名規格およびXML暗号化規格を提唱しています。
Oracle XML Securityの機能と実装するコード例を扱います。
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鍵ラップ
Oracleセキュリティ開発ツールは、Oracle WebLogic ServerとともにORACLE_HOME/modules/oracle.osdt_11.1.1
にインストールされます。
システム要件
Oracle XML Securityを使用するには、JDK 5以上が必要です。
CLASSPATH環境変数
次の項目をCLASSPATH
に指定します。
osdt_core.jar
osdt_cert.jar
osdt_xmlsec.jar
(すべてのOracle XML Securityクラスを含むメインjar)
org.jaxen_1.1.1.jar
($ORACLE_HOME/modules/
に存在)
Oracle XML Securityは、XPathの処理のためにJaxen XPathエンジンを利用します。
関連項目:
Oracleセキュリティ開発ツールのOracle XML Security APIを使用すると、XML文書、XML文書のフラグメントまたは一部のバイナリ・データに署名できます。この項では、データ署名の概念について説明します。
基本手順は次のとおりです。
関連項目:
Oracle XML Security APIを使用したデータ署名の詳細は、「Oracle XML Security APIを使用したデータの署名」から「Oracle XML Security APIを使用したデータの復号化」を参照してください。
最初の手順は、署名が必要なデータおよび署名の配置場所を識別することです。
署名の最も一般的な例は、文書の一部に署名している場合で、署名も同じ文書内に配置されます。この場合は、該当の部分を参照する方法を決定する必要があります。最も簡単な方法は、たとえば次のように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を使用して参照できます。
この例では、署名と署名対象の要素が完全に別個である非結合署名を使用します。
署名には、次の2つ正反対の方法があります。
エンベロープされる(署名要素が署名対象の要素の子/子孫)
エンベロープする(署名要素が署名対象の要素の親/祖先)
エンベロープされる署名の例を示します。
<myDoc> <importantInfo xml:id="foo1"> ... <dsig:Signature> ... <dsig:Reference URI="#foo1"> ... <Transform Algorithm="...enveloped-signature"> ... </dsig:Reference> ... </dsig:Signature> ... </importantInfo> </myDoc>
エンベロープされる署名を使用する場合は、EnvelopedSignatureTransform
を使用して、署名の計算から署名自身を除外する必要があります。除外しないと、署名を生成する処理によってimporttantInfo
要素の内容が変更され、検証が失敗します。
バイナリ・データに署名することもできます。この場合は、バイナリ・データを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
)を設定する必要があります。
同じ署名に複数のXMLフラグメントを含めることができます。たとえば、IDベースの参照が2つある場合に、両方の参照を同じ署名に含めることができます。また、複数のサブツリーに解決されるXpath式を使用することもできます。
ローカルIDベースの参照とリモートのURI参照を混在して一致させ、すべての参照を同じ署名に含めることもできます。
実際は、複数の部分を同じ署名に含め、暗号的に一緒にバインドするすることをお薦めします。たとえば、XML署名を使用して発注書の承認に署名する場合は、購入対象の品目、承認したユーザー、承認時刻をすべて同じ署名に含める必要があります。ユーザーを含めることを忘れると、第三者がこのメッセージを盗んでユーザー名を変更し、再送信することが可能になり、この場合も署名は検証されます。
署名対象と参照方法を決定したら、署名鍵を決定する必要があります。オプションは次のとおりです。
X509Certificateを使用します。
これは最も一般的なメカニズムです。秘密鍵を使用して署名し、対応する公開鍵を持つユーザーはその鍵で検証できます。
DSA、RSA、DH鍵などのRAW非対称署名鍵を使用します。
X509certificateを使用して署名している場合は、実際は証明書に関連付けられたDSA/RSA/DH署名鍵で署名していることになります。証明書に関連付けられていないDSA/RSA/DH署名鍵を使用することもできますが、このような処理には意味がありません。
対称鍵を使用します。
対象鍵を使用してHMAC署名を行うこともできます。これは、署名した側と検証する側で対称鍵をすでに共有している場合に有効で、この場合、パスワードから導出された鍵や、対称鍵を使用するKerberosシステムから導出された鍵にすることができます。Oracleセキュリティ開発ツールのWS Security APIには、パスワードベースの鍵用とKerberos鍵用に明示的なAPIが用意されています。
鍵交換は帯域外で処理する必要があります。たとえば、証明書を使用して署名している場合は、受信者側で証明書を検証できるように、トラスト・ポイントを使用して受信者が設定されている必要があります。また、対称鍵を使用して署名している場合は、受信者側でこの対称鍵を把握している必要があります。XML Signature仕様では、このような最初の鍵交換のメカニズムについては定義していません。
署名の検証方法を把握できるように、受信者にヒントを提供する必要もあります。これは、<dsig:Signature>
内の<dsig:KeyInfo>
タグにあります。ヒントの提供は、次の方法で可能です。
ヒントを提供しないこともできます。鍵を受信者にすでに渡してある場合は、この方法でもまったく問題がなく、受信者側では、すべての署名がこの鍵で署名されることを前提としています。ただし、このような状況はあまりありません。
X509Certificate
を使用して署名する場合は、次の中から1つ以上を提供できます。
X509Certificate
全体。これが最も一般的な用法です。
証明書のSubject
DN。これは、受信者側でLDAPディレクトリにアクセスできる場合に有効で、受信者はDNに基づいて証明書を検索できます。
SubjectKeyIdentifier
またはIssuerDN/Serial番号ペア。これは、受信者側で証明書のセットから1つの署名を要求するだけの場合に有効です。受信者は、署名を検証する必要があるたびに、すべての証明書をループ処理して、一致するSKIまたはIssuerSerial
を持つ証明書を検索できます。
RAW非対称鍵を使用して署名する場合は、RSA/DSA/DH公開鍵の実際の値を提供できます。これは、受信者側で鍵を検証できないためお薦めしませんが、かわりに、証明書を含んでいる場合は、受信者側でPKIX処理を実行して検証できます。つまり、受信者は証明書の妥当性をチェックしてOCSPまたはCRLと照合できます。
対称鍵を使用して署名する場合は、鍵名を提供できます。これは、受信者側で対称鍵の取得/構成に使用できる情報を伝える文字列にすぎません。
この項では、データ検証の概念について説明します。
署名の作成方法について理解したら、同様の手順を使用して署名を検証できます。基本手順は次のとおりです。
関連項目:
Oracle XML Security APIを使用したデータ検証の詳細は、次を参照してください
この項では、データの暗号化の概念について説明します。
Oracle XML Security APIを使用すると、XML文書、XML文書のフラグメントまたは一部のバイナリ・データに署名できます。基本手順は次のとおりです。
関連項目:
Oracle XML Security APIを使用したデータ暗号化の詳細は、「Oracle XML Security APIを使用したデータの暗号化」を参照してください。
最も一般的な暗号化のシナリオは、暗号化と置換です。文書の一部を暗号化する場合は、暗号化したバイトで文書を置換します。
次に例を示します。
<myDoc> <importantInfo> ... </importantInfo> </myDoc>
importantInfo要素を暗号化すると、次のようになります。
<myDoc> <xenc:EncryptedData> ... </xenc:EncryptedData> </myDoc>
この場合は、<importantInfo>
全体およびすべての内容が、EncryptedData
要素によって置き換えられます。この要素は、基本的に暗号化された<importantInfo>
要素のbase64エンコーディングであるbase64の大きな文字列を含みます。
このモードでは、<importantInfo>
要素は完全に非表示になっており、受信者は復号化されるまで内容を知ることはできません。
コンテンツのみの暗号化モードもあります。このモードでは、要素タグ自身は暗号化されませんが、すべての内容が暗号化されます。
<myDoc> <importantInfo> <xenc:EncryptedData> ... </xenc:EncryptedData> </importantInfo> </myDoc>
コンテンツのみのモードを使用するのは、全員が<importantInfo>
の存在を知っていることが適切な場合です。<importantInfo>
要素の内容の復号化および確認方法を知るのは対象の相手のみになります。
base64エンコード文字列として存在するバイナリ・データを暗号化する場合は、正規のXMLデータであるかのように暗号化できます。
ただし、外部のバイナリ・データ(XML文書の外部にあるデータ)を暗号化する場合は、暗号化したデータの格納場所に応じてオプションが異なります。
データは暗号化されたデータ要素の外または内側に格納できます。
1つのオプションは、暗号化したデータを外部にも格納する方法です。SOAP添付ファイルの場合は、添付ファイルの暗号化メカニズムと、暗号化したデータを添付ファイルとして格納するメカニズムについて指定している、WS Security SOAP Attachments (リンクを挿入)を参照してください。
暗号化したデータを外部に格納するには、xencEncryptedData
のサブ要素であるxenc:CipherReference
を使用し、暗号化したバイトをURIを使用して参照するする必要があります。
もう1つのオプションは、インプレースのXML暗号化と同様に、暗号化したバイトをEncryptedData
内に格納する方法です。
この方法は、非対称鍵を使用して直接暗号化を行わない点を除いて、署名鍵を決定するタスク(項「署名鍵の決定」を参照)と非常に似ています。通常は次のようにします。
ランダムの対称鍵を選択します。
この鍵でデータを暗号化します。
非対称鍵でランダムの対称鍵を暗号化します。
暗号化したデータと暗号化した鍵の両方を受信者に送信します。
対称鍵を使用した場合も、次の方法を選択できます。
このような暗号化した鍵のメカニズムを使用するには、xenc:EncryptedKey
を文書内のどこに配置するかを決定する必要があります。
encryptedData
要素が1つしかない場合は、EncryptedKey
をEncryptedData
のKeyInfo
に配置します。
それ以外の場合は個別に配置し、一方がもう一方を参照するようにします。
EncryptedKey
の復号化に使用できる証明書、非対称鍵または鍵名を参照するには、EncryptedKey
内で<dsig:KeyInfo>
を使用します。
データの復号化では、データの暗号化と同じプロセスに従いますが、処理手順が逆です。基本手順は次のとおりです。
適切な位置に配置した単純な暗号化を使用してデータが暗号化されている場合は、EncryptedData
要素を検索し、そのKeyInfo
を参照します。
既知の対称鍵で直接暗号化されている場合は、その部分を復号化します。
ランダムの対称鍵で暗号化されている場合は、次のようにします。
対応するEncryptedKey
を検索します。
その部分を最初に復号化します。
復号化したランダムの対称鍵を使用し、EncryptedData
を復号化します。
関連項目:
Oracle XML Security 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でラッパー・オブジェクトを処理する方法について説明します。内容は次のとおりです。
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
は、この表を使用して適切なコンストラクタを起動し、ラッパー・クラスのインスタンスを返します。
基礎となるDOM要素は、すぐに利用できます。すべてのラッパー・クラスは、基礎となるDOM要素を取得できるように、メソッドXMLElement.getElement()
を提供するXMLElement
から拡張されています。
サブ要素の階層を含む複合要素がある場合は、同等のラッパー・オブジェクトの階層も常に存在します。たとえば、次のように署名を含む文書を受信するとします。
<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を変更すると、ラッパー・オブジェクトには常に最新の変更が反映されます。
ここでは、前述と同じ例を検討しますが、受信文書に存在する署名ではなく、署名を含む文書を作成し、この文書を第三者に送信します。
<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を変更するだけです。
この場合、setSignedInfo
はdsig:SignedInfo
要素を取得し、dsig:Signature
要素の子にします。したがって、setSignedInfo(sigInfo)
を起動した後に、sigInfo = null
を実行しても、影響を受けるものはありません。
最後に、最上位レベルのオブジェクトをDOMの任意の場所に挿入する必要があります。
elem.appendChild(sig.getElement());
この項では、Oracle XML Security APIでデータに署名する技術について説明します。
内容は次のとおりです。
デタッチされた署名を作成するには、次のようにします。
<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
オブジェクトを文書に挿入することも忘れないでください。
基本的な署名手順に対するバリエーションには、複数の参照、エンベロープされた署名、XPath式、証明書ヒントおよびHMAC鍵署名があります。
署名に複数の参照を含めるには、XSReference
オブジェクトをXSSignedInfo
オブジェクトに追加するだけです。各XSReference
オブジェクトには、独自の変換リストが必要です。
エンベロープされた署名を使用するには、エンベロープされた署名変換を参照に追加します。つまり、排他変換を追加するコードの直前に次のコードを挿入します。
XSAlgorithmIdentifier transform1 = new XSAlgorithmIdentifier(doc, "Transform", XMLURI.alg_envelopedSignature); ref.addTransform(transform1);
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);
鍵情報に証明書全体を含めず、証明書のヒントのみを含める場合は、引数なしの形式のXSKeyInfo.createX509Data()
を使用し、メソッドX509Data.addIssuerSerial
、addSubjectName
またはaddSubjectKeyID
のいずれかをコールします。
Oracle XML Security APIを使用して署名を検証できます。
署名の検証のトピックには次が含まれます。
署名を検証するには、最初に文書内の<dsig:Signature>
要素を検索し、この要素を使用してXSSignature
ラッパー・オブジェクトを構成します。
Element sigElem = … XSSignature sig = new XSSignature(sigElem);
次に、署名のKeyInfo
をフェッチし、鍵を調べて署名者が信頼できるかどうかを判断します。KeyInfo
を処理するには、次のような様々な方法があります。
非常に単純な場合は、検証鍵が事前にわかっている場合があるため、KeyInfo
を確認する必要はありません。
これに対し、ほとんどの場合では、KeyInfo
を確認する必要があります。1つの方法はコールバックを設定することであるため、XSSignature.verify()
をコールする場合は、検証鍵なしてコールします。内部的に、Oracleセキュリティ開発ツールでは、KeyInfo
を確認し、コールバックを起動して鍵をフェッチするかどうかを判断します。
その他のオプションには、KeyInfo
を事前に確認して、鍵を自身で判断する方法があります。
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));
これらの組込みの取得機能が適切でない場合は、カスタムのKeyRetriever
をKeyRetriever
クラスから導出して記述できます。これは、たとえばKeyInfo
にsubjectDN
が含まれていることが想定され、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
に含まれている場合は、この鍵名に基づいて対称鍵をフェッチできるカスタムの鍵取得機能を記述します。
次の手順では、この署名で署名対象を実際に署名するかどうかをチェックします。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 }
最後の手順では、署名を実際に検証します。コール・プロトコルはコールバックが設定されているかどうかによって異なります。
コールバックを設定したら、次のようにコールを実行します。
boolean result = sig.verify();
次のように、失敗した結果と例外の両方をチェックする必要があります。
署名形式が正しいが参照ダイジェストのいずれかが一致していない場合や、署名が検証されない場合、sig.verify()
はfalse
を返します。
署名の構成に問題がある場合、たとえば、アルゴリズム名に問題がある場合や署名のバイトが正しいサイズでない場合、sig.verify()
は例外をスローします。
コールバックを設定しておらず、鍵を自身で判断した場合は、次をコールする必要があります。
sig.verify(byte[])
(HMAC鍵の場合)
sig.verify(PublicKey)
(DSA/RSA鍵の場合)
Oracle XML Securityを使用したデータ暗号化には様々なオプションがあります。
次の<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 );
「共有対称鍵を使用した暗号化」で紹介した例では、共有対称鍵があると想定した場合を簡素化していました。実際は、ランダムの対称鍵を生成してその鍵で暗号化し、このランダム対称鍵を受信者の公開鍵で暗号化するのが一般的です。この方法は次のとおりです。
// 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);
復号化技術は、共有対称鍵が存在するか、ランダムの対称鍵を使用するかによって異なります。
共有対称鍵がある場合は、次のようにします。
// search for the EncryptedData element Element edElem = ... // decrypt the data SecretKey dataDecKey = ... XEEncrytedData.decryptAndReplace(dataDecKey, edElem, true);
この項では、Oracle XML Security APIのその他のクラスとインタフェースについて説明します。この項の内容は、次のとおりです。
このインタフェースは、アルゴリズム、ネームスペースおよびオブジェクトのURI文字列定数を定義します。次のネーミング規則が使用されます。
アルゴリズムのURIはalg_で始まります。
ネームスペースのURIはns_で始まります。
オブジェクト・タイプのURIはobj_で始まります。
この項では、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オブジェクトを解析してコンポーネント部に分ける必要があります。