This question already has an answer here:
SSLEngine unwrap() javax.crypto.BadPaddingException: bad record MAC
                                
                                    (1个答案)
                                
                        
                                2年前关闭。
            
                    
我正在使用Java 9提供的DTLS1.0。它成功生成Client Hello,服务器响应返回

 1. Server Hello
 2. Certificate
 3. Server Key Exchange
 4. Certificate Request
 5. Server Hello Done


然后SSLEngine给出NEED_UNWRAP。解包包含Server Hello Done的数据包后,它再次给出NEED_UNWRAP。解开下一个重新传输的Server Hello Done后,它再次给出NEED_UNWRAP。一遍又一遍。但是我认为它应该通过给出NEED_WRAP来生成下一个握手信号。

如果我错了,请纠正我。否则为什么会发生?

信托经理:

    final TrustManager[] trustAllCerts = new TrustManager[] {
        new X509TrustManager() {

            public X509Certificate[] getAcceptedIssuers() {
                // TODO Auto-generated method stub
                return null;
            }

            public void checkServerTrusted(X509Certificate[] arg0, String arg1)
                    throws CertificateException {
                // TODO Auto-generated method stub

            }

            public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                    throws CertificateException {
                // TODO Auto-generated method stub

            }
        }
    };


SSLEngine:

        char[] passphrase = "123456".toCharArray();//This is the password

        // First initialize the key and trust material
        KeyStore ksKeys = KeyStore.getInstance("JKS");
        ksKeys.load(new FileInputStream("keystore"), passphrase);

        // KeyManagers decide which key material to use
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(ksKeys, passphrase);


        SSLContext sslContext = SSLContext.getInstance("DTLSv1.0");
        sslContext.init(kmf.getKeyManagers(), trustAllCerts, null);


        int port2 = Queuemanager.switchMediaHandler.get("192.168.19.148").realPort;
        // Create the engine
        engine = sslContext.createSSLEngine("192.168.19.148", port2);

        // Use as client
        engine.setUseClientMode(true);
        engine.setEnableSessionCreation(true);


握手:

    void doHandshake(){
    engine.beginHandshake();
    SSLEngineResult result;
    HandshakeStatus handshakeStatus;
    int appBufferSize = engine.getSession().getApplicationBufferSize();
    ByteBuffer myAppData = ByteBuffer.allocate(appBufferSize);
    ByteBuffer peerAppData = ByteBuffer.allocate(appBufferSize);
    myNetData.clear();
    peerNetData.clear();

    handshakeStatus = engine.getHandshakeStatus();
    while (handshakeStatus != SSLEngineResult.HandshakeStatus.FINISHED && handshakeStatus != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
        switch (handshakeStatus) {
        case NEED_UNWRAP_AGAIN:
            logger.debug("NEED_UNWRAP_AGAIN");
        case NEED_UNWRAP:
            logger.debug("NEED_UNWRAP");
            DatagramPacket packet = null;
           if(handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP ) {
            try {
                byte[] buf = new byte[1024];
                packet = new DatagramPacket(buf, buf.length);
                socket.receive(packet);
                peerNetData = ByteBuffer.wrap(buf, 0, packet.getLength());
                peerAppData =  ByteBuffer.allocate(appBufferSize);
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
          }else{
               peerNetData = ByteBuffer.allocate(0);
               peerAppData =  ByteBuffer.allocate(appBufferSize);
           }


            SSLEngineResult.Status rs;
            result = null;
            try {

                handshakeStatus = engine.getHandshakeStatus();
                while(handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP || handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP_AGAIN) {
                    result = engine.unwrap(peerNetData, peerAppData);
                    peerNetData.compact();
                    handshakeStatus = result.getHandshakeStatus();
                 }

                handshakeStatus = result.getHandshakeStatus();

                rs = result.getStatus();

            } catch (SSLException sslException) {
                engine.closeOutbound();
                break;
            }
            switch (rs) {
            case OK:
                break;
            case BUFFER_OVERFLOW:
                break;
            case BUFFER_UNDERFLOW:
                break;
            case CLOSED:
            default:
                throw new IllegalStateException("Invalid SSL status: " + result.getStatus());
            }
            break;
        case NEED_WRAP:
            logger.debug("NEED_WRAP");
            myNetData.clear();
            try {
                result = engine.wrap(myAppData, myNetData);
                handshakeStatus = result.getHandshakeStatus();
            } catch (SSLException sslException) {
                engine.closeOutbound();
                handshakeStatus = engine.getHandshakeStatus();
                break;
            }
            switch (result.getStatus()) {
            case OK :

                while (myNetData.hasRemaining()) {
                    //String str = myNetData.toString();
                    byte[] arr = new byte[myNetData.remaining()];
                    myNetData.get(arr);
                    recvPacket = new DatagramPacket(arr, arr.length);
                    recvPacket.setData(arr);

                    try {
                        int port2 = Queuemanager.switchMediaHandler.get("192.168.19.148").realPort;

                        InetAddress ip = InetAddress.getByName("192.168.19.148");

                        recvPacket.setAddress(ip);
                        recvPacket.setPort(port2);

                        socket.send(recvPacket);

                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    //socketChannel.write(myNetData);
                }

            case BUFFER_OVERFLOW:
            case BUFFER_UNDERFLOW:
            case CLOSED:
            case NEED_TASK:
                 Runnable task;
                 while ((task = engine.getDelegatedTask()) != null) {
                      new Thread(task).start();
                 }
                 handshakeStatus = engine.getHandshakeStatus();
                 break;
    }
}

最佳答案

您正在这样做。当引擎显示NEED_UNWRAP时,请展开。然后,如果返回BUFFER_UNDERFLOW,请进行读取,然后再次尝试展开。不要仅仅假设您需要再次阅读NEED_UNWRAP。您可能正在通过peerNetData丢失数据。并且不要通过peerNetDataByteBuffer.wrap()创建新的.allocate():继续使用相同的内容,并使用put()将数据报数据放入其中。每次成功解开引擎后,再按compact()即可。

换句话说,只做准确的事情,只做它告诉你的事情即可。

SSLEngine是很难解决的事情。许多人尝试过:很少成功。要取得成功,这是商业产品的基础,请参阅我的《 Java基础网络》一书的源代码中的SSLEngineManager类,Springer 2006,here

关于java - 展开服务器问好后,SSLEngine给出NEED_UNWRAP ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49607139/

10-10 08:35