1
votes

Firstly, I want to use session ticket in android, My code as follows: String keyStoreType = KeyStore.getDefaultType(); KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(null, null);

    String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
    tmf.init(keyStore);

    SSLContext cpmContext = SSLContext.getInstance("TLSv1.2");
    cpmContext.init(null, null, null);
    SSLSocket socket = (SSLSocket) cpmContext.getSocketFactory().createSocket(ip, port);
    socket.setEnabledProtocols(socket.getEnabledProtocols());
    socket.setEnabledCipherSuites(socket.getEnabledCipherSuites());
    Class c = socket.getClass();
    try {
        Method m = c.getMethod("setUseSessionTickets",boolean.class);
        m.invoke(socket,true);
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
    SSLSession session = socket.getSession();

I capture the data blcok by tcpdump, the code can get " TLSv1.2 224 New Session Ticket, Change Cipher Spec, Hello Request, Hello Request" ,so I think I get the session ticket, but when I reconnect to server, "session ticket "content of client hello is as follow: "Extension:sessionTicket TLS Type: SessionTicket TLS(0x0023) length:0 Data:(0 bytes)" it did not execute resume.

then I use SSLCertificateSocketFactory to create SSLSocket:

private Socket createSocketOnLine(final String ip, final int port) throws UnknownHostException, IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException, KeyManagementException {
    SSLCertificateSocketFactory sf = (SSLCertificateSocketFactory) SSLCertificateSocketFactory
            .getDefault(30 * 1000);
    SSLSocket socket = (SSLSocket) sf.createSocket(ip, port);
    socket.setEnabledProtocols(socket.getEnabledProtocols());
    socket.setEnabledCipherSuites(socket.getEnabledCipherSuites());
    enableSessionTicket(sf, socket);
    SSLSession session = socket.getSession();
    return socket;
}

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public void enableSessionTicket(SSLCertificateSocketFactory sf, Socket socket) {
    if (VERSION.SDK_INT > 17) {
        sf.setUseSessionTickets(socket, true);
    }
}

this code donot even enable session and the version of tls is always TLSv1.0,who can tell me how to enable it and set version of tls to be tlsv1.2? PS:I test it on android 4.4 and L

1

1 Answers

0
votes

Android's SSLCertificateSocketFactory is broken for you on some/many devices. It does not provide an interface/method for you to specify the enabled protocols. Instead, it simply uses the system default for the enabledProtocols. On earlier Android devices, that would be TLS and SSL3 and not TLSv1.2.

Because of the way it is implemented, you can't subclass it and attempt to override its behavior. There is no way for you to set the TLS protocol you want, let alone to set the ciphersuites that you may need to control.

Unfortunately, some of the other features of SSLCertificateSocketFactory are lost as well. For example, you can't enable SNI or set alpns protocols "officially" without it.

Thus, your solution will need to subclass SSLSocketFactory to provide your own socketfactory to control the settings you need as you do in your first code example. You can use your reflection trick above to enable session tickets in your own createSocket() method implementations.