Jipher JCE 与原生镜像

Jipher JCE 是一个 Oracle 开发的 Java 加密架构 (JCA) 提供程序,它打包了一个预配置的且经过 FIPS 验证的 OpenSSL 3.0 版本。Jipher 提供程序支持由 FIPS 允许的算法,包括 OpenSSL 3.0 的 FIPS 提供程序。与 Bouncy Castle 或默认 JDK 提供程序相比,Jipher 具有竞争力的性能。建议在仅应使用 FIPS 允许的算法的环境中,使用原生镜像启用 Jipher。请注意,某些算法仅在特定用例下才被 FIPS 允许。因此,Jipher 提供的某些算法可能不适用于 FIPS 的所有用途。

注意:Jipher 在 GraalVM 社区版中不可用。它在 AMD64 和 AArch64 架构的 Linux 和 macOS(macOS 10.15 及更高版本)上受支持。

Jipher JAR 文件包含在 Oracle GraalVM 核心包中,位于:lib/jipher/jipher-jce.jarlib/jipher/jipher-pki.jar。要启用 Jipher,请将这些 JAR 文件传递到应用程序类路径。

本页介绍如何在 GraalVM 原生镜像中使用 Jipher。

使用 Jipher 构建原生可执行文件 #

JCA 算法依赖于反射。为了在提前编译期间将所有必需的代码路径包含在原生可执行文件中,native-image 工具需要通过反射了解运行时访问的任何动态 Java 代码,以及可能被调用的原生代码。(在此处了解更多 信息)。这可以通过提供基于 JSON 的 代理收集的元数据 来完成。代理也会自动注册通过 Jipher 访问的任何动态 JCA 服务。

以下步骤展示了如何将 Jipher 嵌入到原生可执行文件中,使用一个简单的 Java 应用程序来进行一些基于 RSA 的签名创建和验证。

  1. 将以下代码保存到名为 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);
         }
     }
    
  2. 使用 Jipher JAR 文件在类路径上编译应用程序

     javac -cp $GRAALVM_HOME/lib/jipher/jipher-jce.jar:$GRAALVM_HOME/lib/jipher/jipher-pki.jar JipherExample.java
    
  3. 在启用了代理的 JVM 上运行应用程序。跟踪代理会捕获并记录在测试运行期间遇到的所有动态功能,并将其写入多个 *-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"] }]}
       ]
     }
    
  4. 为了让代理发现所有对 Jipher 的可能调用,请在 JVM 上重新运行启用了代理的应用程序(您可以根据需要多次重新运行代理)。这将重新生成整个配置套件,包括任何负面测试用例(允许捕获异常类)。对于后续运行,请使用以下命令

     java -agentlib:native-image-agent=config-merge-dir=<path> JipherExample
    

    config-merge-dir 命令会将新的配置与先前测试运行中的配置合并。

  5. 使用提供的配置构建原生可执行文件

     native-image JipherExample
    

    如果配置文件位于 /META-INF/native-image/ 以外的目录中,请在构建时传递此标志 -H:ConfigurationFileDirectories=<path>,以通知 native-image 工具新的位置

     native-image -H:ConfigurationFileDirectories=<path> JipherExample
    
  6. 运行原生可执行文件

     ./jipherexample
    

当 Jipher 嵌入到原生可执行文件中,而是由 JVM 加载时,它会将嵌入在 JAR 文件中的原生库和 openssl.cnf 文件提取到文件系统,然后动态地将它们加载到 JVM 进程中。当 Jipher 嵌入到原生可执行文件中时,它会继续将原生库和 openssl.cnf 文件提取到文件系统,并动态地将它们加载到原生进程中。当仅应使用 FIPS 允许的算法时,建议在 GraalVM 原生镜像中使用 Jipher。在此处了解有关原生镜像中 JCA 服务支持的更多信息 here.

联系我们