下面是解开从sslengine收到的数据包的代码:
private ByteBuffer doUnwrap() throws IOException {
if (mPeerNetData.position() == 0) {
// The network input buffer is empty; read data from the channel before doing the unwrap
final int count = mSocketChannel.read(mPeerNetData);
Log.d(TAG, "bytesRead : " + count);
if (count == -1) {
handleEndOfStream(mSocketChannel, mSslEngine);
return null;
}
}
Log.d(TAG, "isReadPending :" + isReadPending);
if (!isReadPending) {
mPeerNetData.flip();
}
final SSLEngineResult result;
try {
result = mSslEngine.unwrap(mPeerNetData, mPeerAppData);
} catch (SSLException e) {
Log.d(TAG, "Exception while calling SSLEngine.unwrap()" + e);
shutdown();
return null;
}
mPeerNetData.compact();
Log.d(TAG, "Result of SSLEngine.unwrap(): {}" + result.getStatus());
final SSLEngineResult.Status status = result.getStatus();
switch (status) {
case OK:
if (mPeerNetData.position() != 0) {
isReadPending = true;
mPeerAppData = ensureRemaining(mPeerAppData, mSslEngine.getSession().getApplicationBufferSize());
doUnwrap();
}
break;
case CLOSED:
closeConnection(mSocketChannel, mSslEngine);
break;
case BUFFER_UNDERFLOW:
// The network input buffer might not have enough space, re-allocate if necessary
// (NOTE: packet buffer size as reported by the SSL session might change dynamically)
mPeerNetData = ensureRemaining(mPeerNetData, mSslEngine.getSession().getPacketBufferSize());
// Read data from the channel, retry unwrap if not end-of-stream
final int count = mSocketChannel.read(mPeerNetData);
if (count == -1) {
handleEndOfStream(mSocketChannel, mSslEngine);
return null;
}
doUnwrap();
break;
case BUFFER_OVERFLOW:
// The application input buffer does not have enough space, re-allocate and retry unwrap
// (NOTE: application buffer size as reported by the SSL session might change dynamically)
mPeerAppData = ensureRemaining(mPeerAppData, mSslEngine.getSession().getApplicationBufferSize());
doUnwrap();
break;
default:
throw new IllegalStateException("Invalid SSL status: " + status);
}
return mPeerAppData;
}
在展开过程中,mPeerNetData缓冲区有一些数据需要读取,因此,我已经扩大了mPeerAppData缓冲区,以容纳在下一次迭代中必须从mPeerNetData缓冲区读取的更多数据。
我已经调试了流,可以验证mPeerAppData缓冲区是否有足够的空间来保存数据,并且mPeerNetData缓冲区是否有待解包装的数据。
但在解包过程中,我得到的错误如下:
javax.net.ssl.SSLException: Unable to parse TLS packet header
at org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:798)
at org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:738)
请建议我们如何避免这个错误?
发布于 2020-08-14 23:07:54
在花了几天时间调试代码后,我能够知道这个问题的根本原因。
在我发现下面的操作过程中,上面的代码开始正常工作
result = mSslEngine.unwrap(mPeerNetData, mPeerAppData);
其中mPeerNetData
是包含从socketChannel
读取的加密字节的缓冲区,mPeerAppData
是在unwrap
操作后保存解密字节的缓冲区。
解包操作成功解密来自mPeerNetData
的数据包后,仍有一些字节剩余,不足以再次执行unwrap
操作。为了做进一步的unwrap
操作,我们需要再次从socketChannel
读取更多的数据,但请记住,我们不应该清除mPeerNetData
,而是应该将新数据添加到mPeerNetData
中,它之前还留有一些字节。
对于数据的成功-完全解密,这些先前的剩余字节必须在缓冲器中,因为每次展开都试图以这种方式从packet.In读取一些初始字节,在下一次展开操作期间,动作将成功-完全。
另外请注意,要读取完整的socketChannel
数据,您应该有一些while loop
逻辑来调用此方法,直到您从通道读取完整的数据。
https://stackoverflow.com/questions/63337561
复制相似问题