2
votes

I am using WebRequest to connect to a webpage that uses https.

If I try to use a client certificate that is in the personal store in LocalMachine by using

var myStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
myStore.Open(OpenFlags.ReadOnly);

var clientCertificates = myStore.Certificates.Find(X509FindType.FindBySubjectName, "foobar",
  validOnly: false);

and then I create a connection with

var req = (HttpWebRequest)WebRequest.Create("https://theserver.com/the/url");
req.Method = "POST";
req.ContentType = "application/json";
req.ProtocolVersion = HttpVersion.Version11;

req.ClientCertificates = clientCertificates; 

req.ServerCertificateValidationCallback += (o, certificate, chain, errors) =>
{
  return true;
};

using (var stream = req.GetRequestStream())
{
  stream.Write(data, 0, data.Length);
  stream.Flush();
}

var response = req.GetResponse();

I fail on the req.GetResponse line with

System.Net.WebException: 'The request was aborted: Could not create SSL/TLS secure channel.'

But if I instead load the client certificate from file, (the same file that I had previously installed in the store) with

var certificatePath = @"C:\temp\file.p12";

var clientCertificate = new X509Certificate2(certificatePath, "pwd", 
  X509KeyStorageFlags.Exportable);

and

req.ClientCertificates.Add(clientCertificate);

I will be able to run the https query successfully.

This requires both that I keep a file in the file system and that I put a password in the source code.

  • How do I use the store instead of the file system?

  • Why do I have to use validOnly: false to get the client certificates?

edit

The preferrable way of getting access to those certificates (client and server certificate) would be to have them in web.config as endpoints, but I have not succeeded doing that.

2
Does the user you are running this application as have access to the private key of the cert?jtate
Yes, the user is in the group administrators. Its a desktop app.Anders Lindén
How did you import the certificate into the store? Is there a chance the private key was missed?Ash Saf
If I right click on the certificate in "Manage computer certificates", all tasks -> manage private keys will show me permissions for the private keys. Is that an indicator there is a private key there?Anders Lindén
In the clientCertificates collection from Find, is it a non-empty collection? Does it have any certs that report true for HasPrivateKey?bartonjs

2 Answers

0
votes

To solve the symptoms of the problem/many problems, I had to add the user Everyone to the ACL of the private key of the certificate.

0
votes

Instead of changing the ACL of the private key, I found that the ClientCertificates property worked perfectly well if I only gave it public keys. Yes, the authentication won't work if you don't have the private key in the store, but converting to a public-key-only certificate appears to work for me every time.

var publicKeyOnly = new X509Certificate2(authenticationCert.Export((X509ContentType.Cert));