I am building an ACS protected Azure WCF service that will require clients to authenticate via a certificate.
I would like the client (and the server) to load their respective password certs from the X509Store instead of from the file system.
I am using this code:
private static X509Certificate2 GetCertificate(string thumbprint)
{
var certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
certStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = certStore.Certificates.Find(
X509FindType.FindByThumbprint,
thumbprint, false);
certStore.Close();
if (certCollection.Count == 0)
{
throw new System.Security.SecurityException(string.Format(CultureInfo.InvariantCulture, "No certificate was found for thumbprint {0}", thumbprint));
}
return certCollection[0];
}
Problem is, it's not loading the private key which it needs for authentication. I have tried to modify the return statement to this:
return new X509Certificate2(certCollection[0].Export(X509ContentType.Pfx, "password"));
However, this fails with a CryptographicException "The spcecified network password is incorrect".
Edit: The .Export() method works properly if you don't pass the password argument in.
Any help on this?
When you export, the password you provide is the password you want to use for the exported file, it's not the password for the source certificate.
I'm not sure what you can do with X509Store and password-protected certs because the password should be supplied to the X509Certificate constructor and you get already-instantiated objects out of the store.
I think you can just get the raw data from the cert you want and construct a new one with the password you want. For example:
X509Certificate2 cert = new X509Certificate2(certCollection[0].GetRawCertData, password);
I would also suggest you try to use SecureString
when dealing with passwords (but that's a different bag of worms...)