안 드 로 이 드 에서 TLS 버 전 별 지원 현황

14942 단어 Android
저작권 성명: 전 재 는 반드시 본 고 를 엄 진 걸 의 블 로그 로 옮 겨 야 한다.http://blog.yanzhenjie.com
본 고 에서 해결 해 야 할 두 가지 문제:
  • Android 4.1 - Andreid 5.0 시스템 에서 TLSv 1.1 과 TLSv 1.2
  • 사용 하기
  • java.lang.IllegalArgumentException: protocol TLSv1.1 is not supported

  • 이 두 문 제 는 비교적 대표 적 이 고 단체 에서 토론 할 때 본 횟수 도 가장 많 기 때문에 어떤 사람들 이 겪 는 문 제 는 협의 명칭 이 다 를 수 있 지만 본질 은 모두 유사 하 다.
    문제 원인 과 해결 방향 분석
    Android 5.0 행동 변경 을 보면 Android 5.0 부터 TLSv 1.1 과 TLSv 1.2 를 기본 으로 사 용 했 지만 Android 4.1 부터 TLSv 1.1 과 TLSv 1.2 가 지원 되 었 습 니 다. 기본 값 으로 사용 되 지 않 았 을 뿐 입 니 다.
    우리 가 가장 자주 사용 하 는 몇 가지 협 의 는 SSLv 3, TLSv 1, TLSv 1.1 과 TLSv 1.2 입 니 다. 상기 두 가지 문 제 를 해결 하려 면 이 몇 가지 협의 가 안 드 로 이 드 시스템 에서 지원 되 는 상황 과 사용 되 는 상황 을 알 아야 합 니 다. 그리고 우 리 는 minSdkVersion 과 targetSdkVersion 을 결합 하여 협 의 를 선택 하면 됩 니 다. 서로 다른 버 전의 안 드 로 이 드 시스템 이 상기 협의 에 대한 지원 상황 은 다음 과 같 습 니 다.
    클 라 이언 트 (SSLSocket) 의 지원 현황:
    협의
    지원 됨 (Api 레벨)
    활성화 됨 (Api 레벨)
    SSLv3
    1–25
    1–22
    TLSv1
    1+
    1+
    TLSv1.1
    16+
    20+
    TLSv1.2
    16+
    20+
    서버 (SSLServerSocket) 의 지원 현황:
    협의
    지원 됨 (Api 레벨)
    활성화 됨 (Api 레벨)
    SSLv3
    1–25
    1–22
    TLSv1
    1+
    1+
    TLSv1.1
    16+
    16+
    TLSv1.2
    16+
    16+
    데이터 원본:https://developer.android.com/reference/javax/net/ssl/SSLSocket
    메모: 여기 서 말 하 는 클 라 이언 트 와 서버 는 안 드 로 이 드 엔 드 와 자바 엔 드 / PHP 엔 드 (그리고 Python,. NET 등) 가 아니 라 안 드 로 이 드 개발 중인 클 라 이언 트 Socket (SSLSocket) 과 서버 Socket (SSLServerSocket) 을 말 합 니 다.
    여기 서 본문 이 시작 한 문제 의 원인 을 알 수 있 습 니 다. TLSv 1.1 과 TLSv 1.2 는 Android 4.1 (Api 급 16) 부터 지원 되 고 Android 4.4 Wear (Api 급 20) 에서 만 사용 되 기 때문에 서로 다른 버 전의 Android 시스템 에서 타 임 스 를 사용 하고 사용 해 야 하 는 문제 가 발생 합 니 다.
    TLS 프로 토 콜 에서 통용 되 는 호 환 클래스 를 쓸 수 있 습 니 다. 모든 Android 에서 지원 되 는 모든 프로 토 콜 을 강제로 사용 할 수 있 습 니 다. 요약 하면 Android 8.0 이상 시스템 은 TLSv 1, TLSv 1.1 과 TLSv 1.2 프로 토 콜 을 강제 적 으로 사용 할 수 있 습 니 다. Android 4.1 - android 7.1.1 시스템 은 SSLv 3, TLSv 1, TLSv 1.1 과 TLSv 1.2 프로 토 콜 을 강제 적 으로 사용 할 수 있 습 니 다.다른 버 전 시스템 은 SSLv 3 와 TLSv 1 프로 토 콜 을 강제로 사용 할 수 있 습 니 다.
    다시 말 하면 개발 자가 SSLv 3 프로 토 콜 을 사용 하면 minSdkVersion 은 제한 이 없고 targetSdkVersion 은 25 보다 높 지 않 으 며 TLSv 1.1 프로 토 콜 이나 TLS 1.2 프로 토 콜 로 빨리 업데이트 해 야 합 니 다.개발 자가 TLSv 1.1 프로 토 콜 이나 TLSv 1.2 프로 토 콜 을 사용한다 면 minSdkVersion 은 16 보다 낮 지 않 고 targetSdkVersion 은 제한 하지 않 습 니 다.개발 자가 TLSv 1 프로 토 콜 을 사용한다 면 현재 제한 을 받 지 않 습 니 다.
    본 논문 의 내용 은 현재 본인 이 알 고 있 는 지식 입 니 다. 만약 에 다른 더 좋 은 해결 방안 이나 본 고 에서 말 하지 못 한 요점 이 있 으 면 독자 가 평론 에서 알려 주 십시오!
    코드 구현
    SSLSocket 에 해당 하 는 프로 토 콜 을 사용 하도록 해 야 합 니 다. 코드 에 대응 하 는 방법 은:
    SSLSocket#setEnabledProtocols(String[]);
    

    따라서 우 리 는 먼저 서로 다른 버 전의 안 드 로 이 드 시스템 에서 서로 다른 프로 토 콜 배열 을 생 성 해 야 한다.
    private static final String PROTOCOL_ARRAY[];
    
    static {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            PROTOCOL_ARRAY = new String[]{"TLSv1", "TLSv1.1", "TLSv1.2"};
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            PROTOCOL_ARRAY = new String[]{"SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"};
        } else {
            PROTOCOL_ARRAY = new String[]{"SSLv3", "TLSv1"};
        }
    }
    

    SSLSocket 은 SSLSocketFactory 가 책임 지고 생 성 된 것 입 니 다. SSLSocketFactory 의 포장 류 를 하나 더 쓰 겠 습 니 다. 주요 코드 는 다음 과 같 습 니 다.
    public class TLSSocketFactory extends SSLSocketFactory {
    
        private static final String PROTOCOL_ARRAY[];
    
        static {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                PROTOCOL_ARRAY = new String[]{"TLSv1", "TLSv1.1", "TLSv1.2"};
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                PROTOCOL_ARRAY = new String[]{"SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"};
            } else {
                PROTOCOL_ARRAY = new String[]{"SSLv3", "TLSv1"};
            }
        }
    
        private SSLSocketFactory delegate;
    
        /**
         *       ,           SSLSocket。
         */
        public TLSSocketFactory() {
            try {
                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, new TrustManager[]{DEFAULT_TRUST_MANAGERS}, new SecureRandom());
                delegate = sslContext.getSocketFactory();
            } catch (GeneralSecurityException e) {
                throw new AssertionError(); // The system has no TLS. Just give up.
            }
        }
    
        /**
         *   SSLSocketFactory     ,      SSLScoket      。
         */
        public TLSSocketFactory(SSLSocketFactory factory) {
            this.delegate = factory;
        }
    
        /**
         *    SSLSocket,      。
         */
        private static void setSupportProtocolAndCipherSuites(Socket socket) {
            if (socket instanceof SSLSocket) {
                ((SSLSocket) socket).setEnabledProtocols(PROTOCOL_ARRAY);
            }
        }
    
        // TODO        createSocket()    setSupportProtocolAndCipherSuites()     。
    }
    

    전체 소스 코드 는 gist 를 Github 에 넣 었 습 니 다.https://gist.github.com/yanzhenjie/f7217f3fc0f641d9ef50ca0145a7185c
    특히 멤버 변수 delegate 는 클 라 이언 트 가 OkHttp (본인 이 okhttp - urlconnection 을 사용 할 때 발생 하 는 문제 이 며, OkHttp 를 직접 사용 하 는 데 문제 가 있 는 지 테스트 하지 않 았 을 때 OkHttp 는 SSLSocketFactory delegate 변 수 를 반사 하여 조작 을 합 니 다. 그렇지 않 으 면 Https 요청 에 실패 하 는 문제 가 발생 할 수 있 습 니 다.
    본문 을 쓸 때 OkHttp 의 버 전 은 3.10.0 이 고 관련 소스 주소:https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/internal/platform/Platform.java
    저작권 성명: 전 재 는 반드시 본 고 를 엄 진 걸 의 블 로그 로 옮 겨 야 한다.http://blog.yanzhenjie.com

    좋은 웹페이지 즐겨찾기