原文はこちら。
The original article was written by Sean Mullan (Java Security Tech Lead, Oracle).
https://seanjmullan.org/blog/2025/04/07/jdk24
JDK 24 が 2025年3月18日にリリースされました!以前のブログと同様、このリリースで最も興味深く有用なセキュリティ強化点をまとめました。また、それらを適切なカテゴリ(暗号、PKI など)に分類しましたので、各分野での変更点を確認しやすくなっています。JDK 24のリリースノートには、これらの強化点を含む詳細情報が記載されています。
JDK 24
https://openjdk.java.net/projects/jdk/24/
原著者のこれまでのブログエントリ
https://seanjmullan.org/blog/
JDK 24リリースノート
https://jdk.java.net/24/release-notes
このリリースは、Javaセキュリティにとって重要なリリースです。量子耐性のある新しい暗号アルゴリズムが2個(キーカプセル化用の ML-KEM とデジタル署名用の ML-DSA)が追加されたほか、今後の量子耐性暗号化作業の重要な基盤となる新しいプレビュー API「Key Derivation Functions」も含まれています。また、このリリースでは Security Managerが永久に無効化されました。
JEP 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism
https://openjdk.org/jeps/496
JEP 497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm
https://openjdk.org/jeps/497
JEP 478: Key Derivation Function API (Preview)
https://openjdk.org/jeps/478
JEP 411: Deprecate the Security Manager for Removal
https://openjdk.org/jeps/411
さらに、セキュリティライブラリ領域には含まれないながらも、セキュリティを向上させる重要な機能が1つJDK 24に追加されています。
JEP 498: Warn upon Use of Memory-Access Methods in sun.misc.Unsafe
https://openjdk.org/jeps/498
sun.misc.Unsafeのメモリアクセスメソッドを初めて使用すると、実行時に警告が表示されます。これらのメソッドは、JEP 471でJDK 23で廃止予定になっています。
JEP 471: Deprecate the Memory-Access Methods in sun.misc.Unsafe for Removal
https://openjdk.org/jeps/471
Table of Contents
Crypto
JEP 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism
https://openjdk.org/jeps/496
SunJCEプロバイダは、量子耐性のある、キーカプセル化メカニズムのML-KEM(Module Lattice Key Encapsulation Mechanism)をサポートするようになりました。このメカニズムはFIPS 203で規定されており、格子(lattice)に基づいています。
FIPS 203: Module-Lattice-Based Key-Encapsulation Mechanism Standard
https://csrc.nist.gov/pubs/fips/203/final
ML-KEM用の新しいKeyPairGenerator、KeyFactory、およびKEM実装が追加されました。強度を上げる3個のパラメーターセットがサポートされています。
- ML-KEM-512
- ML-KEM-768
- ML-KEM-1024
以下は、ML-KEMを使用して送信者と受信者の2つの当事者間で共有秘密鍵を確立する例です。
// The receiver generates an ML-KEM-768 key pair
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ML-KEM");
kpg.initialize(NamedParameterSpec.ML_KEM_768);
KeyPair kp = kpg.genKeyPair();
// The sender obtains the receiver's public key from
// an X.509 certificate (this part is not shown)
// The sender generates a key encapsulation message and secret key
// from the receiver’s public key
KEM kem = KEM.getInstance("ML-KEM");
KEM.Encapsulator enc = kem.newEncapsulator(receiverCert.getPublicKey());
KEM.Encapsulated encap = enc.encapsulate();
SecretKey skey = encap.key();
byte[] msg = encap.encapsulation(); // send this to the receiver
// The sender then sends the encapsulated message to the receiver
// (this part is not shown)
// The receiver decapsulates the key encapsulation message with its
// private key to obtain the secret key
byte[] msg = …; // received from sender
KEM kem = KEM.getInstance("ML-KEM");
KEM.Decapsulator dec = kem.newDecapsulator(kp.getPrivateKey());
SecretKey skey = dec.decapsulate(msg);
keytoolユーティリティは、ML-KEMキーペアの生成もサポートしています。以下は、ML-KEMキーペアと証明書を生成する例です。
$ keytool -keystore ks -storepass changeit \
-genkeypair -alias ec -keyalg EC \
-dname CN=EC -ext bc
Generating 384-bit EC (secp384r1) key pair and self-signed certificate (SHA384withECDSA) with a validity of 90 days
for: CN=EC
$ keytool -keystore ks -storepass changeit \
-genkeypair -alias mlkem -keyalg ML-KEM \
-groupname ML-KEM-768 -dname CN=ML-KEM \
-signer ec
Generating ML-KEM-768 key pair and a certificate (SHA384withECDSA) issued by <ec> with a validity of 90 days
for: CN=ML-KEM
ML-KEM自体は署名アルゴリズムではないため、証明書を作成するには、証明書に署名するための別のキーが必要になることにご注意ください。最初のコマンドでECキーペアと自己署名証明書を作成し、2 番目のコマンドでML-KEM-768キーペアとECキーで署名された証明書を作成します。
JEP 497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm
https://openjdk.org/jeps/497
SUN プロバイダーは、量子耐性のある署名アルゴリズムのML-DSA (Module Lattice Digital Signature Algorithm)署名アルゴリズムをサポートするようになりました。このアルゴリズムはFIPS 204で規定されており、格子に基づいています。
FIPS 204: Module-Lattice-Based Digital Signature Standard
https://csrc.nist.gov/pubs/fips/204/final
ML-DSA 用の新しいKeyPairGenerator、KeyFactory、およびSignature実装が追加されました。強度を上げる3個のパラメーターセットがサポートされています。
- ML-DSA-44
- ML-DSA-65
- ML-DSA-87
アプリケーションでML-DSAを使用する方法は、他の署名アルゴリズムと非常に類似しています。以下は、ML-DSAを使用してメッセージに署名し検証する例です:
// The signer generates an ML-DSA-65 key pair
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ML-DSA");
kpg.initialize(NamedParameterSpec.ML_DSA_65);
KeyPair kp = kpg.genKeyPair();
// The signer signs a message using its private key
Signature sig = Signature.getInstance("ML-DSA");
sig.initSign(kp.getPrivate());
sig.update(message);
byte[] signature = sig.sign();
// The signer then sends the signed message to the verifier
// (this part is not shown)
// The verifier verifies the message using the signer’s public key
// (which in this case is in an X.509 certificate)
Signature sig = Signature.getInstance("ML-DSA");
sig.initVerify(signerCert);
sig.update(message);
assert sig.verify(signature);
keytoolユーティリティは、ML-DSAキーペアの生成もサポートしています。以下は、ML-DSAキーペアと証明書を生成する例です。
$ keytool -keystore ks -storepass changeit \
-genkeypair -alias mldsa -keyalg ML-DSA \
-groupname ML-DSA-65 -dname CN=ML-DSA
Generating ML-DSA-65 key pair and self-signed certificate (ML-DSA-65) with a validity of 90 days
for: CN=ML-DSA
このコマンドで、ML-DSA-65キーペアと自己署名証明書を作成します。
JEP 478: Key Derivation Function API (Preview)
https://openjdk.org/jeps/478
このリリースでは、キーマテリアル(key material)からキーを導出するための新しいプレビューAPIが導入されました。詳細についてはJEP 478を参照してください。この API には、RFC 5869で定義されている HMACベースのExtract-and-Expand鍵導出関数 (HKDF) の実装が含まれています。
RFC 5869: HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
https://www.rfc-editor.org/rfc/rfc5869.html
KDFは、鍵導出に依存する今後の複数の機能強化において非常に有用なAPIとなるでしょう。これには、TLS 1.3(IETFドラフト)のハイブリッド鍵交換やハイブリッド公開鍵暗号化(RFC 9180)などのPQCメカニズムが含まれます。
Hybrid key exchange in TLS 1.3 (draft-ietf-tls-hybrid-design-12)
https://datatracker.ietf.org/doc/draft-ietf-tls-hybrid-design/
RFC 9180: Hybrid Public Key Encryption
https://www.rfc-editor.org/rfc/rfc9180.html
このAPIは、Argon2(RFC 9106)などの強固で現代的なパスワードベースのアルゴリズムにも使用できるように設計されています。
RFC 9106: Argon2 Memory-Hard Function for Password Hashing and Proof-of-Work Applications
https://www.rfc-editor.org/rfc/rfc9106.html
主な新しいクラスはjavax.crypto.KDFです。
KDF (Java SE 24 & JDK 24)
https://docs.oracle.com/en/java/javase/24/docs/api/java.base/javax/crypto/KDF.html
JEPでは、HKDF-SHA256アルゴリズムを使用して32バイトのAESキーを導出する例を示しています:
// Create a KDF object for the specified algorithm
KDF hkdf = KDF.getInstance("HKDF-SHA256");
// Create an ExtractExpand parameter specification
AlgorithmParameterSpec params =
HKDFParameterSpec.ofExtract()
.addIKM(initialKeyMaterial)
.addSalt(salt).thenExpand(info, 32);
// Derive a 32-byte AES key
SecretKey key = hkdf.deriveKey("AES", params);
Standard Hash and MGF Algorithm Names Defined for RSASSA-PSS Signatures
https://bugs.openjdk.org/browse/JDK-8248981
Java Security Standard Algorithm Names Specification に、java.security.spec.PSSParameterSpecオブジェクトをインスタンス化する際に指定できる標準のハッシュおよび MGF (メッセージ生成関数) アルゴリズムを記載した新しいPSSParameterSpecセクションが追加されました。
Java Security Standard Algorithm Names
https://docs.oracle.com/en/java/javase/24/docs/specs/security/standard-names.html#pssparameterspec
PSSParameterSpec (Java SE 24 & JDK 24)
https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/security/spec/PSSParameterSpec.html#%3Cinit%3E(java.lang.String,java.lang.String,java.security.spec.AlgorithmParameterSpec,int,int)
SHA3 Performance Improved
https://bugs.openjdk.org/browse/JDK-8333867
SHA3 MessageDigest実装のパフォーマンスが、プラットフォームおよびメッセージダイジェストの長さに応じて6%から27%向上しました。このパフォーマンスの向上は、SHA3-224、SHA3-256、SHA3-384、およびSHA3-512アルゴリズムに適用されます。AVX-512対応プラットフォームでは、そのプラットフォーム向けの新しい組み込み関数実装により、さらに30~40%の性能向上が期待できます。
PKCS#11 Support for AES CTS (Ciphertext Stealing) Mode
https://bugs.openjdk.org/browse/JDK-8330842
SunPKCS11プロバイダは、構成済みのPKCS#11トークンが対応している場合、AES Ciphertext Stealingモードをサポートするように強化されました。サポートされる暗号アルゴリズムは以下の通りです。
- AES/CTS/NoPadding
- AES_128/CTS/NoPadding
- AES_192/CTS/NoPadding
- AES_256/CTS/NoPadding
PKCS#11 cipherTextStealingVariant属性は、PKCS#11実装で使用されるCTSバリエーションに設定する必要があります。これらは、NIST SP 800-38Aで定義された3個のバリエーション(CS1、CS2、および CS3)に対応しています。PKCS#11実装としてNSSを使用する場合、自動的にCS1に設定されます。この属性が設定されていない場合、CTSモードはデフォルトで無効になります。
PKI
New Root CA Certificates
https://bugs.openjdk.org/browse/JDK-8341057
cacertsキーストアに、新しいルートCA証明書が追加されました。
2個のSSL.comルートCA証明書
SSL.com TLS ECC Root CA 2022
https://crt.sh/?id=7439766705
# distinguished name
CN=SSL.com TLS ECC Root CA 2022, O=SSL Corporation, C=US
SSL.com TLS RSA Root CA 2022
https://crt.sh/?id=7439767372
# distinguished name
CN=SSL.com TLS RSA Root CA 2022, O=SSL Corporation, C=US
これらのルート証明書は、以下のOracle JDKのcacertsキーストアにも追加されています。
- 23.0.1
- 21.0.5
- 17.0.13
- 11.0.25
- 8u431
TLS
New Wildcard Mechanism for Disabling TLS Cipher Suites
https://bugs.openjdk.org/browse/JDK-8341964
セキュリティプロパティ jdk.tls.disabledAlgorithms の機能強化により、ワイルドカード構文を使ってTLS cipher suiteを無効化できるようになりました。この新たな構文を使うと、より簡単に1個以上のcipher suiteを無効化できます。例えば。 TLS_RSA_* と指定すると、TLS_RSA_で始まる全てのcipher suiteを無効化します。TLS_ で始まるcipher suiteのみこのメカニズムで無効化できます。
Entrust TLS Server Certificates Distrusted
https://bugs.openjdk.org/browse/JDK-8337664
The JDKはEntrustが発行したTLSサーバー証明書を信頼しなくなりました。影響を受ける証明書のリストには、Entrustと(Entrustが管理していた)AffirmTrustブランドの証明書が含まれています。2024年11月11日以前に発行されたTLSサーバー証明書は有効期限まで信頼され続けます。その日以後に発行された証明書は信頼されません。詳細はリリースノートおよび影響を受けるCA(certificate authorities)のリストをご覧ください。
JDK 24.0.1 Release Notes
https://jdk.java.net/24/release-notes#JDK-8337664
(訳注:JDK 24のリリースノートが24.0.1のものに変わっているので、Oracle Java SE 24のリリースノートをチェックしてください)
https://www.oracle.com/java/technologies/javase/24-relnote-issues.html#JDK-8337664
この変更は既に以下のOracle JDKに適用されています。
- 23.0.1
- 21.0.5
- 17.0.13
- 11.0.25
- 8u431
TLS_RSA Cipher Suites Disabled by Default
https://bugs.openjdk.org/browse/JDK-8245545
TLS_RSA cipher suiteはデフォルトで無効になりました。これらのcipher suiteは前方秘匿性(forward secrecy)を保持せず、RFC 9325では使用しないことが推奨されています。この変更により、TLS_RSA_で始まるすべてのcipher suiteが無効になります。
RFC 9325: Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)
https://www.rfc-editor.org/rfc/rfc9325
設定ファイルjava.securityのjdk.tls.disabledAlgorithmsセキュリティ プロパティからTLS_RSA_*を削除することで、これらのcipher suiteを自己責任で再有効化できます。
Security Manager
Permanently Disable the Security Manager
https://openjdk.org/jeps/486
JDK 17で、JEP 411によりSecurity Managerが廃止予定になり、java.lang.SecurityManager API およびSecurity Managerに関連する複数のAPIが対象となりました。
このリリースでは、次の主要なステップとして、JEP 486でSecurity Managerを永久に無効化しました。コマンドラインでの起動時またはSystem.setSecurityManagerを呼び出し、実行時にSecurity Managerを有効化できなくなりました。Security Managerに関連する API は、機能しないように、もしくはSecurity Managerが有効化されていない以前のリリースと同じ動作をするように機能低下されました。
開発者は、必要に応じてSecurity Managerへの依存関係を削除する措置を講じてください。コードがSecurity Managerに依存しているかどうかを確認するための方法はいくつかあります。
- スクリプトやSecurity Managerリファレンスのドキュメントをチェックしてください
- JDK 17から23までのどれか一つでアプリケーションを実行し、コンソール上の非推奨警告を探してください
- コマンドラインオプション
-Djava.security.manager=disallowを付けて、JDK 17から23までのどれか一つでアプリケーションを実行してください。コードが動的にSecurity Managerを設定している場合、UnsupportedOperationExceptionをスローします - JDK 17以後の
jdeprscanを使って非推奨のSecurity Manager APIの利用をスキャンしてください
Security Managerと共にアプリケーションを実行すると、JVMは起動時に致命的なエラーで終了します。
java –Djava.security.manager MyApp
Error occurred during initialization of VM
java.lang.Error: A command line option has attempted to allow or enable the Security Manager. Enabling a Security Manager is not supported.
at java.lang.System.initPhase3(java.base@24-internal/System.java:2067)
アプリケーションがSecurity Managerを実行時に有効化している場合、UnsupportedOperationExceptionがスローされます。
java MyApp
Exception in thread "main" java.lang.UnsupportedOperationException: Setting a Security Manager is not supported
at java.base/java.lang.System.setSecurityManager(System.java:320)
...
Security Managerをサポートするライブラリは、通常1個もしくは2個の共通コーディングパターンを使っています。
// checking permissions
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(...);
}
// asserting privileges
SomeType v = AccessController.doPrivileged(
(PrivilegedAction<SomeType>)() -> {
...
return theResult;
});
これらのメソッドは、Security Managerが有効になっていない以前の JDK リリースと同じ動作をします。System.getSecurityManagerは常にnullを返し、AccessController.doPrivilegedはアクションを即座に実行します。
ごく一部のアプリケーションやライブラリでは、Security Manager API の高度な部分を使用しています。例えば、AccessController::checkPermissionを使用して権限を直接確認したり、Policy::setPolicyを使用してカスタムポリシー実装を使用したりしています。
これらのAPIを含むAPIは無効化され、例外をスローしたり、デフォルトで全てのリソースに対するアクセスを禁止する実行環境を提供するようになっています。
JAASを利用するアプリケーションの場合、Subject.getSubjectが変更され、常にUnsupportedOperationExceptionがスローされるようになりました。このAPIは最終的に廃止予定のAccessControlContext APIに依存しています。JDK 18で置き換えのためのAPIが追加されました。この API を使用する場合、Subject.getSubjectの呼び出しをSubject.currentに置き換え、Subject.doAsの呼び出しをSubject.callAsに置き換える必要があります。
API変更の完全なリストは、CSR を参照してください。
[JDK-8266577] Implement JEP 411: Deprecate the Security Manager for Removal
https://bugs.openjdk.org/browse/JDK-8266577
今後のリリースで、Security Manager API は削除されます。
Miscellaneous
Support for Including Security Properties Files
https://bugs.openjdk.org/browse/JDK-8319332
java.securityセキュリティプロパティファイルで、他のプロパティファイルを含めることができるようになりました。新たな include <file> ディレクティブが追加され、別のプロパティファイルを追加できるようになっています。ファイルのインクルードの効果は、当該プロパティをインクルードポイントでインラインで定義することと同じです。様々なセキュリティプロファイルを基にしてインクルード可能な様々プロパティファイルを定義する上で、この機能は非常に有用です。
詳細および例については、Security Developer GuideのSecurity Properties Files Inclusionのセクションをご覧ください。
Including a Security Properties File
https://docs.oracle.com/en/java/javase/24/security/security-properties-file.html#GUID-FF09EB34-CD27-4D1B-B55B-A4A4E6A0F039