[英]SSLEngine: Invalid TLS padding data when unwrapping after a successful handshake
我正在使用非阻塞的socketChannel和SSLEngine SSL服务器。 因此,在成功握手之后,我读取了套接字(第一次读取184字节/ 384字节),然后将此缓冲区传递给unwrap方法。 unwrap方法抛出以下异常:
javax.net.ssl.SSLHandshakeException: Invalid TLS padding data
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.SSLEngineImpl.fatal(Unknown Source)
at sun.security.ssl.SSLEngineImpl.readRecord(Unknown Source)
at sun.security.ssl.SSLEngineImpl.readNetRecord(Unknown Source)
at sun.security.ssl.SSLEngineImpl.unwrap(Unknown Source)
at javax.net.ssl.SSLEngine.unwrap(Unknown Source)
但是,如果我是第一次读取所有字节(384/384),那么就不会出现此异常。
我认为,如果sslengine没有足够的字节来解包,它将返回bufferUnderflow状态。
我真的需要所有字节来调用unwrap方法吗? 如果是,我如何确定我读取了非阻塞套接字的所有字节?
编辑:代码:
public boolean doHandShake(SocketChannel socket) throws Exception{
if(!socket.isConnected()){
return false;
}
outAppData.clear();
inAppData.clear();
inNetData.clear();
outNetData.clear();
if(engine==null || socket==null)
return false;
engine.beginHandshake();
SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();
while (hs != SSLEngineResult.HandshakeStatus.FINISHED &&
hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
switch (hs) {
case NEED_UNWRAP:
int read=1;
while (read > 0) {
read=socket.read(inNetData);
if(read==-1){
throw new IOException ("channel closed");
}
}
inNetData.flip();
engineRes=engine.unwrap(inNetData, outAppData);
inNetData.compact();
switch(engineRes.getStatus()){
case BUFFER_OVERFLOW:
System.out.println("overFlow");
break;
case CLOSED:
return false;
case OK:
//outAppData.clear();
// inNetData.clear();
break;
default:
break;
}
break;
case NEED_WRAP :
outNetData.clear();
engineRes=engine.wrap(inAppData, outNetData);
outNetData.flip();
switch (engineRes.getStatus()){
case BUFFER_OVERFLOW:
System.out.println("overFlow");
break;
case BUFFER_UNDERFLOW:
System.out.println("underFlowa");
break;
case CLOSED:
return false;
case OK:
//outNetData.flip();
while(outNetData.hasRemaining()){
if(socket.write(outNetData)<0){
throw new Exception("Channel Has been Closed");
}
}
break;
default:
break;
}
break;
case NEED_TASK :
Runnable r=engine.getDelegatedTask();
r.run();
break;
case FINISHED:
System.out.println("finished");
break;
case NOT_HANDSHAKING:
break;
default:
throw new IllegalArgumentException("Inexpected/Unhadled SSLEngineResult :"+hs);
}
hs = engine.getHandshakeStatus();
}
return true;
}
然后我使用非阻塞通道读取了184/384字节。
读取= _socketChannel.read(缓冲区);
然后将传递给要解密的buffer
:
public ByteBuffer decrypt(ByteBuffer inNetData) throws SSLException{
if(!isValidSession()){
return null;
}
outAppData.clear();
try{
engineRes=engine.unwrap(inNetData, outAppData);
}catch(Exception e){
e.printStackTrace();
}
inNetData.compact();
switch(engineRes.getStatus()){
case BUFFER_OVERFLOW:
outAppData=ByteBuffer.allocate(outNetData.capacity()*2);
inNetData.position(0);
return encrypt(inNetData);
case BUFFER_UNDERFLOW:
return null;
case CLOSED:
return null;
case OK:
outAppData.flip();
System.out.println(new String(outAppData.array(),0,400));
return outAppData;
default:
break;
}
return null;
}
在engine.unwrap engineRes = engine.unwrap(inNetData,outAppData)中引发了异常;
这里有几个问题。
如果得到BUFFER_OVERFLOW
,则必须flip(), write(), compact(),
然后重复wrap()
。 不只是打印并放弃上述方法。
如果得到BUFFER_UNDERFLOW
,则必须阅读()并重复BUFFER_UNDERFLOW
()。 这是您的特定问题。
如果您收到任何类型的Exception
,仅打印异常并像未发生一样继续运行是不够的。
getHandshakeStatus()
永远不会返回FINISHED
。 仅在wrap()
和unwrap()
返回的SSLEngineResult
中将其设置为握手状态。
您正在从decrypt()
方法中调用encrypt()
。 这没有道理。
您的整体技术将无法正常工作。 在读或写过程中,握手可以随时发生,并且您必须编写代码来应对这种情况。 成功完成此操作后,您根本不需要调用自己的doHandshake()
方法,因为您的代码无论如何都会对此进行处理。
SSLEngine是状态机。 您必须完全按照其指示执行的操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.