I'm trying to use the jlink tool in order to build a java executable. I'm using it in the following way:
jlink.exe --module-path <path-to-modules> --add-modules <my-module-name> --output dist --launcher launch=org.demo/org.demo.Main --strip-debug --compress 2 --no-header-files --no-man-pages
but it gives me the following error:
Error: signed modular JAR <path-to-modules>\bcprov.jdk15on.jar is currently not supported, use --ignore-signing-information to suppress error
When I add the "--ignore-signing-information" option, it builds my executable fine, but it gives me the following warning:
WARNING: signed modular JAR <path-to-modules>\bcprov.jdk15on.jar is currently not supported
And then later on, when I execute the already built executable, I get the following exception:
org.apache.sshd.common.SshException: Failed (NoSuchProviderException) to execute: JCE cannot authenticate the provider BC
at sshd.core/org.apache.sshd.common.future.AbstractSshFuture.verifyResult(Unknown Source)
at sshd.core/org.apache.sshd.client.future.DefaultAuthFuture.verify(Unknown Source)
at sshd.core/org.apache.sshd.client.future.DefaultAuthFuture.verify(Unknown Source)
Caused by: java.util.jar.JarException: Non-Oracle JCE providers may not be linked into the image,they must be provided as signed JAR files.
at java.base/javax.crypto.ProviderVerifier.verify(Unknown Source)
at java.base/javax.crypto.JceSecurity.verifyProvider(Unknown Source)
at java.base/javax.crypto.JceSecurity.getVerificationResult(Unknown Source)
at java.base/javax.crypto.JceSecurity.getInstance(Unknown Source)
at java.base/javax.crypto.KeyAgreement.getInstance(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
My question is - is there any way to use signed jars with the "jlink" tool, or is there any way to avoid the error "Non-Oracle JCE providers may not be linked into the image"?
I know it's old, but I've ran into the same issue recently. Looks like it's one of "exclusive features" of Oracle OpenJDK, just like Alan Bateman said in comments. I tested Adopt and Liberica OpenJDK and while jlink
still warns that signed jars aren't supported, there's no runtime exceptions.
Here's a simple test in case someone got interested. I use moditect Maven plugin, which uses Maven toolchains to select JDK to build runtime image.
public class Main {
public static void main(String[] args) {
try {
if (Security.getProvider("BC") == null) {
Security.insertProviderAt(new BouncyCastleProvider(), 0);
}
for (final Provider provider : Security.getProviders()) {
System.out.println("provider: " + provider.getName());
}
Cipher cipher = Cipher.getInstance("AES", "BC");
System.out.println(cipher.getProvider().getName());
} catch (NoSuchAlgorithmException | NoSuchPaddingException | NoSuchProviderException e) {
e.printStackTrace();
}
}
}
module bctest {
requires org.bouncycastle.pkix;
requires org.bouncycastle.provider;
}
<toolchain>
<type>jdk</type>
<provides>
<version>16</version>
<vendor>liberica</vendor>
<platform>win64</platform>
</provides>
<configuration>
<jdkHome>%dir_path%\jdk16-win64-full-liberica</jdkHome>
</configuration>
</toolchain>
<toolchain>
<type>jdk</type>
<provides>
<version>16</version>
<vendor>oracle</vendor>
<platform>win64</platform>
</provides>
<configuration>
<jdkHome>%dir_path%\jdk16-win64-std-oracle</jdkHome>
</configuration>
</toolchain>
<toolchain>
<type>jdk</type>
<provides>
<version>16</version>
<vendor>adopt</vendor>
<platform>win64</platform>
</provides>
<configuration>
<jdkHome>%dir_path%\jdk16-win64-std-adopt</jdkHome>
</configuration>
</toolchain>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>${lib.bouncycastle.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>${lib.bouncycastle.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${plugin.compiler.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<!-- copy project JAR to modules directory -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${plugin.jar.version}</version>
<configuration>
<outputDirectory>${bld.modulesDirectory}</outputDirectory>
</configuration>
</plugin>
<plugin>
<!-- copy all dependencies JAR to modules directory -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>${plugin.dependency.version}</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${bld.modulesDirectory}</outputDirectory>
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.moditect</groupId>
<artifactId>moditect-maven-plugin</artifactId>
<version>${plugin.moditect.version}</version>
<executions>
<execution>
<id>create-runtime-image</id>
<phase>package</phase>
<goals>
<goal>create-runtime-image</goal>
</goals>
<configuration>
<!-- switch between verdors described in ~/.m2/toolchains.xml -->
<baseJdk>version=16,vendor=adopt,platform=win64</baseJdk>
<modulePath>
<!-- source modules (JARs) -->
<path>${bld.modulesDirectory}</path>
</modulePath>
<modules>
<module>bctest</module>
<module>jdk.crypto.cryptoki</module>
</modules>
<launcher>
<name>bctest</name>
<module>bctest/rootpack.Main</module>
</launcher>
<outputDirectory>${project.build.directory}/jrt</outputDirectory>
<compression>2</compression>
<!-- exclude signing info from runtime image, otherwise jlink refuses to create it -->
<ignoreSigningInformation>true</ignoreSigningInformation>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Liberica and Adopt:
provider: SUN
provider: SunRsaSign
provider: SunEC
provider: SunJSSE
provider: SunJCE
provider: SunSASL
provider: JdkLDAP
provider: SunPKCS11
provider: BC
BC
Oracle:
provider: SUN
provider: SunRsaSign
provider: SunEC
provider: SunJSSE
provider: SunJCE
provider: SunSASL
provider: JdkLDAP
provider: SunPKCS11
provider: BC
Exception in thread "main" java.lang.SecurityException: JCE cannot authenticate the provider BC
at java.base/javax.crypto.Cipher.getInstance(Cipher.java:722)
at java.base/javax.crypto.Cipher.getInstance(Cipher.java:642)
at [email protected]/rootpack.Main.main(Main.java:24)
Caused by: java.util.jar.JarException: Non-Oracle JCE providers may not be linked into the image,they must be provided as signed JAR files.
at java.base/javax.crypto.ProviderVerifier.verify(ProviderVerifier.java:123)
at java.base/javax.crypto.JceSecurity.verifyProvider(JceSecurity.java:189)
at java.base/javax.crypto.JceSecurity.getVerificationResult(JceSecurity.java:217)
at java.base/javax.crypto.Cipher.getInstance(Cipher.java:718)
... 2 more
Unless you're using Oracle JDK, use --ignore-signing-information
and ignore corresponding warning. If you're using Oracle JDK, there's no way to avoid runtime exception, because of compile-time nature of JPMS. There's no such thing as "provided scope" in Java modules. So, consider supporting OpenJDK vendors those do not place nonsense restrictions on their users.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With