Không tìm thấy Anchor tin cậy cho Kết nối SSL Android


184

Tôi đang cố gắng kết nối với hộp IIS6 đang chạy chứng chỉ SSL 256 bit thần thánh và tôi đang gặp lỗi:

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

Đã cố gắng xác định những gì có thể gây ra điều đó, nhưng vẽ những khoảng trống ngay bây giờ.

Đây là cách tôi kết nối:

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

Câu trả lời:


78

Giải pháp của @Chrispix rất nguy hiểm! Tin tưởng tất cả các chứng chỉ cho phép bất cứ ai làm một người đàn ông trong cuộc tấn công giữa! Chỉ cần gửi bất kỳ chứng chỉ nào cho khách hàng và nó sẽ chấp nhận nó!

Thêm (các) chứng chỉ của bạn vào trình quản lý ủy thác tùy chỉnh như được mô tả trong bài đăng này: Tin tưởng tất cả các chứng chỉ bằng cách sử dụng HttpClient qua HTTPS

Mặc dù việc thiết lập kết nối an toàn với chứng chỉ tùy chỉnh phức tạp hơn một chút, nhưng nó sẽ mang lại cho bạn bảo mật mã hóa ssl mong muốn mà không gặp nguy hiểm trong cuộc tấn công trung gian!


1
Điều này ổn khi làm việc với một chứng chỉ tự tạo, nhưng đối với một (như OP) có chuỗi hợp lệ trở lại CA gốc thì đó chỉ là một cách giải quyết cho một máy chủ được cấu hình kém - xem câu trả lời của tôi.
Stevie

4
@Stevie Chấp nhận MỌI chứng chỉ chỉ là một tùy chọn cho bằng chứng kiểm tra khái niệm, trong đó kết nối SSL không phải là phần bạn muốn kiểm tra. Nếu không, bạn không phải sử dụng SSL, nếu bạn chấp nhận mọi chứng chỉ, vì kết nối không an toàn!
Matthias B

1
À, tôi xin lỗi, tôi nghĩ có một sự hiểu lầm - tôi hoàn toàn đồng ý rằng không ai nên chấp nhận mọi chứng chỉ! :) Nhận xét của tôi liên quan đến đoạn 2 của bạn - đề xuất sử dụng trình quản lý ủy thác tùy chỉnh - IMHO nên là giải pháp cuối cùng thay vì giải pháp được đề xuất.
Stevie

2
Hãy cố gắng lên .. Tôi đã gỡ bỏ 'giải pháp' mà tôi đã dán như một cách giải quyết để không gây ra nhiều vấn đề hơn, vì mọi người không coi đó là một 'công việc tạm thời'.
Chrispix

7
@Chrispix, bạn không nên xóa phần sửa lỗi, tốt cho mục đích thử nghiệm
Hugo Allexis Cardona

224

Trái với câu trả lời được chấp nhận mà bạn không cần người quản lý ủy thác tùy chỉnh, bạn cần sửa cấu hình máy chủ của mình!

Tôi gặp vấn đề tương tự trong khi kết nối với máy chủ Apache với chứng chỉ dynadot / alphassl được cài đặt không chính xác. Tôi đang kết nối bằng HttpsUrlConnection (Java / Android) đang ném -

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

Vấn đề thực tế là cấu hình sai của máy chủ - kiểm tra nó bằng http://www.digicert.com/help/ hoặc tương tự, và thậm chí nó sẽ cho bạn biết giải pháp:

"Chứng chỉ không được ký bởi cơ quan đáng tin cậy (kiểm tra cửa hàng gốc của Mozilla). Nếu bạn đã mua chứng chỉ từ cơ quan đáng tin cậy, có lẽ bạn chỉ cần cài đặt một hoặc nhiều chứng chỉ Trung gian . Liên hệ với nhà cung cấp chứng chỉ của bạn để được hỗ trợ làm việc này cho bạn nền tảng máy chủ. "

Bạn cũng có thể kiểm tra chứng chỉ với openssl:

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

Bạn có thể sẽ thấy:

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

và, sớm hơn trong đầu ra:

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`

Chuỗi chứng chỉ sẽ chỉ chứa 1 phần tử (chứng chỉ của bạn):

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

... Nhưng nên tham khảo các cơ quan ký kết trong chuỗi trở lại một tổ chức được Android tin cậy (Verisign, GlobalSign, v.v.):

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

Hướng dẫn (và chứng chỉ trung gian) để định cấu hình máy chủ của bạn thường được cung cấp bởi cơ quan cấp chứng chỉ của bạn, ví dụ: http://www.alphassl.com/support/install-root-cert ve.html

Sau khi cài đặt các chứng chỉ trung gian do nhà phát hành chứng chỉ của tôi cung cấp, bây giờ tôi không gặp lỗi khi kết nối bằng HttpsUrlConnection.


3
Trong trường hợp OP có quyền truy cập vào cấu hình SSL máy chủ mà anh ta đang kết nối, đây có thể là một giải pháp. Nhưng nếu anh ta không phải là người tổ chức dịch vụ mà anh ta kết nối với anh ta thì phải khắc phục vấn đề về phía anh ta, nghĩa là thực hiện một trình quản lý ủy thác tùy chỉnh.
Matthias B

9
Giải pháp của bạn hoạt động, không có câu hỏi, nhưng bạn không đồng ý rằng đó là một cách giải quyết chứ không phải là một sửa chữa cho nguyên nhân gốc rễ? Nếu tôi phải kết nối với máy chủ từ 3 máy khách (Android, iOS, Windows Mobile) thì tôi phải áp dụng cách giải quyết trên cả 3, trong khi tôi có thể sửa máy chủ một lần và tất cả đều "chỉ hoạt động".
Stevie

2
Cảm ơn Stevie, tôi đã cấu hình sai máy chủ trong 3 tháng và chỉ đến bây giờ tôi mới phát hiện ra điều này! Bây giờ ứng dụng Android của tôi đang hoạt động 100%
jpros

2
@Stevie Tôi thực hiện nhiều cuộc gọi đến các API khác nhau có chung tên miền, nhưng chỉ một trong số chúng thất bại với (javax.net.ssl.SSLHandshakeException) ... có ý tưởng nào tại sao điều đó lại xảy ra không? và nhân tiện, Chứng chỉ SSL không đáng tin cậy. Vì vậy, tôi nghĩ rằng tất cả các cuộc gọi sẽ thất bại với cùng một ngoại lệ.
một người chơi công bằng

1
@dvaey liên lạc với bất kỳ ai sở hữu máy chủ và nói với họ rằng cấu hình của họ bị hỏng và https của họ không hoạt động đúng - hãy cung cấp cho họ liên kết này để chứng minh điều đó digicert.com/help ... Tôi tưởng tượng họ sẽ đánh giá cao và nhanh chóng giải quyết. Nếu không, bạn sẽ phải thực hiện một trong các bước giải quyết trong các câu trả lời khác, nhưng sau đó bạn sẽ phải chấp nhận không bảo mật (bỏ qua certs) hoặc triển khai lại ứng dụng của bạn khi chứng chỉ hết hạn và cửa hàng tin cậy tùy chỉnh của bạn không còn phù hợp với cái mới chứng nhận
Stevie

17

Bạn có thể tin tưởng chứng chỉ cụ thể trong thời gian chạy.
Chỉ cần tải xuống từ máy chủ, đặt tài sản và tải như thế này bằng ssl-utils-android :

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

Trong ví dụ trên tôi đã sử dụng OkHttpClientnhưng SSLContextcó thể được sử dụng với bất kỳ máy khách nào trong Java.

Nếu bạn có bất kỳ câu hỏi hãy hỏi. Tôi là tác giả của thư viện nhỏ này.


Còn .pfx thì sao?
Choletski

2
Điều này không an toàn vì bất kỳ người dùng nào cũng có thể truy cập vào thư mục tài sản cho một ứng dụng một khi họ có apk?
Patrice Andala

@PatriceAndala, Root CAs có sẵn công khai, vì vậy nó ổn
BekaBot

16

Cập nhật dựa trên tài liệu Android mới nhất (tháng 3 năm 2017):

Khi bạn gặp loại lỗi này:

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)

vấn đề có thể là một trong những điều sau đây:

  1. CA đã cấp chứng chỉ máy chủ không xác định
  2. Chứng chỉ máy chủ không được ký bởi CA, nhưng tự ký
  3. Cấu hình máy chủ thiếu CA trung gian

Giải pháp là dạy HttpsURLConnectionđể tin tưởng một bộ CA cụ thể. Làm sao? Vui lòng kiểm tra https://developer.android.com/training/articles/security-ssl.html#CommonProbols

Những người khác đang sử dụng AsyncHTTPClienttừ com.loopj.android:android-async-httpthư viện, vui lòng kiểm tra Cài đặt AsyncHttpClient để sử dụng HTTPS .


5
Điều gì về nếu một người đang sử dụng một khách hàng okhttp?
TheLearner

Đối với okhttp, vui lòng kiểm tra câu trả lời của @ mklimek.
user1506104

14

Nếu bạn sử dụng trang bị thêm, bạn cần tùy chỉnh OkHttpClient của mình.

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

Mã đầy đủ như dưới đây.

    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;
    }

}

1
Tôi đang cố gắng sử dụng mã nhưng tôi lại gặp lỗi sau .. "javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Không tin cậy neo cho đường dẫn chứng nhận." bạn có thể giúp gì trong việc này không
Vishwa Pratap

Đây là triệt để không an toàn. Không được dùng.
Hầu tước Lorne

Cảm ơn! Viết lại phương thức getUnsafeOkHttpClient()trong Kotlin: stackoverflow.com/a/60507560/2914140 .
CoolMind

11

Trả lời bài rất cũ. Nhưng có lẽ nó sẽ giúp một số người mới và nếu không làm việc ở trên.

Giải thích: Tôi biết không ai muốn giải thích tào lao; đúng hơn là giải pháp. Nhưng trong một lớp lót, bạn đang cố gắng truy cập một dịch vụ từ máy cục bộ của mình đến một máy từ xa không tin tưởng vào máy của bạn. Bạn yêu cầu cần phải có được sự tin tưởng từ máy chủ từ xa.

Giải pháp: Giải pháp sau đây giả định rằng bạn có các điều kiện sau được đáp ứng

  1. Đang cố gắng truy cập một api từ xa từ máy cục bộ của bạn.
  2. Bạn đang xây dựng cho ứng dụng Android
  3. Máy chủ từ xa của bạn đang được lọc proxy (bạn sử dụng proxy trong cài đặt trình duyệt của mình để truy cập dịch vụ api từ xa, thường là máy chủ dàn hoặc dev)
  4. Bạn đang thử nghiệm trên thiết bị thực

Các bước:

Bạn cần một tệp mở rộng .keystore để đăng ký ứng dụng của bạn. Nếu bạn không biết cách tạo tệp .keystore; sau đó làm theo cùng với phần sau Tạo tệp .keystore hoặc bỏ qua phần tiếp theo Đăng nhập tệp Apk

Tạo tập tin .keystore

Mở Android Studio. Nhấp vào menu trên cùng Xây dựng> Tạo APK đã ký. Trong cửa sổ tiếp theo nhấp vào mới ... Tạo nút. Trong cửa sổ mới, vui lòng nhập dữ liệu vào tất cả các trường. Hãy nhớ hai trường Mật khẩu tôi khuyên nên có cùng một mật khẩu; không sử dụng mật khẩu khác nhau; và cũng nhớ đường dẫn lưu ở đầu hầu hết trường Đường dẫn lưu trữ khóa : . Sau khi bạn nhập tất cả các trường bấm vào nút OK.

Đăng nhập tập tin Apk

Bây giờ bạn cần xây dựng một ứng dụng đã ký với tệp .keystore bạn vừa tạo. Thực hiện theo các bước sau

  1. Xây dựng> Dự án sạch, đợi cho đến khi hoàn thành việc dọn dẹp
  2. Xây dựng> Tạo APK đã ký
  3. Nhấn vào Choose existing...nút
  4. Chọn tập tin .keystore chúng ta vừa tạo ở Tạo .keystore tập tin phần
  5. Nhập cùng một mật khẩu bạn đã tạo trong khi tạo trong phần Tạo tệp .keystore . Sử dụng cùng một mật khẩu cho Key store passwordKey passwordcác lĩnh vực. Cũng nhập bí danh
  6. Nhấn nút tiếp theo
  7. Trong màn hình tiếp theo; có thể khác nhau dựa trên cài đặt của bạn trong build.gradletệp, bạn cần chọn Build TypesFlavors.
  8. Đối với Build Typeslựa chọn releasetừ thả xuống
  9. Flavorstuy nhiên nó sẽ phụ thuộc vào các thiết lập của bạn trong build.gradletập tin. Chọn stagingtừ lĩnh vực này. Tôi đã sử dụng các cài đặt sau trong build.gradle, bạn có thể sử dụng giống như của tôi, nhưng hãy đảm bảo bạn thay đổi applicationIdtên gói của bạn

    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. Nhấp vào hai Signature Versionshộp kiểm dưới cùng và nhấp vào Finishnút.

Hầu như ở đó:

Tất cả các công việc khó khăn đã được thực hiện, bây giờ là sự chuyển động của sự thật. Đặt hàng để truy cập máy chủ Staging được sao lưu bằng proxy, bạn cần thực hiện một số cài đặt trong các thiết bị Android thử nghiệm thực sự của mình.

Cài đặt proxy trong thiết bị Android:

  1. Nhấp vào Cài đặt bên trong điện thoại Android và sau đó wi-fi
  2. Nhấn và giữ kết nối wifi và chọn Modify network
  3. Nhấp vào Advanced optionsnếu bạn không thể nhìn thấy Proxy Hostnametrường
  4. Trong Proxy HostnameIP nhập hoặc tên máy chủ bạn muốn kết nối. Một máy chủ dàn điển hình sẽ được đặt tên làstg.api.mygoodcompany.com
  5. Ví dụ, đối với cổng, hãy nhập số cổng gồm bốn chữ số 9502
  6. Nhấn Savenút

Điểm dừng cuối cùng:

Hãy nhớ rằng chúng tôi đã tạo tệp apk đã ký trong phần Tệp APK Đăng nhập . Bây giờ là lúc để cài đặt tệp APK đó.

  1. Mở một thiết bị đầu cuối và thay đổi vào thư mục tệp apk đã ký
  2. Kết nối thiết bị Android của bạn với máy
  3. Xóa mọi tệp apk đã cài đặt trước đó khỏi thiết bị Android
  4. Chạy adb install name of the apk file
  5. Nếu vì lý do nào đó, lệnh trên trở lại với adb command not found. Nhập đường dẫn đầy đủ nhưC:\Users\shah\AppData\Local\Android\sdk\platform-tools\adb.exe install name of the apk file

Tôi hy vọng vấn đề có thể được giải quyết. Nếu không xin vui lòng để lại cho tôi một ý kiến.

Salam!


4

Thông báo lỗi tôi nhận được tương tự nhưng lý do là chứng chỉ tự ký đã hết hạn. Khi máy khách openssl được thử, nó cho tôi lý do bị bỏ qua khi tôi kiểm tra hộp thoại chứng chỉ từ firefox.

Vì vậy, nói chung, nếu chứng chỉ có trong kho khóa và "GIÁ TRỊ" của nó, lỗi này sẽ tắt.


1
Nếu chứng chỉ hết hạn, thì nó không có giá trị theo một số tiêu chuẩn. Bạn có thể sử dụng một tùy chỉnh TrustManagervà sử dụng một bộ tiêu chí khác nhau. Nhưng ngoài ra, đó là những gì bạn phải làm việc với.
jww

4

Tôi gặp vấn đề tương tự khi kết nối từ máy khách Android đến máy chủ Kurento. Máy chủ Kurento sử dụng chứng chỉ jks, vì vậy tôi phải chuyển đổi pem sang nó. Là đầu vào cho chuyển đổi, tôi đã sử dụng tệp cert.pem và nó dẫn đến các lỗi như vậy. Nhưng nếu sử dụng fullchain.pem thay vì cert.pem - tất cả đều ổn.


3

Sử dụng https://www.ssllabs.com/ssltest/ để kiểm tra tên miền.

Giải pháp của Shihab Uddin trong 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)
        }
}

2

Tôi đã có cùng một vấn đề mà tôi tìm thấy là tệp .crt chứng chỉ tôi cung cấp thiếu chứng chỉ trung gian. Vì vậy, tôi đã hỏi tất cả các tệp .crt từ quản trị viên máy chủ của mình, sau đó kết nối chúng theo thứ tự ngược lại.

Ví dụ. 1. Root.crt 2. Inter.crt 3. myCrt.crt

trong windows tôi đã thực thi sao chép Inter.crt + Root.crt newCert ve.crt

(Ở đây tôi bỏ qua myCrt.crt)

Sau đó, tôi đã cung cấp tệp newCertert.crt thành mã thông qua đầu vào. Công việc đã hoàn thành.


Chúng tôi cũng có vấn đề tương tự. Chứng chỉ trung gian bị thiếu
Nidhin Chandran

1

Lỗi neo tin cậy có thể xảy ra vì rất nhiều lý do. Đối với tôi, đơn giản là tôi đã cố gắng truy cập https://example.com/thay vìhttps://www.example.com/ .

Vì vậy, bạn có thể muốn kiểm tra kỹ các URL của mình trước khi bắt đầu xây dựng Trình quản lý ủy thác của riêng bạn (như tôi đã làm).


0

Trong điện thoại Gingerbread, tôi luôn gặp lỗi này: Trust Anchor not found for Android SSL Connection , ngay cả khi tôi thiết lập để dựa vào chứng chỉ của mình.

Đây là mã tôi sử dụng (bằng ngôn ngữ 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 _ 
        }
    }
}

và đây là mã kết nối:

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)
}

Về cơ bản, tôi thiết lập để tin tưởng vào chứng chỉ tùy chỉnh của mình. Nếu thất bại, sau đó tôi vô hiệu hóa bảo mật. Đây không phải là lựa chọn tốt nhất, nhưng là lựa chọn duy nhất tôi biết với điện thoại cũ và lỗi.

Mã mẫu này, có thể dễ dàng dịch sang Java.


Giải pháp cho Android 2.3.x trong trường hợp ai đó cần nó, stackoverflow.com/a/46465722/7125370
Newbie009

0

Trong trường hợp của tôi, điều này đã xảy ra sau khi cập nhật lên Android 8.0. Chứng chỉ tự ký Android được đặt thành tin cậy là sử dụng thuật toán chữ ký SHA1withRSA. Chuyển sang một chứng chỉ mới, sử dụng thuật toán chữ ký SHA256withRSA đã khắc phục sự cố.


0

Tôi biết rằng bạn không cần phải tin tưởng tất cả các chứng chỉ nhưng trong trường hợp của tôi, tôi gặp vấn đề với một số môi trường gỡ lỗi nơi chúng tôi có chứng chỉ tự ký và tôi cần một giải pháp bẩn.

Tất cả tôi phải làm là thay đổi việc khởi tạo sslContext

mySSLContext.init(null, trustAllCerts, null); 

nơi trustAllCertsđược tạo ra như thế này:

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 {
    }
} };

Hy vọng rằng điều này sẽ có ích.


Đó là điều tôi muốn tìm! Cảm ơn
oxed 18/12/18

Tôi nhận được lỗi Hostname '192.168.0.16' was not verified. Tôi đang kiểm tra webapi của mình thông qua trình gỡ lỗi (IIS Express) cục bộ. Bất kỳ ý tưởng làm thế nào để khắc phục điều này? Cảm ơn :)
Sam

1
Điều này là hoàn toàn không an toàn. Không được dùng.
Hầu tước Lorne

0

Tôi đã có một vấn đề tương tự và tôi đã loại trừ hoàn toàn chiến lược tin tưởng tất cả các nguồn.

Tôi chia sẻ ở đây giải pháp của tôi áp dụng cho một ứng dụng được triển khai trong Kotlin

Trước tiên tôi khuyên bạn nên sử dụng trang web sau để có được thông tin về chứng chỉ và hiệu lực của nó

Nếu nó không xuất hiện dưới dạng 'Nhà phát hành được chấp nhận' trong cửa hàng ủy thác mặc định của Android , chúng tôi phải lấy chứng chỉ đó và kết hợp nó vào ứng dụng để tạo cửa hàng ủy thác tùy chỉnh

Giải pháp lý tưởng trong trường hợp của tôi là tạo Trình quản lý ủy thác cấp cao kết hợp cửa hàng ủy thác mặc định tùy chỉnh và Android

Tại đây, anh ta trưng ra mã cấp cao được sử dụng để cấu hình OkHttpClient mà anh ta đã sử dụng với Retrofit.

override fun onBuildHttpClient(httpClientBuild: OkHttpClient.Builder) {

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

        printX509TrustManagerAcceptedIssuers(trustManagerWrapper)

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

    }

Bằng cách này, tôi có thể giao tiếp với máy chủ bằng chứng chỉ tự ký và với các máy chủ khác có chứng chỉ do tổ chức chứng nhận tin cậy cấp

Đây là nó, tôi hy vọng nó có thể giúp ai đó.


0

Tôi biết đây là một bài viết rất cũ, nhưng tôi đã xem qua bài viết này khi cố gắng giải quyết các vấn đề neo tin cậy của tôi. Tôi đã đăng cách tôi sửa nó. Nếu bạn đã cài đặt sẵn Root CA, bạn cần thêm cấu hình vào tệp kê khai.

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


chỉ dành cho API 24+
BekaBot

@BekaBot - điều này có thể đúng, nhưng theo tài liệu 23 và thấp hơn theo mặc định người dùng tin tưởng theo mặc định, các kết nối an toàn (sử dụng các giao thức như TLS và HTTPS) từ tất cả các ứng dụng tin tưởng các CA hệ thống được cài đặt sẵn và các ứng dụng nhắm mục tiêu Android 6.0 (API cấp 23) và thấp hơn cũng tin tưởng vào cửa hàng CA do người dùng thêm vào theo mặc định
GR Envoy

-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);

-2

Tôi cũng đã phải đối mặt với vấn đề tương tự. Tôi chỉ xóa hhtps để http, chẳng hạn như

final public static String ROOT_URL = "https://example.com"; đến final public static String ROOT_URL = "http://example.com";

Cuối cùng, tôi đã giải quyết vấn đề này.


Chắc chắn đây chỉ là loại bỏ bảo mật SSL khỏi phương trình, có lẽ là một ý tưởng tồi cho môi trường sản xuất.
Dragonthoughts

Đây thực sự không phải là một giải pháp, loại bỏ bảo mật SSL.
omega1
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.