Npgsql 与 .net 核心 web 中的 ssl 证书连接 api
Npgsql connection with ssl certificates in .net core web api
我正在使用 NpgSqlConnection for .net core web api 项目。当前的 PostgreSQL 服务器已移至另一台,需要使用客户端证书进行连接。我们提供了 3 个证书文件,分别名为 client-cert.pem、client-key.pem 和 server-ca.pem。我能够通过浏览器的 pgAdmin 使用客户端证书和密钥文件连接到服务器。但是,我无法通过我的代码进行连接。从互联网上尝试了几种方法,但我仍然收到以下错误。
{"28000: connection requires a valid client certificate"}
下面给出了我正在尝试的代码片段。
var connectionString = "User ID=" + _dOptions.Value.AuthenticationCredentials.UserName
+ ";Password=" + _dOptions.Value.AuthenticationCredentials.PassWord
+ ";Server=" + _dOptions.Value.Server
+ ";Port=" + _dOptions.Value.Port.ToString()
+ ";Database=" + _dOptions.Value.Database
+ ";Integrated Security=true;Pooling=true;SSL Mode=Require;Trust Server Certificate=true";
_con = new NpgsqlConnection(connectionString);
_con.ProvideClientCertificatesCallback += new ProvideClientCertificatesCallback(MyClientCertificates);
private void MyClientCertificates(X509CertificateCollection certificates)
{
var cert = new X509Certificate("C:\Users\c-Anish\Documents\cloud_sql_replica_certs\DEV\client-cert.pem");
certificates.Add(cert);
}
此外,这里我们只使用名为 client-cert.pem 的客户端证书,但是,我认为我们可能需要使用 client-key.pem ?如果是这样,我该如何添加?我在这里错过了什么?
非常感谢任何帮助,因为我遇到了这个问题。
我找到了一个解决方案,并考虑将其张贴在这里,这可能会对面临类似问题的其他人有所帮助。
它不适用于 .pem 文件。我已使用以下命令将其转换为 .pfx 文件,并且开始正常工作。
openssl pkcs12 -inkey C:\Certs\client-key.pem -in C:\Certs\client-cert.pem -export -out C:\Certs\client-cert.pfx
参考:Certificate Authentication Support
编辑
我没有创建物理 pfx 文件,而是能够合并两个 pem 文件并让它工作。下面给出代码片段,供日后参考。
public X509Certificate2 GetCombinedCertificateAndKey(string certificatePath, string privateKeyPath)
{
using var publicKey = new X509Certificate2(certificatePath);
var privateKeyText = System.IO.File.ReadAllText(privateKeyPath);
var privateKeyBlocks = privateKeyText.Split("-", StringSplitOptions.RemoveEmptyEntries);
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);
var Certificate = new X509Certificate2(keyPair.Export(X509ContentType.Pfx));
return Certificate;
}
我正在使用 NpgSqlConnection for .net core web api 项目。当前的 PostgreSQL 服务器已移至另一台,需要使用客户端证书进行连接。我们提供了 3 个证书文件,分别名为 client-cert.pem、client-key.pem 和 server-ca.pem。我能够通过浏览器的 pgAdmin 使用客户端证书和密钥文件连接到服务器。但是,我无法通过我的代码进行连接。从互联网上尝试了几种方法,但我仍然收到以下错误。
{"28000: connection requires a valid client certificate"}
下面给出了我正在尝试的代码片段。
var connectionString = "User ID=" + _dOptions.Value.AuthenticationCredentials.UserName
+ ";Password=" + _dOptions.Value.AuthenticationCredentials.PassWord
+ ";Server=" + _dOptions.Value.Server
+ ";Port=" + _dOptions.Value.Port.ToString()
+ ";Database=" + _dOptions.Value.Database
+ ";Integrated Security=true;Pooling=true;SSL Mode=Require;Trust Server Certificate=true";
_con = new NpgsqlConnection(connectionString);
_con.ProvideClientCertificatesCallback += new ProvideClientCertificatesCallback(MyClientCertificates);
private void MyClientCertificates(X509CertificateCollection certificates)
{
var cert = new X509Certificate("C:\Users\c-Anish\Documents\cloud_sql_replica_certs\DEV\client-cert.pem");
certificates.Add(cert);
}
此外,这里我们只使用名为 client-cert.pem 的客户端证书,但是,我认为我们可能需要使用 client-key.pem ?如果是这样,我该如何添加?我在这里错过了什么?
非常感谢任何帮助,因为我遇到了这个问题。
我找到了一个解决方案,并考虑将其张贴在这里,这可能会对面临类似问题的其他人有所帮助。
它不适用于 .pem 文件。我已使用以下命令将其转换为 .pfx 文件,并且开始正常工作。
openssl pkcs12 -inkey C:\Certs\client-key.pem -in C:\Certs\client-cert.pem -export -out C:\Certs\client-cert.pfx
参考:Certificate Authentication Support
编辑
我没有创建物理 pfx 文件,而是能够合并两个 pem 文件并让它工作。下面给出代码片段,供日后参考。
public X509Certificate2 GetCombinedCertificateAndKey(string certificatePath, string privateKeyPath)
{
using var publicKey = new X509Certificate2(certificatePath);
var privateKeyText = System.IO.File.ReadAllText(privateKeyPath);
var privateKeyBlocks = privateKeyText.Split("-", StringSplitOptions.RemoveEmptyEntries);
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);
var Certificate = new X509Certificate2(keyPair.Export(X509ContentType.Pfx));
return Certificate;
}