XML署名付与は、こちらを参照する。
##署名検証の手順
1.署名要素と署名対象要素の特定
// 署名要素(Signature)の特定
Element sigNode = (Element) doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature").item(0);
// 署名検証対象要素(Product)の取得
Element targetNode = (Element)doc.getElementsByTagName("Product").item(0);
2.KeySelectorクラスの実装
KeySelector は、XMLSignature の検証に必要な鍵をKeyInfo要素から取得するために使用される。
※検証対象XMLにKeyInfo要素がない場合に、別途で鍵を用意する必要がある。
※下記の例には、KeyInfoから取得した鍵が信頼できるかどうかの判定は実施していない。
/**
* KeySelectorの実装
*/
public class KeySelectorImp extends KeySelector {
/**
* 鍵の取得
*/
@Override
public KeySelectorResult select(KeyInfo keyInfo, Purpose purpose,
AlgorithmMethod method, XMLCryptoContext context)
throws KeySelectorException {
if (keyInfo == null) {
throw new KeySelectorException("KeyInfo is null");
}
// KeyInfo配下に検索し、X509サーバ証明書を取得する
// サーバ証明書から公開鍵を取得し、KeySelectorResultを返却する
for (Object keyInfoContent : keyInfo.getContent()) {
if (keyInfoContent instanceof X509Data) {
for (Object x509Content : ((X509Data)keyInfoContent).getContent()) {
X509Certificate cert = (X509Certificate)x509Content;
return new KeySelectorResultImp(cert.getPublicKey());
}
}
}
throw new KeySelectorException("Can't get KeySelectorResult from keyInfo");
}
/**
* KeySelectorResultの実装(インナークラス)
*/
private class KeySelectorResultImp implements KeySelectorResult {
private Key key;
public KeySelectorResultImp(Key key) {
this.key = key;
}
@Override
public Key getKey() {
return this.key;
}
}
}
3.検証コンテキストの作成
署名を検証するためのXMLValidateContextインスタンスを作成する。
DOMValidateContext validateContext = new DOMValidateContext(new KeySelectorImp(), sigNode);
validateContext.setIdAttributeNS(targetNode, null, "id");
4.XML 署名の非整列化(XML文書⇒オブジェクト)
XMLSignatureFactory オブジェクトのunmarshalXMLSignatureメソッドを利用して署名要素をXMLSignatureオブジェクトに変換する。
XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM");
XMLSignature signature = signatureFactory.unmarshalXMLSignature(validateContext);
5.署名検証
XMLSignature オブジェクトで validate メソッドを呼び出して署名検証する。
boolean result = signature.validate(validateContext);
##上記手順のまとめ
/**
* XML署名検証
*
* @param doc
* @return
* @throws MarshalException
* @throws XMLSignatureException
*/
public boolean validate(Document doc) throws MarshalException, XMLSignatureException {
// 署名要素(Signature)の取得
Element sigNode = (Element) doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature").item(0);
// 署名検証対象要素(Product)の取得
Element targetNode = (Element)doc.getElementsByTagName("Product").item(0);
// 検証コンテキストの作成
DOMValidateContext validateContext = new DOMValidateContext(new KeySelectorImp(), sigNode);
validateContext.setIdAttributeNS(targetNode, null, "id");
// 署名要素の非整列化
XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM");
XMLSignature signature = signatureFactory.unmarshalXMLSignature(validateContext);
// 署名検証
boolean result = signature.validate(validateContext);
return result;
}
/**
* KeySelectorの実装(インナークラス)
*/
private class KeySelectorImp extends KeySelector {
/**
* 鍵の取得
*/
@Override
public KeySelectorResult select(KeyInfo keyInfo, Purpose purpose,
AlgorithmMethod method, XMLCryptoContext context)
throws KeySelectorException {
if (keyInfo == null) {
throw new KeySelectorException("KeyInfo is null");
}
// KeyInfo配下に検索し、X509サーバ証明書を取得する
// サーバ証明書から公開鍵を取得し、KeySelectorResultを返却する
for (Object keyInfoContent : keyInfo.getContent()) {
if (keyInfoContent instanceof X509Data) {
for (Object x509Content : ((X509Data)keyInfoContent).getContent()) {
X509Certificate cert = (X509Certificate)x509Content;
return new KeySelectorResultImp(cert.getPublicKey());
}
}
}
throw new KeySelectorException("Can't get key from keyInfo");
}
/**
* KeySelectorResultの実装(インナークラス)
*/
private class KeySelectorResultImp implements KeySelectorResult {
private Key key;
public KeySelectorResultImp(Key key) {
this.key = key;
}
@Override
public Key getKey() {
return this.key;
}
}
}