Błąd uzgadniania mógł wystąpić z różnych powodów:
- Niezgodne zestawy szyfrów używane przez klienta i serwer. Wymagałoby to od klienta użycia (lub włączenia) zestawu szyfrów obsługiwanego przez serwer.
- Używane niezgodne wersje SSL (serwer może akceptować tylko TLS v1, podczas gdy klient może używać tylko SSL v3). Ponownie, klient może być zmuszony do upewnienia się, że używa kompatybilnej wersji protokołu SSL / TLS.
- Niekompletna ścieżka zaufania dla certyfikatu serwera; certyfikat serwera prawdopodobnie nie jest zaufany przez klienta. Zwykle powodowałoby to bardziej szczegółowy błąd, ale jest całkiem możliwe. Zwykle rozwiązaniem jest zaimportowanie certyfikatu CA serwera do magazynu zaufanych certyfikatów klienta.
- Certyfikat wydawany jest dla innej domeny. Ponownie spowodowałoby to bardziej szczegółowy komunikat, ale podam tutaj poprawkę na wypadek, gdyby to była przyczyna. Rozwiązanie w tym przypadku byłoby takie, aby serwer (nie wygląda na Twój) używał prawidłowego certyfikatu.
Ponieważ nie można wskazać podstawowej awarii, lepiej jest włączyć -Djavax.net.debug=all
flagę, aby umożliwić debugowanie nawiązanego połączenia SSL. Przy włączonym debugowaniu można określić, jakie działanie podczas uzgadniania nie powiodło się.
Aktualizacja
Na podstawie obecnie dostępnych szczegółów wydaje się, że problem jest spowodowany niepełną ścieżką zaufania certyfikatu między certyfikatem wydanym na serwerze a głównym urzędem certyfikacji. W większości przypadków jest to spowodowane brakiem certyfikatu głównego urzędu certyfikacji w magazynie zaufanych certyfikatów, co prowadzi do sytuacji, w której ścieżka zaufania certyfikatu nie może istnieć; certyfikat jest zasadniczo niezaufany przez klienta. Przeglądarki mogą wyświetlać ostrzeżenie, aby użytkownicy mogli to zignorować, ale to samo nie dotyczy klientów SSL (takich jak klasa HttpsURLConnection lub dowolna biblioteka klienta HTTP, taka jak klient Apache HttpComponents ).
Większość tych klas / bibliotek klienta polegałaby na magazynie zaufanych certyfikatów używanym przez maszynę JVM do sprawdzania poprawności certyfikatu. W większości przypadków będzie to cacerts
plik w katalogu JRE_HOME / lib / security. Jeśli lokalizacja zaufanego magazynu została określona przy użyciu właściwości systemowej maszyny JVM javax.net.ssl.trustStore
, wówczas magazyn w tej ścieżce jest zwykle tym, który jest używany przez bibliotekę klienta. Jeśli masz wątpliwości, spójrz na swoją Merchant
klasę i dowiedz się, której klasy / biblioteki używa do nawiązania połączenia.
Dodanie urzędu certyfikacji wystawiającego certyfikat serwera do tego magazynu zaufanych certyfikatów powinno rozwiązać problem. Możesz odnieść się do mojej odpowiedzi na powiązane pytanie dotyczące uzyskiwania narzędzi do tego celu, ale narzędzie Java Keytool jest do tego wystarczające.
Ostrzeżenie : magazyn zaufanych certyfikatów to zasadniczo lista wszystkich zaufanych urzędów certyfikacji. Jeśli umieścisz certyfikat, który nie należy do urzędu certyfikacji, któremu nie ufasz, połączenia SSL / TLS z witrynami posiadającymi certyfikaty wydane przez tę jednostkę mogą zostać odszyfrowane, jeśli klucz prywatny jest dostępny.
Aktualizacja nr 2: Zrozumienie danych wyjściowych śledzenia JSSE
Magazyn kluczy i zaufane magazyny używane przez maszynę JVM są zwykle wymienione na samym początku, podobnie jak poniżej:
keyStore is :
keyStore type is : jks
keyStore provider is :
init keystore
init keymanager of type SunX509
trustStore is: C:\Java\jdk1.6.0_21\jre\lib\security\cacerts
trustStore type is : jks
trustStore provider is :
Jeśli używany jest niewłaściwy magazyn zaufanych certyfikatów, musisz ponownie zaimportować certyfikat serwera do właściwego lub ponownie skonfigurować serwer, aby używał tego wymienionego (niezalecane, jeśli masz wiele maszyn JVM i wszystkie są używane do różnych wymagania).
Jeśli chcesz sprawdzić, czy lista certyfikatów zaufania zawiera wymagane certyfikaty, istnieje sekcja dotycząca tego samego, która zaczyna się jako:
adding as trusted cert:
Subject: CN=blah, O=blah, C=blah
Issuer: CN=biggerblah, O=biggerblah, C=biggerblah
Algorithm: RSA; Serial number: yadda
Valid from SomeDate until SomeDate
Musisz sprawdzić, czy podmiotem jest urząd certyfikacji serwera.
Proces uzgadniania będzie miał kilka istotnych wpisów (musisz znać SSL, aby je szczegółowo zrozumieć, ale w celu debugowania bieżącego problemu wystarczy wiedzieć, że błąd handshake_failure jest zwykle zgłaszany w ServerHello.
1. ClientHello
Seria wpisów zostanie zgłoszona podczas inicjowania połączenia. Pierwszą wiadomością wysłaną przez klienta w konfiguracji połączenia SSL / TLS jest wiadomość ClientHello, zwykle zgłaszana w dziennikach jako:
*** ClientHello, TLSv1
RandomCookie: GMT: 1291302508 bytes = { some byte array }
Session ID: {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA]
Compression Methods: { 0 }
***
Zwróć uwagę na używane zestawy szyfrów. Może to być zgodne z wpisem w pliku merchant.properties, ponieważ ta sama konwencja może być stosowana przez bibliotekę banku. Jeśli zastosowana konwencja jest inna, nie ma powodu do zmartwień, ponieważ ServerHello poinformuje o tym, jeśli zestaw szyfrów jest niekompatybilny.
2. ServerHello
Serwer odpowiada za pomocą ServerHello, które wskaże, czy można kontynuować konfigurację połączenia. Wpisy w dziennikach są zwykle następującego typu:
*** ServerHello, TLSv1
RandomCookie: GMT: 1291302499 bytes = { some byte array}
Cipher Suite: SSL_RSA_WITH_RC4_128_SHA
Compression Method: 0
***
Zwróć uwagę na wybrany zestaw szyfrów; jest to najlepszy pakiet dostępny zarówno dla serwera, jak i klienta. Zwykle zestaw szyfrów nie jest określany, jeśli występuje błąd. Certyfikat serwera (i opcjonalnie całego łańcucha) jest wysyłany przez serwer i znajdowałby się we wpisach jako:
*** Certificate chain
chain [0] = [
[
Version: V3
Subject: CN=server, O=server's org, L=server's location, ST =Server's state, C=Server's country
Signature Algorithm: SHA1withRSA, OID = some identifer
.... the rest of the certificate
***
Jeśli weryfikacja certyfikatu powiodła się, znajdziesz wpis podobny do:
Found trusted certificate:
[
[
Version: V1
Subject: OU=Server's CA, O="Server's CA's company name", C=CA's country
Signature Algorithm: SHA1withRSA, OID = some identifier
Jeden z powyższych kroków nie powiódłby się, powodując błąd handshake_failure, ponieważ uzgadnianie jest zwykle zakończone na tym etapie (nie do końca, ale kolejne etapy uzgadniania zwykle nie powodują niepowodzenia uzgadniania). Musisz dowiedzieć się, który krok się nie powiódł, i opublikować odpowiednią wiadomość jako aktualizację pytania (chyba że już zrozumiałeś komunikat i wiesz, co zrobić, aby go rozwiązać).