SSLEngine unwrap()javax.crypto.BadPaddingException:错误记录MAC

时间:2013-11-20 01:09:57

标签: java ssl nio jsse sslengine

这让我疯狂了好几天了。我使用带有ssl加密的java nio创建了一个使用SSLEngine的客户端。握手工作正常,我写了一个网站的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:糟糕的记录MAC       在sun.security.ssl.Alerts.getSSLException(未知来源)       at sun.security.ssl.SSLEngineImpl.fatal(Unknown Source)       at sun.security.ssl.SSLEngineImpl.readRecord(Unknown Source)       at sun.security.ssl.SSLEngineImpl.readNetRecord(Unknown Source)       在sun.security.ssl.SSLEngineImpl.unwrap(未知来源)       在javax.net.ssl.SSLEngine.unwrap(未知来源)       在ssl.engine.impl.SecureIO.read(SecureIO.java:244)       在ssl.engine.impl.ChannelHandler.read(ChannelHandler.java:144)       在ssl.engine.impl.ChannelHandler.run(ChannelHandler.java:69)       在java.lang.Thread.run(未知来源)   引起:javax.crypto.BadPaddingException:坏记录MAC       at sun.security.ssl.EngineInputRecord.decrypt(Unknown Source)       ... 8更多关闭

1 个答案:

答案 0 :(得分:2)

你做错了。当您需要获取数据时,您应该:

  1. 从你的app接收缓冲区中获取。
  2. 如果该项为空,请尝试unwrap().
  3. 如果它给你一个缓冲区下溢,请阅读该频道。
  4. 同样,当您需要输入数据时,您应该:

    1. 放入您的应用发送缓冲区。
    2. 如果填写,wrap().
    3. 写入是否会导致缓冲区溢出。
    4. 或者在你需要冲洗时做所有这些。

      您的主界面应该与引擎一起使用,并且只有引擎告诉您有关缓冲区下溢和溢出的信息才能使用通道。

      同样,您必须让引擎指示握手(NEED_WRAP / NEED_UNWRAP),而不是试图指示它。

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