2013-12-20

2013-12-20 19:05

サーバ間のSSL通信を行う際に、相手サーバのSSLを対応しているルート証明書が必要とされます。
相手のサーバのSSLが1024bitから2048bit版に変更された際にも、2048bitに対応したルート証明書が必要です。
今回は、Keytoolを利用してサーバにルート証明書を追加する方法について整理してみました。

該当のSSLに対応しているか確認する

確認する方法:該当のSSLが入っているURLにサーバから接続して、問題なく該当のページが取得できるかどうかを見る

該当のSSLが入っているURLは以下の方法で取得できます。
1.相手サーバのURL(既に相手のサーバの証明書が更新された場合)
2.WEBサイトにてゲット
  例)verisignの場合はhttps://www.verisign.co.jp/developer/step03.htmlでテストが出来ます。

サーバから相手のサーバにURLで接続するサンプルを作って見ました。(JSP)
以下のサンプルはverisignサイトの「VeriSign Class 3 Public Primary Certification Authority - G5」SSLが設置されているURLに接続するロジックです。

<%-- page content type & import --%>
<%@ page contentType="text/xml; charset=UTF-8" %>
<%@ page import="java.io.*, java.util.*, java.sql.*, java.net.*, java.text.*" %>

<%-- common Header & Initialzation --%>
<%!
public String readURL(String urlPage, String method, String param, boolean isNewLine) throws Exception {
 //SEND
 URL url = null;
 HttpURLConnection urlConn = null;
 String suffix = isNewLine ? "\n" : "";

 url = new URL(urlPage);
 urlConn = (HttpURLConnection)url.openConnection();

 byte[] sendByte = new String(param).getBytes();
 urlConn.setDefaultUseCaches(false);
 urlConn.setDoInput(true);
 urlConn.setDoOutput(true);
 urlConn.setRequestMethod(method);
 urlConn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
 DataOutputStream out = null;
 out = new DataOutputStream(urlConn.getOutputStream());
 out.write(sendByte);
 out.flush();

 //RECIEVE
 BufferedReader reader=null;
 String line = null;
 String result = "";
 try {
  reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
  while ((line = reader.readLine()) != null) {result += line + suffix;}
 } finally {if (reader != null) {reader.close();}}

 return result;
}
%>


<%
/*********************************************
 * MAIN LOGIC
 *********************************************/
out.clear();
 
try {
/*
以下のページにてURL取得
https://www.verisign.co.jp/developer/step03.html
*/
 out.println(readURL("https://ssltest6.verisign.co.jp/", "POST", "", true));

} catch(Exception ex) {
 System.out.println(new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date()) + " [ERROR] " + ex.getMessage());
 ex.printStackTrace();
}
%>


Tomcatに以下のようなエラーが発生した場合は、該当のルート証明書を追加する必要があります。
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

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

Keytoolを利用してルート証明書を追加する

ルート証明書を提供しているサイトにてルート証明書をダウンロードします。
例)https://www.symantec.com/page.jsp?id=roots
$ wget http://www.verisign.com/repository/roots/root-certificates/PCA-3G5.pem

設置されているJavaの経路を確認し、keytoolコマンドで証明書を追加します。
Javaの経路確認
# whereis java

Javaが複数設置されている場合は、必ず現在利用中のJavaに追加する必要があります。
# java -version

keytoolを利用してダウンロードした証明書を追加
形式:keytool -import -alias ”別名(小文字)” -keystore ”Keyストアのパス指定” -file ”ダウンロードしたルート証明書の経路を指定”

# keytool -import -alias verisign_class3_g5_2048 -keystore /usr/local/jdk/jre/lib/security/cacerts -file /home/test/PCA-3G5.pem
Enter keystore password:
Owner: CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU="(c) 2006 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US

…省略…

#4: ObjectId: 1.3.6.1.5.5.7.1.12 Criticality=false

Trust this certificate? [no]:  yes
Certificate was added to keystore
Certificate was added to keystoreメッセージが出力されたらOK
※Keyストアのパスは基本的にJavaのホームディレクトリのjre/lib/security/cacertsになります。
※keytoolのDefaultパスワードはchangeitです。

追加したルート証明書を確認してみます。

# keytool -list -v -keystore /usr/local/jdk/jre/lib/security/cacerts -alias verisign_class3_g5_2048 -storepass changeit

aliasオプションを削除すると、該当のキーストアに登録されているすべてのリストが確認できます。

ルート証明書の追加が完了されたら、Tomcatを再起動してください。
※Tomcatを再起動しないと追加した証明書が反映されないので、必ずTomcatの再起動を行ってください。

0 コメント:

コメントを投稿