トップ/記事一覧/Bouncy Castleに秘密鍵を盗まれる脆弱性 CVE-2024-14041、1.78以降は安全
bouncy-castle-cve-cover-ja

Bouncy Castleに秘密鍵を盗まれる脆弱性 CVE-2024-14041、1.78以降は安全

Javaの定番暗号ライブラリ『Bouncy Castle』に、耐量子暗号の処理にかかる時間の差から秘密鍵を割り出される脆弱性が公表されました。ただし修正は2024年4月公開の1.78で済んでおり、現行の1.85を使っていれば影響はありません。危ないのは1.73から1.77で止まっている環境だけです。

ニュース2026年7月28日公開 本日更新
目次
この記事のポイント

Javaの定番暗号ライブラリ『Bouncy Castle』に、耐量子暗号の処理にかかる時間の差から秘密鍵を割り出される脆弱性が公表されました。ただし修正は2024年4月公開の1.78で済んでおり、現行の1.85を使っていれば影響はありません。危ないのは1.73から1.77で止まっている環境だけです。

2026年7月28日、Javaの定番暗号ライブラリ「Bouncy Castle」に、秘密鍵を割り出される脆弱性 CVE-2024-14041が公表されました。処理にかかる時間のわずかな差を大量に測ることで、外に出してはいけない鍵が復元できてしまうというものです。

ただし、先に結論を書きます。この欠陥は2024年4月公開の1.78ですでに直っています。現行の最新版は1.85で、そこそこ新しい版を使っていれば影響はありません。危ないのは、1.73から1.77のあいだで止まっている環境だけです。番号が「CVE-2024-」で始まるとおり、修正のほうが2年以上先に済んでいた案件に、いま識別番号が付いた形になります。

とはいえ、明日以降に脆弱性検査ツールがこの番号を拾い始めると、「うちのシステムは大丈夫か」という確認が各所で走るはずです。自分が対象かの見分け方、何がどう危ないのか、そしてなぜ2年前の修正にいま番号が付いたのかを整理します。

自分が対象かどうかの見分け方

確認するのは1点だけです。Javaのプロジェクトで使っている org.bouncycastle:bcprov-jdk18on(または同系列のプロバイダ)のバージョン番号を見てください。

使っているバージョン判定やること
1.72 以前対象外この機能自体が入っていない
(別の理由で更新は推奨)
1.73 〜 1.77影響あり1.78 以降へ更新
(最新の1.85が望ましい)
1.78 〜 1.84この件は対処済み対応不要
(通常の更新方針で)
1.85(最新)対処済み対応不要

1.72以前が対象外なのは、この脆弱性の舞台であるML-KEM(旧称Kyber)という新しい暗号方式の実装が、1.73で初めて入ったためです。それより前の版には、そもそも該当するコードがありません。ただし古い版には別の欠陥がありますから、「対象外だから放置してよい」という意味ではありません。

危険度は、新しい評価方式であるCVSS 4.0で8.2(重要)と付けられています。従来のCVSS 3.1のスコアは公表されていないため、検査ツールによっては数値が出ない、あるいはツール独自の推定値が出ることがあります。数値の食い違いを見かけても、判断は上の表のバージョンで行ってください。

割り算にかかる時間から、鍵が割れる

今回の欠陥の種類はタイミング攻撃と呼ばれます。プログラムの出力そのものではなく、処理にかかった時間から、中で扱っている秘密の値を推測する手口です。

鍵になっているのは、CPUの割り算です。多くのCPUでは、割り算の所要時間が「割られる数」の中身によって微妙に変わります。ところがML-KEMの実装では、秘密の値を、誰でも知っている固定の数(3329)で割る処理が何か所かに入っていました。割る数は公開されていても、割られる数が秘密であれば、かかった時間はその秘密の情報を漏らします。これを大量の通信で観測して統計的に積み上げると、長期利用している秘密鍵そのものが復元できてしまいます。

この問題はKyberSlashという名前で知られています。Bouncy Castleで該当したのは3か所で、復号したメッセージを取り出す Poly.toMsg(KyberSlash1と呼ばれる箇所)と、暗号文を圧縮する Poly.compressPolyPolyVec.compressPolyVec(KyberSlash2)です。暗号化のときに動く圧縮処理は対象外で、そこで扱う値は最終的に公開される暗号文になるため、時間から漏れても問題になりません。危ないのは復号側だけです。

修正は素直で、2023年12月16日2024年1月5日の2つの変更で、秘密の値に対する割り算をすべて掛け算とビットのずらし操作の組み合わせに置き換えています。掛け算とシフトは、中身によって所要時間が変わりません。前者の変更には「割り算の命令が生成されて、秘密の入力がタイミングの信号として漏れる可能性があるため、このようにした」という開発者のコメントが残っています。

日本語訳

KyberSlashに関する新しい資料ページを公開した。秘密の入力に対して割り算を行い、その結果としてさまざまな環境で秘密情報をタイミングに漏らしているKyber実装についてまとめている。どのライブラリにこの割り算があり、どれが修正済みかを追跡している。

この投稿は、暗号研究者のダニエル・J・バーンスタイン氏が2023年12月に問題を公表したときのものです。KyberSlashはもともと、形式検証されたKyber実装を作っていたCryspenのチーム(Goutam Tamvada氏、Karthikeyan Bhargavan氏、Franziskus Kiefer氏)が最初に気づき、開発元のpq-crystalsへ報告して2023年12月1日に1か所目が修正されました。バーンスタイン氏はこれとは独立に発見し、同年12月30日には実際に鍵を復元する実演を公開しています。その後の研究をまとめた論文はCHES 2025の最優秀論文賞を受賞しており、そこでは「KyberSlash2なら数分、KyberSlash1でも数時間で鍵を復元できた」と報告されています。理屈の上の話ではなく、実際に動く攻撃です。

誰が、何のために狙うのか

この手口を実際に使えるのは、無差別に脆弱なサーバーを探し回る相手ではありません。狙えるのは、同じ鍵を使い続けているサーバーに対して、何万回・何十万回と通信を投げ、その一回ごとの応答時間を精密に測り続けられる立場にいる相手です。同じクラウドの隣の仮想マシンにいる、同じネットワークの内側にいる、あるいは長期間その相手と通信できる関係にある、といった条件が要ります。

その相手がやるのは、測った時間の分布から、サーバーが持っている長期の秘密鍵を計算で組み立て直すことです。鍵さえ手に入れば、あとは正規の受信者として通信を復号できます。侵入した形跡は残りません。攻撃の途中で不正なログインが起きるわけでも、変なファイルが置かれるわけでもないため、通常の監視ではまず気づけないのが、この種の攻撃の嫌なところです。

失われるのは、その鍵で守られていた通信の中身すべてです。過去に記録されていた通信までさかのぼって読まれる可能性もあります。もっとも、ここまでの条件を揃えられる相手は限られており、悪用の難易度は高いと評価されています(CVSS 4.0の内訳でも攻撃の複雑さは「高」、前提条件ありと判定されています)。ばら撒き型の攻撃で踏まれる類のものではありません。

なぜ2年前に直った欠陥に、いま番号が付いたのか

修正は2024年初頭、1.78の公開が2024年4月6日。それなのにCVE番号の公表は2026年7月28日です。この2年強のずれは、記事を読む側からすると気持ちの悪い点だと思います。

まず事実として、Bouncy Castleの開発元から、この遅れについての説明は出ていません。CVEの記録が参照先として挙げているプロジェクトのWiki解説ページは、現時点では存在せず、トップページへ転送されます。GitHubのセキュリティアドバイザリも登録されていません。

確認できる事実から言えるのは、次の2点です。ひとつは、Bouncy Castleの運営団体が自分でCVE番号を採番する組織(CNA)になったのが比較的最近だということ。同団体名義のCVEは全部で14件しかなく、最も古いものでも2025年8月の公表です。もうひとつは、今回のCVEにRobustaという研究チームの名前が謝辞として載っていることです。同チームは2025年7月、バイトコード解析で見つけた57件の懸念をBouncy Castle側へまとめて報告したことが、開発者の講演記録に残っています。同チームは、2026年4月に公表された別の脆弱性(FrodoKEMの秘密鍵が比較処理から漏れるCVE-2026-5598)にも名前が載っています。

つまり、大規模な監査を受けた結果、まだ番号の付いていなかった過去の修正までまとめて洗い出され、遡って採番されている——というのが、公開情報から読める最も自然な説明です。ただしこれは当方の推測であり、開発元の公式見解ではありません。番号の年(2024)が公表年ではなく修正が入った年に合わせられているのも、この読み方と整合します。

実務的には、この経緯自体は害になりません。むしろ「昔直したものにも番号を付けて追跡できるようにする」動きは、依存関係の点検をする側にとってはありがたい方向です。困るのは、検査ツールが番号を拾ったときに「新しい脆弱性が出た」と誤解されて、不要な緊急対応が走ることのほうです。

耐量子暗号への移行で、これから増える種類の欠陥

この件を単なる古い話として片づけないほうがよい理由があります。ML-KEMは、将来の量子コンピュータでも破られないことを目指した耐量子暗号の代表格で、米国立標準技術研究所がFIPS 203として2024年に標準化したものです。いま各国の政府や大手クラウドが本格的な移行を進めている真っ最中の技術です。Googleは2029年を暗号が破られ始める節目と見ていると公表しています。

KyberSlashが示したのは、暗号方式そのものが数学的に安全でも、実装の書き方ひとつで鍵は漏れるという、地味だが重い事実です。しかも漏れた原因は、高度な暗号解読ではなく「割り算を1つ使っていた」ことでした。新しい方式は実装の蓄積が浅いぶん、こうした素朴な取りこぼしが今後も出てきます。実際、KyberSlashの資料ページを見ると、2025年8月時点でもまだ修正されていない実装が残っています。

なお、Bouncy Castleは1.85を最後に、KyberやDilithiumといった選定前の呼び名をプロバイダから外し、ML-KEMなどの正式名称へ整理していく方針を公表しています。移行期特有の名前の揺れがあるため、社内の依存関係の棚卸しでは、旧名と新名の両方で検索しておくと取りこぼしが減ります。暗号ライブラリの欠陥は、node-forgeの署名偽造のように、気づきにくい形で信頼の土台を崩すのが常です。

いま確認すべきこと

やることは多くありません。順に見ていきます。

第一に、使っているBouncy Castleのバージョンを数えることです。直接の依存として書いていなくても、他のライブラリが内部で引き込んでいることがよくあります。Java界隈でのBouncy Castleの利用の広さは相当なもので、公開されている依存関係のデータでは、プロバイダだけで4,000件を超える依存元が記録されています。認証基盤のKeycloakのような有名どころも、Bouncy Castleの脆弱性対応を課題として追跡しています。mvn dependency:treegradle dependencies で、間接的に入っている版まで含めて洗い出してください。依存関係の点検を手早く済ませたい場合は、パッケージ一覧を貼るだけで確認できるスキャナーのような仕組みを併用する手もあります(こちらはnpmとPythonが対象なので、Javaは上記のコマンドで補ってください)。

第二に、1.73から1.77が見つかった場合だけ、更新の計画を立てることです。この範囲でML-KEMの復号を実際に使っているかまで確認できればなお正確ですが、判断に時間をかけるより、1.85へ上げてしまうほうが早く済むはずです。

第三に、1.78以降なら、記録を残して終わりにすることです。この番号については対応済みである、と社内の管理台帳に書いておけば、次に別のツールが同じ番号を拾ったときに二度手間になりません。Javaの定番部品に穴が見つかったときの騒ぎ方という点では、Fastjsonの乗っ取りの件とは事情がまるで違います。あちらは無認証で即座に乗っ取られるもので、こちらは条件の厳しい情報漏れです。同じ「Javaライブラリの重大な脆弱性」でも、急ぎ方は分けて考えてください。この脆弱性は米政府CISAの実際に攻撃が確認された脆弱性のリスト(KEV)には載っておらず、悪用の報告もありません。

まとめ

CVE-2024-14041は、Bouncy Castleの耐量子暗号ML-KEMの実装に、処理時間から秘密鍵が漏れる箇所が3か所あったというものです。危険度はCVSS 4.0で8.2。ただし該当するのは1.73から1.77までで、2024年4月の1.78ですでに修正済み、現行は1.85です。悪用には、同じ鍵に対して大量の通信の時間を精密に測れる立場が要り、ばら撒き型で踏むものではありません。

やるべきことは、依存関係の中のバージョンを数えて、1.73〜1.77が残っていないかを見ることだけです。残っていなければ、記録を残して終わりで構いません。この件で覚えておく価値があるのは、脆弱性そのものより、数学的に安全な暗号でも実装の一行で鍵は漏れるという点のほうです。耐量子暗号への移行がこれから本格化するなかで、同じ形の指摘は今後も出てきます。新しい情報が確認できた場合は、この記事に追記します。

参照元

avatar-m-1

堀川 慎

Backend Engineer / AWS / Django / Go