質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

1149閲覧

OpenJDKのcacertsに登録されていないのに、google.co.jpに接続できます

UserOfJava

総合スコア57

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

1クリップ

投稿2018/07/31 07:38

編集2018/07/31 09:21

前提・実現したいこと

OpenJDK-10.0.2 でhttps接続し、web pageを取得し、加工しようかなと思い
接続テストプログラムを書いています。

発生している問題・エラーメッセージ

OpenJDKのcacertsをkeytoolで一覧表示すると、alias名とsha256のfingerprintの一覧が得られます。
https://www.google.co.jp/のroot certのfingeprintがcacerts一覧にありません。にもかかわらず、テストプログラムでcertの表示と内容のダンプが取れています。おかしいですね。

該当のソースコード

java

1import java.io.*; 2import java.net.*; 3import javax.net.ssl.HttpsURLConnection; 4import java.security.cert.Certificate; 5 6 7 8public class HttpsTest { 9 public static void main(String[] args) { 10 String urlString = args[0]; 11 connectResult(urlString); 12 } 13 14 public static void connectResult(String urlString){ 15 HttpURLConnection urlconn = null; 16 HttpsURLConnection urlconns = null; 17 URL url = null; 18 19 try{ 20 url = new URL(urlString); 21 }catch(Exception e){ 22 System.out.println(e); 23 System.exit(1); 24 } 25 26 try{ 27 urlconn = (HttpURLConnection)url.openConnection(); 28 }catch(Exception e){ 29 System.out.println(e); 30 System.exit(1); 31 } 32 33 try{ 34 urlconn.setRequestMethod("GET"); 35 }catch(Exception e){ 36 System.out.println(e); 37 System.exit(1); 38 } 39 40 try{ 41 urlconn.connect(); 42 }catch(Exception e){ 43 System.out.println(e); 44 System.exit(1); 45 } 46 47 if(urlString.indexOf("https") > -1){ 48 urlconns = (HttpsURLConnection)urlconn; 49 try{ 50 Certificate[] certs = urlconns.getServerCertificates(); 51 for(int i= 0; i < certs.length; i++){ 52 System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); 53 System.out.println(); 54 System.out.println(certs[i].toString()); 55 } 56 }catch(Exception e){ 57 System.out.println(e); 58 System.exit(1); 59 } 60 } 61 62 System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); 63 System.out.println(); 64 readPage(urlconn, "UTF-8"); 65 66 urlconn.disconnect(); 67 68 return; 69 } 70 71 public static void readPage(HttpURLConnection urlconn, 72 String charset){ 73 String line = null; 74 int i = 0; 75 boolean continueFlag = false; 76 77 try{ 78 BufferedReader reader = new BufferedReader( 79 new InputStreamReader(urlconn.getInputStream(),charset)); 80 81 i = 0; 82 continueFlag = true; 83 while (continueFlag){ 84 line = reader.readLine(); 85 if (line == null){ 86 break; 87 } 88 System.out.println(line); 89 } 90 }catch(IOException e){} 91 return; 92 } 93} 94

試したこと

OracleJDK 10.0.2でも同じです。
実行方法は

java HttpsTest https://www.google.co.jp/

です。

補足情報(FW/ツールのバージョンなど)

OpenJDKでもOracleJDKでもcacertsの一覧は以下の方法でできます。

keytool -list -cacerts > certs.txt

public keyのfingerprint(sha256)はEdgeでサイトを見て、鍵の証明書をみるのが一番楽だと思います。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

少々 try - catchが多かったので、以下で検証はしてみましたが、特にキーストアを何もしてないOpenJDK 10.0.2 ではルートCA証明書が入っていないため、

Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at java.base/sun.security.ssl.Alerts.getSSLException(Alerts.java:198) at java.base/sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1974) at java.base/sun.security.ssl.Handshaker.fatalSE(Handshaker.java:345) ....

となり、OracleJDK 10.0.2 では

2018-08-08 22:24:54,276 INFO o.g.a.j.CertificationReader [main] cert : [ [ Version: V3 Subject: CN=*.google.com, O=Google LLC, L=Mountain View, ST=California, C=US Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11 Key: Sun EC public key, 256 bits public x coord: 78226844107172140816602728215785865852948897417762845700219349569937839729710 public y coord: 57412027014253819486192935088276186089146207774631521371630436159824343403818 parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7) Validity: [From: Wed Jul 25 01:08:25 GMT+09:00 2018, To: Wed Oct 03 01:00:00 GMT+09:00 2018] Issuer: CN=Google Internet Authority G3, O=Google Trust Services, C=US SerialNumber: [ 0732f614 c41f4956] Certificate Extensions: 9 [1]: ObjectId: 1.3.6.1.5.5.7.1.1 Criticality=false .....(中略)..... [8]: ObjectId: 2.5.29.14 Criticality=false SubjectKeyIdentifier [ KeyIdentifier [ 0000: 77 C2 B8 50 9A 67 76 76 B1 2D C2 86 D0 83 A0 7E w..P.gvv.-...... 0010: A6 7E BA 4B ...K ] ] ] Algorithm: [SHA256withRSA] Signature: 0000: 1C B7 89 96 E4 53 ED BB EC DB A8 32 01 9F 2C A3 .....S.....2..,. 0010: CD 6D AD 42 12 77 B3 B8 E6 C9 03 52 60 20 7B 57 .m.B.w.....R` .W 0020: 27 C6 11 B5 3F 67 0D 99 2C 5B 5A CA 22 0A DD 9E '...?g..,[Z."... 0030: BB 1F 4B 48 3F 8F 02 3D 8B 21 84 45 1D 6D F5 FF ..KH?..=.!.E.m.. 0040: AC 68 89 CD 64 E2 D6 D6 5E 40 C2 8E 2A F7 EF 14 .h..d...^@..*... 0050: D3 36 A4 40 30 F5 32 15 15 92 76 FB 7E 9E 53 EA .6.@0.2...v...S. 0060: C2 76 FC 39 AD 88 FE 66 92 26 E9 1C C4 38 CD 49 .v.9...f.&...8.I 0070: FA 43 87 F0 5D D6 56 4D 81 D7 7F F1 C2 DD B0 4D .C..].VM.......M 0080: FE C3 2A 6E 7C 9F 6E 5C ED 62 42 99 E1 F7 36 EE ..*n..n.bB...6. 0090: 14 8C 2C 20 E3 46 97 5A 77 03 C0 A0 C6 4A 88 FD .., .F.Zw....J.. 00A0: 40 22 87 72 5A 18 EA 9C A5 C7 5A 08 8C E4 05 A4 @".rZ.....Z..... 00B0: 7D B9 84 35 5F 89 36 56 0E 40 3D 12 E8 BB 35 72 ...5_.6V.@=...5r 00C0: ED AF 08 56 4E B0 BB 2E A9 9B E4 FB 1D 3E 0B 63 ...VN........>.c 00D0: C8 9B 4B 91 44 66 57 C0 14 B4 96 F0 DC 2C 57 3F ..K.DfW......,W? 00E0: 52 04 AD 95 AA 7D 4D D0 F2 0C 9F 9C 40 E8 D6 55 R.....M.....@..U 00F0: 73 BA 3C DF 90 CB 00 5B 21 11 67 C2 ED 32 1E DE s.<....[!.g..2.. ]

と取得できていますので、Javaランタイム実行時のパスがOracleJDKを指定しているのではないでしょうか。

以下は検証コードです。(ログ出力用にlombok 1.18.0を利用)

java

1package org.github.apz.java10sample; 2 3import java.io.IOException; 4import java.net.URL; 5import java.net.URLConnection; 6import java.security.cert.Certificate; 7import java.util.Arrays; 8 9import javax.net.ssl.HttpsURLConnection; 10 11import lombok.extern.log4j.Log4j2; 12 13/** 14 * @author a-pz 15 * 16 */ 17@Log4j2 18public class CertificationReader { 19 public void connect(String inputUrl) throws IOException { 20 URL url = new URL(inputUrl); 21 22 URLConnection urlConnection = url.openConnection(); 23 HttpsURLConnection https = (HttpsURLConnection)urlConnection; 24 https.setRequestMethod("GET"); 25 https.connect(); 26 27 Certificate[] certs = https.getServerCertificates(); 28 29 Arrays.stream(certs).forEach(cert -> { 30 log.info("cert : {}", cert.toString()); 31 }); 32 33 https.disconnect(); 34 } 35 36 public static void main(String argv[]) throws Exception { 37 CertificationReader certReader = new CertificationReader(); 38 certReader.connect("https://www.google.co.jp"); 39 } 40}

投稿2018/08/08 13:27

A-pZ

総合スコア12011

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

UserOfJava

2018/08/09 00:53

こんな質問にわざわざ答えて頂いて、感謝します。同じWin10 PCにOpenJDKとOracleJDKを同居させているので、Windows側の作ったPathを完全に削除していなかったのが原因のようです。これらPathを削除し、改めてOpenJDK配下でやると、エラーが表示され、cacerts通りの結果になっています。 一方、OracleJDKのcacertsを確認すると、google.co.jpのrootのglobalsignr2caのfinger printが確認でき、google.co.jpサイトからコンテンツが取れました。 ご指摘がなければ、Windows側のPath削除については気が付かなかったと思います。誠にすっきりしたコードでの検証、勉強になります。Javaの書き方の進化について行っていないのはお許し下さい。
UserOfJava

2018/08/09 05:00

確かに、OpenJDK環境でgoogle.co.jpはエラーがでるようになったのですが、同じ環境でkeytool -list -cacerts で出力結果を見ての質問だったのですが、このcacertsの出力はOpenJDKのpathのlib/security/cacertsの一覧だったのです。javaで実行すると、たまたま残渣で残っていたwin側の設定を手繰って、OracleJDKのcacertsを見に行ってくれて、keytoolの場合は違うとは、なかなか納得の行かないところです。
A-pZ

2018/08/09 15:31

確かに、keytoolは独立したツールではあるのですが、同じパッケージからの提供物なのだから見てもいいのではないか…?と思うところはありますね…。
UserOfJava

2018/08/10 02:31

keytoolの-cacertsオプションは自パッケージのみを対象にしているが、私のプログラムの実行では、すべてのpathのcacertsを探索しての接続の仕様になっているのかな?と考えると分かるように思えるのですが。 Windowsのpathの見落としで変な質問をしてしまいました。try/catchを動作ごとにつけているのは、まだHttp(s)URLConnectionまわりでのExceptionの出方が分からないので書いているだけです。Exceptionにしているのは、結構2つ以上のExceptionが発生することもあるので、めんどくさいのでIOExcelptionだけでなく、catchできるように考えたからです。 まだ、この辺の動作を探っている段階です。
UserOfJava

2018/08/10 02:35

keytoolでGlobalSign root CA 2 をimportしたら、www.goolg.co.jpは接続できています。OpenJDKのcacertsはまずは80個で結構漏れが多いので用心です。
guest

0

OpenJDKのcacertsをkeytoolで一覧表示すると、alias名とsha256のfingerprintの一覧が得られます。

いまgoogle.co.jpのドメインをSSL Testにかけてみたところ、ルート証明書のハッシュはSHA-1でした。SHA-256のリストと符合しないのも、そういう理由ではないでしょうか。

なお、ルート証明書の真正性はこのハッシュで確認するわけではないので、SHA-1であっても特に問題はありません(過去の質問)。

投稿2018/07/31 08:07

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

UserOfJava

2018/07/31 08:53

すみません。書き方が悪かったのでと思います。cacertsの一覧にpublic keyのfingerprintが便宜上表示され、それでcertを区別しています。cacertsのalias名は適当なので、certsの区別にsha256にfingerprintを使って、識別しているだけです。おっしゃる通りgoogleのroot certの署名アルゴリズムはsha-1です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問