4.1.4 Enveloped署名,Enveloping署名,またはDetached署名を検証する
この項では,XML署名(Enveloped署名,Enveloping署名,またはDetached署名)を検証する場合の処理内容とコーディング例を説明します。
(1) XML署名文書のDocumentオブジェクトの取得
JAXPのDocumentBuilderクラスを使用して,検証の対象となるXML文書を読み込み,Documentオブジェクトを取得します。このとき,XML署名構文の構築のために,あらかじめDocumentオブジェクトからSignature要素を取得しておく必要があります。また,Documentオブジェクトを取得するときに,名前空間が有効になるように設定してください。Enveloped署名の場合は文書要素の末尾が,Enveloping署名またはDetached署名の場合は文書要素がSignature要素となっているときのコーディングの例を次に示します。
- Enveloped署名の場合
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().parse(input); Node last = doc.getDocumentElement().getLastChild(); if ((last == null) || !(DOMUtils.matchesName( last, XMLSignature.XMLNS,"Signature"))) { throw new Exception("missing ds:Signature"); } Element sigelem = (Element) last;
- Enveloping署名またはDetached署名の場合
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().parse(input); Element sigelem = doc.getDocumentElement(); if (!(DOMUtils.matchesName(sigelem, XMLSignature.XMLNS, "Signature"))) { throw new Exception("missing ds:Signature"); }
(2) XML署名構文の構築
XMLSignatureFactoryクラスを使用して,XMLSignatureオブジェクトを生成します。コンテキストおよびDocumentオブジェクト中のSignature要素を指定します。XMLSignatureオブジェクトが生成されると同時に,Signature要素の下位要素に対応するオブジェクトも自動的に生成されます。なお,コンテキストの処理モードは,「署名検証」を指定してください。コーディングの例を次に示します。
XMLSignatureFactory xsf = XMLSignatureFactory.newInstance(); XMLSecurityContext context = new XMLSecurityContext( XMLSecurityContext.Mode.VERIFY, doc); XMLSignature sig = xsf.newXMLSignature(context, sigelem);
(3) XML署名データの検証
XML署名データを検証するときは,コンテキストを指定する必要があります。ここでは,次の処理について,コーディング例を示して説明します。
-
コンテキストの設定
-
XML署名データの検証
(a) コンテキストの設定
XML署名データの検証に必要なコンテキストを設定します。検証に使用する鍵を使って鍵リゾルバを生成して,コンテキストに鍵リゾルバを設定します。コーディングの例を次に示します。
context.setKeyResolver( new AdhocKeyResolver(Utilities.getPublicKey()));
(b) XML署名データの検証
XMLSignatureクラスのverifyメソッドで,Signature要素の署名値を検証します。このとき,Signature要素の署名値と同時に,Reference要素のダイジェスト値も検証されます。
なお,署名情報や署名対象データが改ざんされていた場合,検証結果は失敗(verifyメソッドの結果がfalse)となります。検証結果が失敗の場合,署名対象データの改ざんの有無については,ReferenceValidityクラスを使用して調べることができます。ReferenceValidityクラスで調べた結果,署名対象データが改ざんされていないにもかかわらず,検証に失敗する場合は,署名情報が改ざんされているおそれがあります。コーディングの例を次に示します。
boolean result = sig.verify(context); if (result == true) { System.out.println("signature is valid."); } else { Iterator itr = sig.getSignedInfo().getReferences().iterator(); while (itr.hasNext()) { Reference ref = (Reference) itr.next(); ReferenceValidity validity = ref.getReferenceValidity(); System.out.println("reference: URI=" + ref.getURI() + ", validity=" + validity.getStatus()); } System.out.println("signature is invalid."); }