I am trying to decrypt some data using a certificate private key. It all works fine when the certificate is installed on the local machine (I am using a self signed certificate for testing and I have the private key for the certificate) but When I try to access the private key from a remote machine using the same code, I get the "Keyset does not exist" exception.
I am using a console application for testing, and I have made sure that my id have read permissions on the private key on the remote server. Here is the sample code I am using:
var store = new X509Store(@"\\server1\My", StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var result = store.Certificates.Find(X509FindType.FindBySubjectName, "server1.test.com", false);
var certificate = result[0];
store.Close();
//This succeeds from both local and remote server
var rsaPublic = (RSACryptoServiceProvider)certificate.PublicKey.Key;
//This succeeds from local, but fails from remote server
var rsaPrivate = (RSACryptoServiceProvider)certificate.PrivateKey;
Here is the exception call stack
Unhandled Exception: System.Security.Cryptography.CryptographicException: Keyset does not exist
at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()
at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)
at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()
at RsaPoc.Program.Main(String[] args)
I have found a similar unanswered question on SO, but it is using un-managed code, whereas I am using the managed API, but both seems to be having the same root cause.
We contacted Microsoft support for a solution and here is the response that we got:
Why is the private key not available when the code is executed on server2?
A: This is actually by design. Certificate stores are different from private key storage. While you can enumerate certificates remotely, private keys cannot be accessed remotely.
Can this issue be fixed by giving the user extra privileges or by changes in group policy settings? A: No. This doesn’t involve privileges or permission to the file.
If not both of the above then can you suggest the suitable solution?
A: 1. You can install the certificate on all machines so each one has a copy of the private key.
2. You can create a roaming domain user. A roaming certificate is the only situation where private keys can be roamed between machines.
Roaming profiles are located on a server, when the user logs on, a temporary copy of the profile (including private key) is created.
3. Use a third party cryptographic provider. There are some cryptographic providers that do allow remote private key access and cryptographic operations.