| Oracle® Fusion Middleware Oracle Security Developer Toolsによるセキュアなアプリケーションの開発 11gリリース1 (11.1.1) B61386-04 |
|
![]() 前 |
![]() 次 |
Oracle Web Services Securityでは、OASIS WS Security 1.1規格の完全な実装が提供されます。この章では、SDKのインストールおよび使用方法について説明します。
この章に含まれる内容は次のとおりです。
Webサービス・セキュリティの詳細は、次のリソースを参照してください。
OASIS WSS SOAPメッセージ・セキュリティ仕様
OASIS WSSユーザー名トークン・プロファイル仕様
OASIS WSS X.509証明書トークン・プロファイル仕様
OASIS WSS SAMLアサーション・トークン・プロファイル仕様
OASIS WSS SWAトークン・プロファイル仕様1.1
Oracleセキュリティ開発ツールは、Oracle Application ServerとともにORACLE_HOME/modules/oracle.osdt_11.1.1にインストールされます。
Oracle Web Services Securityを使用するには、Java Development Kit (JDK)バージョン1.6以上が必要です。
次の項目をCLASSPATHに指定します。
osdt_core.jar
osdt_cert.jar
osdt_xmlsec.jar - Oracle XML Security jarです。
osdt_saml.jar - Oracle SAML 1.0および1.1 jarです。
osdt_saml2.jar - Oracle SAML 2.0 jarです。
org.jaxen_1.1.1.jar: $ORACLE_HOME/modules/に含まれます。
osdt_wss.jar - Oracle Web Services Securityを含むメインjarです。
saaj-api.jar - 標準のSAAJ APIでJDK6に含まれます。以前のJDKの場合、JavaEEコンテナから取得できます。
mail.jar、activation.jar - これらのjarはJavaEEコンテナから取得できます。
この項では、Oracle Web Services SecurityのAPIのクラスおよびインタフェースについて説明します。次の項目について説明します。
Oracle Web Services Securityでは、要素ラッパーの概念を使用します。
表10-1 Oracle Web Services Securityの要素ラッパー
| XMLタグ名 | Javaクラス名 |
|---|---|
|
<wsse:Security> |
oracle.security.xmlsec.wss.WSSecurity |
|
<wsse:BinarySecurityToken> |
oracle.security.xmlsec.wss.WSSBinarySecurityToken、またはその導出されたクラス(valueType属性に応じて、次のいずれかになります。) |
|
<wsse: SecurityTokenReference> |
oracle.security.xmlsec.wss.WSSecurityTokenReference |
|
<wsse: Embedded> |
oracle.security.xmlsec.wss.WSSEmbedded |
|
<wsse11:EncryptedHeader> |
oracle.security.xmlsec.wss.WSSEncryptedHeader |
|
<wsse11:SignatureConfirmation> |
oracle.security.xmlsec.wss.WSSignatureConfirmation |
|
<wsse:KeyIdentifier> |
oracle.security.xmlsec.wss.WSSKeyIdentifier、またはその導出されたクラス(valueType属性に応じて、次のいずれかになります。) |
|
<wsse:Reference> |
oracle.security.xmlsec.wss.WSSReference |
|
<wsu:Created> |
oracle.security.xmlsec.wss.WSUCreated |
|
<wsu:Expires> |
oracle.security.xmlsec.wss.WSUExpires |
|
<wsu:Timestamp> |
oracle.security.xmlsec.wss.WSUTimestamp |
|
<wsse:UsernameToken> |
oracle.security.xmlsec.wss.username.UsernameToken |
8.7項「OSDT XML APIでの要素ラッパーの使用方法」で説明しているように、Javaクラスは棄却型ラッパーにすぎませんが、DOM要素は真のソースです。これらのラッパー・クラスは、DOM要素を取り込む適切なコンストラクタを使用して作成できます。基礎となるDOM要素はgetElementメソッドを使用して取得できます。
WS Security仕様では、<wsse:Security>と呼ばれる新しいSOAPヘッダーが定義されています。すべてのセキュリティ情報は、このヘッダー内に格納され、次のようになります。
セキュリティ・トークン - ユーザー名トークン、証明書、SAMLアサーションなどを格納します(次の項を参照)。
タイムスタンプ - 現在のタイムスタンプは、多くの場合セキュリティ・ヘッダーに含まれ、リプレイ攻撃を防ぐために、通常は署名に含まれます。
署名 - すべての署名はヘッダー内に格納されます。署名がSecurityヘッダーにある場合でも、署名対象は多くの場合ヘッダーの外部になり、たとえば、1つの署名でSOAP本文、複数のSOAP添付ファイル、Securityヘッダー内のUserNameトークン、およびSecurityヘッダー内のTimestampトークンに署名できます。
EncryptedKey - 暗号化されたすべてのセッション鍵はここに格納されます。
ReferenceList - すべてのEncryptedDataセクションのリストを格納します。
送信メッセージの場合は、新しい<wsse:Security>ヘッダーを作成して、セキュリティ・トークンを追加し、文書の一部を暗号化または署名(あるいはその両方を実行)する必要があります。このタスクを実行する方法は、次のとおりです。
// Assuming we the outgoing message has already been constructed into // a SOAPMessage object (part of SAAJ API) SOAPMessage msg = ... // Now create a new <wsse:Security> Header // newInstance will internally use SOAPHeader.addHeaderElement SOAPEnvelope env = msg.getSOAPPart().getEnvelope(); WSSecurity ws = WSSecurity.newInstance(env); // Add required prefixes to this SOAP header // Now add some security tokens (refer to the next section on // how to create security tokens) UsernameToken ut = ... ws.addUsernameToken(ut); // Create some security token references to this token // (refer to following sections) ws.createSTR... // Now sign or encrypt some data (refer to following sections) // These should use the above STRs ws.sign(...); ws.encryptWithEncKey(...); ws.encryptNoEncKey(...);
WS Security仕様では、セキュリティ・トークン(STと略して表記される場合もあります)の概念を定義しています。
セキュリティ・トークンは、証明書、Kerberosチケット、パスワード付きのユーザー名、シングル・サインオンのトークンなどのアーティファクトを表します。通常、鍵はこのトークンから導出および抽出され、メッセージの一部の暗号化、復号化、署名および検証に使用されます。これに対し、セキュリティ・トークンはデータ・オブジェクトと同じように使用することもできます。
表10-2 Oracle Web Services Securityのセキュリティ・トークン
| トークンのタイプ(Javaクラス) | バリエーション | 鍵 |
|---|---|---|
|
ユーザー名トークン |
|
ユーザーのパスワードでKeyDerivationを実行して取得した対称鍵 |
|
X509証明書 |
|
|
|
Kerberosチケット |
|
チケットに存在するセッション鍵、またはサブキー。 |
|
SAMLアサーション1.1 SAMLアサーション2.0 |
|
holder_of_keyの場合は、サブジェクトの鍵(<saml:Assertion>内にある<saml:SubjectConfirmation>内の鍵)が使用されます。 sender_vouchesの場合は、証明元のエンティティの鍵が使用されます。 鍵はbearerトークンからは抽出されません。 |
最初に、UsernameTokenを作成し、WSSecurityヘッダー内に配置します。UsernameToken内の唯一の必須フィールドは、次のようにユーザー名です。
// create a Username token
WSSecurity ws = ...
UsernameToken ut = new UsernameToken(doc);
ut.setUserName("Zoe");
// remember to put this inside your WSSecurity header.
// addUserNameToken puts it at the beginning, you can also
// use a regular DOM method appendChild or insertChild to put it in.
ws.addUsernameToken(ut);
// optionally add an wsu:Id, so you can refer to it
ut.setWsuId("MyUser");
次に、このトークンにパスワードを配置する方法を決定します。次のように複数の方法を選択できます。
クリア・テキスト・パスワードを追加します。この方法は、メッセージ全体がSSLなどのセキュアなチャネルで送信されている場合にのみ考慮します。
パスワードのダイジェストまたはその他の種類の導出されたパスワードのダイジェストを追加します。ダイジェストは、nonceと時間によって保護されないかぎりリプレイすることもできるため、クリア・テキスト・パスワードよりも必ずしも安全とはかぎりません。
WS Security仕様で指定されているダイジェスト・メカニズムを使用してパスワードのダイジェストを追加します。この方法では、nonceとcreatedDateを使用します。
パスワードまたはそのダイジェストをまったく追加しません。鍵を知っていることを示すには、かわりにパスワードから鍵を導出し、その鍵をメッセージの署名に使用します。
// For options 1 and 2, use the setPassword method
ut.setPassword("IloveDogs");
// With this mechanism, the reciever should simply call
// UsernameToken.getPassword to check if the password is as expected.
// For option 3, use the setPasswordDigest method, but before doing
// thatfor that you have to at first set a nonce and a created date.
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
byte nonce[] = new byte[20];
random.nextBytes(nonce); // compute a 20 byte random nonce
ut.setNonce(nonce);
ut.setCreatedDate(new Date()); // Set the date to now
ut.setPasswordDigest("IloveDogs"); // will compute the digest from
// this clear text password using
// nonce and createdDate
// For this mechanism, the reciever should use the following
byte nonce[] = ut.getNonce();
.. check against the used nonces, to make sure this is a new nonce
Date createdDate = ut.getCreated();
.. check that this createdDate is within an expected clock skew
boolean valid = ut.isValid(userName, passwd),
// above call will recompute the digest from the passwd
// and the nonce and created date, and check if this digest matches
// the digest in the username token
// For option 4, set the salt and iteration count
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
byte salt[] = new byte[15];
random.nextBytes(salt); // compute a 15 byte random salt
ut.setSalt(1, salt);
ut.setIteration(1000);
SecretKey key = ut.deriveKey("IloveDogs");
これで、この秘密鍵を使用してデータを署名または暗号化できます。
次のように、X509BinarySecurityTokenコンストラクタの後にsetTokenメソッドを使用するか、または同等のヘルパー・メソッドWSSecurity.createBST_X509を使用できます。
WSSecurity ws = ...
X509Certificate cert = ...
X509BinarySecurityToken x509token = WSSecurity.createBST_X509(cert);
// remember to put this inside your WSSecurity header.
// addX509CertificateToken puts it at the beginning, you can also
// use a regular DOM method appendChild or insertChild to put it in.
ws.addX509CertificateToken(x509Token);
// optionally add an wsu:Id, so you can refer to it
x509Token.setWsuId("MyCert");
証明連鎖全体を含める場合は、CertPathオブジェクトからX509BinarySecurityTokenを作成することもできます。
この証明書でデータを暗号化する場合は、cert.getPublicKey()を使用して取得できる公開鍵が必要です。これに対し署名の場合は、キーストアに保持する必要がある秘密鍵が必要です。
一般的に、KerberosトークンはJava GSS-APIと組み合せて使用します。
クライアント側
//Use JAAS Authentication with Kerberos Login Module
// Set up the config files and then call login()
// to login using this module. This will cause the client to contact
// the Kerberos Authentication-Service and get a ticket to talk to the
// Kerberos Ticket-Granting-Service
LoginContext lc = new LoginContext(...);
lc.login();
//Use JAAS Authorization to set the subject into the thread context
Subject.doAs(lc.getSubject(), action)
// The rest of the code should be executed as a Privileged action
// Create a GSSContext to talk to a particular server.
GSSManager gssManager = GSSManager.getInstance();
GSSName serviceName = gssManager.createName(svcPrincipalName, null);
GSSContext gssContext = gssManager.createContext(serviceName, null,
null, GSSCredential.DEFAULT_LIFETIME);
// Then call initSecContext. this will cause the client to contact
// the Ticket-Granting-Service to obtain a ticket for talking to that
// particular server. The token that is returned by the initSecContext
// is a GSS wrapped AP_REQ packet.
byte[] token = new byte[1];
token = gssContext.initSecContext(token, 0, token.length);
// Create a Kerberos BST using this AP_REQ packet
WSSecurity ws = ...
KerberosBinarySecurityToken kbst = ws.createBST_Kerberos(token,
WSSURI.vt_GSSKerberosv5);
ws.addKerberosToken(kbst);
// Get the sessionKey that is present inside the AP_REQ packet,
// this is the session that is generated by the TGT and returned
// to the client in the initSecContext class
//
// This getSessionKey call simply calls Subject.getPrivateCredentials
// to get a list of tickets associated with the subject, and then
// iterates through them to find the one to be used for
// for that particular server
SecretKey sessionKey =
KerberosUtils.getSessionKey(lc.getSubject(),svcPrincipalName);
これで、この秘密鍵を使用してデータを署名または暗号化できます。
サーバー側
// Use JAAS Authentication and Authorization as for the client // Create GSSContext will null credentials </b><br> SSManager manager = GSSManager.getInstance(); GSSContext gssContext = manager.createContext((GSSCredential)null); // Locate the KerberosBinarySecurityToken in the incoming WSSecurity // header. You can do this by doing a DOM search WSSecurity = ... KerberosBinarySecurityToken kbst = ... // Now extract the AP_REQ from the BST and call acceptSecContext byte ap_req[] = kbst.getValue(); gssContext.acceptSecContext(ap_req); // The context is now extablished. (Note Mutual authentication would // need one more round trip) // Now extract the session key // KerberosUtils.getSession is an overloaded method, and this // particular one is meant to be used by server. Internally // it decrypts the ap_req packet using the server's key (or the // tgtSession key) and extracts the key from the decrypted ap_req // packet Subject srvrSubject = ... SecretKey sessionKey = KerberosUtils.getSessionKey(srvrSubject, ap_req);
これで、この鍵を使用して復号化または検証できます。
Assertionオブジェクトの作成方法の詳細は、第8章「Oracle XML Security」を参照してください。SAMLアサーション・トークンは、SAMLAssertionToken(Assertion assertion)コンストラクタを起動するだけでAssertionオブジェクトから作成できます。
WS Security仕様では、セキュリティ・トークンを参照するメカニズムであるセキュリティ・トークン参照(STRと略して表記される場合もあります)の概念も定義しています。SignatureまたはEncryptionでは、このSTRメカニズムを使用して、署名または暗号化に使用した鍵を識別します。
通常、STRでは次のメカニズムをサポートしています。
直接参照: STRではURIを使用してSTを参照します。
キー識別子: STRでは、トークンの識別にURIではなく、発行者のシリアル(X509トークンの場合)やアサーションID (SAMLトークンの場合)などの別のメカニズムを使用します。トークンがメッセージに存在しない場合もあります。
埋込み: トークンはKeyInfoに直接埋め込まれます。
STRを作成する前に、前述のトークンを最初に作成し、.setWsuId()をコールしてそのトークンにIDを設定します。次に、そのIDでSTRを作成し、そのSTRを次のようにWSSSignatureParamsまたはWSEncryptionParamsに渡します。
WSSecurity ws = ...
WSSecurityTokenReference str =
ws.createSTR_Username_ref("#MyUser");
WSSecurity ws = ...
WSSecurityTokenReference str =
ws.createSTR_X509_Ref("#MyCert");
WSSecurity ws = ... // use the appropriate value type String valueType = WSSURI.vt_GSSKerberosv5; WSSecurityTokenReference str = ws.createSTR_KerberosKeyRef ( "#MyToken");
WSSecurity ws = ...
WSSecurityTokenReference str =
ws.createSTR_SAML_Assertion_Ref20("MySAMLAssertion")
WSSecurity ws = ...
WSSecurityTokenReference str =
ws.createSTR_EncKeyRef("MyEncKey")
createSTRメソッドを使用するかわりに、次のように適切なvalueTypeとtokenTypeを使用して参照を直接作成することもできます。
WSSecurity ws = ... String uri = "#MyToken"; WSSReference ref = new WSSReference(doc, uri); ref.setValueType(valueType); // set an optional valueType WSSecurityTokenReference str = new WSSecurityTokenReference(doc); str.setTokenType(tokenType); // set an optional tokenType str.appendChild(ref);
KeyIdentifierは、assertionID (SAMLトークンの場合)やSubject Key Identifier (X509トークンの場合)など、トークンの固有プロパティを使用するセキュリティ・トークンを参照する別の方法です。
KeyIdentifersは、トークン自身が文書内に存在しない場合に多く使用されます。たとえば、受信メッセージはX509Certで暗号化できますが、メッセージには、そのX509Certを格納するかわりに、SubjectKeyIdentifierの形式でヒントのみを格納できます。
X509トークンを識別するには、次の3つの方法があります。
発行者のシリアル: 発行者のDNと証明書のシリアル番号の組合せ
サブジェクト・キー識別子: 証明書のサブジェクト・キー識別子
サムプリントSHA1: 証明書のSHA1
X509Certificate cert = ... WSSecurity ws = ... WSSecurityTokenReference str = ws.createSTR_X509_IssuerSerial(cert); // alternatively use ws.createSTR_X509_SKI(cert) // or ws. createSTR_X509_ThumbprintSHA1(cert)
Kerberosトークンは、AP_REQパケットのSHA1またはGSSでラップされたAP_REQパケットのSHA1で識別できます。
byte ap_req[] = ... WSSecurity ws = ... String valueType = WSSURI.vt_GSSKerberosv5; WSSecurityTokenReference str = ws.createSTR_KerberosKeyIdSHA1(ap_req, valueType);
SAMLアサーションはアサーションIDで識別できます。
ローカルSAML 1.1アサーションでは、次を使用します。
WSSecurity.createSTR_SAML_AssertionIdv11(byte assertionId[])
リモートSAML 1.1アサーションでは、次を使用します。
createSTR_SAML_AssertionIdv11( byte assertionId[], AuthorityBinding authorityBinding)
ローカルSAML 2.0アサーションでは、次を使用します。
createSTR_SAML_AssertionIdv20(byte assertionId[])
リモートSAML 2.0アサーションでは、次のように参照URIを使用します。
createSTR_SAML_Assertion_Ref20("MySAMLAssertion")
この項では、データの署名と検証について説明します。
SOAPメッセージに署名するには、次の手順に従います。
署名対象のデータを指定する方法を決定します。最も一般的なメカニズムはIDを使用することですが、IDを使用するかわりにXPath式を使用することもできます。
追加の変換を決定します。排他的c14nとSTR変換は、追加可能な一般的な変換です。
署名鍵を決定します。対称鍵を使用するHMAC署名またはRSA/DSA署名のいずれかを実行できます。
この署名鍵を受信者に示す方法を決定します。この場合は通常、前述のSTRを作成する必要があります。
次の関数を使用します。
WSSUtils.addWsuIdToElement(String id, Element element)
これにより、署名対象の要素にwsu:Idを追加します。このメカニズムを使用すると、IDを追加して、DOM要素、またはDOM要素からも導出されるSAAJオブジェクトを正規化できます。
wsuネームスペースの接頭辞を宣言する必要があります。たとえば、次のようにSOAPエンベロープ・レベルで宣言できます。
SOAPEnvelope env = ...
env.addNamespaceDeclaration("wsu" , WSSURI.ns_wsu);
添付ファイルに署名するには、各添付ファイルにContentIdを割り当てる必要があります。この場合は、次のメソッドを使用する必要があります。
setContentId(String contentId)
このメソッドは、SAAJ AttachmentPartオブジェクトの一部です。
WSSSignatureParamsオブジェクトは、すべての署名パラメータを使用して作成する必要があります。
最初のWSSignatureParamsオブジェクトを作成するには、次のコンストラクタを使用します。HMAC署名を使用する場合は、hmacKeyに値を渡し、signingKeyにnullを渡します。非対称署名を使用するには、signingKeyに値を渡し、hmacKeyにnullを渡します。
WSSignatureParams(byte[] hmacKey, PrivateKey signingKey);
このコストラクタは、c14nMethod=excC14N、digestMethod=SHA1、signMethod=hmacSHA/rsaSHA1/dsaSHA1(鍵に応じて)を前提とします。異なるアルゴリズムが必要な場合は、次のsetterを使用して設定します。
setDigestMethod(String digestMethod) setSignMethod(String signMethod) setC14nMethod(String method)
前に作成したSTRをこのオブジェクトに設定する必要もあります。STRを設定するには、setKeyInfoDataを使用します。
setKeyInfoData(KeyInfoData keyInfoData)
添付ファイルに署名する場合は、このWSSignatureParamsオブジェクトにSOAPMessageを設定し、対応する添付ファイルを特定してcid参照を解決できるようにします。
setSOAPMessage(SOAPMessage msg)
変換を指定するには、単純だが制限がある方法と、高度で柔軟な方法の2つの方法があります。単純な方法では、次のパラメータをWSSignatureParamsに設定する必要があります。
· setAttachmentContentOnly(boolean)
単純なモードでは、すべてのcid参照によってAttachmentContentOnly変換が自動的に取得されますが、setAttachmentContentOnly(false)をコールすると、cid参照によってAttachmentComplete変換が取得されます。
· setUsingSTRTransform(boolean)
これをtrueに設定すると、各参照がSTRを指しているかどうかチェックされ、STRを指している場合は、該当の参照にSTRTransformが追加されます。STRTransformが追加されるのは、参照がSTRを直接指している場合のみで、参照がSTRの祖先を指している場合は追加されないことに注意してください。
· setC14Nmethod(String)
このパラメータは、デフォルトで排他的c14nに設定され、各参照の正規化メソッドとSignedInfoセクションの正規化メソッドの両方を指定します。
· setUsingDecryptTransfom(boolean)
復号化変換を追加する場合は、これをtrueに設定します。
最後に、WSSecurityの次のメソッドをコールし、実際の署名を実行します。
XSSignature sign (String[] uris, WSSignatureParams sigParams, XSAlgorithmIdentifier[][] trans)
このメソッドでは、<Signature>要素を作成して、各参照のダイジェストを計算し、最後に署名を計算します。
urisは署名対象のIDの配列です。この配列の要素ごとに、個別の<Reference>が作成されます。
前述のように、変換を指定するには2つの方法がありますが、単純な方法では、変換をnullにする必要があり、変換情報は前述の様々なsetメソッド(WSSignatureParams内)で指定されます。高度な方法では、参照ごとに変換パラメータですべての変換を明示的に指定する、つまり、trans.lengthとuris.lengthが等しくなるようにする必要があります。
署名を検証する場合は、最初に<wsse:Security>ヘッダーで署名要素を特定する必要があります。この場合は、次のメソッドを使用できます。
WSSecurity ws = ... List<XSSignature>sigs = ws.getSignatures();
このメソッドでは、DOMツリーを検索して、<dsig:Signature>である<wsse:Security>の直接の子をすべて特定し、これらの要素ごとにXSSignatureラッパー・オブジェクトを作成して返します。(ネームスペースの接頭辞にはwsseとdsigを使用する必要がないことに注意)
検証鍵がすでにある場合は、次のメソッドをコールし、hmacKey(HMAC署名の場合)またはsigningKey(非対称鍵の署名の場合)のいずれかを渡します。SOAPMessageが必要になるのは、添付ファイルが署名される場合のみです。
XSSignature sig = sigs[0]; byte [] hmacKey = ... PublicKey signingKey = ... ; // Need either hmacKey of signingKey SOAPMessage msg = null; // needed only for attachments boolean res = WSSecurity.verify(sig, byte[] hmacKey, signingKey, msg);
ただし、検証鍵がない場合は、STRキー識別子を解決するために、次のコールバックを設定する必要があります。通常、STRキー識別子は文書外部のトークンの参照になるため、Oracleセキュリティ開発ツールでは、これらのコールバックを明示的に設定しないかぎり、これらのトークンを特定することはできません。
表10-3 STRキー識別子を解決するためのコールバック
| トークン・タイプ | 実装インタフェースと登録 | 注意事項 |
|---|---|---|
|
ユーザー名トークン |
インタフェース: 登録: |
このコールバックでは、UsernameTokenの参照STRを解決します。 getPassword()コールバックでは、ユーザーに対応するパスワードを返します。 この秘密鍵は、パスワード、反復カウントおよびsaltから導出されます。 login()コールバックとlogout()コールバックは使用されません。 |
|
インタフェース: 登録: |
このコールバックもUsernameTokenの参照STRを解決します。独自の鍵導出アルゴリズムを使用する場合に使用します。resolve()コールバックでは、鍵を導出して返します。 |
|
|
X509 |
インタフェース: X509KeyIdentifierResolver 登録: |
このコールバックでは、サムプリントとSKIキー識別子のSTRを解決します。 証明書を返すにはresolve()コールバックを実装し、秘密鍵を返すにはgetPrivateKey()コールバックを実装します。 注意: 秘密鍵は検証には不要ですが、復号化には必要です。 証明書の配列がある場合は、X509KeyIdentifier.matches()メソッドを使用し、 渡したX509 KeyIdentifierに対して各証明書を照合します。 |
|
インタフェース: 登録: |
このコールバックでは、発行者のシリアル・キー識別子のSTRを解決します。 前述の場合と同様に、resolve()コールバックとgetPrivateKey()コールバックを実装します。 |
|
|
Kerberos |
インタフェース: 登録: |
このコールバックでは、Kerberos STRを解決します。 resolve()およびresolveKey()メソッドを実装して、ap_reqパケットと、セッション鍵/サブキーを返します (これは、KeyIdentifierに存在するSHA1値に対応します)。 ap_reqパケットの配列がある場合は、その配列の各パケットのSHA1を計算し、 KerberosKeyIdentifier.getValue()によって返される値に一致するSHA1を持つものを検索します。 このap_reqパケットは、resolve()メソッドで返します。 resolveKey()メソッドの場合は、もう1つステップを実行して、 ap_Reqパケット内に存在する鍵を返します。この場合は、KerberosUtils.getSessionKey(Subject, byte[])メソッドを使用できます (これは、サブジェクトの鍵を使用してap_reqパケットを復号化し、そこからセッション鍵/サブキーを抽出します)。 |
|
SAMLアサーション・バージョン1.1 |
インタフェース: 登録: |
このコールバックでは、SAMLアサーションのKeyIdentifier STRを解決します。 SAMLアサーションを返すにはresolve()メソッド、SAMLX509Certを返すにはgetPublicKey()メソッド、秘密鍵を返すにはgetPrivateKey()メソッドを実装します。(注意: 秘密鍵は復号化のみに必要で、検証には不要です。) |
|
SAMLアサーション・バージョン2.0 |
インタフェース: 登録: |
SAMLアサーション・バージョン1.1の注意事項を参照してください。 |
対称鍵を使用するトークン(UserNameトークン、KerberosおよびEncryptedKey)の場合、この対称鍵は文書内にないため、リゾルバを設定する必要があります。Oracleセキュリティ開発ツールでは、リゾルバを設定しないかぎり検証(復号化)はできません。
非対称鍵を使用するトークン(SAMLアサーションとX509トークン)の場合は、Oracleセキュリティ開発ツールだけで証明書を特定できるため、直接のURI参照STRまたは埋込みのトークンを使用する場合は、リゾルバを設定する必要はありません。ただし、Oracleセキュリティ開発ツールでは、コールバックで証明書を検証していないかぎり、メッセージ内の証明書をむやみに使用しないため、CertificateValidatorコールバックを設定する必要があります。
すべてのリゾルバとCertificateValidatorを設定したら、次のメソッドを使用します。
SOAPMessage msg = null; // needed only for attachments boolean searchTokens = true; boolean res = WSSecurity.verify(sig, searchTokens, msg);
このメソッドでは、署名のKeyInfoを調べ、証明書を検索するか、適切なリゾルバをコールして署名用の鍵を取得します。
WSSecurity.verifyAllメソッドを使用することもできます。このメソッドでは、署名を検索して1つずつ検証します。
署名確認の要素を構成して処理するには、WSSignatureConfirmationラッパー・クラスを使用します。
暗号化には、主に次の2つの方法があります。
EncryptedKeyを使用する方法: ランダム・セッション鍵で要素を暗号化して、このセッション鍵を<EncryptedKey>要素に暗号化し、この要素を<wsse:Security>ヘッダーに配置します。
EncryptedKeyを使用しない方法: 各要素で異なる可能性のある既知の対称鍵で要素を暗号化し、暗号化したこれらの各データ・セクションの参照で<ReferenceList>要素を構成し、<ReferenceList>を<wsse:Security>ヘッダーに配置します。
|
注意: 正規のDOM要素を暗号化するのが標準的な技法ですが、SOAPヘッダー、SOAP本文および添付ファイルを暗号化することもできます。これらのオブジェクトを暗号化する場合は、後述するように特に注意が必要です。 |
次のように、このランダム・セッション鍵の暗号化に使用する鍵を最初に決定し、受信者がこの復号化鍵の特定に使用する情報を使用してSTRを作成します。
Key keyEncKey = ... ; WSSecurityTokenReference str = ...
次の情報を使用してWSSEncryptionParamsを作成します。
// Choose a data encryption algorithm - say AES 128 String dataEncAlg = XMLURI.alg_aes128_CBC; // Either generate a random session key yourself, or set this to // null to indicate that OSDT should generate it SecretKey dataEncKey = null; // Depending on the KeyEncryptionKey that you have chosen choose // either an RSA key wrap or a symmetric key wrap String keyEncAlg = XMLURI.alg_rsaOAEP_MGF1; // Now put all this information into a WSSEncryptionParams WSSEncryptionParams eParam = new WSSEncryptionParams( dataEncAlg, dataEncKey, keyEncAlg, keyEncKey, str);
次のように、DOM要素、SOAPヘッダー、SOAP本文またはAttachmentPartsを正規化します。
Element elem1 = ... // one object to be encrypted Element elem2 = … // another object to be encrypted ArrayList objectList[] = new ArrayList(); objectList.add(elem1); objectList.add(elem2);
次のように配列を2つ作成し、各オブジェクトを暗号化されたコンテンツのみにするかどうかを指定し、生成されるEncryptedDataオブジェクトに割り当てるIDを指定します。
|
注意: SOAP本文は、このフラグで渡すものに関係なく、常に暗号化されたコンテンツのみになります。添付ファイルの場合、「コンテンツのみではない」は、コンテンツにmimeヘッダーを加えることを意味します。 |
// both these elements are not content only
boolean[] contentOnlys = { false, false };
// After encryption the EncryptedData elements will get these ids
String encDataIds[] = { "id1", "id2" };
最後に、次のようにencryptWithEncKeyメソッドをコールします。
WSSecurity ws = ... XEEncryptedKey encKey = ws.encryptWithEncKey(objectList, contentOnlys, encDataIds, eParam);
EncryptedKeyを使用しない場合は、次の手順を使用します。
データの暗号化鍵を決定します。すべてのEncryptedDataセクションで同じ鍵を使用できますが、セクションごとに異なる鍵を使用することもできます。または、受信者がこの復号化鍵の特定に使用する情報を使用してSTRを作成し、次のようにWSSEncryptionParamsオブジェクトに配置します。
SecretKey dataEncKey = ... ; // assuming 128 bit AES key String dataEncAlg = XMLURI.alg_aes128_CBC; WSSecurityTokenReference str = ... // Now put all this information into a WSSEncryptionParams WSSEncryptionParams eParam = new WSSEncryptionParams( dataEncAlg, dataEncKey, null, null, str);
前述の場合と同様、次のように暗号化対象の要素のリストと、関連するcontentOnlyとencDataIds配列を作成します。
Element elem1 = ... // one object to be encrypted
Element elem2 = … // another object to be encrypted
ArrayList objectList[] = new ArrayList();
objectList.add(elem1);
objectList.add(elem2);
// both these elements are not content only
boolean[] contentOnlys = { false, false };
// After encryption the EncryptedData elements will get these ids
String encDataIds[] = { "id1", "id2" };
最後に、次のようにencryptWithNoEncKeyメソッドをコールします。
WSSecurity ws = ...
XEEncryptedKey encKey = ws.encryptWithNoEncKey(objectList,
contentOnlys, encDataIds, new WSEncryptionParams[]{eParam, eParam});
この例では、両方の要素で同じencryptionParamsを使用しています。
コンテンツのみをfalseに設定して、SOAPヘッダー・ブロックで暗号化メソッドをコールすると、SOAPヘッダー・ブロック全体がEncryptedData要素に暗号化されます。この要素はEncryptedHeader要素内に配置され、元のSOAPヘッダー・ブロックを置き換えます。
mustUnderstand属性とactor属性が現在のwsse:Securityヘッダーからコピーされます。
EncryptedKeyを使用してSOAPメッセージを復号化するには、次を使用します。
WSSecurity.decrypt(XEEncryptedKey, PrivateKey, SOAPMessage)
最初に、所定のPrivateKeyでEncryptedKeyを復号化して対称鍵を取得し、この対称鍵を使用して、EncryptedKey内のすべての参照を復号化します。
PrivateKeyがわからない場合は、次をコールします。
decrypt(XEEncryptedKey, SOAPMessage)
これにより、EncryptedKeyのKeyInfoが調べられ、登録されたコールバックがコールされて秘密鍵が取得されます。
EncryptedKeyの復号化形式がわかっている場合は、次を使用します。
decrypt(XEEncryptedKey, SecretKey, SOAPMessage)
これにより、所定の対称鍵を使用して、EncryptedKey内のすべての参照が復号化されます。
最上位レベルのReferenceListに示されたすべての要素(または添付ファイル)を復号化する場合は、次を使用します。
decrypt(XEReferenceList, SecretKey, SOAPMessage)
これにより、所定の対称鍵を使用して、ReferenceList内のすべての参照が復号化されます。この関数は、すべての参照が同じ鍵で暗号化されていることを前提としています。
SecretKeyがわからない場合、またはすべての参照が同じ鍵で暗号化されていない場合は、SecretKeyにnullを入れてdecryptし、各EncrytedDataのKeyInfoを調べ、登録されたコールバックをコールして対称鍵を取得します。