Reputation: 13
installing my WCF service I also install certificate with private key. Since I will be running service as a different user, that user needs access to the private key. I extensively read other stackoverflow questions and they all suggest permission on private key file in file system needs to adjusted. I do this by,
private static void AddUserPermissions(X509Certificate2 certificate, NTAccount user, StoreLocation storeLocation)
{
RSACryptoServiceProvider rsaProvider = (RSACryptoServiceProvider)certificate.PrivateKey;
// Find file
string keyPath = FindKeyLocation(rsaProvider.CspKeyContainerInfo.UniqueKeyContainerName, storeLocation);
FileInfo keyFileInfo = new FileInfo(keyPath);
// Create new FileSecurity
FileSecurity keyFileSecurity = keyFileInfo.GetAccessControl();
keyFileSecurity.AddAccessRule(new FileSystemAccessRule(user, FileSystemRights.Read, AccessControlType.Allow));
// Apply file security to the file
keyFileInfo.SetAccessControl(keyFileSecurity);
}
When I run my program and inspect the private key file I can see, for example "Network Service" has been added to the permissions list.
Great, that's working, but when WCF tries to use private key, it cannot access it.
Looking at certlm, certificate -> All Tasks -> Manage Private Keys.. I can see that my user is not on the list. Adding my user through GUI solves the issue, but I need to do it in code!!
Upvotes: 1
Views: 1956
Reputation: 503
Anyone who gets this far looking for a solution for ECDSA certificate keys, I found a way!
string keyUniqueName = (certificate.GetECDsaPrivateKey() as ECDsaCng)?.Key.UniqueName
?? (certificate.GetRSAPrivateKey() as RSACng)?.Key.UniqueName
?? throw new NotSupportedException("No ECDSA or RSA key found");
In the example code from the question, the FindKeyLocation
gets passed rsaProvider.CspKeyContainerInfo.UniqueKeyContainerName
, instead you would pass keyUniqueName
as taken from my example.
One more good note, the accepted answer from Daniel Fisher lennybacon correctly documents where keys are stored based on where they were generated/installed. But you should use Environment.SpecialFolder.CommonApplicationData
or Environment.SpecialFolder.ApplicationData
for key file paths.
Also, I found my keys in c:\ProgramData\Microsoft\Crypto\
, not c:\ProgramData\Application Data\Microsoft\Crypto\
.
Upvotes: 1
Reputation: 4194
The keys are located in C:\ProgramData\Application Data\Microsoft\Crypto\RSA\MachineKeys
and setting a normal file permission here is reflected in certlm.msc
.
The keys are located in C:\ProgramData\Application Data\Microsoft\Crypto\Keys
and setting a normal file permission here is reflected in certlm.msc
.
Ensure you modify the permissions on the right file in the right location.
Upvotes: 1