Kegagalan jabat tangan bisa terjadi karena berbagai alasan:
- Suite sandi yang tidak kompatibel digunakan oleh klien dan server. Ini akan mengharuskan klien untuk menggunakan (atau mengaktifkan) suite sandi yang didukung oleh server.
- Versi SSL yang tidak kompatibel sedang digunakan (server mungkin hanya menerima TLS v1, sementara klien hanya mampu menggunakan SSL v3). Sekali lagi, klien mungkin harus memastikan bahwa ia menggunakan versi protokol SSL / TLS yang kompatibel.
- Jalur kepercayaan tidak lengkap untuk sertifikat server; sertifikat server mungkin tidak dipercaya oleh klien. Ini biasanya menghasilkan kesalahan yang lebih banyak, tetapi sangat mungkin. Biasanya perbaikannya adalah mengimpor sertifikat CA server ke toko kepercayaan klien.
- Sertifikat dikeluarkan untuk domain yang berbeda. Sekali lagi, ini akan menghasilkan pesan yang lebih jelas, tetapi saya akan menyatakan perbaikannya jika ini penyebabnya. Resolusi dalam hal ini adalah mendapatkan server (tampaknya bukan milik Anda) untuk menggunakan sertifikat yang benar.
Karena, kegagalan mendasar tidak dapat ditunjukkan, lebih baik untuk mengaktifkan -Djavax.net.debug=all
flag untuk mengaktifkan debugging koneksi SSL yang dibuat. Dengan debug diaktifkan, Anda dapat menentukan aktivitas apa yang gagal dalam jabat tangan.
Memperbarui
Berdasarkan perincian yang sekarang tersedia, tampaknya masalahnya disebabkan oleh jalur perwalian sertifikat yang tidak lengkap antara sertifikat yang dikeluarkan ke server, dan root CA. Dalam kebanyakan kasus, ini karena sertifikat CA root tidak ada di toko kepercayaan, yang mengarah ke situasi di mana jalur kepercayaan sertifikat tidak ada; sertifikat pada dasarnya tidak dipercaya oleh klien. Browser dapat memberikan peringatan sehingga pengguna dapat mengabaikan ini, tetapi hal yang sama tidak berlaku untuk klien SSL (seperti kelas HttpsURLConnection , atau perpustakaan Klien HTTP seperti Klien Apache HttpComponents ).
Sebagian besar kelas / pustaka klien ini akan bergantung pada toko kepercayaan yang digunakan oleh JVM untuk validasi sertifikat. Dalam kebanyakan kasus, ini akan menjadi cacerts
file di direktori JRE_HOME / lib / security. Jika lokasi toko kepercayaan telah ditentukan menggunakan properti sistem JVM javax.net.ssl.trustStore
, maka toko di jalur itu biasanya yang digunakan oleh perpustakaan klien. Jika Anda ragu, lihat Merchant
kelas Anda , dan cari tahu kelas / pustaka yang digunakannya untuk membuat koneksi.
Menambahkan sertifikat server yang mengeluarkan CA ke toko kepercayaan ini harus menyelesaikan masalah. Anda dapat merujuk ke jawaban saya pada pertanyaan terkait tentang cara mendapatkan alat untuk tujuan ini, tetapi utilitas Java keytool cukup untuk tujuan ini.
Peringatan : Toko kepercayaan pada dasarnya adalah daftar semua CA yang Anda percayai. Jika Anda memasukkan sertifikat yang bukan milik CA yang tidak Anda percayai, maka koneksi SSL / TLS ke situs yang memiliki sertifikat yang dikeluarkan oleh entitas itu dapat didekripsi jika kunci privat tersedia.
Pembaruan # 2: Memahami output dari jejak JSSE
Keystore dan truststores yang digunakan oleh JVM biasanya terdaftar di awal, agak seperti yang berikut:
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 :
Jika truststore yang salah digunakan, maka Anda harus mengimpor kembali sertifikat server ke yang benar, atau mengkonfigurasi ulang server untuk menggunakan yang terdaftar (tidak disarankan jika Anda memiliki beberapa JVM, dan semuanya digunakan untuk berbagai kebutuhan).
Jika Anda ingin memverifikasi apakah daftar sertifikat kepercayaan berisi sertifikat yang diperlukan, maka ada bagian yang sama, yang dimulai dengan:
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
Anda harus mencari apakah CA server adalah subjek.
Proses jabat tangan akan memiliki beberapa entri yang menonjol (Anda harus tahu SSL untuk memahaminya secara detail, tetapi untuk tujuan debugging masalah saat ini, cukuplah untuk mengetahui bahwa handshake_failure biasanya dilaporkan di ServerHello.
1. ClientHello
Serangkaian entri akan dilaporkan ketika koneksi sedang diinisialisasi. Pesan pertama yang dikirim oleh klien dalam pengaturan koneksi SSL / TLS adalah pesan ClientHello, biasanya dilaporkan dalam log sebagai:
*** 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 }
***
Perhatikan cipher suite yang digunakan. Ini mungkin harus setuju dengan entri dalam file merchant.properties Anda, untuk konvensi yang sama mungkin digunakan oleh perpustakaan bank. Jika konvensi yang digunakan berbeda, tidak ada alasan untuk khawatir, karena ServerHello akan menyatakan demikian, jika cipher suite tidak kompatibel.
2. ServerHello
Server merespons dengan ServerHello, yang akan menunjukkan apakah pengaturan koneksi dapat dilanjutkan. Entri dalam log biasanya dari jenis berikut:
*** ServerHello, TLSv1
RandomCookie: GMT: 1291302499 bytes = { some byte array}
Cipher Suite: SSL_RSA_WITH_RC4_128_SHA
Compression Method: 0
***
Perhatikan paket sandi yang telah dipilihnya; suite terbaik ini tersedia untuk server dan klien. Biasanya suite sandi tidak ditentukan jika ada kesalahan. Sertifikat server (dan opsional seluruh rantai) dikirim oleh server, dan akan ditemukan dalam entri sebagai:
*** 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
***
Jika verifikasi sertifikat berhasil, Anda akan menemukan entri yang mirip dengan:
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
Salah satu langkah di atas tidak akan berhasil, sehingga kegagalan handshake_f, untuk handshake biasanya selesai pada tahap ini (tidak benar-benar, tetapi tahap-tahap berikutnya dari handshake biasanya tidak menyebabkan kegagalan handshake). Anda harus mengetahui langkah mana yang gagal, dan memposting pesan yang sesuai sebagai pembaruan untuk pertanyaan (kecuali Anda sudah memahami pesannya, dan Anda tahu apa yang harus dilakukan untuk menyelesaikannya).