我正在开发一个TCP客户端来连接OpenSSL服务器和证书身份验证.我使用服务器团队共享的.crt和.key文件.这些证书由OpenSSL命令生成.
我使用的SslStream
对象调用来验证TCP客户端SslStream.AuthenticateAsClient
通过将服务器的方法IP
,SslProtocols.Ssl3
和X509CertificateCollection
.
我收到以下错误:
身份验证失败,因为远程方已关闭传输流
.NET的SslStream
类close_notify
在关闭连接之前不发送警报.
如何close_notify
手动发送警报?
我最近一直在尝试用C#创建一个SSL加密的服务器/客户端.
我在MSDN上遵循了本教程,但是,它需要使用makecert.exe为服务器和客户端使用创建证书,所以我找到了一个示例,它创建了证书:
makecert -sr LocalMachine -ss My -n"CN = Test"-sky exchange -sk 123456 c:/Test.cer
但现在问题是服务器启动并等待客户端,当客户端连接它时使用机器名称,在这种情况下,我可以收集的是我的IP:
127.0.0.1
,然后它需要服务器名称,该名称必须与证书(Test.cer)上的服务器名称匹配.我尝试了多种组合(例如"Test""LocalMachine","127.0.0.1"但似乎无法让客户端给出服务器名称以匹配,从而允许连接.我得到的错误是:
证书错误:RemoteCertificateNameMismatch,RemoteCertificateChainErrors例外:根据验证程序,远程证书无效
这里是我使用它的代码与MSDN示例的不同之处仅在于我在应用程序中为服务器分配证书路径以及客户端的机器名和服务器名称:
SslTcpServer.cs
using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.IO;
namespace Examples.System.Net
{
public sealed class SslTcpServer
{
static X509Certificate serverCertificate = null;
// The certificate parameter specifies the name of the file
// containing the …
Run Code Online (Sandbox Code Playgroud) 我需要在使用TCP/IP套接字进行通信的各种进程之间提供安全通信.我想要身份验证和加密.我不想重新发明轮子,而是真的想使用SSL和SslStream类以及自签名证书.我想要做的是根据本地应用程序中的已知副本验证远程进程的证书.(不需要是证书颁发机构,因为我打算手动复制证书).
为此,我希望应用程序能够在第一次运行时自动生成新的证书.除了makecert.exe之外,看起来此链接显示了一种自动生成自签名证书的方法,因此这是一个开始.
我查看了SslStream的AuthenticateAsServer和AuthenticateAsClient方法.您可以提供回电验证,因此看起来可能.但是现在我已经了解了它的细节,我真的不认为这样做是可能的.
我正朝着正确的方向前进吗?还有更好的选择吗?有没有人之前做过这样的事情(基本上是点对点SSL而不是客户端服务器)?
我只需N
要从a 读取字节,SslStream
但如果在超时之前没有收到任何字节,则取消,同时将流保持在有效状态,以便稍后再试.(*)
对于非SSL流,这可以很容易地完成,即NetworkStream
只需使用其ReadTimeout
属性,这将使流在超时时抛出异常.不幸的是,这种方法不适SslStream
用于官方文档:
SslStream假定当从内部流抛出一个IOException时,超时以及任何其他IOException将被其调用者视为致命的.超时后重用SslStream实例将返回垃圾.应用程序应该关闭SslStream并在这些情况下抛出异常.
[更新1]我尝试了一种不同的方法:
task = stream->ReadAsync(buffer, 0, buffer->Length);
if (task->Wait(timeout_ms)) {
count = task->Result;
...
}
Run Code Online (Sandbox Code Playgroud)
但是如果Wait()
返回则这不起作用false
:ReadAsync()
稍后再次调用它会抛出异常:
抛出异常:System.dll Tests.exe中的"System.NotSupportedException"警告:0:从套接字读取失败:System.NotSupportedException:当另一个读取操作挂起时,无法调用BeginRead方法.
[更新2]我尝试另一种方法,通过调用实现超时Poll(timeout, ...READ)
基础上的TcpClient
插座:如果返回true
,然后调用Read()
上SSlStream
,或者如果它返回false
,然后我们有一个超时.这也不起作用:因为SslStream
可能使用它自己的内部中间缓冲区,即使还有数据需要读取,Poll()
也可以返回.false
SslStream
[更新3]另一种可能性是编写一个自定义Stream
子类,它位于NetworkStream
和之间SslStream
并捕获超时异常并返回0字节SslStream
.我不知道如何做到这一点,更重要的是,我不知道是否返回0字节读取SslStream
仍然不会以某种方式破坏它.
(*)我试图这样做的原因是,与非安全或安全套接字的超时同步读取是我已经在iOS,OS X,Linux和Android上用于某些跨平台代码的模式.它适用于.NET中的非安全套接字,因此唯一的情况是SslStream
.
由于Heartbleed,我们的网关服务器已更新,此问题出现了.
由于POODLE,不再支持SSLv3.
客户端应用程序(.NET 2.0)位于Windows 7(或8)框中.服务器在网关服务器后面的DMZ内运行.请注意,我发现.NET 4.0+上不再存在这个问题 - 但是由于遗留代码,我没有更新的奢侈.
Gateway Server是一个传递框,运行带有SSL的Apache HTTP Server.它的位置在DMZ之外,用于访问DMZ内部的服务器.在Gateway服务器上运行的软件版本是Apache/2.2.25(Win32),mod_jk/1.2.39,mod_ssl/2.2.25,OpenSSL/1.0.1g
以下是客户端应用程序上使用的代码(添加了大量的日志记录)...注意,'serverName'通常包含诸如" https://some.url.com "之类的值.
private bool ConnectAndAuthenicate(string serverName, out TcpClient client, out SslStream sslStream)
{
client = null;
sslStream = null;
try
{
client = new TcpClient(serverName, 443); // Create a TCP/IP client; ctor attempts connection
Log("ConnectAndAuthenicate: Client CONNECTED"));
sslStream = new SslStream(client.GetStream(), false, ValidateServerCertificate, null);
Log("ConnectAndAuthenicate: SSL Stream CREATED"));
}
catch (Exception x)
{
Log("ConnectAndAuthenicate: EXCEPTION >> CONNECTING to server: …
Run Code Online (Sandbox Code Playgroud) 根据@ Len-Holgate 在这个问题中的建议,我异步请求0字节读取,并且在回调中,接受字节可用字节和同步读取,因为我知道数据是可用的并且不会阻塞.这看起来非常有效和精彩.
但后来我为SslStream添加了选项,并且方法崩溃了.零字节读取很好,但是SslStream解密字节,在TcpClient的缓冲区中保留零字节计数(恰当如此),我无法确定SslStream中现在有多少字节可用于读取.
有一个简单的伎俩吗?
一些代码,仅用于上下文:
sslStream.BeginRead(this.zeroByteBuffer, 0, 0, DataAvailable, this);
Run Code Online (Sandbox Code Playgroud)
在EndRead()(正确返回0)之后,DataAvailable包含:
// by now this is 0, because sslStream has already consumed the bytes
available = myTcpClient.Available;
if (0 < available) // Never occurs
{
// this part can be distractingly complicated, but
// it's based on the available byte count
sslStream.Read(...);
}
Run Code Online (Sandbox Code Playgroud)
由于协议,我需要逐字节评估和解码可变字节宽度的unicode和东西.我不想异步读取逐字节!
我正在尝试使用.Net的sslStream类创建TLS1.1/TLS1.2服务器.默认情况下,此流接受的唯一密码套件似乎是:
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
Run Code Online (Sandbox Code Playgroud)
我想启用这些的非ECDHE版本(即TLS_RSA_WITH_AES_128_CBC_SHA256).我google了一下,人们谈论通过修改默认的SChannel设置来更改密码套件 - 通过"SSL密码套件订单"或使用CNG功能:http://msdn.microsoft.com/en-us/library/窗户/桌面/ bb870930(v = vs.85)的.aspx
但是,我试过这个,我无法得到任何工作.使用上面链接的C++代码列出启用的密码套件,其中BCryptEnumContextFunctions()
显示我想要的密码套件默认启用.我甚至添加了TLS_RSA_WITH_AES_128_CBC_SHA256作为最高优先级套件,并且sslStream仍然拒绝来自仅支持该密码的客户端的TLS连接(例外:"客户端和服务器无法通信,因为它们没有通用算法")任何想法是什么去吧?
(顺便说一句,如果我的客户支持其中一个ECDHE密码套件,一切都很好)
其他人如何在.Net 4.5中实现TLS?我应该看看开源解决方案吗?SChannel的包装器如何更直接地使用CNG api?
我正在新机器上安装Windows服务.该服务通过TCP对SslStream执行各种操作,该操作使用问题中的证书.
该服务在其他2台Windows 2003计算机上使用相同的代码和相同的证书运行良好.但是,这台新机器也是带有64位处理器的Windows 2003.
当我尝试使用"服务帐户"身份运行服务时,我遇到了这个问题.它使用我自己的凭据工作正常.(同样,它在使用此服务帐户的其他2台计算机上运行正常)
导入证书时,我没有启用"强保护".
这是堆栈跟踪.
System.ComponentModel.Win32Exception:System.Net.Security.SecureChannel.AcquireCredentialsHandle上的System.Net.SSPIWrapper.AcquireCredentialsHandle(SSPIInterface SecModule,String package,CredentialUse intent,SecureCredential scc)无法识别提供给包的凭据(CredentialUse credUsage, SecureCredential&secureCredential)System.Net.Security.SecureChannel.AcquireClientCredentials(Byte []&thumbPrint)在System.Net.Security.SecureChannel.GenerateToken(Byte []输入,Int32偏移,Int32计数,字节[]和输出)在系统.Net.Security.SecureChannel.NextMessage(字节[]来电,的Int32偏移的Int32计数)
在System.Net.Security.SslState.StartSendBlob(字节[]来电,的Int32计数,AsyncProtocolRequest asyncRequest)
在System.Net.Security.SslState
System.Net.Securi上的System.Net.Security.SslState.StartReadFrame(Byte []缓冲区,Int32 readBytes,AsyncProtocolRequest asyncRequest)
中的.ProcessReceivedBlob(Byte []缓冲区,Int32计数,AsyncProtocolRequest asyncRequest)在System.Net.Security.SslState.StartSendBlob(Byte []传入,Int32计数,System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message,AsyncProtocolRequest asyncRequest)中的ty.SslState.StartReceiveBlob(Byte []缓冲区,AsyncProtocolRequest asyncRequest),
位于System.Net.Security.SslStream.AuthenticateAsClient的System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)的System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst,Byte [] buffer,AsyncProtocolRequest asyncRequest)
中的AsyncProtocolRequest asyncRequest( String targetHost,X509CertificateCollection clientCertificates,SslProtocols enabledSslProtocols,Boolean checkCertificateRevocation)
我使用OpenSSL生成了CA和多个证书(由CA签名),我有一个.NET/C#客户端和服务器SslStream
,每个都使用自己的证书/密钥,启用相互身份验证并禁用吊销.
我使用RemoteCertificateValidationCallback
了SslStream
验证远程服务器的证书,我希望我可以只加载CA的公钥证书(作为文件)的程序,并用它来验证远程证书而不是实际安装CA在Windows证书存储区.问题是X509Chain
除非我将CA安装到商店中,否则不会显示任何其他内容,当我打开其中一个证书的PEM版本时,Windows CryptoAPI shell也会显示.
我的问题是,我怎么能确认证书已签署了我的特定的CA只使用CA的公钥证书文件,而无需使用Windows证书存储区或WCF的时候RemoteCertificateValidationCallback
,X509Certificate
和X509Chain
似乎并没有给我什么合作?
sslstream ×10
c# ×6
.net ×4
ssl ×4
openssl ×2
tcpclient ×2
asynchronous ×1
c#-2.0 ×1
certificate ×1
ioexception ×1
makecert ×1