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

这让我疯狂了好几天了。 我使用带有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:在sun.security.ssl.SSLEngineImpl.fatal(未知来源)sun.security.ssl.SLEngineImpl.readRecord上的sun.security.ssl.Alerts.getSSLException(未知来源)中的错误记录MAC(来自ssl.engine的javax.net.ssl.SSLEngine.unwrap(未知来源)的sun.security.ssl.SSLEngineImpl.unwrap(未知来源)sun.security.ssl.SSLEngineImpl.readNetRecord(未知来源)的未知来源。 impl.SecureIO.read(SecureIO.java:244)位于ssl.engine.impl.ChannelHandler.read(ChannelHandler.java:144)的ssl.engine.impl.ChannelHandler.run(ChannelHandler.java:69)at java.lang .Thread.run(Unknown Source)引起:javax.crypto.BadPaddingException:在sun.security.ssl.EngineInputRecord.decrypt(未知来源)的错误记录MAC … 8更多关闭

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

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

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

  1. 放入你的app发送缓冲区。
  2. 如果填充,请wrap().
  3. 写,如果这给你一个缓冲区溢出。

或者在你需要冲洗时做所有这些。

你的主要接口应该是引擎,并且只有引擎告诉你有关缓冲区下溢和溢出的信道才能使用通道。

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

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