![](/img/trans.png)
[英]The server mode SSL must use a certificate with the associated private key - during TLS handshake
[英]Get "The server mode SSL must use a certificate with the associated private key." error in X509Certificate2 by use .cer instead of .pfx
我在自定义 web 服务器中使用 .cer 和 .key 文件使用 SslStream.AuthenticateAsServerAsync() 验证 ssl。 X509Certificate2 的创建过程是这样的:
var bytes = File.ReadAllBytes(certificatePath);
using var publicKey = new X509Certificate2(bytes,default(string));
var privateKeyText = File.ReadAllText(privateKeyPath);
var privateKeyBlocks = privateKeyText.Split("-", StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim('\n')).ToArray();
var privateKeyBytes = Convert.FromBase64String(privateKeyBlocks[1]);
using var rsa = RSA.Create();
if (privateKeyBlocks[0] == "BEGIN PRIVATE KEY")
{
rsa.ImportPkcs8PrivateKey(privateKeyBytes, out _);
}
else if (privateKeyBlocks[0] == "BEGIN RSA PRIVATE KEY")
{
rsa.ImportRSAPrivateKey(privateKeyBytes, out _);
}
var keyPair = publicKey.CopyWithPrivateKey(rsa);
return new X509Certificate2(keyPair.Export(X509ContentType.Pfx));
在使用.pfx 中,这一切都可以,但是通过在 SslStream.AuthenticateAsServerAsync() 中将此代码用于 replace.pfx 文件(及其生成过程)与 .cer 和 .key 文件,我得到了这个错误:
System.Security.Authentication.AuthenticationException: The server mode SSL must use a certificate with the associated private key.
我用于执行此操作的其他方式:
X509Certificate2 certWithKey = default;
try
{
string keyPem = File.ReadAllText(keyFile);
byte[] keyDer = UnPem(keyPem);
using (X509Certificate2 certOnly = new X509Certificate2(cerFile))
{
using (RSA rsa = RSA.Create())
{
// For "BEGIN PRIVATE KEY"
rsa.ImportPkcs8PrivateKey(keyDer, out _);
var tmp = certOnly.CopyWithPrivateKey(rsa);
certWithKey = new X509Certificate2(tmp.Export(X509ContentType.Pfx));
}
}
Serilog.Log.ForContext("Path", cerFile).Information("Create certificate from {FileName} successfully.", Path.GetFileName(cerFile));
}
catch (Exception ex)
{
Logger.LogError(ex, "Error in create certificate from {Path}", cerFile);
}
return certWithKey;
static byte[] UnPem(string pem)
{
// This is a shortcut that assumes valid PEM
// -----BEGIN words-----\nbase64\n-----END words-----
const string Dashes = "-----";
int index0 = pem.IndexOf(Dashes);
int index1 = pem.IndexOf('\n', index0 + Dashes.Length);
int index2 = pem.IndexOf(Dashes, index1 + 1);
return Convert.FromBase64String(pem.Substring(index1, index2 - index1));
}
同样在.net 5中使用这种新方式:
return X509Certificate2.CreateFromPemFile(certificatePath,privateKeyPath);
但是问题没有解决。
我想要的所有东西都是从.cer 和 .key 文件创建 X509Certificate2,而不是从.pfx 文件。 我不知道问题在哪里以及问题在哪里。创建 X509Certificate2 导致问题,或者我错过了其他一些东西(例如在验证 sslstream 中)。 坦克帮助我了解问题和最好的方法。
通过bartonjs的坦克,我的问题解决了:
string pass = Guid.NewGuid().ToString();
var certificate = X509Certificate2.CreateFromPemFile(certificatePath, privateKeyPath);
return new X509Certificate2(certificate.Export(X509ContentType.Pfx, pass), pass);
使用随机密码从.cer 文件创建 in-memory.pfx 类型的证书,并使用它代替原始证书。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.