ChannelManager 类的代码分析(CNG 示例)
更新: 2008 年 7 月
在下一代加密技术 (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 类用在以下五种不同的上下文中:应用程序控制、通道名称传输、消息传输、数字签名密钥传输和加密公钥传输。在下面的列表中,按照这些上下文在源代码中的出现顺序对它们进行了讨论。
应用程序控制: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 对象。
通道名称传输:会话选项已传输后,Alice 发送给 Bob 一个新通道名称。
Alice 使用 SendChannelName 方法,而 Bob 和 Mallory 使用 ReceiveChannelName 方法。每个方法均创建一个临时的 ChannelManager 管道服务器或客户端。新通道名称已发送或接收后,将释放临时的 ChannelManager 实例。
如果 Mallory 比 Bob 提前 200 毫秒调用 ReceiveChannelName 来截获新通道名称,将会出现安全漏洞。有关此安全漏洞的讨论,请参见执行中间人攻击(CNG 示例)。
消息传输:会话选项和新通道名称已传输后,Alice、Bob 和 Mallory 创建 Communicator 对象。Communicator 构造函数接收在上一步中发送的新通道的名称,并用它来创建长期的 ChannelManager 实例。这些对象是仅有的非临时性 ChannelManager 实例。它们持续到发送和接收最后一条消息,然后将被释放。
说明: Alice 创建的 ChannelManager 对象封装名为 AliceAndBobChannel 的管道服务器。但 Mallory 截获此名称并将一个不同的通道名称 (AliceAndBobChannel1) 发送给 Bob。Bob 将此字符串作为 name 参数传递给 Communicator 构造函数,以创建一个名为 AliceAndBobChannel1 的管道客户端。通过此名称更改,Mallory 可以模拟 Alice 发送消息给 Bob。
数字签名密钥传输:在 Alice 创建其 Communicator 对象后,将检查 Version 标志。在版本 3 中,她通过 PublicChannel 命名管道发送给 Bob 一个数字签名密钥,而此密钥在该管道中被 Mallory 截获。在版本 4 和 5 中,她创建了一个临时的机密 ChannelManager 实例。该实例之后将用于向 Bob 发送一个数字签名私钥。
说明: 由于 Mallory 不具有版本 4 或 5 的即时消息 (IM) 软件,因此并不了解此私有命名管道。Alice 继续使用在第 3 步中创建的长期消息处理 ChannelManager 对象来发送一个假数字签名给 Bob。在版本 4 和 5 中,对 Bob 的 IM 工具进行了更新以忽略此对象。但 Mallory 认为此签名有效,并用它来对其加密密钥和消息进行签名。经过证明,这就是他失算的地方。
加密公钥传输:再次检查 Version 标志。在版本 2 及更高版本中,在第 3 步中创建的长期消息处理 ChannelManager 对象用于发送和接收加密公钥。
通道名称、数字签名和加密密钥交换后,Alice 和 Bob 使用在第 3 步中创建的 ChannelManager 来发送消息。
请参见
概念
参考
修订记录
日期 |
修订记录 |
原因 |
---|---|---|
2008 年 7 月 |
新增主题。 |
信息补充。 |