【发布时间】:2019-08-04 00:04:11
【问题描述】:
我想在我的 C# 应用程序中实现证书/公钥固定。我已经看到了很多直接固定服务器证书的解决方案,例如在this question。但是,为了更灵活,我只想固定根证书。服务器在设置中获得的证书由中间 CA 签名,该 CA 本身由根签名。
到目前为止,我实现的是一个从 PKCS#12 (.pfx) 文件加载自己的证书、私钥、中间证书和根证书的服务器。我使用以下命令创建了文件:
openssl pkcs12 -export -inkey privkey.pem -in server_cert.pem -certfile chain.pem -out outfile.pfx
chain.pem 文件包含根证书和中间证书。
服务器加载此证书并希望对客户端进行身份验证:
// certPath is the path to the .pfx file created before
var cert = new X509Certificate2(certPath, certPass)
var clientSocket = Socket.Accept();
var sslStream = new SslStream(
new NetworkStream(clientSocket),
false
);
try {
sslStream.AuthenticateAsServer(cert, false, SslProtocols.Tls12, false);
} catch(Exception) {
// Error during authentication
}
现在,客户端要对服务器进行身份验证:
public void Connect() {
var con = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
con.Connect(new IPEndPoint(this.address, this.port));
var sslStream = new SslStream(
new NetworkStream(con),
false,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
sslStream.AuthenticateAsClient("serverCN");
}
public static bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors
)
{
// ??
}
现在的问题是服务器只向客户端发送自己的证书。 chain 参数也不包含更多信息。 这在某种程度上是合理的,因为 X509Certificate2 证书(在服务器代码中)仅包含服务器证书,没有关于中间证书或根证书的信息。但是,客户端无法验证整个链,因为(至少)缺少中间证书。
到目前为止,我没有发现任何让 .NET 发送整个证书链的可能性,但我不想自己固定服务器证书或中间证书,因为这破坏了根证书固定的灵活性。
因此,有没有人知道让 SslStream 发送整个链进行身份验证或使用其他方法实现功能的可能性?还是我必须以不同的方式包装证书?
谢谢!
编辑:
我做了一些其他的测试来检测这个问题。正如 cmets 中所建议的,我创建了一个包含所有证书的 X509Store。之后,我使用我的服务器证书和存储构建了一个X509Chain。在服务器本身上,新链正确包含所有证书,但不在 ValidateServerCertificate 函数中..
【问题讨论】:
-
X509Chain包含与服务器证书关联的证书颁发机构链,您可以在RemoteCertificateValidationCallback中看到。但是您使用的是自己的 pfx 证书,请尝试先枚举它并导入服务器存储。还有一些文章stackoverflow.com/questions/9141198/…和stackoverflow.com/questions/5036590/… -
我将文件中的所有证书添加到服务器存储中。但是,我不太明白客户端的链现在应该如何访问整个链。你能在这里更明确一点吗?
-
ChainElementschain对象在您的ValidateServerCertificate方法中的属性应该具有完整的链 -
我知道,但
ChainElements在客户端上只包含一个元素。也许我创建 PKCS#12 文件的方式有问题?你知道验证的方法吗? -
我没有自己创建 pfx 文件,只是使用现有的。根据这篇文章stackoverflow.com/questions/6307886/…,您应该在
openssl命令中包含根 CA 和中间证书
标签: c# .net certificate sslstream pinning