2

这几天让我发疯了。我使用带有 SSLEngine 的 ssl 加密的 java nio 创建了一个客户端。握手工作正常,我向网站写了一个 GET 请求,它工作正常(我得到带有 200 代码的标题)。问题是当网站发回数据包时,在第二个数据包上我得到一个 BadPaddingException。这是我的阅读方法:

    public void read(SelectionKey key,ByteBuffer readBuffer) throws IOException, BadPaddingException {

    SocketChannel socketChannel = (SocketChannel) key.channel();

    ByteBuffer clientSSLData = ByteBuffer.allocate(getPacketBufferSize());
    System.out.println("Reading data. PacketBufferSize: "+(getPacketBufferSize()));
    int length = socketChannel.read(clientSSLData);

    System.out.println("read "+length+" bytes");
    if (length == -1){
        System.out.println("Length is -1 which means nothing was read from the channel  ");
        socketChannel.close();
        return;
    }
    clientSSLData.flip();
    readBuffer.clear();
    SSLEngineResult res = sslEngine.unwrap(clientSSLData, readBuffer);
    System.out.println(res.toString());
}

我的获取请求很简单,如下所示:“GET \r\nHost: www.google.com\r\n\r\n”

基本上,如果它是一个像https://www.example.com这样的小网站,我可以毫无问题地接收,因为它是一次性发送的。但是,如果我执行类似https://www.google.com的操作,我会得到 BadPaddingException。有任何想法吗?谢谢!

编辑:例外是......

javax.net.ssl.SSLException:在 sun.security.ssl.SSLEngineImpl.fatal(Unknown Source) 在 sun.security.ssl.Alerts.getSSLException(Unknown Source) 在 sun.security.ssl.SSLEngineImpl.readRecord( Sun.security.ssl.SSLEngineImpl.readNetRecord(Unknown Source) 在 sun.security.ssl.SSLEngineImpl.unwrap(Unknown Source) 在 javax.net.ssl.SSLEngine.unwrap(Unknown Source) 在 ssl.engine。 impl.SecureIO.read(SecureIO.java:244) at ssl.engine.impl.ChannelHandler.read(ChannelHandler.java:144) at ssl.engine.impl.ChannelHandler.run(ChannelHandler.java:69) at java.lang .Thread.run(Unknown Source) Caused by: javax.crypto.BadPaddingException: bad record MAC at sun.security.ssl.EngineInputRecord.decrypt(Unknown Source) ... 8 更多关闭

4

1 回答 1

2

你这样做是错误的。当您需要获取数据时,您应该:

  1. 从您的应用接收缓冲区中获取。
  2. 如果那是空的,请尝试unwrap().
  3. 如果这给您带来缓冲区下溢,请读取通道。

同样,当您需要放置数据时,您应该:

  1. 放入您的应用发送缓冲区。
  2. 如果满了,wrap().
  3. 写如果这给你一个缓冲区溢出。

或者在需要冲洗时执行所有操作。

您的主要接口应该与引擎有关,并且仅与通道有关,因为引擎会告诉您有关缓冲区下溢和溢出的信息。

同样,您必须让引擎指示握手(NEED_WRAP/NEED_UNWRAP),而不是尝试对其进行指示。

SSLEngine是一件非常困难的事情。许多人尝试过:很少有人成功。对于一个工作上的成功,这是商业产品的基础,请参阅我的《 Java 中的基础网络SSLEngineManager》一书的源代码中的类,Springer 2006,这里

于 2013-11-20T04:56:43.687 回答