将 X509 证书存储在数据库中

Posted

技术标签:

【中文标题】将 X509 证书存储在数据库中【英文标题】:Store X509 Certificate in database 【发布时间】:2011-02-08 13:42:53 【问题描述】:

为了访问网络服务,我需要一个证书。

我生成了我的证书:

openssl genrsa 1024 > private.key
openssl req -new -x509 -nodes -sha1 -days 1100 -key private.key > public.cer

然后将这两者合并为一个 pfx 证书

openssl pkcs12 -in public.cer -inkey private.key -export -out client.pfx

然后将我的 pfx 文件加载为 X509Certificate2

X509Certificate2 clientCert = new X509Certificate2("cert.pfx", "password");

现在,我想在数据库中创建一个包含以下字段的表:

PrivateKey NVARCHAR  
PublicCer NVARCHAR  
Password NVARCHAR  

然后从 private.key 文件中复制内容,连同 -----BEGIN CERTIFICATE----- 和 -----END CERTIFICATE-----,与 public.cer 相同,并设置密码。 现在,如何通过从 DB 读取这些数据来获得 X509Certificate2 的正确实例? 换句话说,如何根据私钥和证书从代码生成 pfx 文件?

我会尽量准确:

 string connectionString; string query; string cert;

    connectionString = ConfigurationManager.ConnectionStrings[0].ConnectionString;
    query = "SELECT clientcert FROM settings_services WHERE ID = 1";

    using (SqlConnection cn = new SqlConnection(connectionString))
    
        SqlCommand cmd = new SqlCommand(query, cn);
        cn.Open();
        cert = (string)cmd.ExecuteScalar();
    

    X509Certificate2  serverCert = new X509Certificate2(Encoding.UTF8.GetBytes(cert));

此代码将正确加载证书字符串(x509 证书,以 -----BEGIN CERTIFICATE----- 开头并以 -----END CERTIFICATE----- 结尾)。

现在我需要获取私钥:

我的私钥是 RSA 格式(-----BEGIN RSA PRIVATE KEY---- etc...)

我需要加载它,并将其分配给 serverCert,以便能够使用此证书在 Web 服务上进行身份验证。

关于如何做到这一点的任何建议?

【问题讨论】:

这个问题的答案你会在这里找到。 codeproject.com/KB/security/CertificatesToDBandBack.aspx 问候 相关:***.com/questions/893757 【参考方案1】:

所以这实际上很简单,虽然我没有找到简单的描述。我将证书字符串留在了我的要点中(示例证书,没有安全数据)

https://gist.github.com/BillKeenan/5435753

[TestMethod]
public void TestCertificate()

    const string publicCert = @"MIIBrzCCARigAwIBAgIQEkeKoXKDFEuzql5XQnkY9zANBgkqhkiG9w0BAQUFADAYMRYwFAYDVQQDEw1DZXJ0QXV0aG9yaXR5MB4XDTEzMDQxOTIwMDAwOFoXDTM5MTIzMTIzNTk1OVowFjEUMBIGA1UEAxMLc2VydmVyMS5jb20wgZ0wDQYJKoZIhvcNAQEBBQADgYsAMIGHAoGBAIEmC1/io4RNMPCpYanPakMYZGboMCrN6kqoIuSI1n0ufzCbwRkpUjJplsvRH9ijIHMKw8UVs0i0Ihn9EnTCxHgM7icB69u9EaikVBtfSGl4qUy5c5TZfbN0P3MmBq4YXo/vXvCDDVklsMFem57COAaVvAhv+oGv5oiqEJMXt+j3AgERMA0GCSqGSIb3DQEBBQUAA4GBAICWZ9/2zkiC1uAend3s2w0pGQSz4RQeh9+WiT4n3HMwBGjDUxAx73fhaKADMZTHuHT6+6Q4agnTnoSaU+Fet1syVVxjLeDHOb0i7o/IDUWoEvYATi8gCtcV20KxsQVLEc5jkkajzUc0eyg050KZaLzV+EkCKBafNoVFHoMCbm3n";
    const string privateCert = @"<RSAKeyValue><Modulus>gSYLX+KjhE0w8Klhqc9qQxhkZugwKs3qSqgi5IjWfS5/MJvBGSlSMmmWy9Ef2KMgcwrDxRWzSLQiGf0SdMLEeAzuJwHr270RqKRUG19IaXipTLlzlNl9s3Q/cyYGrhhej+9e8IMNWSWwwV6bnsI4BpW8CG/6ga/miKoQkxe36Pc=</Modulus><Exponent>EQ==</Exponent><P>mmRPs28vh0mOsnQOder5fsxKsuGhBkz+mApKTNQZkkn7Ak3CWKaFzCI3ZBZUpTJag841LL45uM2NvesFn/T25Q==</P><Q>1iTLW2zHVIYi+A6Pb0UarMaBvOnH0CTP7xMEtLZD5MFYtqG+u45mtFj1w49ez7n5tq8WyOs90Jq1qhnKGJ0mqw==</Q><DP>JFPWhJKhxXq4Kf0wlDdJw3tc3sutauTwnD6oEhPJyBFoPMcAjVRbt4+UkAVBF8+c07gMgv+VHGyZ0lVqvDmjgQ==</DP><DQ>lykIBEzI8F6vRa/sxwOaW9dqo3fYVrCSxuA/jp7Gg1tNrhfR7c3uJPOATc6dR1YZriE9QofvZhLaljBSa7o5aQ==</DQ><InverseQ>KrrKkN4IKqqhrcpZbYIWH4rWoCcnfTI5jxMfUDKUac+UFGNxHCUGLe1x+rwz4HcOA7bKVECyGe6C9xeiN3XKuQ==</InverseQ><D>Fsp6elUr6iu9V6Vrlm/lk16oTmU1rTNllLRCZJCeUlN/22bHuSVo27hHyZ1f+Q26bqeL9Zpq7rZgXvBsqzFt9tBOESrkr+uEHIZwQ1HIDw2ajxwOnlrj+zjn6EKshrMOsEXXbgSAi6SvGifRC2f+TKawt9lZmGElV4QgMYlC56k=</D></RSAKeyValue>";

    var certificate = new X509Certificate2(Convert.FromBase64String(publicCert));

    var crypto = new RSACryptoServiceProvider();

    crypto.FromXmlString(privateCert);

    certificate.PrivateKey = crypto;

    //export a private key
    var exportedPrivate = certificate.PrivateKey.ToXmlString(true);
    var exportedPublic = Convert.ToBase64String(certificate.RawData);

    Assert.AreEqual(publicCert, exportedPublic);
    Assert.AreEqual(privateCert, exportedPrivate);
 

【讨论】:

【参考方案2】:

你有一个带有 byte[] 的构造函数。因此,您可以将证书存储为字节数组并使用

加载您的证书
public X509Certificate2(
    byte[] rawData
)

链接:http://msdn.microsoft.com/en-us/library/ms148413%28v=VS.100%29.aspx

【讨论】:

这不适用于我的情况。我需要能够让客户端生成 private.key 和公共证书,然后他需要将这两个文件的内容复制到数据库中,并将私钥的密码也保存到数据库中。现在,基于这些数据,我需要从代码中创建一个有效的 X509Certificate2 对象。 @MaiO:这是您应该在问题中包含的细节。无论如何,-----BEGIN CERTIFICATE----------END CERTIFICATE----- 之间的内容只是 Base64 编码数据。一个好的开始可能是通过Covert.FromBase64String() 运行文本。 这实际上似乎不起作用,尽管文档说了什么。错误是 CryptographicException:找不到请求的对象

以上是关于将 X509 证书存储在数据库中的主要内容,如果未能解决你的问题,请参考以下文章

使用 C# 从 CA 证书为设备创建 X509 证书

X509Certificate2类怎样导入一个公钥字符串

C# 如何验证 Root-CA-Cert 证书 (x509) 链?

如何在 PyCrypto 中使用 X509 证书?

OpenSSL之X509证书用法

在 Hyperledger Fabric 中使用的外部 x509 证书签名和密钥算法的要求