1

Background

I've been playing around with the idea of using an protected private key wrapped by an API, like Azure KeyVault or Amazon KMS keys to sign certificates for internal Private Key Infrastructure.

Conceptually, this is similar to using the OpenSSH Agent to sign connection requests for SSH. The key is never exposed to the application that prepared the request.

My interest is primarily academic. I handle RSA keys frequently for work, and just love peeking under the covers at how it all works. But if I can find something that is actually production-ready, I might use it for my day-to-day work with web deployments.

Options I've Explored

Azure KeyVault provides an interface for creating self-signed certificates, but if I want to use the certificates as client certificates with MongoDB (for example), then it would be helpful to have a certificate to use as the root.

I've looked at a number of options to achieve this goal. The one that seemed most promising is to write a custom PKCS11 provider to act as an intermediary to the API-wrapped key. Maybe using libcurl or something like that to make the API call. I'm not that competent a C/C++ programmer, so this wouldn't be a very practical solution for me... though I may be interested in pursuing it for the learning experience.

I could use a third-party solution like Hashicorp Vault PKI or CredHub Certificates. Hashicorp Vault has a storage provider to keep the resulting key in Azure KeyVault. But from the documentation, it appears both these services still leave the Private Key exposed to themselves.

I looked at pyOpenSSL as a higher-level abstraction to sign a CSR, but the API takes a private key as a parameter.

Benefits of Solution

To me, the perceived benefits of using such a solution are that the Private Key is never accessible (even to me). So an exposure of access to the Root CA key is limited to whatever certificates an attacker manages to issue while they have access.

Since access to the Key has an audit log, it would simplify tracking of it's use, and identifying unauthorized access.

The Actual Question

I'm trying to find or develop a solution where the digital signature is processed by a third party, but the logic of constructing the content to sign is handled locally, preferably by known standard solutions like OpenSSL (as library or CLI).

Does a solution exist for processing an x509 CSR into an x509 Certificate where the Private Key and signing algorithms are wrapped in a Web API?

Failing that, is there any good documentation somewhere to use existing libraries to convert a CSR into a Certificate on a low level? Blog posts welcome.

nbering
  • 3,988
  • 1
  • 21
  • 22
  • @bartonjs has provided a promising lead for development in .NET Core. I'm still willing to accept an answer if anyone knows about an already packaged solution. I can't be the only one thinking about this problem. – nbering Mar 18 '18 at 16:42
  • This is exactly how SSL Certificate reseller works. All the major CAs have a certificate reseller program. – Lie Ryan Mar 19 '18 at 00:23
  • @LieRyan I haven’t worked with a CA or reseller program to know if this is true. I’d like to be clear... this is not about submitting a CSR to be signed, this is about processing a CSR and offloading only the signing algorithm portion of creating a certificate. It’s very close to using PKCS11 with OpenSSL to have a hardware module to the signing, except it’s a web API and I have not so far found any software implementation that can do this. – nbering Mar 19 '18 at 00:28
  • I've done something like this with .NET 5.0. The signing cert is stored in Azure Key Vault. The API call is protected with Azure Active Directory authentication. The local processing is done with a .NET desktop application. The difference is that in my solution the certificate is created on the server and sent to the client in serialized form over a secure connection. – Peter Mar 23 '22 at 10:47

1 Answers1

2

Many cryptographic APIs support network-attached Hardware Security Modules (HSMs), and using those APIs would already seem to qualify for your theoretical construct.

.NET Core has a CertificateRequest class. If you make a custom class which extends RSA to communicate with KeyVault (or use an existing one) then you can create certificates where the signing key lives in KeyVault.

X509SignatureGenerator generator = 
    X509SignatureGenerator.CreateForRSA(keyVaultRsa, RSASignaturePadding.Pkcs1);

X509Certificate2 cert =
    request.Create(issuerCert.SubjectName, generator, notBefore, notAfter, serialNumber);

It can write CSRs, but not read them. So that's only a partial answer, unless you don't actually have need for CSRs in your scenario.

bartonjs
  • 1,723
  • 7
  • 9
  • Interesting... this is part of the .NET Standard? I'm on Mac and Linux these days, but I used to do ASP.Net and WPF development. I'd be willing to explore .NET Core if it gets me to this goal faster. It would certainly seem easier and safer than a C/C++ implementation. As for being able to read a CSR, it would make a lot of security models for leaving Private Keys in the place they're generated easier to implement. But for playing around, I'd be happy to start out signing a certificate without a CSR. – nbering Mar 18 '18 at 04:02
  • 1
    It's part of the .NET Core 2.0 release (netcoreapp20) and part of .NET Framework 4.7.2 early access, but isn't in netstandard20. Just means you need to target netcoreapp20 explicitly (and won't run on older .NET Framework versions) – bartonjs Mar 18 '18 at 04:18