okhttp3.recipes.CustomCipherSuites Maven / Gradle / Ivy
/*
* Copyright (C) 2017 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.recipes;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.security.GeneralSecurityException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import okhttp3.CipherSuite;
import okhttp3.ConnectionSpec;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public final class CustomCipherSuites {
private final OkHttpClient client;
public CustomCipherSuites() throws GeneralSecurityException {
// Configure cipher suites to demonstrate how to customize which cipher suites will be used for
// an OkHttp request. In order to be selected a cipher suite must be included in both OkHttp's
// connection spec and in the SSLSocket's enabled cipher suites array. Most applications should
// not customize the cipher suites list.
List customCipherSuites = Arrays.asList(
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384);
final ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.cipherSuites(customCipherSuites.toArray(new CipherSuite[0]))
.build();
X509TrustManager trustManager = defaultTrustManager();
SSLSocketFactory sslSocketFactory = defaultSslSocketFactory(trustManager);
SSLSocketFactory customSslSocketFactory = new DelegatingSSLSocketFactory(sslSocketFactory) {
@Override protected SSLSocket configureSocket(SSLSocket socket) throws IOException {
socket.setEnabledCipherSuites(javaNames(spec.cipherSuites()));
return socket;
}
};
client = new OkHttpClient.Builder()
.connectionSpecs(Collections.singletonList(spec))
.sslSocketFactory(customSslSocketFactory, trustManager)
.build();
}
/**
* Returns the VM's default SSL socket factory, using {@code trustManager} for trusted root
* certificates.
*/
private SSLSocketFactory defaultSslSocketFactory(X509TrustManager trustManager)
throws NoSuchAlgorithmException, KeyManagementException {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { trustManager }, null);
return sslContext.getSocketFactory();
}
/** Returns a trust manager that trusts the VM's default certificate authorities. */
private X509TrustManager defaultTrustManager() throws GeneralSecurityException {
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];
}
private String[] javaNames(List cipherSuites) {
String[] result = new String[cipherSuites.size()];
for (int i = 0; i < result.length; i++) {
result[i] = cipherSuites.get(i).javaName();
}
return result;
}
/**
* An SSL socket factory that forwards all calls to a delegate. Override {@link #configureSocket}
* to customize a created socket before it is returned.
*/
static class DelegatingSSLSocketFactory extends SSLSocketFactory {
protected final SSLSocketFactory delegate;
DelegatingSSLSocketFactory(SSLSocketFactory delegate) {
this.delegate = delegate;
}
@Override public String[] getDefaultCipherSuites() {
return delegate.getDefaultCipherSuites();
}
@Override public String[] getSupportedCipherSuites() {
return delegate.getSupportedCipherSuites();
}
@Override public Socket createSocket(
Socket socket, String host, int port, boolean autoClose) throws IOException {
return configureSocket((SSLSocket) delegate.createSocket(socket, host, port, autoClose));
}
@Override public Socket createSocket(String host, int port) throws IOException {
return configureSocket((SSLSocket) delegate.createSocket(host, port));
}
@Override public Socket createSocket(
String host, int port, InetAddress localHost, int localPort) throws IOException {
return configureSocket((SSLSocket) delegate.createSocket(host, port, localHost, localPort));
}
@Override public Socket createSocket(InetAddress host, int port) throws IOException {
return configureSocket((SSLSocket) delegate.createSocket(host, port));
}
@Override public Socket createSocket(
InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return configureSocket((SSLSocket) delegate.createSocket(
address, port, localAddress, localPort));
}
protected SSLSocket configureSocket(SSLSocket socket) throws IOException {
return socket;
}
}
public void run() throws Exception {
Request request = new Request.Builder()
.url("https://publicobject.com/helloworld.txt")
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.handshake().cipherSuite());
System.out.println(response.body().string());
}
}
public static void main(String... args) throws Exception {
new CustomCipherSuites().run();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy