C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: xades4jの検証機能で自作XML署名を検証したい


(過去ログ 177 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■101783 / inTopicNo.1)  xades4jの検証機能で自作XML署名を検証したい
  
□投稿者/ Angolmois (5回)-(2023/04/19(Wed) 15:10:39)

分類:[Java] 

JDK-11, apache-maven-3.9.1,
Windows 10 Pro
IntelliJ IDEA Community版 と Eclipse 2021 を併用


この度はお世話になります。

xades4jというオープンソースのライブラリがあります。xades4jはXML署名に関するライブラリで言語はJavaです。
https://github.com/luisgoncalves/xades4j

その一部の機能である「検証機能」を使用して自作のXML署名(XAdES-X-L)を検証したいと考えています。

wikiの中に検証機能(Verifier)に関する説明があります。
https://github.com/luisgoncalves/xades4j/wiki/SignatureVerification

[困っている事]
上記URLの中程にに
KeyStore trustAnchors = ...;
という記述があります。
この ... の所に具体的にどのような記述をしたら良いのかがわからなくて困っています。

自分の考えでは、「キーストア」というからには、署名に使用した証明書の信頼のルートに関する記述をするのだと思っていますが、合っているかどうかわかりません。
(署名時の証明書が信頼に値するかどうかの検証に使うという理解です)
(検証には秘密鍵は不要です)

実は私は普段はJavaを扱っていない者でして、Javaは非常に不慣れです。(C++/C#が専門です。)

XML署名をする自作アプリはC#で作成しました。
自作アプリで作った署名が世間様の署名の規格に合っている事を確認したいと思ってxades4jを見つけた次第です。


[作成中のソース]
----------------------
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.xml.security.utils.Constants;
import org.w3c.dom.Document;
import xades4j.providers.CertificateValidationProvider;
import xades4j.providers.impl.PKIXCertificateValidationProvider;
import xades4j.utils.FileSystemDirectoryCertStore;
import xades4j.verification.XAdESVerificationResult;
import xades4j.verification.XadesVerificationProfile;
import xades4j.verification.XadesVerifier;
import org.w3c.dom.Element;

public class XmlVerifier  {

    public static boolean
    verify(
	String filePath,		// 入力した署名ファイル名
	String certStorePath)	// ルート証明書を集めたフォルダ名
	throws Exception
    {
        // 署名XMLファイルを読込
        File file = new File(filePath);
        FileInputStream fis = new FileInputStream(file);
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(fis);
        Element signatureNode = getSigElement(doc);

        // certValidatorの作成
        FileSystemDirectoryCertStore certStore = new FileSystemDirectoryCertStore(certStorePath);
		// ↑ルート証明書を集めたフォルダを指定しているが、
		// 正しいのかどうか自信ありません

        KeyStore trustAnchors = (ここの記述がわかりません);

        CertificateValidationProvider certValidator = PKIXCertificateValidationProvider
                .builder(trustAnchors)
                .checkRevocation(false)
                .intermediateCertStores(certStore.getStore())
                .build();

        // XML署名を検証する
        XadesVerificationProfile p = new XadesVerificationProfile(certValidator);
        XadesVerifier v = p.newVerifier();
        XAdESVerificationResult valid = v.verify(signatureNode, null);

        return true;
    }

    static public Element
	getSigElement(
	Document doc) throws Exception
    {
        return (Element)doc.getElementsByTagNameNS(Constants.SignatureSpecNS, Constants._TAG_SIGNATURE).item(0);
    }

}

----------------------

KeyStoreの所について、見よう見真似で下記の様な記述をしましたが、理解していないので当然のように動作しません。
KeyStore trustAnchors = KeyStore.getInstance(KeyStore.getDefaultType());

何日も四苦八苦した末、当掲示板の皆様のお知恵をお借りする判断になりました。
どうか宜しくお願いします。



引用返信 編集キー/
■101785 / inTopicNo.2)  Re[1]: xades4jの検証機能で自作XML署名を検証したい
□投稿者/ 伝説のカレー (93回)-(2023/04/19(Wed) 17:09:45)
No101783 (Angolmois さん) に返信

KeyStoreオブジェクトに証明書(検証キーとその所有者の識別情報のデータ)を読み込むんじゃないですかね

https://docs.oracle.com/javase/jp/8/docs/api/java/security/KeyStore.html

>    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
>
>    // get user password and file input stream
>    char[] password = getPassword();
>
>    try (FileInputStream fis = new FileInputStream("keyStoreName")) {
>        ks.load(fis, password);
>    }

こんな使用例が載ってます

引用返信 編集キー/
■101787 / inTopicNo.3)  Re[2]: xades4jの検証機能で自作XML署名を検証したい
□投稿者/ Angolmois (6回)-(2023/04/19(Wed) 18:29:48)
2023/04/19(Wed) 18:49:48 編集(投稿者)

No101785 (伝説のカレー さん) に返信


伝説のカレーさん、レスありがとうございます。
示して頂いたURLの説明は私も見ておりました。

例にあげて頂いた
>> char[] password = getPassword();

という記述についてですが、この「パスワード」というのは、PKCS#12ファイルを作る時に指定するパスワードの事と思います。
証明書と秘密鍵のペアを用意し、そのペアをPKCS#12ファイルに仕立てる時にパスワードを指定します。
SSL証明書と秘密鍵のペアをIISに設定する時に作るあれでお馴染みかも知れないです。
https://mseeeen.msen.jp/how-to-create-a-pfx-certificate-and-import-it-into-iis/

このペアは署名を作成する時に必要になりますので、それらが入ったPKCS#12ファイルの事をあのページではKeyStoreと言っているのだと思います。

本件問題は署名作成ではなくて検証になりますので、このKeyStoreの部分が私にとって謎になっています。(検証に秘密鍵は不要な為パスワードは無関係になります)

ちなみに、同じURLの説明の、
KeyStore trustAnchors = KeyStore.getInstance("JKS");
という記述についても、「JKS」って何者だと思いながらやってみたのですが、下記の例外が発生します。
xades4j.providers.ConnotBuildCertificationPathException: Trust anchors KeyStore is not initialized


同じURLの説明の「KeyStore.TrustedCertificateEntry」というのが本件に関係あるかも知れないと思うのですが、なにぶんJavaが不自由な為、理解に時間がかかっています。
今はそのような状況です。

アドバイスありがとうございました。

引用返信 編集キー/
■101788 / inTopicNo.4)  Re[3]: xades4jの検証機能で自作XML署名を検証したい
□投稿者/ 伝説のカレー (94回)-(2023/04/19(Wed) 20:27:00)
No101787 (Angolmois さん) に返信

> xades4j.providers.ConnotBuildCertificationPathException: Trust anchors KeyStore is not initialized

「KeyStoreが初期化されていません」なのでloadを行っていないからでしょうね
パスワードを設定していないなら空文字列かnullでいんじゃないですかね

            // JKS ファイルのパス
            String jksFilePath = "path/to/your/keystore_without_password.jks";

            // KeyStore に JKS ファイルをロードする(パスワードなし)
            try (FileInputStream fis = new FileInputStream(jksFilePath)) {
                trustAnchors.load(fis, null);
            }

こんな感じで

JKSはJava Key StoreでKeyStoreの形式の一つです
keytoolコマンドで作れます

引用返信 編集キー/
■101789 / inTopicNo.5)  Re[4]: xades4jの検証機能で自作XML署名を検証したい
□投稿者/ Angolmois (7回)-(2023/04/20(Thu) 09:51:02)
No101788 (伝説のカレー さん) に返信

> 「KeyStoreが初期化されていません」なのでloadを行っていないからでしょうね
> パスワードを設定していないなら空文字列かnullでいんじゃないですかね

> JKSはJava Key StoreでKeyStoreの形式の一つです
> keytoolコマンドで作れます

伝説のカレーさん、レスありがとうございます。とても参考になります。

示して下さった記述と、
自分が只今追及中の「KeyStore.TrustedCertificateEntry」というクラスとの
両方でいろいろ試してみます。

何か進展がありましたら返信致します。
ありがとうございました。


引用返信 編集キー/
■101793 / inTopicNo.6)  Re[5]: xades4jの検証機能で自作XML署名を検証したい
□投稿者/ Angolmois (8回)-(2023/04/20(Thu) 14:22:26)
No101788 (伝説のカレー さん) に返信

>>「KeyStoreが初期化されていません」なのでloadを行っていないからでしょうね
>>パスワードを設定していないなら空文字列かnullでいんじゃないですかね

について、その通りでした。


最初の質問のソース中の
KeyStore trustAnchors = (ここの記述がわかりません);
の所をどう記述するのかという問題について、下記の様に記述したところ無事に記述できました!

不明部分を分離する為、上記部分を下記の様に関数にします。
KeyStore trustAnchors = makeTrustStore(certStorePath, rootCertFilename);
第二引数は、信頼されたルート証明書で certStorePath フォルダ上にあるとします。


関数の中身は下記です。
-------------
// トラストストアを読み込む
public static KeyStore
makeTrustStore(
String certStorePath,
String rootCertFilename) throws Exception
{
String tcFilePath = certStorePath+"\\"+rootCertFilename;
Certificate rootCert = readX509Certificate(tcFilePath);

// キーストアを作成
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);

// TrustedCertificateEntry を使用して、信頼されたルート証明書をキーストアに設定する
String anomName = "root"; // 別名;
KeyStore.TrustedCertificateEntry tce = new KeyStore.TrustedCertificateEntry(rootCert);
;
keyStore.setEntry(anomName, tce, null); // nullはパスワードなし

return keyStore;
}

// 証明書ファイルを読込
private static X509Certificate
readX509Certificate(
String certificateFilePath)
throws IOException, CertificateException
{
FileInputStream fis = new FileInputStream(certificateFilePath);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(fis);
return cert;
}
-------------

最初の質問の趣旨である「記述がわからない」という問題は解決しましたので、解決済と致します。
実はこの状態でもエラーは出るのですが、上記をベースに手直しします。

GPT先生の助けもありますが、伝説のカレーさんとの今回のやりとりがヒントになったので解決に導く事ができました。
ありがとうございました。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -