rabbit51

it's since Nov.30 2005
May.29 2014, transferred from broach

法務省 不動産登記の電子署名をValidate.javaで検証してみた

2024-04-10 14:00:00 | 

法務省 不動産登記の電子署名を確認してみた」ではopensslを使い電子署名の検証をおこなったが、「Java XMLデジタル署名API仕様」の例11-4 4.XMLデジタル署名の検証で提示されているValidate.javaで電子署名を確認してみた。eTaxの署名データも確認してみた。

JDKは、JDK22を使用した。

Validate.java
import java.io.File;
import java.io.FileInputStream;
import java.security.Key;
import java.security.KeyException;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.List;

import javax.xml.crypto.AlgorithmMethod;
import javax.xml.crypto.KeySelector;
import javax.xml.crypto.KeySelectorException;
import javax.xml.crypto.KeySelectorResult;
import javax.xml.crypto.XMLCryptoContext;
import javax.xml.crypto.XMLStructure;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyValue;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Element;  //-- added

/**
 * This is a simple example of validating an XML Signature using the JSR 105
 * API. It assumes the key needed to validate the signature is contained in a
 * KeyValue KeyInfo.
 */
public class Validate {

	//
	// Synopsis: java Validate [document]
	//
	// where "document" is the name of a file containing the XML document
	// to be validated.
	//
	public static void main(String[] args) throws Exception {
		String fileName = args[0];

		// Instantiate the document to be validated
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		dbf.setNamespaceAware(true);
		Document doc = dbf.newDocumentBuilder().parse(
				new FileInputStream(fileName));

		// Find Signature element
		NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS,
				"Signature");
		if (nl.getLength() == 0) {
			throw new Exception("Cannot find Signature element");
		}

		// Create a DOM XMLSignatureFactory that will be used to unmarshal the
		// document containing the XMLSignature
		XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

		// Create a DOMValidateContext and specify a KeyValue KeySelector
		// and document context
		DOMValidateContext valContext = new DOMValidateContext(
				new KeyValueKeySelector(), nl.item(0));

//-- added(外部ファイルのベースディレクトリを指定)
String cpath = new File(fileName).getParent();
cpath = "file://" + cpath.replace('\\', '/') + "/";
valContext.setBaseURI(cpath);
System.out.println("setBaseURI-> " + cpath);
//-- added(署名対象XMLエレメントのアトリビュートを指定)
// 申請用総合ソフト 登録通知
NodeList tg = doc.getElementsByTagName("BODY");
if ( tg.getLength() != 0 ) {
    valContext.setIdAttributeNS( (Element)tg.item(0), null, "ID");
    System.out.println("Find BODY element and setIdAttibute=\"ID\"");
}
// 医療費通知(保険組合)
NodeList tg1 = doc.getElementsByTagName("TEG700");
if ( tg1.getLength() != 0 ) {
    valContext.setIdAttributeNS( (Element)tg1.item(0), null, "id");
    System.out.println("Find TEG700 element and setIdAttribute=\"id\"");
}
// e-Tax( 所得税 RKO0010. 証明書更新 PTE0010, 電子申請等証明書 TEB120
NodeList tg2 = doc.getElementsByTagName("RKO0010");
if ( tg2.getLength() != 0 ) {
    valContext.setIdAttributeNS( (Element)tg2.item(0), null, "id");
    System.out.println("Find RKO0010 element and setIdAttribute=\"id\"");
}
NodeList tg3 = doc.getElementsByTagName("PTE0010");
if ( tg3.getLength() != 0 ) {
    valContext.setIdAttributeNS( (Element)tg3.item(0), null, "id");
    System.out.println("Find PTE0010 element and setIdAttribute=\"id\"");
}
NodeList tg4 = doc.getElementsByTagName("TEB120");
if ( tg4.getLength() != 0 ) {
    valContext.setIdAttributeNS( (Element)tg4.item(0), null, "id");
    System.out.println("Find TEB120 element and setIdAttribute=\"id\"");
}

		// unmarshal the XMLSignature
		XMLSignature signature = fac.unmarshalXMLSignature(valContext);

		// Validate the XMLSignature (generated above)
		boolean coreValidity = signature.validate(valContext);

		// Check core validation status
		if (coreValidity == false) {
			System.err.println("Signature failed core validation");
			boolean sv = signature.getSignatureValue().validate(valContext);
			System.out.println("signature validation status: " + sv);
			// check the validation status of each Reference
			Iterator<?> i = signature.getSignedInfo().getReferences().iterator();
			for (int j = 0; i.hasNext(); j++) {
				boolean refValid = ((Reference) i.next()).validate(valContext);
				System.out.println("ref[" + j + "] validity status: "
						+ refValid);
			}
		} else {
			System.out.println("Signature passed core validation");
		}
	}

	/**
	 * KeySelector which retrieves the public key out of the KeyValue element
	 * and returns it. NOTE: If the key algorithm doesn't match signature
	 * algorithm, then the public key will be ignored.
	 */
	private static class KeyValueKeySelector extends KeySelector {
		public KeySelectorResult select(KeyInfo keyInfo,
				KeySelector.Purpose purpose, AlgorithmMethod method,
				XMLCryptoContext context) throws KeySelectorException {
			
			if (keyInfo == null) {
				throw new KeySelectorException("Null KeyInfo object!");
			}
			SignatureMethod sm = (SignatureMethod) method;
			List<?> list = keyInfo.getContent();

			for (int i = 0; i < list.size(); i++) {
				XMLStructure xmlStructure = (XMLStructure) list.get(i);
				if (xmlStructure instanceof X509Data) {
					PublicKey pk = null;
					List<?> l = ((X509Data) xmlStructure).getContent();
					if (l.size() > 0) {
						X509Certificate cert = (X509Certificate) l.get(0);
						pk = cert.getPublicKey();
//-- added(署名公開鍵のDNと有効期限を表示)
System.out.println("X509Certificate Subject -> " + cert.getSubjectX500Principal().getName() );
System.out.println("X509Certificate NotAfter -> " + cert.getNotAfter().toString() );
						if (algEquals(sm.getAlgorithm(), pk.getAlgorithm())) {
							return new SimpleKeySelectorResult(pk);
						}
					}
				}
				if (xmlStructure instanceof KeyValue) {
					PublicKey pk = null;
					try {
						pk = ((KeyValue) xmlStructure).getPublicKey();
					} catch (KeyException ke) {
						throw new KeySelectorException(ke);
					}
					// make sure algorithm is compatible with method
					if (algEquals(sm.getAlgorithm(), pk.getAlgorithm())) {
						return new SimpleKeySelectorResult(pk);
					}
				}
			}
			throw new KeySelectorException("No KeyValue element found!");
		}

		// @@@FIXME: this should also work for key types other than DSA/RSA
		static boolean algEquals(String algURI, String algName) {
//-- added(署名に指定されたアルゴリズム)
System.out.println("Algorithm: " + algURI );
			if (algName.equalsIgnoreCase("DSA")
					&& algURI.equalsIgnoreCase(SignatureMethod.DSA_SHA1)) {
				return true;
			} else if (algName.equalsIgnoreCase("RSA")
					&& algURI.equalsIgnoreCase(SignatureMethod.RSA_SHA256)) {
				return true;
//-- added (sha1も対象とする設定)
			} else if (algName.equalsIgnoreCase("RSA")
					&& algURI.equalsIgnoreCase(SignatureMethod.RSA_SHA1)) {
				return true;
			} else {
				return false;
			}
		}
	}

	private static class SimpleKeySelectorResult implements KeySelectorResult {
		private PublicKey pk;

		SimpleKeySelectorResult(PublicKey pk) {
			this.pk = pk;
		}

		public Key getKey() {
			return pk;
		}
	}
}
Validate.javaをコンパイルする
$ javac Validate.java
Detouched型の署名検証時に外部ファイルをアクセスさせる設定とsha1アルゴリズムを許可する設定を行う。
「java.security」ファイルをホームディレクトリに配置しValidate.java実行時に指定する。
macOS BigSur(11.7.10)では、[/Library/Java/JavaVirtualMachines/jdk-22.jdk/Contents/Home/conf/security/java.security]にデフォルトファイルが配置されている。
~/java.security
jdk.xml.dsig.secureValidationPolicy=\
    disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\
    disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\
    disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\
    disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\
    disallowAlg http://www.w3.org/2000/09/xmldsig#dsa-sha1,\
    disallowAlg http://www.w3.org/2007/05/xmldsig-more#sha1-rsa-MGF1,\
    disallowAlg http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1,\
    maxTransforms 5,\
    maxReferences 30,\
    disallowReferenceUriSchemes http https,\
    minKeySize RSA 1024,\
    minKeySize DSA 1024,\
    minKeySize EC 224,\
    noDuplicateIds,\
    noRetrievalMethodLoops

#  disallowAlg http://www.w3.org/2000/09/xmldsig#sha1,\
#  disallowAlg http://www.w3.org/2000/09/xmldsig#rsa-sha1,\
#  disallowReferenceUriSchemes file http https,\
実行ログが取れるよう設定する
macOS BigSur(11.7.10)では、[/Library/Java/JavaVirtualMachines/jdk-22.jdk/Contents/Home/conf/logging.properties]にログ設定用のデフォルトファイルが配置されている。ホームディレクトリにコピー設定する。
~/logging.properties
handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.FileHandler.level = FINER
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
org.jcp.xml.dsig.internal.level = FINER
com.sun.org.apache.xml.internal.security.level = FINER
実行時にログ設定ファイルを指定することで「~/java0.log」ファイルに記録される。Validate.javaが行うcanonicalizeやreferenceで指定された署名対象のハッシュ値が記録される。

申請用総合ソフトの公文書
登記官の電子署名がされた公文書。Detouched型XML署名。同一フォルダにある外部ファイルと同一ファイル内のXML文書を対象とした署名。署名対象外部ファイルは、PDF。XMLエレメント名は「BODY」でアトリビュート名が「ID」。
$ java -Djava.util.logging.config.file=./logging.properties -Djava.security.properties=./java.security Validate /Users/someone/Documents/ShinseiyoSogoSoft/申請案件/2/取得公文書/complete_0001/complete_0001.xml
setBaseURI-> file:///Users/someone/Documents/ShinseiyoSogoSoft/申請案件/2/取得公文書/complete_0001/
Find BODY element and setIdAttibute="ID"
X509Certificate Subject -> CN=Registrar99,OU=XXXX Branch Bureau,OU=Nagano District Legal Affairs Bureau,OU=Ministry of Justice,O=Japanese Government,C=JP
X509Certificate NotAfter -> Tue Jan 14 23:59:59 JST 2025
Algorithm: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
Signature passed core validation
(一部データを秘匿)

申請用総合ソフトの「PDFファイルの署名」
マイナンバーカード等を使用してPDFファイルに電子署名をする。Detouched型XML署名。Signatureエレメントだけの電子署名ファイル。
$ java -Djava.util.logging.config.file=./logging.properties -Djava.security.properties=./java.security Validate /Users/someone/Documents/登記関連/署名テスト/test/test.xml 
setBaseURI-> file:///Users/someone/Documents/登記関連/署名テスト/test/
X509Certificate Subject -> CN=202299999999990000099999993B,L=XXXX,L=Tokyo-to,C=JP
X509Certificate NotAfter -> Mon Jan 99 23:59:59 JST 2027
Algorithm: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
Signature passed core validation
(一部データを秘匿)

申請用総合ソフトの「図面情報ファイルの署名」
マイナンバーカード等を使用してTIFF図面ファイルに電子署名をする。Detouched型XML署名。Signatureエレメントだけの電子署名ファイル。
$ java -Djava.util.logging.config.file=./logging.properties -Djava.security.properties=./java.security Validate /Users/someone/Documents/登記関連/建物/tatemono00001/tatemono00001.tif.sig.xml 
setBaseURI-> file:///Users/someone/Documents/登記関連/建物/tatemono00001/
X509Certificate Subject -> CN=202299999999990000099999993B,L=XXXX,L=Tokyo-to,C=JP
X509Certificate NotAfter -> Mon Jan 99 23:59:59 JST 2027
Algorithm: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
Signature passed core validation
(一部データを秘匿)

eTax用の「医療費控除申請用データファイル」(健康保険組合から入手)
健康保険組合が電子署名したデータファイル。DIACERTというルート認証局に認証されていない認証局(政府と同じ)。日本国政府が運用しているのだから運用を信用しろと言うオレオレ型。日本国政府運用のブリッジ認証局により認証された民間認証局が発行した証明書を使用している。Enveloped型XML署名。署名対象XMLエレメント名は「TEG700」でアトリビュート名が「id」。
$ java -Djava.util.logging.config.file=./logging.properties -Djava.security.properties=./java.security Validate /Volumes/home/確定申告/令和5年度-2023/IK2023999999999900099999_01.xml 
setBaseURI-> file:///Volumes/home/確定申告/令和5年度-2023/
Find TEG700 element and setIdAttribute="id"
X509Certificate Subject -> CN=Taro Urashima,OU=SA000000009999,OU=DIACERT Service,O=DIACERT CA,C=JP
X509Certificate NotAfter -> Wed Dec 31 23:59:59 JST 2025
Algorithm: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
Signature passed core validation
(一部データを秘匿)
参考情報「年末調整保険料控除XML署名確認の顛末

eTax用の「所得税申告書」ファイル
eTaxソフトで所得税を申告する時の申請書ファイル。マイナンバーカード等で署名したデータ。Detouched型XML署名。署名対象XMLエレメント名は「RKO0010」でアトリビュート名が「id」。
$ java -Djava.util.logging.config.file=./logging.properties -Djava.security.properties=./java.security Validate /Volumes/someone/確定申告/令和4年度-2022/令和04年度\(所得税\)-署名後の保存.xtx 
setBaseURI-> file:///Volumes/home/確定申告/令和4年度-2022/
Find RKO0010 element and setIdAttribute="id"
X509Certificate Subject -> CN=202299999999990000099999993B,L=XXXX,L=Tokyo-to,C=JP
X509Certificate NotAfter -> Mon Jan 99 23:59:59 JST 2027
Algorithm: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
Signature passed core validation
(一部データを秘匿)

eTaxソフトの証明書更新
eTaxソフトで申請者の電子証明書を登録する署名データ。Detouched型XML署名。署名対象XMLエレメント名は、「PTE0010」でアトリビュート名が「id」。
$ java -Djava.util.logging.config.file=./logging.properties -Djava.security.properties=./java.security Validate /Volumes/home/確定申告/令和4年度-2022/受信データー証明書更新20230210102741679313.xtx 
setBaseURI-> file:///Volumes/home/確定申告/令和4年度-2022/
Find PTE0010 element and setIdAttribute="id"
X509Certificate Subject -> CN=202299999999990000099999993B,L=XXXX,L=Tokyo-to,C=JP
X509Certificate NotAfter -> Mon Jan 99 23:59:59 JST 2027
Algorithm: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
Signature passed core validation
(一部データを秘匿)

eTax所得税電子申請書(受付後)
平成27年度の所得税申請書の受付後に取得したデータ。Enveloped型XML署名。署名対象エレメント名は、「TEB120」でアトリビュート名「id」。証明書の有効期限が切れている。
$ java -Djava.util.logging.config.file=./logging.properties -Djava.security.properties=./java.security Validate /Volumes/home/確定申告/平成27年度-2015/電子申請等証明書20160201134148979316.xml 
setBaseURI-> file:///Volumes/home/確定申告/平成27年度-2015/
Find TEB120 element and setIdAttribute="id"
X509Certificate Subject -> CN=uketsuke.e-tax.nta.go.jp,OU=Ministry of Finance,O=Japanese Government,C=JP
X509Certificate NotAfter -> Mon Oct 31 23:59:59 JST 2016
Algorithm: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
Signature passed core validation
(一部データを秘匿)

eTax所得税電子申請書(申請時)
平成27年度の所得税申請書の申請時データ。Detouched型XML署名。署名対象エレメント名は、「RKO0010」でアトリビュート名「id」。電子署名用鍵の有効期限が切れている(2018/10/8:住基カードの鍵だったと思う)。ハッシュはsha1。
$ java -Djava.util.logging.config.file=./logging.properties -Djava.security.properties=./java.security Validate /Volumes/home/確定申告/平成27年度-2015/受信データ20160201134148979316.xtx 
setBaseURI-> file:///Volumes/home/確定申告/平成27年度-2015/
Find RKO0010 element and setIdAttribute="id"
X509Certificate Subject -> CN=20159999999901A,L=XXXX,L=Tokyo-to,C=JP
X509Certificate NotAfter -> Mon Oct 08 23:59:59 JST 2018
Algorithm: http://www.w3.org/2000/09/xmldsig#rsa-sha1
Signature passed core validation
(一部データを秘匿)

 

法務省 不動産登記の電子署名を確認してみた
法務省 不動産登記の電子署名をValidate.javaで検証してみた
法務省 不動産登記の複数人電子署名をValidate.javaで検証してみた
法務省 不動産登記の電子署名用証明書をValidate.javaで検証してみた
 


コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 法務省 不動産登記の電子署名... | トップ | ブログ開設から10年 »
最新の画像もっと見る

コメントを投稿

ブログ作成者から承認されるまでコメントは反映されません。

」カテゴリの最新記事