質問

(Java)keytoolを使用して自己署名された証明書を作成しようとしていますが、使用しようとすると、次の例外が得られます(例外全体を参照)。

...<5 more exceptions above this>
Caused by: sun.security.validator.ValidatorException: No trusted certificate found
        at sun.security.validator.SimpleValidator.buildTrustedChain(SimpleValidator.java:304)
        at sun.security.validator.SimpleValidator.engineValidate(SimpleValidator.java:107)
        at sun.security.validator.Validator.validate(Validator.java:203)
        at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)
        at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:841)
        ... 22 more

私はこのコードでこれをバイパスできることを知っています:

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;

HostnameVerifier hv = new HostnameVerifier() {
    public boolean verify(String urlHostName, SSLSession session) {
        System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
        return true;
    }
};

HttpsURLConnection.setDefaultHostnameVerifier(hv);

(ソース)

しかし、私はこのソリューションに興味がありません。なぜなら、それはセキュリティホールを作成すると思うからです。 (私が間違っている場合は私を修正してください)。

誰かが私を正しい方向に向けることができますか?私は今、現時点で地元でテストしているので、物事を変えるのはとても簡単です。サーバーコード、クライアントコード、.keystoreファイルにアクセスできます。

アップデート

クライアントとサーバーの両方に.Keystoreファイルを使用しようとしていましたが、Server.KeyStore(以下を参照)とClient.TrustStore(以下を参照)を作成した問題を簡素化することを期待しています。証明書が正しいと合理的に確信していますが、誰かが確認できれば、私は感謝しています。

server.keystore

hostname[username:/this/is/a/path][711]% keytool -list -keystore server.keystore -v
Enter keystore password:

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: hostname
Creation date: Feb 4, 2010
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=hostname, OU=hostname, O=hostname, L=hostname, ST=hostname, C=hostname
Issuer: CN=hostname, OU=hostname, O=hostname, L=hostname, ST=hostname, C=hostname
Serial number: 4b6b0ea7
Valid from: Thu Feb 04 13:15:03 EST 2010 until: Wed May 05 14:15:03 EDT 2010
Certificate fingerprints:
         MD5:  81:C0:3F:EC:AD:5B:7B:C4:DA:08:CC:D7:11:1F:1D:38
         SHA1: F1:78:AD:C8:D0:3A:4C:0C:9A:4F:89:C0:2A:2F:E2:E6:D5:13:96:40
         Signature algorithm name: SHA1withDSA
         Version: 3


*******************************************
*******************************************

client.truststore

hostname[username:/this/is/a/path][713]% keytool -list -keystore client.truststore -v
Enter keystore password:

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: mykey
Creation date: Feb 4, 2010
Entry type: trustedCertEntry

Owner: CN=hostname, OU=hostname, O=hostname, L=hostname, ST=hostname, C=hostname
Issuer: CN=hostname, OU=hostname, O=hostname, L=hostname, ST=hostname, C=hostname
Serial number: 4b6b0ea7
Valid from: Thu Feb 04 13:15:03 EST 2010 until: Wed May 05 14:15:03 EDT 2010
Certificate fingerprints:
         MD5:  81:C0:3F:EC:AD:5B:7B:C4:DA:08:CC:D7:11:1F:1D:38
         SHA1: F1:78:AD:C8:D0:3A:4C:0C:9A:4F:89:C0:2A:2F:E2:E6:D5:13:96:40
         Signature algorithm name: SHA1withDSA
         Version: 3


*******************************************
*******************************************

アップデート

例外全体を含めると便利だと思いました。

javax.xml.soap.SOAPException: java.io.IOException: Could not transmit message
        at org.jboss.ws.core.soap.SOAPConnectionImpl.callInternal(SOAPConnectionImpl.java:115)
        at org.jboss.ws.core.soap.SOAPConnectionImpl.call(SOAPConnectionImpl.java:66)
        at com.alcatel.tpapps.common.utils.SOAPClient.execute(SOAPClient.java:193)
        at com.alcatel.tpapps.common.utils.SOAPClient.main(SOAPClient.java:280)
Caused by: java.io.IOException: Could not transmit message
        at org.jboss.ws.core.client.RemotingConnectionImpl.invoke(RemotingConnectionImpl.java:192)
        at org.jboss.ws.core.client.SOAPRemotingConnection.invoke(SOAPRemotingConnection.java:77)
        at org.jboss.ws.core.soap.SOAPConnectionImpl.callInternal(SOAPConnectionImpl.java:106)
        ... 3 more
Caused by: org.jboss.remoting.CannotConnectException: Can not connect http client invoker. sun.security.validator.ValidatorException: No trusted certificate found.
        at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:368)
        at org.jboss.remoting.transport.http.HTTPClientInvoker.transport(HTTPClientInvoker.java:148)
        at org.jboss.remoting.MicroRemoteClientInvoker.invoke(MicroRemoteClientInvoker.java:141)
        at org.jboss.remoting.Client.invoke(Client.java:1858)
        at org.jboss.remoting.Client.invoke(Client.java:718)
        at org.jboss.ws.core.client.RemotingConnectionImpl.invoke(RemotingConnectionImpl.java:171)
        ... 5 more
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found
        at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1584)
        at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)
        at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:848)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)
        at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
        at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:877)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1089)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1116)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1100)
        at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:402)
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:170)
        at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:857)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
        at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:288)
        ... 10 more
Caused by: sun.security.validator.ValidatorException: No trusted certificate found
        at sun.security.validator.SimpleValidator.buildTrustedChain(SimpleValidator.java:304)
        at sun.security.validator.SimpleValidator.engineValidate(SimpleValidator.java:107)
        at sun.security.validator.Validator.validate(Validator.java:203)
        at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)
        at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:841)
        ... 22 more
役に立ちましたか?

解決

サーバーとクライアントの間で「信頼を確立する」必要があります(サーバー側の認証を行うだけでいいと思っています)。これは、自己署名証明書を使用するためです。これには、サーバーの証明書をクライアントトラストストアにインポートすることが含まれます。

サーバー側:

keytool -keystore <keystore file> -alias <alias> -export -file <certfilename>.cert

.certファイルをクライアント側にコピーしてから次のようにコピーします。

keytool -keystore <truststore file> -alias <alias> -import -file <certfilename>.cert

他のヒント

キーストアには秘密鍵が含まれているため、クライアントとサーバーの間でキーストアを共有することはできません。認証するとき、クライアントはプライベートキーで証明書をスキップします。上記のように、クライアント側にトラストストアを展開する必要があります。

キーストアの証明書は、それらを生成またはインポートする方法に応じて、同じように動作しません。

インポートされた証明書のエントリタイプ(キーストア全体をverboselyにリストすると見られます -list -v)は「TrustedCertentry」です。生成された証明書のエントリタイプは「privatekeyentry」です。証明書をエクスポートする場合、公開キーとその発行者へのオプションの参照のみをエクスポートするだけです。

キーストアの自己署名証明書をトラストストアの信頼できる証明書としてエクスポートする必要があるようです(ここでは名前が理にかなっています)。

SSL/TLSの実装はおそらくそれをサポートしていないため、私はそれをしません。現実の世界の観点からは、不明瞭なWebサーバーでVerisignから最終的に秘密の秘密鍵を展開してカジュアルなページに署名するようなものです。一方、この秘密鍵の唯一の目的は、安全なままで他の証明書に署名することです。 SSL/TLS実装者は、おそらくそのようなユースケースでコードを汚染することはないでしょう。とにかく、「keyusage」証明書拡張は、証明書の使用量を署名に制限し、エンシファメントを防止する場合があります。

そのため、テスト用の証明書のチェーンを再構築することをお勧めします。

KeyToolドキュメントには、チェーンの作成に関する興味深い部分が含まれています(-gencert コマンド)しかし、それは非常に骨格の例であり、Keystore-Truststoreの関係をカバーしていません。サードパーティ認定機関をシミュレートするために強化しました。

一時的な店 their-keystore.jks 証明書排出機関を表します。の証明書チェーンを供給します ca2 -> ca1 -> caca ルート証明書と見なされる。チェーンは、各非ルート証明書(すなわち、各非ルート証明書)で表示されます ca1ca2)彼らの発行者をとして参照します Certificate[2]. 。すべての証明書は「privatekeyentry」であることに注意してください。

それから私は餌を与えます my-keystore.jks これらの証明書を順番に: ca, ca1, ca2. 。インポートします ca とともに -trustcacerts オプションは、ルート証明書になることを意味します。の my-keystore.jks 現在、輸入された各証明書は「信頼できるCertentry」です。これは、公開キーのみがあることを意味します。発行関係は「発行者」分野にのみ表示されますが、輸入時に信頼関係が最も重要だったため、問題ありません。

この時点で my-keystore.jks 新鮮なJREのような信頼できる証明書を含む環境をシミュレートします。 their-keystore.jks 証明書リクエストに署名する権限を持つ証明書の所有者をシミュレートします。

私も:自己署名証明書を作成します e1my-keystore.jks, 、署名してください ca2 (終えた their-keystore.jks)そして、署名された結果をインポートします my-keystore.jks. e1 まだ「privatekeyentry」です(その秘密鍵はに残っているため my-keystore.jks)しかし、今、私は次のチェーンを構築しました: e1 -> ca2 -> ca1. 。のようだ ca1 -> ca と暗黙的です ca 認定機関であること。

トラストストアを構築するには、証明書をインポートするだけです ca, ca1ca2 私がしたのと同じように my-keystore.jks. 。インポートしないことに注意してください e1, 、SSL/TLSクライアントがそれを検証することを期待しているように ca2.

これは、現実の世界で物事がどのように機能するかをかなり近づいていると思います。ここで素晴らしいのは、証明書を完全に制御し、JREのカカートに依存していないことです。

これが私が実際に言っていることを置くコードです。証明書の取り消しリスト(別の日に残されたトピック)を無効にしている限り、Jetty(クライアントとサーバー)で動作するようです。

#!/bin/bash

rm  their-keystore.jks 2> /dev/null
rm  my-keystore.jks    2> /dev/null
rm  my-truststore.jks  2> /dev/null

echo "===================================================="
echo "Creating fake third-party chain ca2 -> ca1 -> ca ..."
echo "===================================================="

keytool -genkeypair -alias ca  -dname cn=ca                           \
  -validity 10000 -keyalg RSA -keysize 2048                           \
  -ext BasicConstraints:critical=ca:true,pathlen:10000                \
  -keystore their-keystore.jks -keypass Keypass -storepass Storepass

keytool -genkeypair -alias ca1 -dname cn=ca1                          \
  -validity 10000 -keyalg RSA -keysize 2048                           \
  -keystore their-keystore.jks -keypass Keypass -storepass Storepass

keytool -genkeypair -alias ca2 -dname cn=ca2                          \
  -validity 10000 -keyalg RSA -keysize 2048                           \
  -keystore their-keystore.jks -keypass Keypass -storepass Storepass


  keytool -certreq -alias ca1                                            \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass   \
| keytool -gencert -alias ca                                             \
    -ext KeyUsage:critical=keyCertSign                                   \
    -ext SubjectAlternativeName=dns:ca1                                  \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass   \
| keytool -importcert -alias ca1                                         \
    -keystore   their-keystore.jks -keypass Keypass -storepass Storepass

#echo "Debug exit" ; exit 0

  keytool -certreq -alias ca2                                           \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass  \
| keytool -gencert -alias ca1                                           \
    -ext KeyUsage:critical=keyCertSign                                  \
    -ext SubjectAlternativeName=dns:ca2                                 \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass  \
| keytool -importcert -alias ca2                                        \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass

keytool -list -v -storepass Storepass -keystore their-keystore.jks


echo  "===================================================================="
echo  "Fake third-party chain generated. Now generating my-keystore.jks ..."
echo  "===================================================================="
read -p "Press a key to continue."

# Import authority's certificate chain

  keytool -exportcert -alias ca                                         \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass  \
| keytool -importcert -trustcacerts -noprompt -alias ca                 \
    -keystore  my-keystore.jks -keypass Keypass -storepass Storepass

  keytool -exportcert -alias ca1                                        \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass  \
| keytool -importcert -noprompt -alias ca1                              \
    -keystore  my-keystore.jks -keypass Keypass -storepass Storepass

  keytool -exportcert -alias ca2                                        \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass  \
| keytool -importcert -noprompt -alias ca2                              \
    -keystore  my-keystore.jks -keypass Keypass -storepass Storepass

# Create our own certificate, the authority signs it.

keytool -genkeypair -alias e1  -dname cn=e1                        \
  -validity 10000 -keyalg RSA -keysize 2048                        \
  -keystore my-keystore.jks -keypass Keypass -storepass Storepass

  keytool -certreq -alias e1                                            \
    -keystore my-keystore.jks -keypass Keypass -storepass Storepass     \
| keytool -gencert -alias ca2                                           \
    -ext SubjectAlternativeName=dns:localhost                           \
    -ext KeyUsage:critical=keyEncipherment,digitalSignature             \
    -ext ExtendedKeyUsage=serverAuth,clientAuth                         \
    -keystore their-keystore.jks -keypass Keypass -storepass Storepass  \
| keytool -importcert -alias e1                                         \
    -keystore my-keystore.jks -keypass Keypass -storepass Storepass

keytool -list -v  -storepass Storepass -keystore  my-keystore.jks

echo "================================================="
echo "Keystore generated. Now generating truststore ..."
echo "================================================="
read -p "Press a key to continue."

  keytool -exportcert -alias ca                                        \
    -keystore my-keystore.jks -keypass Keypass -storepass Storepass    \
| keytool -importcert -trustcacerts -noprompt -alias ca                \
    -keystore my-truststore.jks -keypass Keypass -storepass Storepass

  keytool -exportcert -alias ca1                                       \
    -keystore my-keystore.jks -keypass Keypass -storepass Storepass    \
| keytool -importcert -noprompt -alias ca1                             \
    -keystore my-truststore.jks -keypass Keypass -storepass Storepass

  keytool -exportcert -alias ca2                                       \
    -keystore my-keystore.jks -keypass Keypass -storepass Storepass    \
| keytool -importcert -noprompt -alias ca2                             \
    -keystore my-truststore.jks -keypass Keypass -storepass Storepass

keytool -list -v  -storepass Storepass -keystore  my-truststore.jks

rm  their-keystore.jks 2> /dev/null

あなたはそれをしてはいけません。キーストアは厳密にプライベートです。誰かに漏れている場合は、セキュリティを致命的に侵害しています。それを機能させるためだけにこの種のことをすることには意味がありません。 そうではありません 動作 - それは単なるセキュリティ侵害です。あなたはそれを正しくしなければなりません:サーバーのキーストアからクライアントのトラストストアに、そしてサーバーのキーストアにある場合はクライアントのキーストアからエクスポートします。

理解できません。クライアントと一緒にサーバーキーストアを使用していますか?あなたのユースケースは正確に何ですか?相互認証をセットアップしようとしていますか?

はいの場合、あなたはここで間違った道を歩んでいます。クライアントキーストア(クライアントの自己署名証明書と秘密キー用)とクライアントトラストストア(サーバーの「スタンドアロン」の自己署名証明書、つまり秘密キーのない)が必要です。どちらもサーバーキーストアとは異なります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top