sockets - 将部分数据包写入 SSL BIO

标签 sockets ssl encryption openssl

我有一个读写数据的套接字应用程序。我正在使用 OpenSSL 进行加密/解密。我的问题是“BIO_write”方法是否可以在内部缓冲数据,或者当我从套接字读取更多内容时是否必须附加到不断增长的缓冲区。这就是我正在做的事情。

我从套接字读取并使用下面的类方法将读取的所有字节写入 BIO:

int CSslConnectionContext::Store(BYTE* pbData, DWORD dwDataLength)
{
    int bytes = 0;
    if (dwDataLength > 0)
    {
        bytes = BIO_write(bio[BIO_RECV], pbData, dwDataLength);
    }

    return bytes;
}

然后我立即调用 SSL_read 方法来获取解密数据:

int CSslConnectionContext::Read(BYTE* pbBuffer, DWORD dwBufferSize)
{
    int bytes = SSL_read(ssl, pbBuffer, dwBufferSize);
    return bytes;
}

如果 SSL_read 返回一个正数,那么我的应用程序可以使用解密数据。

我不确定的是当我的套接字读取没有在一次读取中捕获解密所需的所有数据时会发生什么。

因此,如果我需要 100 个字节才能解密数据,而第一次读取只得到 80 个,我可以用这 80 个调用 BIO_write(),再进行一次套接字读取以获得下一个 20,然后调用 BIO_write()只有那 20 个字节?

或者我是否需要编写我的代码以便当我读到 80 时我会做这样的事情:

  1. 用 80 个字节调用 BIO_write()。
  2. 如果返回失败指示符 - 保留这 80 个字节。
  3. 从套接字中读取接下来的 20 个字节并将其附加到缓冲的 80 个字节中。
  4. 用 100 个字节调用 BIO_write()

最佳答案

OpenSSL 在 TCP 堆栈之上保存内部缓冲区 - 我们称之为 SSL 堆栈。 OpenSSL 库处理 SSL 堆栈。 BIO_xxx() 函数可以在不同的端点上运行:即内存、套接字。 它的行为取决于它所操作的实际项目。例如,如果 BIO_write() 使用内存 (BIO_s_mem),则 BIO_write 永远不会失败,除非内存不足。但是如果它使用套接字,并且套接字是非阻塞的,它可以在失败时返回错误,或者它可以写入一定数量的字节而不是套接字缓冲区已满的所有请求字节。

因此,如何使用/处理缓冲区取决于很多因素,但最值得注意的是:

  • 阻塞或非阻塞 IO
  • 操作(内存、套接字等)的 BIO 对象

例如,如果您正在使用 BIO_s_mem 和非阻塞套接字操作,则可以应用以下技术:

  1. 使用 BIO_write 写入缓冲区,并检查它是否失败。如果没有失败,您可以确定已将所有缓冲区写入 SSL 堆栈。
  2. 调用 Read_SSL 并检查错误,如果错误是 WANT_READ 或 WANT_WRITE,那么您需要将更多数据写入 SSL 堆栈才能读取有效记录。

对于问题和例子:

您可以部分写入(尽可能多,甚至 1 个字节)。例如,如果您从套接字读取 80 个字节,然后使用 BIO_write 写入这些字节。然后调用 SSL_read 可能会失败(WANT_READ、WANT_WRITE 或其他)。然后你从 socket 接收到 20 个字节,然后使用 BIO_write 写入这些字节。然后再次调用 SSL_read。每当 SSL_read 无错误返回时,这意味着 SSL 堆栈解码了有效记录。

但是了解使用 select() 处理 SSL 读/写等待非阻塞套接字非常麻烦是非常重要的。当您已经在等待套接字的 READ 事件时,一次 SSL_write 可能会导致多次写入套接字。

关于sockets - 将部分数据包写入 SSL BIO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47160620/

相关文章:

android - javax.net.ssl.SSLHandshakeException : Remote host closed connection during handshake while inserting rows in bigquery

ssl - Chrome、Firefox、Safari 中的错误消息 "ERR_BAD_SSL_CLIENT_AUTH_CERT"

linux - 当满足某些条件时 Hook 到 linux 身份验证以运行脚本或程序

c++ - boost asio在基于tcp的协议(protocol)中找到消息的开头

sockets - Websphere:本地机器上的 Web 服务调用挂起

c - Linux C 编程 - FTP 服务器不会通过套接字响应

c - C中的 "++="是什么?

Ruby - 如何跨内核/处理器线程化

asp.net-mvc - API 仅在 fiddler 运行时有效

ios - 在 iOS 上使用 RNCryptor 异步解密大文件