- 适用于 JDK 24 的 GraalVM(最新)
- 适用于 JDK 25 的 GraalVM(早期访问)
- 适用于 JDK 21 的 GraalVM
- 适用于 JDK 17 的 GraalVM
- 存档
- 开发构建
Native Image 与 Jipher JCE
Jipher JCE 是 Oracle 开发的 Java Cryptography Architecture (JCA) 提供程序,它封装了一个预配置且经过 FIPS 验证的 OpenSSL 3.0 版本。Jipher 提供程序支持 FIPS 允许的算法,包括 OpenSSL 3.0 的 FIPS 提供程序。与 Bouncy Castle 或默认的 JDK 提供程序相比,Jipher 提供了具有竞争力的性能。建议在仅允许使用 FIPS 算法的上下文中使用 Native Image 启用 Jipher。请注意,某些算法仅在特定用例中才被 FIPS 允许。因此,Jipher 提供的一些算法可能不适用于所有目的的 FIPS。
注意:Jipher 在 GraalVM Community Edition 中不可用。它在 Linux 和 macOS(macOS 10.15 及更高版本)上,同时支持 AMD64 和 AArch64 架构。
Jipher JAR 文件包含在 Oracle GraalVM 核心包中:lib/jipher/jipher-jce.jar 和 lib/jipher/jipher-pki.jar。要启用 Jipher,请在应用程序类路径中传入这些 JAR 文件。
本页介绍了如何将 Jipher 与 GraalVM Native Image 结合使用。
使用 Jipher 构建原生可执行文件 #
JCA 算法依赖于反射。要在提前编译期间将所有必需的代码路径包含在原生可执行文件中,native-image
工具需要了解运行时通过反射动态访问的任何 Java 代码,以及可能调用的原生代码。(在此了解更多)。这可以通过提供基于 JSON 的由代理收集的元数据来完成。通过 Jipher 动态访问的任何 JCA 服务也会自动由代理注册。
以下步骤展示了如何将 Jipher 嵌入到原生可执行文件中,使用一个执行一些基于 RSA 签名创建和验证的简单 Java 应用程序。
-
将以下代码保存到名为 JipherExample.java 的文件中
import java.security.*; import java.util.*; import com.oracle.jipher.provider.*; class JipherExample { public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException { Provider jipher = new JipherJCE(); Security.insertProviderAt(jipher, 1); byte[] data = new byte[1024]; new Random().nextBytes(data); KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA", jipher); keyGen.initialize(4096); KeyPair keypair = keyGen.generateKeyPair(); Signature signer = Signature.getInstance("SHA512withRSA", jipher); signer.initSign(keypair.getPrivate()); signer.update(data); byte[] signature = signer.sign(); Signature verifier = Signature.getInstance("SHA512withRSA", jipher); verifier.initVerify(keypair.getPublic()); verifier.update(data); boolean isValid = verifier.verify(signature); assert(isValid); } }
-
在类路径上使用 Jipher JAR 文件编译应用程序
javac -cp $GRAALVM_HOME/lib/jipher/jipher-jce.jar:$GRAALVM_HOME/lib/jipher/jipher-pki.jar JipherExample.java
-
在启用代理的 JVM 上运行应用程序。Tracing Agent 会捕获并将在测试运行期间遇到的所有动态特性写入多个 *-config.json 文件。
java -cp $GRAALVM_HOME/lib/jipher/jipher-jce.jar:$GRAALVM_HOME/lib/jipher/jipher-pki.jar:. -agentlib:native-image-agent=config-output-dir=<path> JipherExample
其中
<path>
应指向存储配置文件所在的目录。建议输出目录为/META-INF/native-image/
(如果您使用 Maven 或 Gradle 构建,则为/resources/META-INF/native-image/
)。稍后,在构建原生可执行文件时,native-image
构建器将自动从该位置获取文件。对于此 Java 应用程序,代理会创建包含以下内容的 reachability-metadata.json 文件
{ "reflection":[ { "type":"com.oracle.jipher.internal.spi.KeyPairGen$Rsa", "methods":[{"name":"<init>","parameterTypes":[] }] }, { "type":"com.oracle.jipher.internal.spi.RsaDigestSig$Sha512WithRsa", "methods":[{"name":"<init>","parameterTypes":[] }] } ], "resources":[ {"glob":"libs/linux_x64/fips.so.crc32"}, {"glob":"libs/linux_x64/fips.so"}, {"glob":"libs/linux_x64/libjipher.so.crc32"}, {"glob":"libs/linux_x64/libjipher.so"}, {"glob":"libs/linux_x64/openssl.cnf.crc32"}, {"glob":"libs/linux_x64/openssl.cnf"}, {"glob":"libs"} ], "jni":[ {"type":"[B"}, {"type":"[[B"}, {"type":"com.oracle.jipher.internal.openssl.JniOpenSsl"}, {"type":"java.lang.Boolean","methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }]} ] }
-
为了让代理发现对 Jipher 的所有可能调用,请在 JVM 上使用代理重新运行应用程序(您可以根据需要多次重新运行代理)。这将重新生成整个配置套件,包括任何负面测试用例(以允许捕获异常类)。对于后续运行,请使用此命令
java -agentlib:native-image-agent=config-merge-dir=<path> JipherExample
config-merge-dir
命令将新配置与之前测试运行的配置合并。 -
使用提供的配置构建原生可执行文件
native-image JipherExample
如果配置文件已放置在除
/META-INF/native-image/
之外的其他目录中,请在构建时传递此标志-H:ConfigurationFileDirectories=<path>
以告知native-image
工具新位置。native-image -H:ConfigurationFileDirectories=<path> JipherExample
-
运行本机可执行文件:
./jipherexample
当 Jipher 未嵌入到原生可执行文件中,而是由 JVM 加载时,它会将嵌入在 JAR 中的原生库和 openssl.cnf 文件提取到文件系统,然后将其动态加载到 JVM 进程中。当 Jipher 嵌入到原生可执行文件中时,它会继续将原生库和 openssl.cnf 文件提取到文件系统,并将它们动态加载到原生进程中。当只需要使用 FIPS 允许的算法时,推荐将 Jipher 用于 GraalVM Native Image。在此了解更多关于 Native Image 中 JCA 服务支持的信息。