DecryptMessage(Schannel)。处理空输出缓冲区

时间:2017-05-03 19:46:43

标签: windows winapi sspi schannel

我正在尝试使用Schannel SSPI通过SSL连接发送/接收数据,使用套接字。 我对DecryptMessage()

提出了一些问题

1)MSDN表示有时应用程序将从远程方接收数据,然后使用DecryptMessage()成功解密,但输出数据缓冲区将为空。这是正常的,应用程序必须能够处理它。 (据我所知,“空”表示SecBuffer :: cbBuffer == 0)

我该如何处理?我正在尝试创建一个(安全)srecv()函数,它是winsock recv()函数的替代品。因此我不能只返回0.因为调用应用程序会认为远程方已关闭连接。我应该尝试从连接中接收另一个加密块并尝试解密吗?

2)另一个问题。在使用DecryptMessage成功解密数据(返回值= SEC_E_OK)之后,我正在尝试在输出缓冲区中找到SECBUFFER_DATA类型的缓冲区。

  PSecBuffer pDataBuf=NULL;
  for(int i = 1; i < 4; ++i) { // should I always start with 1?
    if(NULL == pDataBuf && SECBUFFER_DATA == buffers[i].BufferType) {
      pDataBuf  = buffers+i;
    }
  }

如果找不到数据缓冲区怎么办?我应该将其视为错误吗?或者我应该再次尝试接收加密块来解密它? (我看了几个例子。其中一个他们正在重试接收数据,另一个他们报告错误)

1 个答案:

答案 0 :(得分:0)

  1. 您似乎正在尝试为您的 Schannel 安全套接字实现复制阻塞 recv 函数。在这种情况下,您别无选择,只能返回 0。另一种方法是将回调传递给您的实现,并且仅在 SecBuffer.cbBuffer > 0 时调用它。

  2. 是的,总是从索引 1 开始检查剩余的缓冲区。您的 for 循环缺少对 SECBUFFER_EXTRA 的检查。如果有额外的数据和 cbBuffer size > 0,那么您需要再次调用 DecryptMessage,并将额外的数据放入索引 0。如果您的 srecv 被阻塞并且您没有实现回调函数(用于发送到应用层的解密数据),那么在将聚合返回给调用应用程序之前,您必须为循环中收到的每个 SECBUFFER_DATA 附加 DecryptMessage 的结果。