首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在OkHttp中保留密码套件列表的顺序?

如何在OkHttp中保留密码套件列表的顺序?
EN

Stack Overflow用户
提问于 2020-11-04 07:30:48
回答 2查看 169关注 0票数 2

我无法保留我的密码套件列表的顺序。我已经将顺序设置为我喜欢的方式,但是,当请求发出时,我检查密码组的顺序,它与我的原始顺序略有不同。我想知道okhttp是否通过MAP结构或其他方式对它们进行了重新排序。如果是,我想知道这是在哪里发生的,以便能够调整它以保持秩序。

我的连接规格使用:

代码语言:javascript
复制
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使用,但顺序不正确。

EN

回答 2

Stack Overflow用户

发布于 2020-11-04 19:35:49

尤里已经提到,这是OkHttp中的一个bug。我不太确定他们会以多快的速度修复它,但作为替代方案,您仍然可以使用委托sslsocketfactory而不是使用ConnectionSpec

设置示例如下:

你的SSL属性

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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,但如果您想自己暂时修复它,那么这将是一个选择。

票数 1
EN

Stack Overflow用户

发布于 2020-11-04 16:04:43

这看起来像是OkHttp https://github.com/square/okhttp/issues/6390中的错误

代码语言:javascript
复制
/**
 * 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>
)
代码语言:javascript
复制
  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

代码语言:javascript
复制
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.
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64672259

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档