Saya cukup baru di sini HTTPS/SSL/TLS
dan saya agak bingung tentang apa yang seharusnya disajikan oleh klien saat mengautentikasi dengan sertifikat.
Saya sedang menulis klien Java yang perlu melakukan POST
data sederhana untuk tertentu URL
. Bagian itu berfungsi dengan baik, satu-satunya masalah adalah itu seharusnya selesai HTTPS
. Bagian HTTPS
ini cukup mudah untuk ditangani (baik dengan HTTPclient
atau menggunakan HTTPS
dukungan bawaan Java ), tetapi saya terjebak pada otentikasi dengan sertifikat klien. Saya perhatikan sudah ada pertanyaan yang sangat mirip di sini, yang belum saya coba dengan kode saya (akan segera melakukannya). Masalah saya saat ini adalah - apa pun yang saya lakukan - klien Java tidak pernah mengirim sertifikat (saya bisa memeriksanya dengan PCAP
dump).
Saya ingin tahu persis apa yang seharusnya dihadirkan klien ke server saat mengautentikasi dengan sertifikat (khusus untuk Java - jika itu penting)? Apakah ini JKS
file, atau PKCS#12
? Apa yang seharusnya ada di dalamnya; hanya sertifikat klien, atau kunci? Jika demikian, kunci yang mana? Ada sedikit kebingungan tentang semua jenis file, tipe sertifikat, dan sebagainya.
Seperti yang telah saya katakan sebelumnya, saya baru HTTPS/SSL/TLS
jadi saya akan menghargai beberapa informasi latar belakang juga (tidak harus menjadi esai; saya akan menerima tautan ke artikel bagus).
sumber
Jawaban:
Akhirnya berhasil menyelesaikan semua masalah, jadi saya akan menjawab pertanyaan saya sendiri. Ini adalah pengaturan / file yang saya gunakan untuk mengelola untuk menyelesaikan masalah khusus saya;
The keystore klien adalah PKCS # 12 Format file yang berisi
Untuk menghasilkannya saya menggunakan
pkcs12
perintah OpenSSL , misalnya;Tip: pastikan Anda mendapatkan OpenSSL terbaru, bukan versi 0.9.8h karena sepertinya ada bug yang tidak memungkinkan Anda menghasilkan file PKCS # 12 dengan benar.
File PKCS # 12 ini akan digunakan oleh klien Java untuk menyajikan sertifikat klien ke server ketika server telah secara eksplisit meminta klien untuk mengotentikasi. Lihat artikel Wikipedia tentang TLS untuk ikhtisar tentang bagaimana protokol untuk otentikasi sertifikat klien benar-benar bekerja (juga menjelaskan mengapa kita memerlukan kunci pribadi klien di sini).
The truststore klien adalah lurus ke depan Format JKS file yang berisi akar atau CA menengah sertifikat . Sertifikat CA ini akan menentukan titik akhir mana Anda akan diizinkan untuk berkomunikasi dengan, dalam hal ini akan memungkinkan klien Anda untuk terhubung ke server mana saja yang menyajikan sertifikat yang ditandatangani oleh salah satu CA truststore.
Untuk menghasilkannya, Anda dapat menggunakan keytool Java standar, misalnya;
Menggunakan truststore ini, klien Anda akan mencoba melakukan jabat tangan SSL lengkap dengan semua server yang menyajikan sertifikat yang ditandatangani oleh CA yang diidentifikasi oleh
myca.crt
.File-file di atas hanya untuk klien. Ketika Anda ingin mengatur server juga, server memerlukan file key- dan truststore sendiri. Sebuah walk-through yang bagus untuk menyiapkan contoh yang berfungsi penuh untuk klien Java dan server (menggunakan Tomcat) dapat ditemukan di situs web ini .
Masalah / Komentar / Kiat
-Djavax.net.debug=ssl
tetapi lebih terstruktur dan (bisa dibilang) lebih mudah untuk ditafsirkan jika Anda tidak nyaman dengan output debug SSL Java.Sangat mungkin untuk menggunakan perpustakaan Apache httpclient. Jika Anda ingin menggunakan httpclient, ganti saja URL tujuan dengan yang setara dengan HTTPS dan tambahkan argumen JVM berikut (yang sama untuk klien lain, terlepas dari pustaka yang ingin Anda gunakan untuk mengirim / menerima data melalui HTTP / HTTPS) :
sumber
SSLContext
seperti pada jawaban @ Magnus.Jawaban lain menunjukkan cara mengkonfigurasi sertifikat klien secara global. Namun jika Anda ingin secara program menentukan kunci klien untuk satu koneksi tertentu, alih-alih mendefinisikannya secara global di setiap aplikasi yang berjalan pada JVM Anda, maka Anda dapat mengonfigurasi SSLContext Anda sendiri seperti:
sumber
sslContext = SSLContexts.custom().loadTrustMaterial(keyFile, PASSWORD).build();
. Saya tidak bisa membuatnya bekerjaloadKeyMaterial(...)
.loadKeyMaterial(keystore, keyPassphrase.toCharArray())
kode 'juga!SSLContext
.File JKS mereka hanyalah wadah untuk sertifikat dan pasangan kunci. Dalam skenario otentikasi sisi klien, berbagai bagian tombol akan ditempatkan di sini:
Pemisahan truststore dan keystore tidak wajib tetapi disarankan. Mereka dapat berupa file fisik yang sama.
Untuk mengatur lokasi sistem file dari dua toko, gunakan properti sistem berikut:
dan di server:
Untuk mengekspor sertifikat klien (kunci publik) ke file, sehingga Anda dapat menyalinnya ke server, gunakan
Untuk mengimpor kunci publik klien ke keystore server, gunakan (seperti yang disebutkan poster, ini sudah dilakukan oleh admin server)
sumber
Maven pom.xml:
Kode Java:
sumber
configureRequest()
untuk mengatur proksi proyek klien benar?Bagi Anda yang hanya ingin mengatur otentikasi dua arah (sertifikat server dan klien), kombinasi dari kedua tautan ini akan membawa Anda ke sana:
Pengaturan auth dua arah:
https://linuxconfig.org/apache-web-server-ssl-authentication
Anda tidak perlu menggunakan file konfigurasi openssl yang mereka sebutkan; gunakan saja
$ openssl genrsa -des3 -keluar ca.key 4096
$ openssl req -baru -x509-hari 365 -kunci ca.key -keluar ca.crt
untuk menghasilkan sertifikat CA Anda sendiri, dan kemudian menghasilkan dan menandatangani kunci server dan klien melalui:
$ openssl genrsa -des3 -out server.key 4096
$ openssl req -baru -kunci server.key -out server.csr
$ openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 100 -out server.crt
dan
$ openssl genrsa -des3 -out client.key 4096
$ openssl req -baru -kunci client.key -keluar client.csr
$ openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 101 -out client.crt
Untuk sisanya ikuti langkah-langkah di tautan. Mengelola sertifikat untuk Chrome berfungsi sama seperti pada contoh untuk firefox yang disebutkan.
Selanjutnya, atur server melalui:
https://www.digitalocean.com/community/tutorials/how-to-create-a-ssl-certificate-on-apache-for-ubuntu-14-04
Perhatikan bahwa Anda telah membuat server .crt dan .key sehingga Anda tidak perlu melakukan langkah itu lagi.
sumber
server.key
tidak menggunakanclient.key
Saya telah terhubung ke bank dengan SSL dua arah (sertifikat klien dan server) dengan Spring Boot. Jadi jelaskan di sini semua langkah saya, semoga membantu seseorang (solusi kerja paling sederhana, saya temukan):
Buat permintaan sertifikat:
Hasilkan kunci pribadi:
Buat permintaan sertifikat:
Simpan
user.key
(dan kata sandi) dan kirim permintaan sertifikatuser.csr
ke bank untuk sertifikat sayaTerima 2 sertifikat: sertifikat root klien saya
clientId.crt
dan sertifikat root bank:bank.crt
Buat Java keystore (masukkan kata sandi kunci dan atur kata sandi keystore):
Tidak memperhatikan pada output:
unable to write 'random state'
. Java PKCS12keystore.p12
dibuat.Tambahkan ke keystore
bank.crt
(untuk kemudahan saya telah menggunakan satu keystore):Periksa sertifikat keystore dengan:
Siap untuk kode Java :) Saya telah menggunakan Spring Boot
RestTemplate
dengan menambahkanorg.apache.httpcomponents.httpcore
ketergantungan:sumber
Diberikan file p12 dengan sertifikat dan kunci privat (dihasilkan oleh openssl, misalnya), kode berikut akan menggunakannya untuk HttpsURLConnection tertentu:
The
SSLContext
mengambil beberapa waktu untuk initialize, sehingga Anda mungkin ingin cache itu.sumber
Saya pikir perbaikan di sini adalah tipe keystore, pkcs12 (pfx) selalu memiliki kunci pribadi dan tipe JKS dapat ada tanpa kunci pribadi. Kecuali Anda menentukan dalam kode Anda atau memilih sertifikat melalui browser, server tidak memiliki cara untuk mengetahui itu mewakili klien di ujung yang lain.
sumber