Java客户端连接错误:ChangeCipherSpec消息序列冲突

时间:2019-01-02 05:19:01

标签: java ssl encryption

我有一个运行了一段时间的客户端服务器应用程序。
尝试从客户端连接时,突然出现以下错误。我在服务器端没有看到错误。证书没有过期,我没有进行任何代码更改。在Google搜索此错误时,没有看到任何结果。

javax.net.ssl.SSLProtocolException: ChangeCipherSpec message sequence violation
    at sun.security.ssl.HandshakeStateManager.changeCipherSpec(Unknown Source)
    at sun.security.ssl.Handshaker.receiveChangeCipherSpec(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.readDataRecord(Unknown Source)
    at sun.security.ssl.AppInputStream.read(Unknown Source)
    at sun.security.ssl.AppInputStream.read(Unknown Source)
    at java.io.DataInputStream.readUnsignedShort(Unknown Source)
    at java.io.DataInputStream.readUTF(Unknown Source)
    at java.io.DataInputStream.readUTF(Unknown Source)
    at com.jayavon.game.client.cj.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

客户代码:

//load your key store as a stream and initialize a KeyStore
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());    

//if your store is password protected then declare it (it can be null however)
String tsName = "res/gamedata/truststore";
char[] trustPassword = "--REMOVED--".toCharArray();

//load the stream to your store
trustStore.load(new FileInputStream(tsName), trustPassword);

//initialize a trust manager factory with the trusted store
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());    
trustFactory.init(trustStore);

//get the trust managers from the factory
TrustManager[] trustManagers = trustFactory.getTrustManagers();

//initialize an ssl context to use these managers and set as default
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManagers, null);
SSLContext.setDefault(sslContext);

//create sslfactory from the ssl context
SSLSocketFactory factory = sslContext.getSocketFactory();

if (isPROD){
    sC = (SSLSocket) factory.createSocket("--REMOVED--", --REMOVED--);
} else {
    sC = (SSLSocket) factory.createSocket("localhost", --REMOVED--);
}

sC.addHandshakeCompletedListener(new HandshakeCompletedListener(){
    @Override
    public void handshakeCompleted(HandshakeCompletedEvent arg0) {
        logger.info("------HANDSHAKE START------");
        logger.info("Cipher suite: " + arg0.getCipherSuite());

        logger.info("Local Principal: " + arg0.getLocalPrincipal());

        X509Certificate[] peerCertChain = null;
        try {
            peerCertChain = arg0.getPeerCertificateChain();
        } catch (SSLPeerUnverifiedException e1) {
            logger.error("arg0.getPeerCertificateChain()", e1);
        }
        for (X509Certificate s: peerCertChain){
            logger.info("Local Certificate(SigAlgName): " + s.getSigAlgName());
            logger.info("Local Certificate(SigAlgOID): " + s.getSigAlgOID());
            logger.info("Local Certificate(Version): " + s.getVersion());
            logger.info("Local Certificate(IssuerDN): " + s.getIssuerDN());
            logger.info("Local Certificate(NotAfter): " + s.getNotAfter());
            logger.info("Local Certificate(NotBefore): " + s.getNotBefore());
            logger.info("Local Certificate(PublicKey): " + s.getPublicKey());
            logger.info("Local Certificate(SerialNumber): " + s.getSerialNumber());
            logger.info("Local Certificate(SubjectDN): " + s.getSubjectDN());
        }

        Certificate[] peerCertificates = null;
        try {
            peerCertificates = arg0.getPeerCertificates();
        } catch (SSLPeerUnverifiedException e) {
            logger.error("arg0.getPeerCertificates()", e);
        }
        for (Certificate s: peerCertificates){
            logger.info("Peer Certificate(public key): " + s.getPublicKey());
        }

        try {
            logger.info("Peer Principal: " + arg0.getPeerPrincipal());
        } catch (SSLPeerUnverifiedException e) {
            logger.error("arg0.getPeerPrincipal()", e);
        }
        logger.info("Session: " + arg0.getSession());
        logger.info("Socket: " + arg0.getSocket());
        logger.info("Source: " + arg0.getSource());
        logger.info("------HANDSHAKE DONE------");
    }
});

sC.startHandshake();

服务器代码:

String ksName = "res/gamedata/server.keystore";
char ksPass[] = "--REMOVED--".toCharArray();

//create new keystore instance
KeyStore ks = KeyStore.getInstance("JKS");

//load the keystore with password into the keystore
ks.load(new FileInputStream(ksName), ksPass);

//create a new keymanagerfactory and initalize with the keystore
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, ksPass);

//initialize an ssl context with TLS with the keymanagers(server certificate/decrypted private key)
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), null, null);

//create sslfactory from the ssl context
SSLServerSocketFactory ssf = sc.getServerSocketFactory();

//create the server socket for clients to connect to
s = (SSLServerSocket) ssf.createServerSocket(--REMOVED--);

sC = (SSLSocket) s.accept();

sC.addHandshakeCompletedListener(new HandshakeCompletedListener(){
    @Override
    public void handshakeCompleted(HandshakeCompletedEvent arg0) {
        LOGGER.info("------HANDSHAKE START------");
        LOGGER.info("Cipher suite: " + arg0.getCipherSuite());

        Certificate[] localCerts = arg0.getLocalCertificates();
        for (Certificate s: localCerts){
            LOGGER.info("Local Certificate(public key): " + s.getPublicKey());
        }

        LOGGER.info("Local Principal: " + arg0.getLocalPrincipal());

        LOGGER.info("Session: " + arg0.getSession());
        LOGGER.info("Socket: " + arg0.getSocket());
        LOGGER.info("Source: " + arg0.getSource());
        LOGGER.info("------HANDSHAKE DONE------");
    }
});

try {
    sC.startHandshake();
} catch (SSLHandshakeException e2){
    LOGGER.error("client handshake issue for IP(" + sC.getLocalAddress().toString() + ")", e2);
}

1 个答案:

答案 0 :(得分:0)

解决方案是遵循David的评论。

sC.setEnabledProtocols(new String[]{"TLSv1.2"});