I work with web services / APIs which use HTTPS Client Certificates to do authentication.
I currently load the certificate, including private key, from Windows cert store and pass that to HttpClient
.
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var thumbprint = "...";
var cert = store.Certificates.SingleOrDefault(c => c.Thumbprint == thumbprint);
var httpClientHandler = new HttpClientHandler();
httpClientHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
httpClientHandler.ClientCertificates.Add(cert);
var httpClient = new HttpClient(httpClientHandler);
using (var requestContent = new StringContent("Some content", Encoding.UTF8, "text/plain"))
using (var request = new HttpRequestMessage(HttpMethod.Post, "https://some.url.com"))
{
request.Content = requestContent;
var response = await httpClient.SendAsync(request);
...
}
There's a new requirement to use Azure Key Vault (or some other cloud HSM service) so we don't need to touch the private key.
Question: is this possible? If so, are there examples?
I've been able to do a proof of concept which uses a non-exportable certificate in Azure to sign arbitrary data, and seen a few code examples of signing XML documents, and Microsoft have a tool to do code signing from Azure. But everything I've seen involving HTTPS Client Authentication involves downloading a PFX with the private key, which entirely defeats the purpose of an HSM or vault.
The armchair cryptographer in me says "this isn't possible, either you need the private key, or the HSM must make the web request on your behalf". I can't see any APIs on Azure Key Vault which would make such web requests.
See also: Using a non-exportable client certificate from Azure Key Vault in C# Azure function (v2) which has no answer.
No, you cannot use a non-exportable key. The policy that's used to create the certificate must indicate that the key is exportable. https://learn.microsoft.com/en-us/azure/key-vault/certificates/about-certificates
The documentation also says, "If the policy indicates that the key is non-exportable, then the private key isn't a part of the value when it's retrieved as a secret."