-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NET 6.0 - mutual TLS with private key stored in TPM2 #94493
Comments
Tagging subscribers to this area: @dotnet/area-system-security, @bartonjs, @vcsjones Issue DetailsFirst of all, I apologize if asking for guidance here is not the right thing to do. I am presented with a business/security requirement to use mTLS with (Private Key stored in TPM2 and the public part stored in a file) as a way to authenticate connections from my NET 6.0 app running on Debian as a service (a management agent) to the management server. I am aware of the latest-and-greatest .NET 8.0 SafeEvpKeyHandle.OpenPrivateKeyFromEnigne, however I am currently locked to .NET 6.0 due to corporate policy to delay migration to the new LTS version. My research:
What I tried:
Next steps (assumed):
Before I continue this effort, I'd be most greateful for some guidance as to whether my goal (mTLS/SslStream via HttpClient using a client certificate with Private Key stored on TPM2.0) is actually achievable on .NET 6 or .NET 8? If yes, which direction could be the most promising in this situation? P/Invoke into libopenssl to get the key handle? Anything else? If anyone could share a reference to an external learning resource on the topic, that would be awesome!
|
The answer is somewhere between outdated, Windows-biased, and wrong.
It is. It has probably worked since .NET Core 2.0 (when CopyWithPrivateKey was introduced); and I know of people having gotten it to work on either Core 2.0 or Core 3.1 (but not with public source code to my recollection). So it's definitely achievable. In .NET 8, if there's an ENGINE provider for TPM keys it should be fairly easy since there's now platform API to help with the boilerplate.
Yeah. Basically you need to do private static X509Certificate2 GetClientCert(string path, ???)
{
using SafeEvpPKeyHandle keyHandle = ???;
using RSAOpenSsl rsa = new RSAOpenSsl(keyHandle);
using X509Certificate2 certOnly = new X509Certificate2(path);
return certOnly.CopyWithPrivateKey(rsa);
} And the returned value from that can be used with SslStream (provided it's a proper client (or server) certificate (as appropriate), of course). |
@bartonjs , thanks a ton for responding so fast! |
@bartonjs , thanks again! I made it work on a Debian, based on your directions. In production I guess I have to be careful about the certificate's and its supporting objects' lifecycle, disposing them at the proper times. Closing the issue. |
@adadurov: I am encountering a similar issue where the key is stored in an Azure KeyVault HSM and marked as non-exportable. Could you guide me towards implementing a similar solution? Essentially, I have the public part of the certificate stored in a database and the private key in the HSM. My goal is to perform client certificate authentication using HttpClient. |
@Soren-Knudsen , did you check the gist https://gist.github.com/adadurov/292818c4da0301f16f5922820da410d0 ? If that doesn't work for you, what is the error you are facing? |
Thanks for replaying @adadurov: After some more research, I troubled on the https://github.com/microsoft/AzureKeyVaultManagedHSMEngine repository, which seems to enable me to offload all the cryptographic operations to the key vault. |
First of all, I apologize if asking for guidance here is not the right thing to do.
I am presented with a business/security requirement to use mTLS (with Private Key stored in TPM2 and the public part stored in a file) as a way to authenticate connections from my NET 6.0 app running on Debian as a service (a management agent) to the management server. I am aware of the latest-and-greatest .NET 8.0 SafeEvpKeyHandle.OpenPrivateKeyFromEnigne, however I am currently locked to .NET 6.0 due to corporate policy to delay migration to the new LTS version.
My research:
What I tried:
Next steps (assumed):
Before I continue this effort, I'd be most greateful for some guidance as to whether my goal (mTLS/SslStream via HttpClient using a client certificate with Private Key stored on TPM2.0) is actually achievable on .NET 6 or .NET 8? If yes, which direction could be the most promising in this situation? P/Invoke into libopenssl to get the key handle? Anything else?
If anyone could share a reference to an external learning resource on the topic, that would be awesome!
The text was updated successfully, but these errors were encountered: