14

Mặc địnhHttpClient trong Android 5.0 Lollipop dường như bị hỏng. Nó không thể thiết lập kết nối đến một số trang web đã được thiết lập thành công bởi các phiên bản trước của Android.HttpClient thất bại với Handshake Không thành công trong Android 5.0 Lollipop

Ví dụ tôi cố gắng để kết nối với https://uralsg.megafon.ru

//Create httpclient like in https://stackoverflow.com/questions/18523784/ssl-tls-protocols-and-cipher-suites-with-the-androidhttpclient 
HttpClient client = new DefaultHttpClient(manager, params); 
HttpGet httpGet = new HttpGet("https://uralsg.megafon.ru"); 
HttpResponse client = httpclient.execute(httpGet); 

Mã này hoạt động trong Android 2,3-4,4, nhưng không thành công trên Android 5.0 (thiết bị và giả lập) với kết nối lỗi đóng by peer. Tất nhiên điều này là dễ hiểu vì Android 5.0 cố gắng kết nối máy chủ cũ này với TLSv1.2 và mật mã hiện đại và nó không hỗ trợ chúng.

Ok, sử dụng mã mẫu trong SSL/TLS protocols and cipher suites with the AndroidHttpClient chúng tôi giới hạn các giao thức và mật mã để TLSv1SSL_RSA_WITH_RC4_128_MD5. Bây giờ nó không thành công với một lỗi khác:

javax.net.ssl.SSLHandshakeException: Handshake failed 
caused by 
    error:140943FC:SSL routines:SSL3_READ_BYTES:sslv3 alert bad record mac 
    (external/openssl/ssl/s3_pkt.c:1286 0x7f74c1ef16e0:0x00000003) 
    at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake 

Và tất nhiên mã này chạy trơn tru trên Android 2.3-4.4.

Tôi đã kiểm tra giao thông với Wireshark:

302 4002.147873000 192.168.156.30 83.149.32.13 TLSv1 138 Client Hello 
303 4002.185362000 83.149.32.13 192.168.156.30 TLSv1 133 Server Hello 
304 4002.186700000 83.149.32.13 192.168.156.30 TLSv1 1244 Certificate 
305 4002.186701000 83.149.32.13 192.168.156.30 TLSv1 63 Server Hello Done 
307 4002.188117000 192.168.156.30 83.149.32.13 TLSv1 364 Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message 
308 4002.240695000 83.149.32.13 192.168.156.30 TLSv1 61 Alert (Level: Fatal, Description: Bad Record MAC) 

Bạn có thể thấy mối quan hệ đó được thành lập nhưng máy chủ báo vì nó có lẽ không thể giải mã thông điệp bắt tay được mã hóa.

Tôi không quản lý kết nối với https://uralsg.megafon.ru bằng cách sử dụng HttpClient trên Android 5.0. Trình duyệt cổ phiếu không kết nối nó mặc dù. Android 2.3-4.4 kết nối trang web này theo bất kỳ cách nào mà không gặp bất kỳ khó khăn nào.

Có cách nào để làm cho HttpClient có thể kết nối các trang web đó không? Đây chỉ là một ví dụ, tôi chắc chắn có rất nhiều máy chủ kế thừa không thể kết nối được với Android 5.0 và HttpClient.

+0

Tôi gặp vấn đề tương tự với điều này. Nếu tôi biết giải pháp, tôi sẽ thêm ý kiến. Nó thực sự khó chịu – cmcromance

Trả lời

5

cập nhật: nó hóa ra là lỗi trong phần back-end, không phải android 5, mặc dù thực sự với mật mã được đề cập.

Tôi gặp vấn đề tương tự. Đối với tôi nó hóa ra là mật mã TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 được chọn từ bộ mật mã mặc định của Android 5 (cập nhật).

Ngay sau khi tôi xóa nó khỏi danh sách khách hàng của mật mã được chấp nhận, kết nối lại hoạt động trở lại.

Các android 5 change log đề cập:

  • AES-GCM (AEAD) cipher suites are now enabled,

Tôi khá chắc chắn đây là thủ phạm. Ngay sau khi TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 được ưa thích (bởi máy chủ), kết nối sẽ không thành công.

Lưu ý rằng TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 hoạt động.

Tôi đoán là việc triển khai Android TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 là lỗi hoặc máy chủ bạn đang nói đến.

Giải pháp:

  1. Di TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 từ thuật toán mã hóa có sẵn trên máy chủ (không ứng dụng tái triển khai cần thiết).
  2. Di TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 từ danh sách các thuật toán mã hóa các cung cấp của khách hàng (trong CLIENT_HELLO).

Bạn có thể làm điều đó trên các mặt hàng bằng cách thực hiện SSLSocketFactory của riêng bạn và gọi

sslSocket.setEnabledCipherSuites(String[] suites); 

trên tạo SSLSocket.

chỉnh sửa: lưu ý rằng đây không nhất thiết phải là lỗi android, có thể là việc triển khai máy chủ bị lỗi. nếu vấn đề của bạn thực sự do mật mã gây ra, vui lòng để lại nhận xét trên trình theo dõi lỗi android] (https://code.google.com/p/android/issues/detail?id=81603). cảm ơn bạn!

+1

Nó không phải như vậy trong trường hợp của tôi. Trong trường hợp của tôi, trang web chỉ hỗ trợ SSL_RSA_WITH_RC4_128_MD5. Và khi tôi đề xuất nó sử dụng SSL_RSA_WITH_RC4_128_MD5 nó không thành công trên Lollipop và kết nối thành công trên Jelly Bean và bên dưới. –

+0

theo như tôi biết, SSL_RSA_WITH_RC4_128_MD5 đã bị xóa khỏi lollipop do cân nhắc bảo mật! xem https://code.google.com/p/android-developer-preview/issues/detail?id=1200#c8 – stefs

+0

Tôi biết, nhưng vấn đề là thêm nó theo cách thủ công không khắc phục được sự cố. . –

0

tôi đã cố gắng thay đổi bộ mật mã trong một nhà máy ổ cắm tùy chỉnh, nhưng điều đó không giúp đỡ. Trong trường hợp của tôi, tôi đã phải loại bỏ các giao thức TLSv1.1 và TLSv1.2 khỏi EnabledProtocols của socket. Nó xuất hiện rằng một số máy chủ cũ không xử lý các giao thức đàm phán cho các giao thức mới rất tốt. Có nhiều ví dụ khác nhau để tạo một nhà máy sản xuất ổ cắm tùy chỉnh, chẳng hạn như How to override the cipherlist sent to the server by Android when using HttpsURLConnection? và các ví dụ khác cho các ổ cắm Apache. Điều đó đang được thực hiện, tôi chỉ cần gọi phương thức AdjustSocket sau đây để loại bỏ các giao thức.

private void AdjustSocket(Socket socket) 
{ 
    String[] protocols = ((SSLSocket) socket).getSSLParameters().getProtocols(); 
    ArrayList<String> protocolList = new ArrayList<String>(Arrays.asList(protocols)); 

    for (int ii = protocolList.size() - 1; ii >= 0; --ii) 
     { 
     if ((protocolList.get(ii).contains("TLSv1.1")) || (protocolList.get(ii).contains("TLSv1.2"))) 
      protocolList.remove(ii); 
     } 

    protocols = protocolList.toArray(new String[protocolList.size()]); 
    ((SSLSocket)socket).setEnabledProtocols(protocols); 
} 
+0

tôi hạn chế các giao thức đến một trong SSLv3 , TLSv1, TLSv1.1 hoặc cao hơn bằng tay tất nhiên, nhưng nó đã không giúp đỡ trong trường hợp của tôi. –

Các vấn đề liên quan