当我尝试使用 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 才会发生这种情况。
我将不胜感激任何帮助。 谢谢。
Bouncy castle 软件是模块化的,您有一个模块。 您需要需要模块中的软件才能使用它。
将此行添加到您的
module-info.java
:
requires org.bouncycastle.pkix;
这将需要 bouncy castle pkix 模块。