「unable to find valid certification path」「PKIX path building failed」が出たら、cacertsを確認します。必要な証明書が入っているかを見てください。
cacertsは「シーエーサーツ」と読みます(Certificate Authority certificatesの略で、「カサーツ」と読む人もいます)。
cacertsとは、Javaが信頼するルート証明書をまとめたキーストアファイルです。中身は、次の2コマンドで確認できます。
# 1. 実際に使われているJavaの場所(java.home)を確認
java -XshowSettings:properties -version 2>&1 | grep java.home
# 2. そのJDKのcacertsに入っている証明書を一覧表示(Java9以降)
keytool -list -cacerts -storepass changeit
Java9以降は-cacertsでパス指定が不要です。Java8は-keystoreでパスを指定します(OS別のパスは「cacertsファイルの場所」)。
この記事でわかること
- keytoolコマンドでcacertsの証明書一覧を確認する方法
- cacertsファイルの場所(Windows/macOS/Linux、Java25対応)
- 「PKIX path building failed」などエラーの原因と対処法
本文では、Windows・macOS・Linux別のcacertsのパスと、-Djavax.net.ssl.trustStoreで別のキーストアを使っていないかの見分け方を扱います。
自己署名証明書をimportcertで追加する手順と、削除時の注意点もコピペで使える形でまとめました。
手元のJDK 23.0.1(macOS)で2つ目のコマンドを実行したところ、112件の証明書が表示されました。件数はJDKのバージョンやディストリビューションで変わります。
まずは、現在使われているjava.homeの確認コマンドから試してください。
PARTS LIST /目次
- keytool・cacertsのコマンド早見表(コピペ用)
- cacertsとは?ルート証明書・keytoolの基本
- keytoolでcacertsの証明書を確認するには?
- cacertsの証明書の有効期限を確認するには?
- プログラム内からルート証明書を確認する方法
- keytool/TrustManager/openssl の使い分け早見表
- PKIXエラー(証明書エラー)はなぜ起きる?原因と対処法
- cacertsのキーストア形式(JKSとPKCS12)の違い
- cacerts確認でハマりやすいポイントTOP3
- ルート証明書はどう更新する?
- cacerts直編集とアプリ専用trustStoreの使い分け
- cacerts以外のキーストアとJavaバージョン別の違い
- よくある質問
- まとめ:cacerts確認の基本
keytool・cacertsのコマンド早見表(コピペ用)
証明書まわりの作業は、たまにしか来ないのに毎回同じコマンドを探すことになります。よく使うものを1つの表にまとめました。ブックマークしておけば、次からはこの表だけで済みます。
デフォルトのパスワードは changeit です。追加・削除の前には、必ずバックアップを取ってください。各コマンドの詳しい使い方は、本文の該当する見出しで説明しています。
cacertsとは?ルート証明書・keytoolの基本
cacertsとは、Javaが標準で信頼するルート証明書をまとめて格納しているキーストアファイルのことです。
cacertsのファイル形式は、Java17まではJKS、Java18以降はパスワードなしのPKCS12です。なお、keytoolで新規に作るキーストアの既定は、Java9以降PKCS12です。
Javaのルート証明書は、ざっくり言うと「この相手なら信じていいよ」とJavaが判断するための“信用リスト”みたいなものです。
私たちがブラウザで普通にネットショッピングできるのも、裏で「このサイト、本物?」と確認してくれているから。
それと同じことをJavaプログラムもやっています。
HTTPSで通信するときは、サーバーから証明書が送られてきます。
Javaは送られてきた証明書を調べて、「この証明書って、信頼できる発行元が出したやつ?」と、自分が持っている“信用リスト”と照らし合わせます。
信用リストの仕組みを知っておくと、通信でエラーが出たときに「証明書の問題かな?」と当たりをつけやすくなるので、トラブル対応がぐっと楽になります。
ルート証明書の役割|信頼チェーンの起点とは
ルート証明書は、信頼の連鎖(チェーン)の起点となる最上位の証明書です。
Javaはこのルート証明書をあらかじめ保持しているため、初めて通信するサーバーでも安全に接続できます。
もし存在しなければ、接続のたびに手動で信頼確認が必要になり、プログラムによる自動処理は実現できません。
イメージしやすいように、現実で例えると“パスポートを発行する国”が近いです。
私たちが誰かの身分証明を信じられるのは、その人のパスポート(=サーバー証明書)が、ちゃんと信用できる国(=ルート認証局)によって発行されているからですよね。
Javaは最初から「信用できる国リスト」を持っていて、その国が発行した“パスポート”だけ通信を許可する仕組みです。
中間証明書との違い|PKIエラーが起きる仕組み
中間証明書は、ルート証明書とサーバー証明書の間をつなぐ役割を持っています。
ルート証明書の秘密鍵が漏洩すると影響が甚大です。そのためルート認証局はオフラインで厳重に保管され、直接署名には使いません。
代わりに、中間認証局に署名権限を委譲しています。一般的な証明書の構成は以下のようになります。
- ルート証明書(Javaが元々持っている)
- 中間証明書(サーバーから送られてくることが多い)
- サーバー証明書(通信したいサーバーのもの)
トラブルが起きる際、Java側にルート証明書がないケースもあれば、サーバー側が中間証明書を送り忘れているケースもあります。
unable to find valid certification path対処: フィンガープリントで確かめてから keytool -importcert でcacertsに追加PKIX path building failed対処: サーバー管理者に中間証明書の組み込みを依頼(暫定: 中間証明書をimportcert)この違いを理解しておくと、自分の環境を直すべきか、相手に設定修正を依頼すべきかの判断が早くなります。
Java証明書管理の全体像
Javaは証明書を、OSの機能ではなく独自の「キーストア」という仕組みで管理しています。
WindowsやmacOSにも証明書を管理する機能はありますが、Javaはそれらを直接参照しません。
Javaのインストールディレクトリ内にある特定のファイル(キーストア)だけを見ています。
管理に使われる主な要素は以下の3つです。
- cacertsファイル:ルート証明書が格納されているデータベースファイル
- keytool:証明書を追加・削除・確認するためのコマンドラインツール
- JRE/JDK:cacertsとkeytoolが入っているインストール先のフォルダ
つまり、Javaの証明書問題に対処するには、OSの設定画面を開くのではなく、Javaフォルダ内のファイルを確認しなければなりません。
keytoolの主な機能
keytoolは証明書の確認だけでなく、鍵ペアの生成やCSR発行までこなせる多機能なコマンドです。
「確認だけしたい」なら本記事の-list/-printcertだけで十分ですが、他の場面で目にするコマンドも簡単に紹介しておきます。
-genkeypair:自己署名証明書と公開鍵・秘密鍵のペアを新規作成する-certreq:認証局(CA)に提出するCSR(証明書署名要求)を発行する-exportcert:キーストア内の証明書を単体の証明書ファイルとしてエクスポートする
証明書エラーの調査で使うkeytoolは、ほぼ-list/-printcert/-importcert/-deleteの4つです。
サーバー証明書を自分で発行・更新する立場になったら、上記3コマンドも覚えておくと迷いません。
keytoolでcacertsの証明書を確認するには?
Javaのルート証明書を確認するには、keytoolというコマンドを使用します。
Javaの証明書ストアはバイナリ形式のファイルであり、テキストエディタで開いても中身を解読できないからです。
証明書一覧の表示コマンドとデフォルトパスワード
証明書の一覧を表示するには、以下のコマンドを使用します。
keytool -list -keystore "cacertsファイルのパス" -storepass changeit
-storepassに渡すパスワードにも注意してください。
Java17以前のcacertsのパスワードは「changeit」です。Java18以降のcacertsはパスワードなしのPKCS12になり、-storepassにどんな値を渡しても読み取れます。
直訳すると「これを変えろ」という意味です。慣習として手順書は-storepass changeitと書くことが多く、この記事のコマンドもそれに合わせています(OpenJDK 23.0.1では、changeitを指定した一覧表示と証明書の追加のどちらも動作を確認しました)。Java18以降の-cacertsは、-storepassを省略しても一覧できます。
もし詳細な情報(有効期限や署名アルゴリズムなど)が見たい場合は、-v(verbose)オプションを追加します。
keytool -list -v -keystore "cacertsファイルのパス" -storepass changeit
登録されているすべての証明書が、ずらりと表示されます。
特定の証明書を探したいときは、Windowsならfindstr、MacやLinuxならgrepコマンドと組み合わせると便利です。
実行すると、以下のような形式で証明書が一覧表示されます(-vなしの場合の出力例)。
キーストアのタイプ: PKCS12
キーストア・プロバイダ: SUN
キーストアには112エントリが含まれます
digicertglobalrootg2 [jdk],2026/09/27, trustedCertEntry,
証明書のフィンガプリント(SHA-256): CB:3C:CB:B7:60:31:E5:E0:...
letsencryptisrgx1 [jdk],2026/09/27, trustedCertEntry,
証明書のフィンガプリント(SHA-256): 96:BC:EC:06:26:49:76:F3:...
「エントリが含まれます」の件数は、Javaのバージョンやディストリビューションによって前後します(手元のOpenJDK 23.0.1では112、Corretto 21.0.5では161でした)。日付も環境によって異なります。上の出力例は、OpenJDK 23.0.1(日本語表示)の実行結果です。
目的の証明書を探すときは、エイリアス名(1行目のletsencryptisrgx1 [jdk]のような部分。[jdk]まで含めてエイリアス名です)でgrep/findstrすると早いです。
証明書ファイルの中身(Subject・Issuer・期限)を読む
キーストア全体を一覧するのではなく、特定の証明書ファイル(.cer/.pem)の中身だけを確認したいときは、keytool -printcert が便利です。
keytool -printcert -file server.cer
これだけで Owner(Subject)・Issuer・Valid from: … until: …(有効期間)・SHA-256フィンガープリントが表示されます(日本語環境では「所有者」「発行者」「有効期間の開始日/終了日」)。
フィンガープリントは公式サイトの値と照合するためにも必須です。
リモートサーバーの証明書を取得して中身を見たい場合は、openssl s_client と組み合わせるのが定番です。
openssl s_client -connect example.com:443 -showcerts < /dev/null | openssl x509 -outform DER > server.cer
keytool -printcert -file server.cer
「証明書をブラウザでエクスポートする」のではなく、ターミナルだけで完結するため、サーバー上で確認するときに重宝します。
cacertsファイルの場所
cacertsファイルは、Javaのバージョンによって格納場所が微妙に異なります。
Java8以前と、Java9以降でフォルダ構成が変わったためです。ここを間違えると「ファイルが見つかりません」というエラーが出ます。
以下に代表的なOSとバージョンの組み合わせごとのパスを示します。
Windows10 / Windows11 の場合- Java8以前:
C:\Program Files\Java\jdk1.8.0_xx\jre\lib\security\cacerts - Java11以降(Java17/Java21/Java25 LTS):
C:\Program Files\Java\jdk-25\lib\security\cacerts(2025年9月リリースのJava25が現行LTS。Java21ならjdk-21、Java17ならjdk-17、Java11ならjdk-11)
- Java8以前:
/Library/Java/JavaVirtualMachines/jdk1.8.0_xx.jdk/Contents/Home/jre/lib/security/cacerts - Java11以降(Java17/Java21/Java25 LTS):
/Library/Java/JavaVirtualMachines/jdk-25.jdk/Contents/Home/lib/security/cacerts(現行LTSのJava25。Java21ならjdk-21.jdk、Java17ならjdk-17.jdk)
- 多くのディストリビューションでは、
/etc/pki/java/cacertsや/usr/lib/jvm/java-xx-openjdk/lib/security/cacertsにシンボリックリンクが貼られています。
Java9以降はJEP 220(Modular Run-Time Images)により独立したJREディストリビューションが廃止され、jreフォルダが消えました。
そのためcacertsは$JAVA_HOME/lib/security/cacertsに直接配置されます。
使用中のJavaが参照しているキーストアを調べる方法
複数のJavaがインストールされている環境では、どのcacertsを見ているか確認が必要です。
環境変数JAVA_HOMEの設定と、実際に動いているjavaコマンドのパスが異なっていることがよくあるからです。
以下のコマンドで、現在アクティブなJavaのホームディレクトリを表示するのがもっとも確実です。
java -XshowSettings:properties -version 2>&1 | findstr "java.home"
※ Mac/Linuxの場合は findstr を grep に置き換えてください。
ここで表示されたパスの下にある lib/security/cacerts が、現在使われている正解のファイルです(Java 8のJDKでは java.home 自体が jre フォルダを指すため、同じく lib/security/cacerts を見ればOKです)。
java.homeを確認せずに作業すると、「証明書を追加したのに反映されない」というトラブルに直面します。
cacertsの証明書の有効期限を確認するには?
ルート証明書は永久に有効ではありません。
多くは20〜30年で期限切れとなり(手元のOpenJDK 23.0.1の112件では、有効期間の中央値が約25年、最短約10年・最長約37年)、ある日突然「TLSハンドシェイクが失敗するようになった」というトラブルの原因になります。
cacerts内の各証明書の有効期限を確認するには、-v オプションを付けて一覧します。
# macOS / Linux
keytool -list -v -keystore "$JAVA_HOME/lib/security/cacerts" -storepass changeit | grep -E "Alias name|Valid"
英語表示の環境では、Alias name: ... と Valid from: ... until: ... がペアで表示されます。日本語環境では 別名: ... と 有効期間の開始日: ... 終了日: ... になり、上の grep では何も出ません。その場合は grep -E "別名|有効期間" に変えるか、keytool -J-Duser.language=en ... で英語表示に固定してください。
「特定の年(たとえば2027年)に切れる証明書」だけ抽出したい場合は、後続のスクリプトで until: ... 2027 を grep するのが手軽です。
JDKのアップデートで cacerts が刷新されると、期限切れ証明書は自動的に削除・差し替えされます。
古いJDKを長期間使い続けている環境では、まずこのコマンドで「いつ切れる証明書を抱えているか」を可視化することが、サイレント障害の予防につながります。
プログラム内からルート証明書を確認する方法
Javaプログラムを実行して、ロードされている証明書を直接出力することもできます。
コマンドでの確認はあくまで「ファイルの中身」の確認であり、実行時に正しく読み込まれているかを保証するものではないからです。
TrustManagerというクラスを使用するコードを書くことで、アプリケーションが実際に信頼している証明書リストをログに出力できます。
開発環境と本番環境で挙動が違う場合など、この方法でデバッグするのが最も確実です。
SSLContext と TrustManager で読み込まれる証明書
Javaのプログラム内でSSL通信を行う際、SSLContextというクラスが中心的な役割を果たします。
このSSLContextは初期化されるときに、デフォルトのTrustManagerを読み込みます。
このTrustManagerこそが、cacertsファイルから証明書をメモリ上に展開して持っている存在です。
プログラムコードからこのTrustManagerにアクセスすることで、現在メモリ上にある=実際に使われている証明書の一覧を取得できます。
TrustManagerから取得すれば、起動オプション-Djavax.net.ssl.trustStoreなどで別のキーストアが指定されていないかも含めて確認できます。
Javaコード例:ロードされた証明書一覧を出力する
以下は、現在有効なTrustManagerからルート証明書のエイリアス(名前)一覧を表示する簡単なサンプルコードです。
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
public class CertCheck {
public static void main(String[] args) throws Exception {
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore) null);
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
X509Certificate[] certs = ((X509TrustManager) tm).getAcceptedIssuers();
System.out.println("読み込まれた証明書数: " + certs.length);
for (X509Certificate cert : certs) {
System.out.println("Subject: " + cert.getSubjectX500Principal().getName());
System.out.println("Issuer: " + cert.getIssuerX500Principal().getName());
System.out.println("-------------------------");
}
}
}
}
}
このコードをコンパイルして実行すれば、JVM既定のTrustManagerが実際に読み込んでいる証明書を確認できます。アプリが独自のSSLContextやトラストストアを組み立てている場合は、そのアプリ側の設定も確認してください。
上のコードから証明書の一覧表示を省き、件数だけ出す形にして、macOS・OpenJDK 23.0.1で実際に動かしました。
起動オプションがなければ、TrustManagerの件数はkeytoolで見たcacertsの件数と一致しました。
一方、空のキーストアを-Djavax.net.ssl.trustStoreで指定すると0件です。この状態でcacertsを編集しても反映されません。「証明書を追加したのに反映されない」ときは、起動オプションを先に疑ってください。
keytool/TrustManager/openssl の使い分け早見表
3つの確認手段はそれぞれ得意分野が違います。使い分けるための早見表を、Java 23.0.1・macOSでの実測をもとにまとめました。
「ファイルを書き換えたのに反映されない」系のトラブルは、JVMが実際に読み込んだ証明書を確かめられるTrustManagerコードが確実です。
「相手サーバーの証明書を疑う」場面ではopenssl s_clientを使い、それ以外の日常確認はkeytoolで済ませると、最短で原因に到達できます。
PKIXエラー(証明書エラー)はなぜ起きる?原因と対処法
証明書エラーが出たら、まずは接続先の証明書がcacertsに入っているかを確かめます。
接続先のサーバーが社内システムや開発環境である場合、公的な認証局ではなく、独自の認証局(オレオレ認証局)を使っていることが多いからです。
エラーログに「unable to find valid certification path」と出ていれば、Javaがその証明書を知らない証拠です。
この場合は、手動で信頼リストに追加します。
ただし、無闇に追加するのではなく、本当に信頼してよい相手かを確認してから行うのが鉄則です。
エラー発生からインポートまでの確認手順を図にすると、次のようになります。
java -XshowSettings:properties -version証明書未登録エラー
最も多い原因は、単純に対象のルート証明書がcacertsに入っていないことです。
公的なWebサイト(GoogleやYahooなど)なら、何もしなくてもつながります。Javaのインストール時に、有名な認証局の証明書が最初から入っているためです。
しかし、社内イントラネットのサーバーや、安価なSSL証明書を使っている場合、Javaのデフォルトリストに含まれていないことがあります。
この場合は、ブラウザで対象サイトの証明書をファイルにエクスポートします。
エクスポートしたファイルをkeytoolでcacertsにインポートすれば接続できます。
「パスの構築に失敗しました」の仕組みと原因
エラーメッセージ「PKIX path building failed」は、証明書のチェーンが完成しなかったことを意味します。
証明書の検証はパズルのようなものです。
サーバーから渡されたピース(サーバー証明書)の親を探し、そのまた親を探し、最終的に自分の手元にある正解ピース(ルート証明書)と合致するかを確かめます。
この途中のピースが欠けていたり、最後のピースが合わなかったりすると、パス(経路)が構築できずにエラーとなります。
中間証明書の欠落(サーバー側の設定漏れ)
PKIXエラーの中で意外と多いのが、Java側ではなく サーバー側が中間証明書を配信し忘れているケースです。
この場合、ブラウザは中間証明書をキャッシュや証明書のAIA(認証局情報アクセス)から補完してしまうため「ブラウザでは開けるのにJavaだけ落ちる」現象が起きます。
原因切り分けには、サーバー側のチェーン配信状況を確認するのが最短です。
openssl s_client -connect example.com:443 -showcerts < /dev/null | grep -E "s:|i:"
結果が「サーバー証明書 1枚しか返さない」なら、サーバー側で中間証明書が組み込まれていないことが確定します。
SSL Labs(https://www.ssllabs.com/ssltest/)でも「Chain issues: Incomplete」と表示されます。
恒久対処は、サーバー管理者に中間証明書(fullchain.pem や CA bundle)を組み込んでもらうことです。
暫定対処として、該当の中間証明書をクライアント側のcacertsにimportcertしておけば通信は通ります。
Let's Encrypt の場合は https://letsencrypt.org/certificates/ から ISRG Root X1/X2 を入手できます。
自己署名証明書への対応
開発環境などでよく使われる「自己署名証明書(オレオレ証明書)」は、デフォルトでは絶対に信頼されません。
誰の承認も受けず、自分で自分を証明している状態だからです。
自己署名証明書を使う場合は、Javaに対して「この証明書は例外的に信頼しろ」と教える必要があります。
具体的には、その自己署名証明書自体をルート証明書としてcacertsにインポートします。
こうすることで、Javaはその証明書を「信頼の起点」として扱うようになり、エラーが解消されます。
証明書を追加する際の危険性とベストプラクティス
証明書をcacertsに追加する際は、セキュリティリスクを理解しておく必要があります。
信頼リストに一度追加すると、その証明書で署名された通信をすべて無条件に信じるためです。
もし悪意のある第三者が作成した証明書を追加してしまうと、通信を盗聴・改ざんされても気づけなくなります。
ベストプラクティスとしては、以下の点を守りましょう。
- 入手元を確認する:メールで送られてきた不明なファイルなどは絶対に追加しない。
- フィンガープリントを照合する:インポート時に表示されるハッシュ値が、正当なものと一致するか確認する。
- 専用のキーストアを使う:可能な限り、システム全体の
cacertsを汚すのではなく、アプリケーション専用のキーストアファイルを用意して読み込ませる。
cacertsのキーストア形式(JKSとPKCS12)の違い
Javaのキーストアには JKS(Java KeyStore)と PKCS12 の2種類が主に使われます(ほかに JCEKS などの形式もあります)。
Java9以降は新規キーストア作成時のデフォルトがPKCS12に変更されました。
- JKS: Java独自形式。古いシステムとの互換性のためだけに残されている
- PKCS12: 業界標準(RFC 7292)。OpenSSLや他言語ともそのまま相互利用できる
Java8時代に作ったJKSをJava11以降のkeytoolで開くと、こんな警告が出ることがあります。
Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore keystore.jks -destkeystore keystore.p12 -deststoretype pkcs12".
動作上は無視しても問題ありませんが、新規でキーストアを作るならPKCS12を選ぶのが原則です。
既存JKSのPKCS12への変換は、警告メッセージにある keytool -importkeystore 一発で完了します。
cacerts確認でハマりやすいポイントTOP3
証明書エラーで「公式手順は試したのに直らない」と詰まるケースは、だいたい次の3パターンです。最初にこのコマンドを打つだけで切り分けが進みます。
- TOP1:複数JDK環境で、IDEとターミナルが別のjavaを使っている
確認:which javaと IDEの「Project Structure → SDK」のパスが一致しているか - TOP2:
-Djavax.net.ssl.trustStoreを指定しているのに、システムのcacertsを編集している
確認: 起動コマンド/Spring Bootのapplication.yml/JAVA_OPTSで trustStore指定があるか grep - TOP3:アプリや依存ライブラリが独自の
SSLContext/TrustManagerを組んでいて、cacertsを見ていない
確認: ソースと設定でSSLContext・TrustManager・trustStoreを grep し、独自の証明書ストアを読み込んでいないかを疑う
逆に言えば、これらに該当しなければ、JDKのバージョンアップで解決するかを確かめてください。
手当たり次第に importcert する前に、上記3点だけ確認するクセをつけると無駄なkeytool操作を減らせます。
ルート証明書はどう更新する?
ルート証明書の更新は、基本的にはJDKのバージョンアップで行うのが推奨です。
OracleやOpenJDKのコミュニティが、信頼できる認証局のリストを精査し、定期的なアップデートで最新の状態に保ってくれているからです。
古いJDK(例えばJava8の初期パッチなど)を使い続けていると、Let's Encryptのサイトに突然つながらなくなることがあります。
新しいルート証明書(RSA系のメインチェーンであるISRG Root X1や、ECDSA用のISRG Root X2)を持っていないためです。
原因は、Let's Encryptが2024年6月6日にDST Root CA X3とのクロス署名付き証明書の新規発行を止めたことです。同年9月30日には、そのクロス署名自体が完全に失効しました。
それ以降、古いJDKでは自己署名のISRG Root X1を直接信頼している必要があります。
手動での追加はあくまで例外的な対応と考え、基本はJDK全体の更新で対応するのが最も安全で楽な運用です。
JDKアップデートでcacertsが自動更新される仕組み
Javaのアップデートパッケージには、その時点での最新のcacertsファイルが含まれています。
JDKをアップデートすると、古いcacertsは新しいものに置き換えられるか、新しいフォルダにインストールされたJDKが新しいcacertsを使うようになります。
この置き換えによって、世の中で無効化された古い認証局は削除され、新しく認定された認証局が追加される仕組みです。
Java自体の脆弱性修正と証明書の更新が一度に済むため、Javaのアップデートは定期作業として運用に組み込んでおくと安全です。
作業前に必ずcacertsをバックアップする方法
keytoolで証明書を追加・削除する前に、必ず cacerts をバックアップしてください。
誤って必要な証明書を削除してしまうと、バックアップがなければ、同じバージョンのJDKからcacertsを取り直すまで元に戻せなくなります。
# macOS / Linux(タイムスタンプ付きでバックアップ)
sudo cp "$JAVA_HOME/lib/security/cacerts" "$JAVA_HOME/lib/security/cacerts.bak.$(date +%Y%m%d_%H%M%S)"
# Windows(PowerShell)
Copy-Item "$env:JAVA_HOME\lib\security\cacerts" "$env:JAVA_HOME\lib\security\cacerts.bak.$(Get-Date -Format yyyyMMdd_HHmmss)"
本番サーバーで作業する場合は、上記に加えて社外ストレージ(社内Wiki等)にもコピーを残しておくと安心です。
トラブル発生時は、バックアップを元のファイル名に戻すだけで即座にロールバックできます。
手動で証明書を追加/削除する方法(keytool add/delete)
どうしても手動で更新が必要な場合は、importcert(追加)とdelete(削除)コマンドを使います。
keytool -importcert -alias "任意の名前" -file "証明書ファイル.cer" -keystore "cacertsのパス" -storepass changeit
実行すると、証明書のOwner・Issuer・有効期限・フィンガープリントが表示されたあとに、以下のようなプロンプトが出ます。
この証明書を信頼しますか。 [いいえ]: y
証明書がキーストアに追加されました
デフォルトの答えは「いいえ」([いいえ])なので、何も入力せずEnterを押すと証明書は追加されません。
必ずyまたはyesと明示的に入力してください。
ここで表示されるフィンガープリントは、事前にopenssl s_clientやブラウザで確認した値と目視で照合してから承認するのが安全です。
keytool -delete -alias "削除したい名前" -keystore "cacertsのパス" -storepass changeit
削除する際は、エイリアス(名前)が正確である必要があります。事前に-listコマンドで正確なエイリアスを確認してから実行しましょう。
なお、システムのcacertsを編集するにはLinux/macOSではroot権限、Windowsでは管理者権限が必要です。
cacerts直編集とアプリ専用trustStoreの使い分け
「証明書を追加する際、システムのcacertsを直接いじるべきか、アプリ専用のtrustStoreを別途用意すべきか」は迷いやすいポイントです。
次の基準で使い分けるのが基本です。
- 個人開発・社内検証環境:
cacerts直編集でOK。手数が少なく即解決できる - 商用本番・チーム共有のサーバー: アプリ別trustStore一択。JDKを再インストールしても証明書設定が消えず、Infrastructure as Code とも相性が良い
- Docker/Kubernetes 環境: cacertsを毎回書き換える運用は再現性が崩れやすいためです。imageビルド時にtrustStoreを焼き込み、起動オプションで読み込むのが推奨です
「とりあえず動かすならcacerts、運用するならtrustStore」と覚えておくと迷いません。
商用環境では「JDK更新で証明書設定が吹き飛んだ」事故が現実に起きるため、最初からアプリ別trustStoreで始める方が安全です。
cacerts以外のキーストアとJavaバージョン別の違い
Javaが参照するキーストアは、cacerts以外にも環境によって複数あります。「証明書を追加したのに反映されない」ときは、次の4点を順に確認してください。jssecacerts、アプリ専用キーストア、Spring Boot/Tomcatの設定、Javaバージョンごとの違いです。
証明書ストアは複数存在するのか?
はい、複数存在する可能性があります。
Javaシステム全体のデフォルトであるlib/security/cacertsのほかに、代替キーストア(jssecacerts)が存在する場合があるからです。
jssecacertsはJavaインストール直下のlib/security/に作成されるファイルで、存在する場合はcacertsよりも優先されます。
意図せずjssecacertsが作られていて、そちらの古い情報を参照しているためにエラーが直らない、というケースも稀にあります。
アプリケーションごとに異なるキーストアを使える?
はい、使えます。
Javaアプリケーションを起動する際のオプションで指定可能です。
-Djavax.net.ssl.trustStore=/path/to/mykeystore
-Djavax.net.ssl.trustStorePassword=mypassword
この方法を使えば、システム全体のcacertsを書き換えることなく、そのアプリ専用の証明書設定を持たせられます。
権限の問題でシステムファイルを触れない場合などに有効です。
Spring Boot/Tomcatで独自キーストアを指定する方法
フレームワーク利用時にシステム全体の cacerts ではなくアプリ専用キーストアを使うパターンは、用途別に設定箇所が異なる点に注意してください。
外向き(HTTPSクライアント)と内向き(mTLSサーバー)でキーが別物です。
外向きHTTPSクライアント(RestTemplate/WebClient等):JVM起動オプションで指定# JVM システムプロパティで指定(JAVA_OPTS を読むのは Tomcat の catalina.sh など。java -jar で起動するときは java $JAVA_OPTS -jar app.jar のように渡す)
export JAVA_OPTS="-Djavax.net.ssl.trustStore=/opt/app/my-truststore.p12 -Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.ssl.trustStoreType=PKCS12"
内向きmTLS(クライアント証明書認証を要求するサーバー側):Spring Bootのserver.ssl.*
# application.properties — 組み込みTomcatがクライアント証明書を検証する用途
server.ssl.client-auth=need
server.ssl.trust-store=classpath:my-truststore.p12
server.ssl.trust-store-password=changeit
server.ssl.trust-store-type=PKCS12
「外部APIをHTTPSで叩いたらPKIXエラー」のときに server.ssl.trust-store をいじっても効きません。
server.ssl.trust-storeは、組み込みサーバーがクライアント証明書を検証するときのトラストストアです。アウトバウンド通信には適用されません。
外向きの解決策はJVMシステムプロパティ(-Djavax.net.ssl.trustStore)か、各HTTPクライアントにSSLContextを注入する方法です。
この方式ならシステムの cacerts を汚さず、デプロイのたびに自動で正しいキーストアが読み込まれます。
Javaバージョン別の管理差異
基本的なコマンド操作や仕組みは変わりませんが、ファイルの配置場所と最初から含まれている証明書の種類が異なります。2025年9月にリリースされたJava25が、2026年9月時点で現行のLTS版です(同月リリースのJava27は非LTSです)。
Java11/Java17/Java21/Java25といった新しいLTSバージョンでは、ディレクトリ構成が整理されています。
また、MD5は古くから無効化されています。JDK標準のルート証明書に連なるSHA-1署名済みTLSサーバー証明書チェーンのデフォルト拒否は、2019年1月リリースの 8u201/11.0.2 以降で jdk.certpath.disabledAlgorithms に追加されました(Java17以降は最初から有効です)。
TLS 1.0/1.1 のデフォルト無効化は Java 8u291/11.0.11(2021年4月)以降です。
MD5・SHA-1・TLS 1.0/1.1の制限は、Java 21固有の挙動ではなく、Java25を含むこれより新しい環境すべてに共通します。古いサーバーへの接続失敗の典型的な原因です。
Java8で動いていた証明書がJava17でエラーになる場合は、配置場所だけでなく、証明書の暗号強度が現在のセキュリティ基準を満たしているかも確認が必要です。
バージョンごとの確認・切り替えコマンドは以下の記事にまとめています。
よくある質問
cacertsの確認や証明書エラーについて、よく聞かれる質問をまとめました。
Q1. cacertsとは何ですか?
A1. cacertsとは、Javaが標準で信頼するルート証明書を格納しているキーストアファイルのことです。JavaのSSL/TLS通信で「この証明書を信頼していいか」を判断する際の基準になります。
Q2. cacertsの読み方は?
A2. 「シーエーサーツ」または「カサーツ」と読みます。Certificate Authority certificatesの略で、公式な読み方は定められていません。
Q3. cacertsのデフォルトパスワードは何ですか?
A3. Java17以前は「changeit」です。Java18以降のcacertsはパスワードなしのPKCS12で、任意の値(慣習的にchangeit)を渡しても、-storepassを省略しても読み取れます。
Q4. cacertsファイルはどこにありますか?
A4. Java11以降では$JAVA_HOME/lib/security/cacerts(Windowsは%JAVA_HOME%\lib\security\cacerts)にあります。Java8以前はjre/lib/security/cacertsのようにjreフォルダの中に配置されている点が異なります。
Q5. PKIXエラー(PKIX path building failed)はどう解決しますか?
A5. 証明書チェーンが途切れていることが原因です。サーバー側の中間証明書配信漏れか、Java側にルート証明書が未登録かのいずれかを疑い、openssl s_clientでチェーンを確認したうえで、必要な証明書をkeytool -importcertでcacertsに追加します。
Q6. jssecacertsとcacertsの違いは何ですか?
A6. どちらもJavaのキーストアファイルですが、jssecacertsが存在する場合はcacertsより優先して読み込まれます。意図せず作成された古いjssecacertsが原因でエラーが直らないケースもあるため、両方の存在を確認してください。
Q7. cacertsの中身はどのコマンドで確認できますか?
A7. Java9以降はkeytool -list -cacerts -storepass changeitで、証明書の一覧を表示できます。Java8以前は-cacertsの代わりに-keystoreでcacertsのパスを指定します。有効期限まで見たいときは-vを追加します。
Q8. 証明書を追加したのにJavaに反映されないのはなぜですか?
A8. 見ているcacertsと、実際に使われているものが違うことが原因になりやすいです。java -XshowSettings:properties -versionでjava.homeを確認し、起動オプションの-Djavax.net.ssl.trustStoreで別のキーストアを指定していないかも見てください。手元のOpenJDK 23.0.1では、空のキーストアを指定するとTrustManagerが読む証明書は0件でした。
まとめ:cacerts確認の基本
Javaのルート証明書にまつわるトラブルは難解に見えますが、押さえるべきポイントは実はシンプルです。
問題の多くは「見ているファイルが違う」か「証明書が入っていない」のどちらかだからです。
- 場所の特定:
java.homeプロパティで実際に使われているパスを確認する。 - 中身の確認:
keytool -listで対象の証明書があるかを見る。 - 追加の対応: 足りなければ
keytool -importcertで追加する。
次に「PKIX path building failed」が出たら、冒頭の2コマンドでjava.homeとcacertsの中身を確認し、足りない証明書だけをimportcertしてください。
それでも直らないときは「cacerts確認でハマりやすいポイントTOP3」の3点を疑うと、原因にたどり着けます。
| REV. | DATE | 内容 |
|---|---|---|
| 6 | 2026-10-19 | 同じ説明の繰り返しを減らし、読みやすく整えた |
| 5 | 2026-10-15 | 図解を描き直し(図面のデザインにそろえた) |
| 4 | 2026-09-27 | 2026年9月時点の情報で全体を見直し(古い記述を2件更新) |
| 3 | 2026-08-22 | 2026年8月時点の情報で全体を見直し |
| … ほか1回の改訂 | ||
| 1 | 2025-11-28 | 初版 |








