Jipher JCEとネイティブ・イメージ
Jipher JCEは、Oracleが開発したJava Cryptography Architecture (JCA)プロバイダで、事前構成され、FIPS検証済のOpenSSL 3.0バージョンをパッケージ化しています。Jipherプロバイダは、OpenSSL 3.0のFIPSプロバイダを含む、FIPSで認められたアルゴリズムをサポートしています。Jipherは、Bouncy CastleまたはデフォルトのJDKプロバイダと比較して、競争力のあるパフォーマンスを提供します。FIPSで認められたアルゴリズムのみを使用するコンテキストで、ネイティブ・イメージを使用するJipherを有効にすることをお薦めします。一部のアルゴリズムは、特定のユース・ケースについてのみFIPSで認められていることに注意してください。そのため、Jipherによって提供されるアルゴリズムの中には、すべての目的についてFIPSで認められているわけではないものもあります。
ノート: Jipherは、GraalVM Community Editionでは使用できません。AMD64とAArch64アーキテクチャのLinuxとmacOS (macOS 10.15以上)でサポートされています。
Jipher JARファイルは、lib/jipher/jipher-jce.jarおよびlib/jipher/jipher-pki.jarにあるOracle GraalVMコア・パッケージに含まれています。Jipherを有効にするには、これらのJARファイルをアプリケーション・クラス・パスに渡します。
このページでは、GraalVMネイティブ・イメージでJipherを使用する方法を説明します。
Jipherを使用したネイティブ実行可能ファイルのビルド
JCAアルゴリズムはリフレクションに依存します。事前コンパイル時に必要なすべてのコード・パスをネイティブ実行可能ファイルに含めるには、native-image
ツールで、リフレクションによって実行時に動的にアクセスされるJavaコードと、呼び出される可能性のあるネイティブ・コードを認識する必要があります。(詳細は、こちらを参照してください)。これを行うには、JSONベースのエージェントによって収集されたメタデータを指定します。Jipherを介して動的にアクセスされるJCAサービスも、エージェントによって自動的に登録されます。
次のステップは、RSAベースの署名の作成および検証を実行する単純なJavaアプリケーションを使用して、ネイティブ実行可能ファイルにJipherを埋め込む方法を示しています。
-
次のコードを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でアプリケーションを実行します。トレース・エージェントは、テスト実行中に検出されたすべての動的機能を捕捉して複数の*-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で認められたアルゴリズムのみを使用する場合は、GraalVMネイティブ・イメージにJipherをお薦めします。ネイティブ・イメージでのJCAサービスのサポートの詳細は、こちらを参照してください。