gpt4 book ai didi

android - 尝试强制 Android 4.x(API 低于 20)上的应用程序使用 TLSv1.2

转载 作者:太空宇宙 更新时间:2023-11-03 13:32:54 29 4
gpt4 key购买 nike

我们的后端从 SHA-1 和 TLS 1.0 更新到 SHA-2 证书和 TLS 1.2。它会破坏我们的 Android 应用在API 级别低于 20 的平台(Android 4.1-4.4)上的 HTTPS 通信。

(我们的 Android 项目正在使用 Retrofit 2.4.0 & okhttp 3.10.0)

我尝试通过使用 TLS 1.2 在 Android 4.x 上强制我们的应用程序来解决上述问题,我的代码的灵感来自 this tutorial (但我排除了教程代码的公钥固定):

我首先创建了一个TLSSocketFactory:

public class TLSSocketFactory extends SSLSocketFactory {

private SSLSocketFactory internalSSLSocketFactory;

public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { systemDefaultTrustManager() }, null);
internalSSLSocketFactory = sslContext.getSocketFactory();
}

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

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

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

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

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

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

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

private Socket enableTLSOnSocket(Socket socket) {
if(socket != null && (socket instanceof SSLSocket)) {
((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
}
return socket;
}

public X509TrustManager systemDefaultTrustManager() {
try {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}
return (X509TrustManager) trustManagers[0];
} catch (GeneralSecurityException e) {
throw new AssertionError(); // The system has no TLS. Just give up.
}
}
}

然后,将上面的TLSSocketFactory应用到OkHttpClient:

OkHttpClient.Builder builder = new OkHttpClient.Builder();

ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_1, TlsVersion.TLS_1_2)
.cipherSuites(
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
.build();

builder.connectionSpecs(Collections.singletonList(spec));


builder.readTimeout(10, TimeUnit.SECONDS);
builder.connectTimeout(10, TimeUnit.SECONDS);
builder.writeTimeout(10, TimeUnit.SECONDS);

// apply TLSSocketFactory

try {
TLSSocketFactory socketFactory = new TLSSocketFactory();
builder.sslSocketFactory(socketFactory, socketFactory.systemDefaultTrustManager());
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}

OkHttpClient client = builder.build();

然后,使用上面的OkHttpClient创建一个Retrofit实例:

Retrofit retrofit = new Retrofit.Builder().baseUrl(myUrl)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client) // my OkHttpClient
.build();

但是,当我现在在与后端通信的 Android 4.x 上运行我的应用程序时,我仍然收到错误:

OkHttp: <-- HTTP FAILED: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

为什么?我错过了什么?

(在 TLSSocketFactory 的构造函数中,我也尝试了 sslContext.init(null, null, null); 但它没有帮助,同样的错误。)

(新证书没问题,适用于Android 5.0+,但新旧证书来自不同的颁发者)

最佳答案

我不明白为什么有必要调用这个方法 systemDefaultTrustManager

要使用系统默认值,请尝试替换

sslContext.init(null, new TrustManager[] { systemDefaultTrustManager() }, null);

通过

sslContext.init(null, null, null);

关于android - 尝试强制 Android 4.x(API 低于 20)上的应用程序使用 TLSv1.2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49394581/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com