数字签名 JavaFX 应用程序在执行图像时抛出 java.lang.NoClassDefFoundError: org/bouncycastle/cert/X509CertificateHolder

问题描述 投票:0回答:1

当我尝试使用 JavaFX 制作的应用程序对文档进行数字签名时,我遇到了 BouncyCastle 库的问题。仅当我使用应用程序的编译映像进行签名时,才会出现该错误。如果我通过 IDE (Intellij Idea) 运行该应用程序,它工作得很好。也许当我编译图像时发生了一些无法提取正确依赖项的事情?

以下是相关代码:

build.gradle 中的依赖项:

dependencies {
  implementation('org.controlsfx:controlsfx:11.2.1')
  implementation('org.kordamp.bootstrapfx:bootstrapfx-core:0.4.0')

  testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
  testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")

  // https://mvnrepository.com/artifact/com.itextpdf/itextpdf
  implementation('com.itextpdf:itextpdf:5.5.13.3')

  // https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15to18
  implementation('org.bouncycastle:bcprov-jdk15to18:1.70')

  // https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on
  implementation('org.bouncycastle:bcpkix-jdk15on:1.70') {
    exclude group: 'org.bouncycastle', module: 'bcprov-jdk15on'
  }
}

我必须从 bcpkix-jdk15on 中排除模块 bcprov-jdk15on,否则我会收到模块重复错误。 我使用的 bcprov 和 bcpkix 版本是 itextpdf 5.5.13.3 版本的 pom.xml 中指示的版本。
另外,我检查了 bcpkix-jdk15on 的 jar,有问题的类就在那里。

模块信息:

module a.b.c {
    requires javafx.controls;
    requires javafx.fxml;

    requires org.controlsfx.controls;
    requires org.kordamp.bootstrapfx.core;
    requires itextpdf;

    opens a.b.c to javafx.fxml;
    exports a.b.c;
    exports a.b.c.controllers;
    exports a.b.c.dtos;
    opens a.b.c.controllers to javafx.fxml;
}

抛出异常的行:

MakeSignature.signDetached(appearance, bouncyCastleDigest, privateKeySignature, chain, null, null, null, 0, MakeSignature.CryptoStandard.CMS);

例外:

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
        at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(Unknown Source)
        at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(Unknown Source)
        at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
        at javafx.base/javafx.event.Event.fireEvent(Unknown Source)
        at javafx.graphics/javafx.scene.Node.fireEvent(Unknown Source)
        at javafx.controls/javafx.scene.control.Button.fire(Unknown Source)
        at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(Unknown Source)
        at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(Unknown Source)
        at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
        at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
        at javafx.base/javafx.event.Event.fireEvent(Unknown Source)
        at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Unknown Source)
        at javafx.graphics/javafx.scene.Scene.processMouseEvent(Unknown Source)
        at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Unknown Source)
        at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
        at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
        at java.base/java.security.AccessController.doPrivileged(Unknown Source)
        at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(Unknown Source)
        at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(Unknown Source)
        at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(Unknown Source)
        at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(Unknown Source)
        at javafx.graphics/com.sun.glass.ui.View.notifyMouse(Unknown Source)
        at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(Unknown Source)
        at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.base/java.lang.reflect.Method.invoke(Unknown Source)
        at com.sun.javafx.reflect.Trampoline.invoke(Unknown Source)
        at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.base/java.lang.reflect.Method.invoke(Unknown Source)
        at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(Unknown Source)
        at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(Unknown Source)
        ... 47 more
Caused by: java.lang.NoClassDefFoundError: org/bouncycastle/cert/X509CertificateHolder
        at [email protected]/com.itextpdf.text.pdf.security.MakeSignature.signDetached(Unknown Source)
        at [email protected]/com.itextpdf.text.pdf.security.MakeSignature.signDetached(Unknown Source)
        at [email protected]/a.b.c.services.Service.sign(Unknown Source)
        at [email protected]/a.b.c.services.Service.signSingle(Unknown Source)
        at [email protected]/a.b.c.controllers.Controller.onSignButtonClick(Unknown Source)
        ... 57 more
Caused by: java.lang.ClassNotFoundException: org.bouncycastle.cert.X509CertificateHolder
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
        at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
        ... 62 more

就像我说的,当我在 IDE 上运行应用程序时,签名工作没有任何问题,但编译后的映像失败。 顺便说一句,为了编译图像,我使用以下命令:./gradlew clean jlinkZip,然后使用 bin 文件夹中的 app.bat 运行程序。

更新 1:我忘了提及,如果我不从 bcpkix 中排除 bcprov,则会出现重复的模块错误,只有在使用 gradle 编译时才会出现此错误。如果我通过 IDE 运行应用程序,则不会收到此错误。

更新 2:我正在比较具有不同依赖项配置的编译映像的大小,我注意到当我仅添加 bcpkix 依赖项时,映像的大小不会增加(更具体地说,位于lib 文件夹)。这是缺少类的依赖项。 gradle 是否有可能没有使用此依赖项来编译应用程序?如果是这样,为什么?依赖项 bcprov-jdk15to18 不会发生这种情况,只有 bcpkix-jdk15on 才会发生这种情况。

我将不胜感激任何帮助。 谢谢。

java gradle javafx bouncycastle jlink
1个回答
0
投票

Bouncy castle 软件是模块化的,您有一个模块。 您需要需要模块中的软件才能使用它。

将此行添加到您的

module-info.java
:

requires org.bouncycastle.pkix;

这将需要 bouncy castle pkix 模块

© www.soinside.com 2019 - 2024. All rights reserved.