Store X509 Certificate in database

user586254 picture user586254 · Feb 8, 2011 · Viewed 18.7k times · Source

In order to access to the web service I need a certificate.

I generated my certs:

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

then merged this two into a pfx certificate by

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

then loaded my pfx file as X509Certificate2

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

Now, I would like to create a table into the data base that contains the following fields:

PrivateKey NVARCHAR  
PublicCer NVARCHAR  
Password NVARCHAR  

Then copy the content from private.key file, along with -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----, same for the public.cer, and set the password. Now, how can I get a proper instance of X509Certificate2 by reading this data from DB? In other words, how can I generate a pfx file from code, based on private key and certificate?

I will try to be more precise:

 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));

This code will correctly load a certificate string (x509 certificate, starting with -----BEGIN CERTIFICATE----- and ending -----END CERTIFICATE-----).

Now I need to get the private key:

My private key is in RSA format (-----BEGIN RSA PRIVATE KEY---- etc...)

I need to load it, and assign it to serverCert, in order to be able to use this certificate for authenticate on web service.

Any suggestions on how to do that?

Answer

Monsters X picture Monsters X · Apr 22, 2013

So this is actually easy, although I found no simple description of it. I've left the cert strings in my gist (sample cert, no secure data)

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);
 }