美文网首页
关于Okhttp3 支持TLSv1.2

关于Okhttp3 支持TLSv1.2

作者: Cheep | 来源:发表于2018-11-19 12:21 被阅读0次

TLSv1.2升级方案讨论

实际上在这次需求之前,我都没有遇到过这方便的需求,了解的也比较少。我是比较佩服我们后台的,我们后台比较霸气,直接在生产环境就升级了后台的协议,而且是只支持TLSv1.2版本。当然最终导致的问题是所有接口都失效了,然后就开始甩锅。我更新了这个是为了整个项目安全,但现在你看看在Ios上面运行没有问题,在Android上面出现了问题,你们Android开发是怎么办事的,略略略。。。
好废话少说我们先进正题。这个是在https要求下的协议对应版本,ps:下面的图片摘自 【csdn严振杰】


协议对应的支持版本

从表上我们可以发现,实际上16+以后我们就支持了TLSv1.2,而TLSv1.2在20+的版本才被启用。这说明在Android16+的版本我们支持了TLSv1.2,但是系统默认使用的是TLSv1.0。这里需要我们支持TLSv1.2,按照支持表,给SSLSocket设置默认使用TLSv1.2版本就可以了。

TLSv1.2方案验证一

重写SSLSocketFactory,setEnabledProtocols ,TLSv1.2

class Tls12SocketFactory extends SSLSocketFactory {
    private  final String[] TLS_SUPPORT_VERSION = {"TLSv1.2"};

    final SSLSocketFactory delegate;

    public Tls12SocketFactory(SSLSocketFactory base) {
        this.delegate = base;
    }

    @Override
    public String[] getDefaultCipherSuites() {
        return delegate.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return delegate.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
        return patch(delegate.createSocket(s, host, port, autoClose));
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
        return patch(delegate.createSocket(host, port));
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
        return patch(delegate.createSocket(host, port, localHost, localPort));
    }

    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        return patch(delegate.createSocket(host, port));
    }

    @Override
    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
        return patch(delegate.createSocket(address, port, localAddress, localPort));
    }

    private Socket patch(Socket s) {
        if (s instanceof SSLSocket) {
            ((SSLSocket) s).setEnabledProtocols(TLS_SUPPORT_VERSION);
        }
        return s;
    }
}

然而我用模拟器测试并卵用,找不到4.4的手机了。

TLSv1.2方案验证二

我就想到是不是SSLContext没有设置对,我换用了一种全面点的写法

public class TLSSocketFactory extends SSLSocketFactory {

private static final String PROTOCOL_ARRAY[];

static {
    // https://developer.android.com/about/versions/android-5.0-changes.html#ssl
    // https://developer.android.com/reference/javax/net/ssl/SSLSocket
    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 static final X509TrustManager DEFAULT_TRUST_MANAGERS = new X509TrustManager() {

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) {
        // Trust.
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) {
        // Trust.
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
};

private static void setSupportProtocolAndCipherSuites(Socket socket) {
    if (socket instanceof SSLSocket) {
        ((SSLSocket) socket).setEnabledProtocols(PROTOCOL_ARRAY);
    }
}

private SSLSocketFactory delegate;

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

public TLSSocketFactory(SSLSocketFactory factory) {
    this.delegate = factory;
}


@Override
public String[] getDefaultCipherSuites() {
    return delegate.getDefaultCipherSuites();
}

@Override
public String[] getSupportedCipherSuites() {
    return delegate.getSupportedCipherSuites();
}

@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
    Socket ssl = delegate.createSocket(s, host, port, autoClose);
    setSupportProtocolAndCipherSuites(ssl);
    return ssl;
}

@Override
public Socket createSocket(String host, int port) throws IOException {
    Socket ssl = delegate.createSocket(host, port);
    setSupportProtocolAndCipherSuites(ssl);
    return ssl;
}

@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
    Socket ssl = delegate.createSocket(host, port, localHost, localPort);
    setSupportProtocolAndCipherSuites(ssl);
    return ssl;
}

@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
    Socket ssl = delegate.createSocket(host, port);
    setSupportProtocolAndCipherSuites(ssl);
    return ssl;
}

@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
    Socket ssl = delegate.createSocket(address, port, localAddress, localPort);
    setSupportProtocolAndCipherSuites(ssl);
    return ssl;
}

@Override
public Socket createSocket() throws IOException {
    Socket ssl = delegate.createSocket();
    setSupportProtocolAndCipherSuites(ssl);
    return ssl;
}
}

好吧,模拟器依然不识别,报错信息如下:
Error-javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb85e6050: Failure in SSL library, usually a protocol
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x84db0770:0x00000000)

结论

暂时我选择的版本升级到20+,甲方目前也接受。从后台统计的用户使用情况可以看出,用户的Android版本几乎在23+。只是有个梗卡着。如果有4.4真机的童鞋,麻烦下面留个言,看看方案是否通过。

相关文章

网友评论

      本文标题:关于Okhttp3 支持TLSv1.2

      本文链接:https://www.haomeiwen.com/subject/yhpofqtx.html