.Net Core Web API中使用SSL证书的Npgsql连接

5

我正在使用 NpgSqlConnection 在 .net core web api 项目中。当前的 PostgreSQL 服务器已被移动到另一个服务器,并需要使用客户端证书进行连接。我们提供了3个证书文件,命名为client-cert.pem,client-key.pem和server-ca.pem。我能够通过从浏览器的 pgAdmin 使用客户端证书和密钥文件连接到服务器,但是我无法从我的代码连接。尝试了互联网上的几种方法,但仍然遇到以下错误。

{"28000: 连接需要一个有效的客户端证书"}

我正在尝试的代码片段如下所示。

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?如果是这样,我该如何添加它?我漏掉了什么吗?

由于我被卡在这个问题上,所以任何帮助将不胜感激。


应该可以提供环境变量 PGSSLCERTPGSSLKEYPGSSLROOTCERT,指向相应的文件。 - clamp
我已经尝试过了,但是还是得到了相同的错误信息。 - Anish V
还没有得到解决方案。有人可以帮忙吗? - Anish V
1个回答

4
我有解决方案并想在这里发布,可能会帮助遇到类似问题的其他人。
使用.pem文件无法工作。我将其转换为.pfx文件,并使用下面的命令,它开始正常工作了。
openssl pkcs12 -inkey C:\Certs\client-key.pem -in C:\Certs\client-cert.pem -export -out C:\Certs\client-cert.pfx

参考: 证书认证支持

编辑

不需要创建物理的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;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接