ChannelManager 类的代码分析(CNG 示例)

在下一代加密技术 (CNG) 安全通信示例中,ChannelManager 类为此示例提供进程间通信 (IPC) 基础结构。

该类负责以下事项:

  • 命名管道的创建、打开、关闭和释放。

  • 发送和接收应用程序控制标志、通道名称、数字签名、加密密钥和消息。

有关本主题提到的版本的示例和说明的概述,请参见下一代加密技术 (CNG) 安全通信示例

ChannelManager.cs 文件内容

ChannelManager.cs 文件包含以下类和方法:

  • ChannelManager 类:

    • 构造函数:创建一个命名管道,然后等待在管道的另一端发生连接。如果命名管道是一个管道服务器,则它通过调用 WaitForConnection 方法来等待客户端连接。如果命名管道是管道客户端,则它通过调用 Connect 方法来等待命名管道服务器。ChannelManager 构造函数直到建立连接后才会返回。

    • Dispose 方法:通过在该类超出范围时释放 System.IDisposable 接口的实例化资源 (Stream m_Stream) 来实现此接口。

    • ReadMessage 方法:接收来自管道客户端的消息。

    • SendMessage 方法:将消息发送到管道客户端。

  • AppControl 方法:Alice 使用此方法将应用程序控制标志发送给 Bob 和 Mallory。这些标志同步三个命令窗口中的 Version、fMallory 和 fVerbose 状态。加密或消息传输过程中不涉及 AppControl。它仅仅是一种应用程序间的控制机制。该方法创建一个临时的 ChannelManager 对象,该对象使用后即释放。

  • SendChannelName 方法:负责将新通道名称发送到客户端的便捷方法。该方法创建一个临时的 ChannelManager 对象,该对象使用后即释放。

  • ReceiveChannelName 方法:负责从服务器接收新通道名称的便捷方法。该方法创建一个临时的 ChannelManager 对象,该对象使用后即释放。

ChannelManager 类详细信息

Alice、Bob 和 Mallory 这三个应用程序是通过由 ChannelManager 实例创建的命名管道连接的。每个应用程序都创建并释放两种类型的 ChannelManager 对象。

  • 长期对象:Alice 和 Bob 均在其 Run 方法的开始处创建一个长期 ChannelManager 对象。他们使用此对象来传输销售联系人。Mallory 在其 Run 方法中创建了两个长期 ChannelManager 对象:一个用于与 Alice 通信,另一个用于与 Bob 通信。通道用于交换加密密钥和加密消息。它们持续到 Run 方法结束,然后被释放。

  • 临时对象:AppControl、SendChannelName 和 ReceiveChannelName 方法创建临时 ChannelManager 对象来执行特定任务。然后会释放这些对象。此外,在版本 4 和 5 中,Alice 也通过使用一个临时 ChannelManager 对象发给 Bob 一个数字签名私钥。

ChannelManager 类实现 System.IDisposable 接口并管理 send 和 receive 传输模式。

该类会让人产生 Alice、Bob 和 Mallory 之间存在动态交换的错觉。实际上,管道一次只能在一种模式下存在:要么是服务器,要么是客户端。因此,Alice、Bob 和 Mallory 应用程序以仔细的线性方式执行。在此示例执行期间,每个应用程序都期望管道在特定的时间打开和关闭。通信不是异步的,尽管可能看上去像是异步的。

线程管理器可能看起来像是在后台管理线程,但实际上没有使用任何线程调用。进程间计时仅仅是通过在 Alice、Bob 和 Mallory 之间仔细交错 send 和 receive 调用来实现的。因此,按照 CNG 示例概述中讨论的方案,三个窗口看起来可轻松通信。

此实现的优点之一是同步,而且代码简单且是线性的。但其缺点是缺乏可靠性:如果管道客户端未能连接到服务器,则服务器将停止响应。一种更好的方法是使用一个多线程管道服务器,它可以有效地处理这种故障。但为了避免复杂性,此示例不采用这种办法。

ChannelManager 类是从 Alice、Bob 和 Mallory Main 方法以及 Communicator.cs 文件中的 Communicator 类构造函数实例化的。

用法详细信息

ChannelManager 类用在以下五种不同的上下文中:应用程序控制、通道名称传输、消息传输、数字签名密钥传输和加密公钥传输。在下面的列表中,按照这些上下文在源代码中的出现顺序对它们进行了讨论。

  1. 应用程序控制:Alice 在其 Main 方法的开始处调用 InitializeOptions 方法,并接收来自用户的会话选项。这些选项(Version、fMallory 和 fVerbose)之后将通过 AppControl 方法发送给 Bob 和 Mallory。如果用户决定通过键入字母“x”来关闭应用程序,则 AppControl 方法将字符串“exit”而不是会话选项发送给 Bob 和 Mallory。

    • Alice 的 AppControl 方法创建两个临时的 ChannelManager 管道服务器:BobControlChannel 和 MalloryControlChannel。

    • Bob 和 Mallory 的 AppControl 方法创建临时的 ChannelManager 管道客户端并连接到其各自的控制通道。

    • Bob 和 Mallory 从 Alice 那里接收会话选项并立即释放临时的 ChannelManager 对象。

  2. 通道名称传输:会话选项已传输后,Alice 发送给 Bob 一个新通道名称。

    • Alice 使用 SendChannelName 方法,而 Bob 和 Mallory 使用 ReceiveChannelName 方法。每个方法均创建一个临时的 ChannelManager 管道服务器或客户端。新通道名称已发送或接收后,将释放临时的 ChannelManager 实例。

    • 如果 Mallory 比 Bob 提前 200 毫秒调用 ReceiveChannelName 来截获新通道名称,将会出现安全漏洞。有关此安全漏洞的讨论,请参见执行中间人攻击(CNG 示例)

  3. 消息传输:会话选项和新通道名称已传输后,Alice、Bob 和 Mallory 创建 Communicator 对象。Communicator 构造函数接收在上一步中发送的新通道的名称,并用它来创建长期的 ChannelManager 实例。这些对象是仅有的非临时性 ChannelManager 实例。它们持续到发送和接收最后一条消息,然后将被释放。

    备注

    Alice 创建的 ChannelManager 对象封装名为 AliceAndBobChannel 的管道服务器。但 Mallory 截获此名称并将一个不同的通道名称 (AliceAndBobChannel1) 发送给 Bob。Bob 将此字符串作为 name 参数传递给 Communicator 构造函数,以创建一个名为 AliceAndBobChannel1 的管道客户端。通过此名称更改,Mallory 可以模拟 Alice 发送消息给 Bob。

  4. 数字签名密钥传输:在 Alice 创建其 Communicator 对象后,将检查 Version 标志。在版本 3 中,她通过 PublicChannel 命名管道发送给 Bob 一个数字签名密钥,而此密钥在该管道中被 Mallory 截获。在版本 4 和 5 中,她创建了一个临时的机密 ChannelManager 实例。该实例之后将用于向 Bob 发送一个数字签名私钥。

    备注

    由于 Mallory 不具有版本 4 或 5 的即时消息 (IM) 软件,因此并不了解此私有命名管道。Alice 继续使用在第 3 步中创建的长期消息处理 ChannelManager 对象来发送一个假数字签名给 Bob。在版本 4 和 5 中,对 Bob 的 IM 工具进行了更新以忽略此对象。但 Mallory 认为此签名有效,并用它来对其加密密钥和消息进行签名。经过证明,这就是他失算的地方。

  5. 加密公钥传输:再次检查 Version 标志。在版本 2 及更高版本中,在第 3 步中创建的长期消息处理 ChannelManager 对象用于发送和接收加密公钥。

通道名称、数字签名和加密密钥交换后,Alice 和 Bob 使用在第 3 步中创建的 ChannelManager 来发送消息。

请参见

参考

NamedPipeServerStream

NamedPipeClientStream

概念

下一代加密技术 (CNG) 安全通信示例

ChannelManager.cs 源代码(CNG 示例)

源代码概述(CNG 示例)