我无法保留我的密码套件列表的顺序。我已经将顺序设置为我喜欢的方式,但是,当请求发出时,我检查密码组的顺序,它与我的原始顺序略有不同。我想知道okhttp是否通过MAP结构或其他方式对它们进行了重新排序。如果是,我想知道这是在哪里发生的,以便能够调整它以保持秩序。
我的连接规格使用:
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_1, TlsVersion.TLS_1_2,TlsVersion.TLS_1_3)
.cipherSuites(
CipherSuite.TLS_AES_128_GCM_SHA256,
CipherSuite.TLS_AES_256_GCM_SHA384,
CipherSuite.TLS_CHACHA20_POLY1305_SHA256,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384,
CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256,
CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256,
CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA
)
.build();我还想分享我正在使用的conscrypt,它支持这些密码套件。它们都由okhttp使用,但顺序不正确。
发布于 2020-11-04 19:35:49
尤里已经提到,这是OkHttp中的一个bug。我不太确定他们会以多快的速度修复它,但作为替代方案,您仍然可以使用委托sslsocketfactory而不是使用ConnectionSpec
设置示例如下:
你的SSL属性
SSLParameters sslParameters = new SSLParameters();
sslParameters.setProtocols(new String[]{"TLSv1.3", "TLSv1.2", "TLSv1.1"});
sslParameters.setCipherSuites(new String[]{
"TLS_AES_128_GCM_SHA256",
"TLS_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_RSA_WITH_AES_256_GCM_SHA384",
"TLS_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_256_CBC_SHA256",
"TLS_RSA_WITH_AES_128_CBC_SHA256",
"TLS_RSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
"TLS_RSA_WITH_3DES_EDE_CBC_SHA"
});您的自定义SSLSocketFactory
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public final class CompositeSSLSocketFactory extends SSLSocketFactory {
private final SSLSocketFactory sslSocketFactory;
private final SSLParameters sslParameters;
public CompositeSSLSocketFactory(SSLSocketFactory sslSocketFactory, SSLParameters sslParameters) {
this.sslSocketFactory = sslSocketFactory;
this.sslParameters = sslParameters;
}
@Override
public String[] getDefaultCipherSuites() {
return sslParameters.getCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return sslParameters.getCipherSuites();
}
@Override
public Socket createSocket() throws IOException {
Socket socket = sslSocketFactory.createSocket();
return withSslParameters(socket);
}
@Override
public Socket createSocket(Socket socket, InputStream inputStream, boolean autoClosable) throws IOException {
Socket newSocket = sslSocketFactory.createSocket(socket, inputStream, autoClosable);
return withSslParameters(newSocket);
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClosable) throws IOException {
Socket newSocket = sslSocketFactory.createSocket(socket, host, port, autoClosable);
return withSslParameters(newSocket);
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
Socket socket = sslSocketFactory.createSocket(host, port);
return withSslParameters(socket);
}
@Override
public Socket createSocket(String host, int port, InetAddress localAddress, int localPort) throws IOException, UnknownHostException {
Socket socket = sslSocketFactory.createSocket(host, port, localAddress, localPort);
return withSslParameters(socket);
}
@Override
public Socket createSocket(InetAddress address, int port) throws IOException {
Socket socket = sslSocketFactory.createSocket(address, port);
return withSslParameters(socket);
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
Socket socket = sslSocketFactory.createSocket(address, port, localAddress, localPort);
return withSslParameters(socket);
}
private Socket withSslParameters(Socket socket) {
if (socket instanceof SSLSocket) {
SSLSocket sslSocket = (SSLSocket) socket;
sslSocket.setSSLParameters(sslParameters);
}
return socket;
}
}Your OkHttp client configuration
SSLContext sslContext = ...; //your already initialised SSLContext
X509TrustManager trustManager = ...; //your already initialised TrustManager
SSLSocketFactory baseSocketFactory = sslContext.getSocketFactory();
SSLSocketFactory customSocketFactory = new CompositeSSLSocketFactory(baseSocketFactory, sslParameters);
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(customSocketFactory, trustManager)
.build();是的,它是冗长的,但是它将保持您定义的顺序:)我建议等待bug-fix,但如果您想自己暂时修复它,那么这将是一个选择。
发布于 2020-11-04 16:04:43
这看起来像是OkHttp https://github.com/square/okhttp/issues/6390中的错误
/**
* Returns an array containing only elements found in this array and also in [other]. The returned
* elements are in the same order as in this.
*/
fun Array<String>.intersect(
other: Array<String>,
comparator: Comparator<in String>
) private fun supportedSpec(sslSocket: SSLSocket, isFallback: Boolean): ConnectionSpec {
var cipherSuitesIntersection = if (cipherSuitesAsString != null) {
sslSocket.enabledCipherSuites.intersect(cipherSuitesAsString, CipherSuite.ORDER_BY_NAME)
} else {
sslSocket.enabledCipherSuites
}https://www.rfc-editor.org/rfc/rfc5246
The cipher suite list, passed from the client to the server in the
ClientHello message, contains the combinations of cryptographic
algorithms supported by the client in order of the client's
preference (favorite choice first). Each cipher suite defines a key
exchange algorithm, a bulk encryption algorithm (including secret key
length), a MAC algorithm, and a PRF. The server will select a cipher
suite or, if no acceptable choices are presented, return a handshake
failure alert and close the connection. If the list contains cipher
suites the server does not recognize, support, or wish to use, the
server MUST ignore those cipher suites, and process the remaining
ones as usual.https://stackoverflow.com/questions/64672259
复制相似问题