自己署名証明書をJavaにインポートして、SSL接続を確立しようとするJavaアプリケーションがこの証明書を信頼するようにしたいのです。
これまでのところ、私はこの証明書を
keytool -import -trustcacerts -noprompt -storepass changeit -alias $REMHOST -file $REMHOST.pem
keytool -import -trustcacerts -noprompt -keystore cacerts -storepass changeit -alias $REMHOST -file $REMHOST.pem
それでも、HTTPSClient.class
を実行しようとすると、やはり以下のようになります。
javax.net.ssl.SSSLHandshakeException: sun.security.validator.ValidatorException.PKIXパスの構築に失敗しました。PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Windowsでは、最も簡単な方法は、プログラムportecleを使用することです。
1.portecleをダウンロードしてインストールします。
1.まず、プログラムの実行に使用されているJREまたはJDKを100%確認してください。64ビットのWindows 7では、かなりの数のJREが使用されている可能性があります。Process Explorerで確認することもできますし、次のような方法もあります。System.out.println(System.getProperty("java.home"));
1.JAVA_HOME_libsecurity\cacertsを別のフォルダにコピーします。
1.PortecleでFile > Open Keystore Fileをクリックします。
1.cacertsファイルを選択する。
1.パスワードを入力する:changeit
1.ツール > 信頼できる証明書のインポート」をクリックする
1.ファイル mycertificate.pem を探す
1.インポート]をクリックする
1.トラストパスに関する警告が表示されるので、[OK]をクリックします。
1.証明書の詳細が表示されるので、OKをクリックする。
1.はい」をクリックして、証明書を信頼できるものとして受け入れる。
1.エイリアスの入力を求められたら「OK」をクリックし、証明書をインポートしたというメッセージが表示されたら再度「OK」をクリックします。
1.保存」をクリックします。これを忘れないようにしないと、変更内容が破棄されます。
1.cacertsファイルを元の場所にコピーする。
**Linuxの場合:***。
すでにSSL証明書を使用しているWebサーバーから、次のようにしてSSL証明書をダウンロードできます。
$ echo -n | openssl s_client -connect www.example.com:443 | \
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/examplecert.crt
オプションで証明書の情報を確認します。
$ openssl x509 -in /tmp/examplecert.crt -text
証明書を Java cacerts キーストアにインポートします。
$ keytool -import -trustcacerts -keystore /opt/java/jre/lib/security/cacerts \
-storepass changeit -noprompt -alias mycert -file /tmp/examplecert.crt
編集します。
最近では、ssls.comから年間5ドルで証明書を入手できるので、証明書をキーストアに追加する必要はあまりありません。念のため、そのようなオプションもあります。
結局、証明書をキーストアに追加する小さなスクリプトを書いたので、より使いやすくなりました。
最新版は https://github.com/ssbarnea/keytool-trust から入手できます。
#!/bin/bash
# version 1.0
# https://github.com/ssbarnea/keytool-trust
REMHOST=$1
REMPORT=${2:-443}
KEYSTORE_PASS=changeit
KEYTOOL="sudo keytool"
# /etc/java-6-sun/security/cacerts
for CACERTS in /usr/lib/jvm/java-8-oracle/jre/lib/security/cacerts \
/usr/lib/jvm/java-7-oracle/jre/lib/security/cacerts \
"/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/security/cacerts" \
"/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/MacOS/itms/java/lib/security/cacerts"
do
if [ -e "$CACERTS" ]
then
echo --- Adding certs to $CACERTS
# FYI: the default keystore is located in ~/.keystore
if [ -z "$REMHOST" ]
then
echo "ERROR: Please specify the server name to import the certificatin from, eventually followed by the port number, if other than 443."
exit 1
fi
set -e
rm -f $REMHOST:$REMPORT.pem
if openssl s_client -connect $REMHOST:$REMPORT 1>/tmp/keytool_stdout 2>/tmp/output </dev/null
then
:
else
cat /tmp/keytool_stdout
cat /tmp/output
exit 1
fi
if sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' </tmp/keytool_stdout > /tmp/$REMHOST:$REMPORT.pem
then
:
else
echo "ERROR: Unable to extract the certificate from $REMHOST:$REMPORT ($?)"
cat /tmp/output
fi
if $KEYTOOL -list -storepass ${KEYSTORE_PASS} -alias $REMHOST:$REMPORT >/dev/null
then
echo "Key of $REMHOST already found, skipping it."
else
$KEYTOOL -import -trustcacerts -noprompt -storepass ${KEYSTORE_PASS} -alias $REMHOST:$REMPORT -file /tmp/$REMHOST:$REMPORT.pem
fi
if $KEYTOOL -list -storepass ${KEYSTORE_PASS} -alias $REMHOST:$REMPORT -keystore "$CACERTS" >/dev/null
then
echo "Key of $REMHOST already found in cacerts, skipping it."
else
$KEYTOOL -import -trustcacerts -noprompt -keystore "$CACERTS" -storepass ${KEYSTORE_PASS} -alias $REMHOST:$REMPORT -file /tmp/$REMHOST:$REMPORT.pem
fi
fi
done