什么是OpenSSL BIO?它们如何工作? OpenSSL中如何使用BIO?

时间:2018-08-03 11:58:33

标签: openssl

我需要一些有关OpenSSL BIO的常规信息。对它的某种介绍。什么是OpenSSL BIO?它的总体思路是什么?我知道这是某种用于输入/输出的API。但是,例如,它与stdio或套接字API有何不同?

我知道有源,接收和过滤BIO。什么是过滤器BIO?什么是源BIO?什么是接收器BIO?

据说过滤器BIO用于处理数据。如何使用过滤器BIO处理数据?我如何通过它运行数据?我是否需要使用BIO_write函数将数据馈送到过滤器BIO并使用BIO_read函数来获取处理后的数据?

为什么在OpenSSL中根本需要BIO?使用OpenSSL编程时如何使用它们?有例子吗?

OpenSSL提供哪些BIO?您能否提供一些BIO的例子并说明它们之间的区别?

1 个答案:

答案 0 :(得分:5)

  

什么是OpenSSL BIO?

OpenSSL BIO是提供输入/输出相关功能的API。

  

其总体思路是什么?与stdio API或套接字API有何不同?

第一个想法是,它不是用于某些特定类型的IO(例如,用于文件或网络)的API。它是用于各种类型的能够进行输入/输出操作的实体的通用API。它类似于具有纯虚函数的C ++抽象类。您仅使用单个接口,但是行为因所使用的特定BIO对象而异。例如,它可以是套接字对象或文件对象。如果将BIO_write函数与套接字对象一起使用,则数据将通过网络发送。如果您将BIO_write函数与文件对象一起使用,则数据将被写入文件。

OpenSSL BIO API背后的第二个想法是BIO对象可以堆叠在一起成为单个线性链。它允许在将数据发送到最终输出(接收器)之前或从初始输入(源)读取数据之后,通过不同的过滤器处理数据。过滤器也是BIO对象。

  

什么是过滤器BIO?什么是源BIO?什么是接收器BIO?

OpenSSL筛选器BIO是一个BIO,它获取数据,对其进行处理并将其传递给另一个BIO。

OpenSSL源BIO是一种BIO,它不会从另一个BIO接收数据,而是从其他地方(从文件,网络等)获取数据。

OpenSSL接收器BIO是不会将数据传递到另一个BIO而是将其传输到其他地方(文件,网络等)的BIO。

关于源BIO和接收BIO,没有特定的源BIO,也没有特定的接收BIO,只有“源-接收” BIO。作为源BIO的BIO也是宿BIO。例如,套接字BIO同时是源BIO和宿BIO。将数据写入套接字BIO时,该BIO充当接收器。从套接字BIO读取数据时,BIO会作为源。源宿BIO始终是BIO链的终结部​​分。这不同于通常的数据处理管道,在常规数据处理管道中,源是管道的开始,而接收器是管道的结束。

  

如何通过过滤器BIO运行数据?我是否需要使用BIO_write函数将数据馈送到过滤器BIO并使用BIO_read函数来获取处理后的数据?

如果使用BIO_write函数将数据放入过滤器,则仅通过在BIO上调用BIO_read函数就无法获取处理后的数据。筛选器BIO的工作方式不同。过滤器BIO可以避免将处理后的数据存储在缓冲器中。它可能只使用输入数据,进行处理,然后立即使用与将数据放入BIO相同的BIO_write函数将其传递到链中的下一个BIO。接下来,下一个BIO可能会在处理后将数据写入链中的下一个BIO。如果某些BIO将数据存储在其内部缓冲区中(如果没有足够的数据来为下一个BIO生成输出),或者该数据到达接收器,则该过程将停止。

如果您只需要通过过滤器BIO运行数据而无需通过网络发送数据或不将其写入文件,则可以将过滤器BIO附加到OpenSSL内存BIO(即,建立以下链:filter bio <-> memory bio) 。内存BIO是源-接收器BIO,但它不会将数据发送到任何地方,而只是将数据存储在内存缓冲区中。将数据写入过滤器BIO之后,数据将被写入存储器BIO,并将其存储在存储器缓冲区中。内存BIO具有特殊的接口,可直接从缓冲区获取数据(尽管您可以使用BIO_read来获取已写入内存BIO的数据,请参见下文)。

从过滤器中读取BIO的工作方式相反。如果您请求从过滤器BIO读取数据,则过滤器BIO可能又请求从链中的下一个BIO读取数据。如果某个BIO具有足够的缓冲数据要返回,或者该过程到达了源BIO,则该过程停止。对过滤器BIO上的BIO_read函数的单次调用可能导致对过滤器BIO中的BIO_read函数的多次调用,以从下一个BIO获取数据。过滤器BIO将继续调用BIO_read,直到获得足够的数据以生成处理结果为止。

如果链的源宿BIO以非阻塞模式工作,则情况会更加复杂。例如,使用非阻塞套接字或使用内存BIO(内存BIO本质上是非阻塞的)。

还请注意,与写入该BIO时所做的处理相比,从过滤器BIO进行读取确实会逆转数据处理。例如,如果使用密码BIO,则对BIO进行写入将对已写入的数据进行加密,但是从该BIO进行读取将对输入数据进行解密。这样可以建立这样的链:your code <-> cipher BIO <-> socket BIO。您将未加密的数据写入密码BIO,该密码对其进行加密并将其发送到套接字。当您从密码BIO中读取时,它首先会从套接字获取加密的数据,然后将其解密并返回未加密的数据给您。这使您可以通过网络设置加密通道。您只需使用BIO_writeBIO_read,所有加密/解密操作都是由BIO链自动完成的。

通常,BIO链如下图所示:

/------\                 /--------\                 /---------\                 /-------------\
| your | -- BIO_write -> | filter | -- BIO_write -> | another | -- BIO_write -> | source/sink |
|      |                 |        |                 |  filter |                 |             |
| code | <- BIO_read  -- |  BIO   | <- BIO_read  -- |   BIO   | <- BIO_read  -- |     BIO     |
\------/                 \--------/                 \---------/                 \-------------/
  

为什么OpenSSL中需要BIO?使用OpenSSL编程时如何使用它们?有例子吗?

在运行SSL / TLS协议时,OpenSSL使用BIO与远程端进行通信。 SSL_set_bio函数用于设置BIO,以在SSL / TLS链接的具体实例中进行通信。例如,您可以使用套接字BIO通过网络连接运行SSL / TLS协议。但是您也可以开发自己的BIO(是可能的),或使用内存BIO通过自己的链接类型运行SSL / TLS协议。

您还可以将SSL / TLS链接的实例包装为BIO本身(BIO_f_ssl)。在SSL BIO上调用BIO_write将导致调用SSL_write。呼叫BIO_read将导致呼叫SSL_read

尽管SSL BIO是过滤器BIO,但与其他过滤器BIO有所不同。在SSL BIO上调用BIO_write可能会导致链中下一个BIO上同时发生BIO_readBIO_write调用。因为SSL_write(在SSL BIO的BIO_write内部使用)不仅发送数据,而且还提供运行的SSL / TLS协议,这可能需要双方之间进行多个数据交换步骤才能进行某些协商。 SSL BIO的BIO_read也是如此。这就是SSL BIO与普通过滤器BIO的不同之处。

还请注意,您不需要使用SSL BIO。您仍然可以直接使用SSL_readSSL_write

  

OpenSSL提供哪些BIO?您能否提供一些BIO的例子并说明它们之间的区别?

以下是OpenSSL提供的源库BIO的示例:

  • 文件BIO(BIO_s_file)。它是stdio的FILE*对象的包装。它用于写入和读取文件。
  • 文件描述符BIO(BIO_s_fd)。它与文件BIO相似,但可用于POSIX文件描述符而不是stdio文件。
  • 套接字BIO(BIO_s_socket)。它是POSIX套接字的包装。它用于通过网络进行通信。
  • BIO为空(BIO_s_null)。它类似于POSIX系统中的/dev/null设备。写入此BIO只会丢弃数据,读取该数据会导致EOF(文件结尾)。
  • 内存BIO(BIO_s_mem)。本质上,这是一个环回BIO。从这种类型的BIO读取将返回先前写入BIO的数据。但是,也可以通过调用特定于此类型BIO的函数(每种类型的BIO都具有特定于此类型的BIO的函数)从内部缓冲区中提取数据(或将数据放置到内部缓冲区中)。
  • “生物” BIO(BIO_s_bio)。它是一个类似管道的生物。可以创建一对这样的BIO。写入该对中的一个BIO的数据将被放置以读取该对中的第二个BIO。反之亦然。它类似于内存BIO,但是内存BIO将数据放置到其自身中,而管道BIO将数据放置到与之配对的BIO中。

有关BIO_s_memBIO_s_bio之间相似性的一些信息,可以在这里找到:OpenSSL “BIO_s_mem” VS “BIO_s_bio”

这是过滤器BIO的示例:

  • base64 BIO(BIO_f_base64)。 BIO_write通过此BIO将数据编码为base64格式。 BIO_read通过此BIO解码base64格式的数据。
  • 密码BIO(BIO_f_cipher)。它加密/解密通过它的数据。可以使用不同的密码算法。
  • 摘要计算BIO(BIO_f_md)。它不会修改通过它的数据。它仅计算流经其中的数据摘要,而数据本身保持不变。可以使用不同的摘要计算算法。可以使用特殊功能来检索计算出的摘要。
  • 一个缓冲BIO(BIO_f_buffer)。它也不会更改通过它的数据。写入该BIO的数据被缓冲,因此并非每次对该BIO的写入操作都会导致将数据写入下一个BIO。至于阅读,情况类似。这样可以减少位于缓冲IO后面的BIO上的IO操作数量。
  • SSL BIO(BIO_f_ssl)。上面已经描述了这种类型的BIO。它将SSL链接包装在其中。