Trust Anchor tidak ditemukan untuk Koneksi SSL Android

185

Saya mencoba untuk terhubung ke kotak IIS6 menjalankan 256bit SSL cert GoDaddy, dan saya mendapatkan kesalahan:

java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

Sudah berusaha untuk menentukan apa yang bisa menyebabkan itu, tetapi menggambar kosong sekarang.

Inilah cara saya terhubung:

HttpsURLConnection conn;              
conn = (HttpsURLConnection) (new URL(mURL)).openConnection();
conn.setConnectTimeout(20000);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.connect();
String tempString = toString(conn.getInputStream()); 
Chrispix
sumber

Jawaban:

78

Solusi dari @Chrispix berbahaya! Mempercayai semua sertifikat memungkinkan siapa saja untuk melakukan serangan tengah!Kirimkan saja sertifikat APA SAJA kepada klien dan itu akan menerimanya!

Tambahkan sertifikat Anda ke pengelola kepercayaan khusus seperti yang dijelaskan dalam posting ini: Percayai semua sertifikat menggunakan HttpClient melalui HTTPS

Meskipun sedikit lebih rumit untuk membuat koneksi yang aman dengan sertifikat khusus, itu akan membawa Anda keamanan enkripsi ssl yang diinginkan tanpa bahaya orang dalam serangan tengah!

Matthias B
sumber
1
Ini tidak masalah untuk bekerja dengan sertifikat yang dibuat sendiri, tetapi untuk sertifikat (seperti OP) yang memiliki rantai yang valid kembali ke root CA, itu hanya solusi untuk server yang dikonfigurasi dengan buruk - lihat jawaban saya.
Stevie
4
@Stevie Menerima SETIAP sertifikat hanya merupakan opsi untuk bukti uji konsep, di mana koneksi SSL bukan bagian yang ingin Anda uji. Kalau tidak, Anda tidak harus menggunakan SSL, jika Anda menerima setiap sertifikat, karena koneksi tidak aman!
Matthias B
1
Ah, maaf, saya pikir ada kesalahpahaman - saya sepenuhnya setuju bahwa tidak ada yang boleh menerima setiap sertifikat! :) Komentar saya berkaitan dengan paragraf ke-2 Anda - saran untuk menggunakan custom trust manager - yang IMHO harus menjadi solusi terakhir daripada solusi yang disarankan.
Stevie
2
Mengangkat kepala .. Saya menghapus 'solusi' yang saya tempel sebagai solusi untuk tidak menyebabkan lebih banyak masalah, karena orang tidak melihatnya sebagai 'pekerjaan sementara'.
Chrispix
7
@ Chrispix, Anda seharusnya tidak menghapus perbaikan parsial, ini bagus untuk tujuan pengujian saja
Hugo Allexis Cardona
224

Berlawanan dengan jawaban yang diterima bahwa Anda tidak memerlukan manajer kepercayaan khusus, Anda harus memperbaiki konfigurasi server Anda!

Saya mengalami masalah yang sama saat menghubungkan ke server Apache dengan sertifikat dynadot / alphassl yang tidak diinstal dengan benar. Saya terhubung menggunakan HttpsUrlConnection (Java / Android), yang melempar -

javax.net.ssl.SSLHandshakeException: 
  java.security.cert.CertPathValidatorException: 
    Trust anchor for certification path not found.

Masalah sebenarnya adalah kesalahan konfigurasi server - mengujinya dengan http://www.digicert.com/help/ atau serupa, dan bahkan akan memberi tahu Anda solusinya:

"Sertifikat tidak ditandatangani oleh otoritas tepercaya (memeriksa terhadap root store Mozilla). Jika Anda membeli sertifikat dari otoritas tepercaya, Anda mungkin hanya perlu menginstal satu atau lebih sertifikat Menengah . Hubungi penyedia sertifikat Anda untuk bantuan melakukan ini untuk Anda platform server. "

Anda juga dapat memeriksa sertifikat dengan openssl:

openssl s_client -debug -connect www.thedomaintocheck.com:443

Anda mungkin akan melihat:

Verify return code: 21 (unable to verify the first certificate)

dan, sebelumnya dalam output:

depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=21:unable to verify the first certificate`

Rantai sertifikat hanya akan berisi 1 elemen (sertifikat Anda):

Certificate chain
 0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com
  i:/O=AlphaSSL/CN=AlphaSSL CA - G2

... tetapi harus merujuk otoritas penandatangan dalam rantai kembali ke rantai yang tepercaya oleh Android (Verisign, GlobalSign, dll):

Certificate chain
 0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com
   i:/O=AlphaSSL/CN=AlphaSSL CA - G2
 1 s:/O=AlphaSSL/CN=AlphaSSL CA - G2
   i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
 2 s:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
   i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA

Petunjuk (dan sertifikat perantara) untuk mengonfigurasi server Anda biasanya disediakan oleh otoritas yang mengeluarkan sertifikat Anda, misalnya: http://www.alphassl.com/support/install-root-certificate.html

Setelah menginstal sertifikat perantara yang disediakan oleh penerbit sertifikat saya, saya sekarang tidak memiliki kesalahan saat menghubungkan menggunakan HttpsUrlConnection.

Stevie
sumber
3
Jika OP memiliki akses ke konfigurasi SSL server yang disambungkan, ini mungkin solusi. Tetapi jika dia bukan orang yang melayani layanan yang dia hubungkan, dia harus memperbaiki masalah di sisinya, yang berarti menerapkan manajer kepercayaan khusus.
Matthias B
9
Solusi Anda berfungsi, tidak perlu dipertanyakan, tetapi tidakkah Anda setuju bahwa ini merupakan solusi daripada perbaikan untuk akar permasalahan? Jika saya harus terhubung ke server dari 3 klien (Android, iOS, Windows Mobile) maka saya harus menerapkan solusi pada ketiga, sedangkan saya dapat memperbaiki server sekali dan mereka semua akan "hanya bekerja".
Stevie
2
Terima kasih Stevie, server saya salah konfigurasi selama 3 bulan, dan baru sekarang saya mendeteksi ini! Sekarang aplikasi android saya bekerja 100%
jpros
2
@Stevie Saya membuat banyak panggilan ke berbagai API yang berbagi domain yang sama, tetapi hanya satu yang gagal dengan (javax.net.ssl.SSLHandshakeException) ... ada ide mengapa hal seperti itu terjadi? dan omong-omong, Sertifikat SSL tidak dipercaya. Jadi, saya pikir semua panggilan harus gagal dengan pengecualian yang sama.
pemain yang adil
1
@ David menghubungi siapa pun yang memiliki server dan memberi tahu mereka bahwa konfigurasi mereka rusak dan https mereka tidak berfungsi dengan baik - beri mereka tautan ini untuk membuktikannya digicert.com/help ... Saya pikir mereka akan menghargai dan cepat untuk menyelesaikan. Jika tidak, Anda harus mengambil salah satu langkah penyelesaian dalam jawaban lainnya, tetapi kemudian Anda harus menerima tidak ada keamanan (abaikan sertifikat) atau gunakan kembali aplikasi Anda ketika sertifikat tersebut kedaluwarsa dan toko kepercayaan khusus Anda tidak lagi cocok dengan yang baru cert.
Stevie
17

Anda dapat mempercayai sertifikat tertentu saat runtime.
Cukup unduh dari server, masukkan aset dan muat seperti ini menggunakan ssl-utils-android :

OkHttpClient client = new OkHttpClient();
SSLContext sslContext = SslUtils.getSslContextForCertificateFile(context, "BPClass2RootCA-sha2.cer");
client.setSslSocketFactory(sslContext.getSocketFactory());

Dalam contoh di atas saya menggunakan OkHttpClienttetapi SSLContextdapat digunakan dengan klien di Jawa.

Jika Anda memiliki pertanyaan, jangan ragu untuk bertanya. Saya penulis perpustakaan kecil ini.

klimat
sumber
bagaimana dengan .pfx?
Choletski
2
Bukankah ini tidak aman karena setiap pengguna dapat mengakses folder aset untuk aplikasi setelah mereka memiliki apk?
Patrice Andala
1
@ PatriceAndala, Root CA tersedia untuk umum, jadi tidak masalah
BekaBot
17

Pembaruan berdasarkan dokumentasi Android terbaru (Maret 2017):

Ketika Anda mendapatkan jenis kesalahan ini:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:374)
        at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)
        at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478)
        at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433)
        at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
        at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
        at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)
        at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
        at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271)

masalahnya bisa salah satu dari yang berikut:

  1. CA yang mengeluarkan sertifikat server tidak diketahui
  2. Sertifikat server tidak ditandatangani oleh CA, tetapi ditandatangani sendiri
  3. Konfigurasi server tidak memiliki CA perantara

Solusinya adalah mengajar HttpsURLConnectionuntuk memercayai serangkaian CA tertentu. Bagaimana? Silakan periksa https://developer.android.com/training/articles/security-ssl.html#CommonProblems

Orang lain yang menggunakan AsyncHTTPClientdari com.loopj.android:android-async-httpperpustakaan, silakan periksa Setup AsyncHttpClient untuk menggunakan HTTPS .

pengguna1506104
sumber
5
Bagaimana jika seseorang menggunakan klien okhttp?
TheLearner
Untuk okhttp, mohon periksa jawaban @ mklimek.
user1506104
14

Jika Anda menggunakan retrofit, Anda perlu menyesuaikan OkHttpClient Anda.

retrofit = new Retrofit.Builder()
                        .baseUrl(ApplicationData.FINAL_URL)
                        .client(getUnsafeOkHttpClient().build())
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();

Kode lengkapnya seperti di bawah ini.

    public class RestAdapter {

    private static Retrofit retrofit = null;
    private static ApiInterface apiInterface;

    public static OkHttpClient.Builder getUnsafeOkHttpClient() {
        try {
            // Create a trust manager that does not validate certificate chains
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new java.security.cert.X509Certificate[]{};
                        }
                    }
            };

            // Install the all-trusting trust manager
            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

            // Create an ssl socket factory with our all-trusting manager
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
            return builder;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static ApiInterface getApiClient() {
        if (apiInterface == null) {

            try {
                retrofit = new Retrofit.Builder()
                        .baseUrl(ApplicationData.FINAL_URL)
                        .client(getUnsafeOkHttpClient().build())
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();

            } catch (Exception e) {

                e.printStackTrace();
            }


            apiInterface = retrofit.create(ApiInterface.class);
        }
        return apiInterface;
    }

}
Shihab Uddin
sumber
1
Saya mencoba menggunakan kode tetapi saya mendapatkan kesalahan berikut lagi .. "javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Percayai jangkar untuk jalur sertifikasi tidak ditemukan." dapatkah Anda membantu dalam hal ini
Vishwa Pratap
Ini adalah rasa tidak aman yang radikal. Jangan gunakan.
Marquis of Lorne
Terima kasih! Tulis ulang metode getUnsafeOkHttpClient()di Kotlin: stackoverflow.com/a/60507560/2914140 .
CoolMind
11

Membalas posting yang sangat lama. Tapi mungkin itu akan membantu pemula dan jika tidak ada yang berhasil.

Penjelasan: Saya tahu tidak ada yang mau penjelasan omong kosong; bukan solusinya. Namun dalam satu liner, Anda mencoba mengakses layanan dari mesin lokal Anda ke mesin jarak jauh yang tidak mempercayai mesin Anda. Anda meminta perlu mendapatkan kepercayaan dari server jauh.

Solusi: Solusi berikut ini mengasumsikan bahwa Anda memiliki kondisi berikut terpenuhi

  1. Mencoba mengakses api jarak jauh dari mesin lokal Anda.
  2. Anda membangun untuk aplikasi Android
  3. Server jauh Anda sedang dalam penyaringan proxy (Anda menggunakan proxy dalam pengaturan browser Anda untuk mengakses layanan api jarak jauh, biasanya server staging atau dev)
  4. Anda menguji pada perangkat nyata

Langkah:

Anda memerlukan file ekstensi .keystore untuk mendaftar aplikasi Anda. Jika Anda tidak tahu cara membuat file .keystore; kemudian ikuti bersama dengan bagian berikut ini. Buat file .keystore atau lewati ke bagian selanjutnya Sign Apk File

Buat file .keystore

Buka Android Studio. Klik menu atas Build> Hasilkan APK yang Ditandatangani. Pada jendela berikutnya klik Buat baru ... tombol. Di jendela baru, silakan masukkan data di semua bidang. Ingat dua bidang Kata Sandi yang saya sarankan harus memiliki kata sandi yang sama; jangan gunakan kata sandi yang berbeda; dan juga ingat save jalan di paling atas lapangan Key jalan toko: . Setelah Anda memasukkan semua bidang, klik tombol OK.

Masuk File Apk

Sekarang Anda perlu membangun aplikasi yang ditandatangani dengan file .keystore yang baru saja Anda buat. Ikuti langkah ini

  1. Build> Clean Project, tunggu sampai selesai dibersihkan
  2. Build> Generate Signed APK
  3. Klik Choose existing...tombol
  4. Pilih file .keystore kita hanya dibuat dalam Membuat file .keystore bagian
  5. Masukkan kata sandi yang sama yang Anda buat saat membuat di bagian Buat .keystore file . Gunakan kata sandi Key store passworddan Key passwordbidang yang sama. Masukkan juga alias
  6. Klik tombol Next
  7. Di layar selanjutnya; yang mungkin berbeda berdasarkan pengaturan Anda dalam build.gradlefile, Anda harus memilih Build Typesdan Flavors.
  8. Untuk Build Typesmemilih releasedari dropdown
  9. Untuk Flavorsnamun akan tergantung pada pengaturan Anda di build.gradleberkas. Pilih stagingdari bidang ini. Saya menggunakan pengaturan berikut ini di build.gradle, Anda dapat menggunakan yang sama seperti milik saya, tetapi pastikan Anda mengubah applicationIdke nama paket Anda

    productFlavors {
        staging {
            applicationId "com.yourapplication.package"
            manifestPlaceholders = [icon: "@drawable/ic_launcher"]
            buildConfigField "boolean", "CATALYST_DEBUG", "true"
            buildConfigField "boolean", "ALLOW_INVALID_CERTIFICATE", "true"
        }
        production {
            buildConfigField "boolean", "CATALYST_DEBUG", "false"
            buildConfigField "boolean", "ALLOW_INVALID_CERTIFICATE", "false"
        }
    }
  10. Klik dua Signature Versionskotak centang di bawah dan klik Finishtombol.

Hampir sampai:

Semua kerja keras dilakukan, sekarang gerakan kebenaran. Agar dapat mengakses server Staging yang didukung oleh proxy, Anda perlu membuat beberapa pengaturan di perangkat Android pengujian Anda yang sebenarnya.

Pengaturan Proxy di Perangkat Android:

  1. Klik Pengaturan di dalam ponsel Android dan kemudian wi-fi
  2. Tekan lama pada wifi yang terhubung dan pilih Modify network
  3. Klik Advanced optionsjika Anda tidak dapat melihat Proxy Hostnamemedan
  4. Di Proxy Hostnamemasukkan IP host atau nama yang ingin Anda sambungkan. Server staging khas akan dinamaistg.api.mygoodcompany.com
  5. Untuk port, masukkan nomor port empat digit misalnya 9502
  6. Tekan Savetombolnya

Satu Perhentian Terakhir:

Ingat kami membuat file apk yang ditandatangani di bagian Sign APK File . Sekarang adalah waktu untuk menginstal file APK itu.

  1. Buka terminal dan ubah ke folder file apk yang ditandatangani
  2. Hubungkan perangkat Android Anda ke mesin Anda
  3. Hapus file apk yang diinstal sebelumnya dari perangkat Android
  4. Lari adb install name of the apk file
  5. Jika karena alasan tertentu perintah di atas kembali dengan adb command not found. Masukkan path lengkap sebagaiC:\Users\shah\AppData\Local\Android\sdk\platform-tools\adb.exe install name of the apk file

Saya harap masalahnya bisa diselesaikan. Jika tidak, silakan tinggalkan saya komentar.

Salam!

HA S
sumber
4

Pesan kesalahan yang saya terima mirip tetapi alasannya adalah bahwa sertifikat yang ditandatangani sendiri telah kedaluwarsa. Ketika klien openssl dicoba, itu memberi saya alasan yang diabaikan ketika saya memeriksa dialog sertifikat dari firefox.

Jadi secara umum, jika sertifikat ada di keystore dan "VALID" -nya, kesalahan ini akan padam.

MPN
sumber
1
Jika sertifikat kedaluwarsa, maka sertifikatnya tidak valid sesuai sejumlah standar. Boleh saja menggunakan kebiasaan TrustManagerdan menggunakan serangkaian kriteria yang berbeda. Tetapi di luar kotak, itulah yang harus Anda kerjakan.
jww
4

Saya memiliki masalah yang sama saat menghubungkan dari klien Android ke server Kurento. Server Kurento menggunakan sertifikat jks, jadi saya harus mengonversi pem ke itu. Sebagai input untuk konversi saya menggunakan file cert.pem dan itu menyebabkan kesalahan seperti itu. Tetapi jika menggunakan fullchain.pem alih-alih cert.pem - semuanya OK.

V.Poddubchak
sumber
3

Gunakan https://www.ssllabs.com/ssltest/ untuk menguji domain.

Solusi Shihab Uddin di Kotlin.

import java.security.SecureRandom
import java.security.cert.X509Certificate
import javax.net.ssl.*
import javax.security.cert.CertificateException

companion object {

    private val gson: Gson
    private val retrofit: Retrofit

    init {

        val okHttpClient = getUnsafeOkHttpClient() // OkHttpClient().newBuilder()
            .build()

        gson = GsonBuilder().setLenient().create()

        retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build()
    }

    private fun getUnsafeOkHttpClient(): OkHttpClient.Builder =
        try {
            // Create a trust manager that does not validate certificate chains
            val trustAllCerts: Array<TrustManager> = arrayOf(
                object : X509TrustManager {
                    @Throws(CertificateException::class)
                    override fun checkClientTrusted(chain: Array<X509Certificate?>?,
                                                    authType: String?) = Unit

                    @Throws(CertificateException::class)
                    override fun checkServerTrusted(chain: Array<X509Certificate?>?,
                                                    authType: String?) = Unit

                    override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
                }
            )
            // Install the all-trusting trust manager
            val sslContext: SSLContext = SSLContext.getInstance("SSL")
            sslContext.init(null, trustAllCerts, SecureRandom())
            // Create an ssl socket factory with our all-trusting manager
            val sslSocketFactory: SSLSocketFactory = sslContext.socketFactory
            val builder = OkHttpClient.Builder()
            builder.sslSocketFactory(sslSocketFactory,
                trustAllCerts[0] as X509TrustManager)
            builder.hostnameVerifier { _, _ -> true }
            builder
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
}
CoolMind
sumber
2

Saya memiliki masalah yang sama dengan apa yang saya temukan adalah file .crt sertifikat yang saya berikan tidak memiliki sertifikat perantara. Jadi saya bertanya semua file .crt dari admin server saya, lalu menyatukannya dalam urutan terbalik.

Ex. 1. Root.crt 2. Inter.crt 3. myCrt.crt

di windows saya menjalankan salinan Inter.crt + Root.crt newCertificate.crt

(Di sini saya mengabaikan myCrt.crt)

Kemudian saya memberikan file newCertificate.crt ke dalam kode melalui inputstream. Kerja selesai.

Sahan Maldeniya
sumber
Kami juga memiliki masalah yang sama. Sertifikat perantara tidak ada
Nidhin Chandran
1

Kesalahan anchor Trust dapat terjadi karena banyak alasan. Bagi saya itu hanya karena saya mencoba mengakses https://example.com/daripada https://www.example.com/.

Jadi, Anda mungkin ingin memeriksa ulang URL Anda sebelum mulai membangun Trust Manager Anda sendiri (seperti yang saya lakukan).

Unkulunkulu
sumber
0

Di ponsel Gingerbread, saya selalu mendapatkan kesalahan ini:, Trust Anchor not found for Android SSL Connectionbahkan jika saya setup untuk mengandalkan sertifikat saya.

Berikut adalah kode yang saya gunakan (dalam bahasa Scala):

object Security {
    private def createCtxSsl(ctx: Context) = {
        val cer = {
            val is = ctx.getAssets.open("mycertificate.crt")
            try
                CertificateFactory.getInstance("X.509").generateCertificate(is)
            finally
                is.close()
        }
        val key = KeyStore.getInstance(KeyStore.getDefaultType)
        key.load(null, null)
        key.setCertificateEntry("ca", cer)

        val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
    tmf.init(key)

        val c = SSLContext.getInstance("TLS")
        c.init(null, tmf.getTrustManagers, null)
        c
    }

    def prepare(url: HttpURLConnection)(implicit ctx: Context) {
        url match {
            case https: HttpsURLConnection 
                val cSsl = ctxSsl match {
                    case None 
                        val res = createCtxSsl(ctx)
                        ctxSsl = Some(res)
                        res
                    case Some(c)  c
                }
                https.setSSLSocketFactory(cSsl.getSocketFactory)
            case _ 
        }
    }

    def noSecurity(url: HttpURLConnection) {
        url match {
            case https: HttpsURLConnection 
                https.setHostnameVerifier(new HostnameVerifier {
                    override def verify(hostname: String, session: SSLSession) = true
                })
            case _ 
        }
    }
}

dan di sini adalah kode koneksi:

def connect(securize: HttpURLConnection  Unit) {
    val conn = url.openConnection().asInstanceOf[HttpURLConnection]
    securize(conn)
    conn.connect();
    ....
}

try {
    connect(Security.prepare)
} catch {
    case ex: SSLHandshakeException /*if ex.getMessage != null && ex.getMessage.contains("Trust anchor for certification path not found")*/ 
        connect(Security.noSecurity)
}

Pada dasarnya, saya mengatur agar mempercayai sertifikat khusus saya. Jika itu gagal, maka saya menonaktifkan keamanan. Ini bukan pilihan terbaik, tetapi satu-satunya pilihan yang saya tahu dengan telepon tua dan kereta.

Kode contoh ini, dapat dengan mudah diterjemahkan ke dalam Java.

david.perez
sumber
Solusi untuk android 2.3.x jika seseorang membutuhkannya, stackoverflow.com/a/46465722/7125370
Newbie009
0

Dalam kasus saya ini terjadi setelah pembaruan ke Android 8.0. Sertifikat yang ditandatangani sendiri oleh Android ditetapkan untuk dipercaya menggunakan algoritma tanda tangan SHA1withRSA. Beralih ke sertifikat baru, menggunakan algoritme tanda tangan SHA256 dengan RSA memperbaiki masalah.

Zds
sumber
0

Saya tahu bahwa Anda tidak perlu mempercayai semua sertifikat, tetapi dalam kasus saya, saya mengalami masalah dengan beberapa lingkungan debugging di mana kami memiliki sertifikat yang ditandatangani sendiri dan saya membutuhkan solusi kotor.

Yang harus saya lakukan adalah mengubah inisialisasi sslContext

mySSLContext.init(null, trustAllCerts, null); 

di mana trustAllCertsdiciptakan seperti ini:

private final TrustManager[] trustAllCerts= new TrustManager[] { new X509TrustManager() {
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return new java.security.cert.X509Certificate[]{};
    }

    public void checkClientTrusted(X509Certificate[] chain,
                                   String authType) throws CertificateException {
    }

    public void checkServerTrusted(X509Certificate[] chain,
                                   String authType) throws CertificateException {
    }
} };

Semoga ini berguna.

Adrian C.
sumber
Itu yang ingin saya temukan! Terima kasih
oxied
Saya mendapatkan kesalahan Hostname '192.168.0.16' was not verified. Saya sedang menguji webapi saya melalui debugger saya (IIS Express) secara lokal. Adakah cara untuk memperbaikinya? Terima kasih :)
Sam
1
Ini sangat tidak aman. Jangan gunakan.
Marquis of Lorne
0

Saya memiliki masalah yang sama dan saya sepenuhnya mengesampingkan strategi mempercayai semua sumber.

Saya berbagi di sini solusi saya diterapkan pada aplikasi yang diimplementasikan di Kotlin

Saya pertama-tama akan merekomendasikan menggunakan situs web berikut untuk mendapatkan informasi tentang sertifikat dan validitasnya

Jika tidak muncul sebagai 'Penerbit yang Diterima' di toko kepercayaan default Android , kita harus mendapatkan sertifikat itu dan memasukkannya ke dalam aplikasi untuk membuat toko kepercayaan khusus

Solusi ideal dalam kasus saya adalah membuat Trust Manager tingkat tinggi yang menggabungkan custom dan toko kepercayaan default Android

Di sini ia memperlihatkan kode tingkat tinggi yang digunakan untuk mengkonfigurasi OkHttpClient yang ia gunakan dengan Retrofit.

override fun onBuildHttpClient(httpClientBuild: OkHttpClient.Builder) {

        val trustManagerWrapper = createX509TrustManagerWrapper(
            arrayOf(
                getCustomX509TrustManager(),
                getDefaultX509TrustManager()
            )
        )

        printX509TrustManagerAcceptedIssuers(trustManagerWrapper)

        val sslSocketFactory = createSocketFactory(trustManagerWrapper)
        httpClientBuild.sslSocketFactory(sslSocketFactory, trustManagerWrapper)

    }

Dengan cara ini, saya bisa berkomunikasi dengan server dengan sertifikat yang ditandatangani sendiri dan dengan server lain dengan sertifikat yang dikeluarkan oleh entitas sertifikasi tepercaya

Ini dia, saya harap ini bisa membantu seseorang.

Sergio Sánchez Sánchez
sumber
0

Saya tahu ini adalah artikel yang sangat lama, tetapi saya menemukan artikel ini ketika mencoba menyelesaikan masalah anchor trust saya. Saya telah memposting bagaimana saya memperbaikinya. Jika Anda telah menginstal CA Root, Anda harus menambahkan konfigurasi ke manifes.

https://stackoverflow.com/a/60102517/114265

Utusan GR
sumber
hanya untuk API 24+
BekaBot
@BekaBot - ini mungkin benar, tetapi menurut dokumentasi 23 dan di bawah mempercayai sertifikat pengguna secara default Secara default, koneksi aman (menggunakan protokol seperti TLS dan HTTPS) dari semua aplikasi mempercayai CAs sistem pra-instal, dan aplikasi yang menargetkan Android 6.0 (API level 23) dan lebih rendah juga memercayai toko CA yang ditambahkan pengguna secara default
Utusan GR
-1
**Set proper alias name**
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509","BC");
            X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(derInputStream);
            String alias = cert.getSubjectX500Principal().getName();
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null);
trustStore.setCertificateEntry(alias, cert);
Dayanand Waghmare
sumber
-2

Saya juga menghadapi masalah yang sama. Saya hanya menghapus hhtps ke http, seperti

final public static String ROOT_URL = "https://example.com"; untuk final public static String ROOT_URL = "http://example.com";

Akhirnya, saya memecahkan masalah ini.

Rasheduzzaman
sumber
Tentunya ini hanya menghapus keamanan SSL dari persamaan, yang mungkin merupakan ide yang buruk untuk lingkungan produksi.
Dragonthoughts
Ini benar-benar bukan solusi, menghapus keamanan SSL.
omega1