Note: this question has been asked numerous times for Java HTTPS clients; my question is about configuring a server.
I'm trying to use MockWebServer to test my OkHttpClient configuration. The real web server my code hits just dropped TLS v1.0 support, so I'm changing my code to use TLS v1.2 and use the server's preferred cipher suites. I'd like to test this change with an in-memory web server that mimics the real server, but I can't figure out how to configure a SSLContext
in my test with a specific list of cipher suites. (All the methods I need to access are pretty well protected inside of SSLContextImpl
and its inner classes.)
The best I've been able to figure out is completely wrapping a SSLServerSocketFactory, overriding the 4 createServerSocket() methods, and calling setEnabledCipherSuites()
on the SSLServerSocket
before returning it, similar to how this answer did with SSLSocketFactoryEx on the client: https://stackoverflow.com/a/23365536/278800
It's frustrating that using a specific TLS version is as simple as calling e.g. SSLContext.getInstance("TLSv1.2")
, but there isn't a similarly easy way to configure the cipher suites.
To add cipher suites, either deploy a group policy or use the TLS cmdlets: To use group policy, configure SSL Cipher Suite Order under Computer Configuration > Administrative Templates > Network > SSL Configuration Settings with the priority list for all cipher suites you want enabled.
The way I ended up doing it was to wrap the underlying SSLSocketFactory, and call sslSocket.setEnabledCipherSuites(..)
on the SSLSocket before returning it, like so:
final class MySSLSocketFactory extends SSLSocketFactory {
final SSLSocketFactory wrappedSSLSocketFactory;
MySSLSocketFactory(SSLSocketFactory wrappedSSLSocketFactory) {
this.wrappedSSLSocketFactory = wrappedSSLSocketFactory;
}
@Override
public String[] getDefaultCipherSuites() {
return getMyCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return getMyCipherSuites();
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
final SSLSocket sslSocket = (SSLSocket) wrappedSSLSocketFactory.createSocket(s, host, port, autoClose);
// change the supported cipher suites on the socket, *before* it's returned to the client
sslSocket.setEnabledCipherSuites(getMyCipherSuites());
return sslSocket;
}
// other overloaded createSocket() methods do the same
private String[] getMyCipherSuites() {
// TODO: change this to return whatever cipher suites you want the server to use, from CipherSuite
return new String[] {...};
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With