I'm using the NpgSqlConnection for .net core web api project. Current PostgreSQL server has been move to another one and need to connect using the client certificates. We are provided with 3 certificate files named client-cert.pem, client-key.pem and server-ca.pem. I was able to connect to the server using the client cert & key files through the pgAdmin from browser. But, I'm not able to connect from my code. Tried several methods from inte.net but still I'm getting the below error.
{"28000: connection requires a valid client certificate"}
The code snippet I'm trying is given below.
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);
}
Also, here we are using only the client certificate named client-cert.pem, but, I think we may need to use the client-key.pem? If so, how can I add that? What am I missing here?
Any help will be highly appreciated as I'm stuck with this issue.
I got a solution for this and thought of posting it here which may help others who are facing the similar issue.
It didn't worked with.pem files. I have converted it to a.pfx file using the below command and it started working fine.
openssl pkcs12 -inkey C:\Certs\client-key.pem -in C:\Certs\client-cert.pem -export -out C:\Certs\client-cert.pfx
Reference: Certificate Authentication Support
EDIT
Instead of creating the physical pfx file, I was able to combine the two pem files and got it worked. Code snippet is given below for someone for reference in future.
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;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.