2

我正在为已经存在的用 C++ 编写的OpenSSL 服务器编写C# 客户端(使用 SSLStream 的 Mono) 。我知道理论上,他们应该能够交流,但我总​​是得到一个例外:

身份验证或解密失败。

当我调用时,这发生在Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallbacksslStream.AuthenticateAsClient(ServerName)中;

我不需要客户端身份验证,因此我不使用任何客户端证书,也无法将服务器证书加载到客户端的信任库中,因为我无法在客户端使用命令行。

在服务器上,我似乎收到了一些不应该发生的随机数据,因为我从未sslStream.Write()在客户端代码中调用过。也许我不完全理解握手是如何发生的。我有一个运行良好的 OpenSSL C++ 客户端。

有人知道我怎么能让这个工作吗?

我在服务器端使用由 OpenSSL 生成的自签名证书,我将其转换为 DER 格式。

我如何进行:

服务器端

  1. 初始化 OpenSSL
  2. 加载服务器证书 (DER) 和私钥 (PEM)
  3. 打开非 SSL 监听套接字
  4. 当客户端连接时,我打开一个连接到 SSL_Bio 并接受连接的新套接字
  5. 读取 SSL 套接字以获取传入数据。

客户端

我正在尝试使用改编自本主题中的临时客户端进行连接。

  1. 打开一个新的 TCPClient
  2. 使用与上述线程中相同的验证回调将新的 SSLStream 链接到它;
  3. 调用 AuthenticateAsClient(ServerName) 会带来此异常。
  4. 调用sslStream.Write但执行永远不会到达这里。

任何帮助将不胜感激,因为我不确定 sslStream 内部是如何工作的。

4

1 回答 1

2

好的,我知道了。事实上,我以错误的顺序设置BIOSSL变量。在实际调用OpenSSL之前,您必须创建 BIO 并将其附加到 SSL SSL_Accept,否则身份验证无法完成,这似乎是合乎逻辑的。

此外,我在客户端使用C# 发送消息,而SSLStream我在服务器端使用 OpenSSL。BIO_readBIO_write

这是行不通的,因为BIO_readandBIO_write 不等同SSL_readand SSL_write。这两个函数只在底层套接字上读写,没有任何加密或解密,使得 SSL 握手几乎无用(除了检查线路另一端的身份)。

这解释了为什么我无法进行通信,因为两端没有说相同的语言:一个发送未加密的消息,而另一个预期 SSL 包装的消息,反之亦然。

和函数负责加密SSL_readSSL_Write解密,所以在这里使用它们。现在它完美地工作了。

如果您需要有关我如何做到这一点的更多详细信息,请评论此答案。

于 2013-07-16T15:03:03.110 回答