如何将C#SSLStream客户端连接到OpenSSL服务器?

时间:2013-07-12 17:41:13

标签: c# openssl client ssl-certificate sslstream

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

  

身份验证或解密失败。

当我调用sslStream.AuthenticateAsClient(ServerName)时, Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback 会发生;

我不需要客户端身份验证,所以我不使用任何客户端证书,我无法将我的服务器证书加载到客户端的信任存储区,因为我无法使用该命令在客户端。

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

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

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

我如何进行:

服务器端

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

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

    1. 打开新的TCPClient
    2. 使用与上述线程中相同的验证回调链接新的SSLStream;
    3. 调用带来此异常的AuthenticateAsClient(ServerName)。
    4. 调用sslStream.Write,但执行永远不会到达。
    5. 我非常感谢任何帮助,因为我不确定sslStream内部是如何工作的。

1 个答案:

答案 0 :(得分:0)

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

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

这可能有效,因为BIO_readBIO_write SSL_readSSL_write不等同。这两个函数只在底层套接字上读写,没有任何加密或解密,使得SSL握手几乎无用(除了检查线路另一端的标识)。

这解释了为什么我无法进行沟通,因为两端不会说同一种语言:一个发送未加密的消息,另一个发送SSL包装的消息,反之亦然。

SSL_readSSL_Write函数负责加密和解密,因此它们是在这里使用的。现在它完美无缺。

如果您需要有关我如何做到这一点的任何进一步细节,请评论此答案。