[解決済み] JavaはLet's Encryptの証明書をサポートしていますか?
質問
私は、HTTPでリモートサーバー上のREST APIに問い合わせるJavaアプリケーションを開発しています。セキュリティ上の理由から、この通信は HTTPS に切り替えられる必要があります。
現在 暗号化しよう がパブリックベータを開始したので、現在 Java がデフォルトで彼らの証明書で動作するのか (または将来的に動作することが確認されているのか) を知りたいのです。
Let's Encrypt は、その中間 IdenTrust によるクロスサイン を取得しました。これは良いニュースであるはずです。しかし、このコマンドの出力には、これら 2 つのいずれも見当たりません。
keytool -keystore "..\lib\security\cacerts" -storepass changeit -list
信頼できるCAを各マシンに手動で追加できることは知っていますが、私のアプリケーションは無料でダウンロードでき、さらなる設定なしで実行できる必要があるため、箱から出してすぐに動作するソリューションを探しています。私に良い知らせはありますか?
どのように解決するのですか?
[ 2016-06-08 更新 : によると https://bugs.openjdk.java.net/browse/JDK-8154757 によると、IdenTrust CA は Oracle Java 8u101 に含まれる予定です]。
[ 2016-08-05 更新 : Java 8u101 がリリースされ、確かに IdenTrust CA が含まれるようになりました。 リリースノート ]
<ブロッククオート
JavaはLet's Encryptの証明書をサポートしていますか?
はい。Let's Encrypt証明書は、通常の公開鍵証明書にすぎません。Javaはそれをサポートしています( Let's Encrypt証明書の互換性 によると、Java 7 >= 7u111 と Java 8 >= 8u101 の場合)。
JavaはLet's Encryptの証明書をそのまま信用するのでしょうか?
いいえ/それはJVMに依存します。8u66までのOracle JDK/JREのトラストストアには、Let's EncryptのCAもクロス署名したIdenTrustのCAも特に含まれていないのです。
new URL("https://letsencrypt.org/").openConnection().connect();
のような場合、結果は
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException
.
しかし、独自のバリデータを提供したり、必要なルートCAを含むカスタム鍵ストアを定義したり、JVMトラストストアに証明書をインポートすることができます。
https://community.letsencrypt.org/t/will-the-cross-root-cover-trust-by-the-default-list-in-the-jdk-jre/134/10 もこの話題を取り上げています。
実行時にデフォルトのトラストストアに証明書を追加する方法を示すサンプル コードがあります。証明書を追加する必要があります (firefox から .der としてエクスポートされ、クラスパスに配置されます)。
ベースとなるのは Java で信頼できるルート証明書のリストを取得するにはどうすればよいですか? と http://developer.android.com/training/articles/security-ssl.html#UnknownCa
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.TrustManagerFactory;
public class SSLExample {
// BEGIN ------- ADDME
static {
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
Path ksPath = Paths.get(System.getProperty("java.home"),
"lib", "security", "cacerts");
keyStore.load(Files.newInputStream(ksPath),
"changeit".toCharArray());
CertificateFactory cf = CertificateFactory.getInstance("X.509");
try (InputStream caInput = new BufferedInputStream(
// this files is shipped with the application
SSLExample.class.getResourceAsStream("DSTRootCAX3.der"))) {
Certificate crt = cf.generateCertificate(caInput);
System.out.println("Added Cert for " + ((X509Certificate) crt)
.getSubjectDN());
keyStore.setCertificateEntry("DSTRootCAX3", crt);
}
if (false) { // enable to see
System.out.println("Truststore now trusting: ");
PKIXParameters params = new PKIXParameters(keyStore);
params.getTrustAnchors().stream()
.map(TrustAnchor::getTrustedCert)
.map(X509Certificate::getSubjectDN)
.forEach(System.out::println);
System.out.println();
}
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
SSLContext.setDefault(sslContext);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// END ---------- ADDME
public static void main(String[] args) throws IOException {
// signed by default trusted CAs.
testUrl(new URL("https://google.com"));
testUrl(new URL("https://www.thawte.com"));
// signed by letsencrypt
testUrl(new URL("https://helloworld.letsencrypt.org"));
// signed by LE's cross-sign CA
testUrl(new URL("https://letsencrypt.org"));
// expired
testUrl(new URL("https://tv.eurosport.com/"));
// self-signed
testUrl(new URL("https://www.pcwebshop.co.uk/"));
}
static void testUrl(URL url) throws IOException {
URLConnection connection = url.openConnection();
try {
connection.connect();
System.out.println("Headers of " + url + " => "
+ connection.getHeaderFields());
} catch (SSLHandshakeException e) {
System.out.println("Untrusted: " + url);
}
}
}
関連
-
Java コンパイルエラー - スレッド "main" で例外 java.lang.Error: 未解決のコンパイル問題です。
-
org.glassfish.jersey.servlet.ServletContainer
-
[解決済み] JavaでInputStreamを読み込んでStringに変換するにはどうすればよいですか?
-
[解決済み] JavaでNullPointerExceptionを回避する方法
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Java Mapの各エントリを効率的に反復処理するには?
-
[解決済み] Javaでメモリーリークを発生させるにはどうしたらいいですか?
-
[解決済み] JavaでArrayListではなくLinkedListを使用するのはいつですか?
-
[解決済み] Javaはパラメータのデフォルト値をサポートしていますか?
-
[解決済み】Javaではfinallyブロックは必ず実行されるのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
スレッド "main "での例外をEclipseで解決 java.lang.Error: 未解決のコンパイル問題、コンパイラとパッケージの不整合
-
myeclipseでコンパイルするとAntエラーが発生する javaの例外が発生しました。
-
jd-gui Java Exceptionが発生しました。
-
eclipseにプロジェクトをインポートした後、Editorにmain typeが含まれない問題
-
サーブレットクラスのインスタンス化エラーの解決法
-
エラーの解決方法 jarfile XXX.jarにアクセスできません。
-
Java コンパイルエラー - スレッド "main" で例外 java.lang.Error: 未解決のコンパイル問題です。
-
javaでクラスを作成すると、enclosing classでないように見える
-
SocketTimeoutExceptionの解決方法です。読み込みがタイムアウトした
-
java 例外。Javaツールの初期化