この項では,XML署名(Enveloped署名,Enveloping署名,またはDetached署名)を検証する場合の処理内容とコーディング例を説明します。
JAXPのDocumentBuilderクラスを使用して,検証の対象となるXML文書を読み込み,Documentオブジェクトを取得します。このとき,XML署名構文の構築のために,あらかじめDocumentオブジェクトからSignature要素を取得しておく必要があります。また,Documentオブジェクトを取得するときに,名前空間が有効になるように設定してください。Enveloped署名の場合は文書要素の末尾が,Enveloping署名またはDetached署名の場合は文書要素がSignature要素となっているときのコーディングの例を次に示します。
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;
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");
}
XMLSignatureFactoryクラスを使用して,XMLSignatureオブジェクトを生成します。コンテキストおよびDocumentオブジェクト中のSignature要素を指定します。XMLSignatureオブジェクトが生成されると同時に,Signature要素の下位要素に対応するオブジェクトも自動的に生成されます。なお,コンテキストの処理モードは,「署名検証」を指定してください。コーディングの例を次に示します。
XMLSignatureFactory xsf = XMLSignatureFactory.newInstance();
XMLSecurityContext context = new XMLSecurityContext(
XMLSecurityContext.Mode.VERIFY, doc);
XMLSignature sig = xsf.newXMLSignature(context, sigelem);
XML署名データを検証するときは,コンテキストを指定する必要があります。ここでは,次の処理について,コーディング例を示して説明します。
XML署名データの検証に必要なコンテキストを設定します。検証に使用する鍵を使って鍵リゾルバを生成して,コンテキストに鍵リゾルバを設定します。コーディングの例を次に示します。
context.setKeyResolver(
new AdhocKeyResolver(Utilities.getPublicKey()));
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.");
}