Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Wednesday, April 11, 2012 5:12 PM | 1 vote
Greetings,
I am trying to install a certificate from a .p12 file into the Local Machine - Personal store and set the permissions for Everyone to full control. I can acheive this manually with mmc on W7 (or mmc + WSE Certificate Tool on XP.) When attempting with the vb.net code below I get no errors but when I try to access the security tab (Manage Private Keys in mmc on W7, or WSE Certificate Tools on XP) I get the error, "No keys found for certificate!"
I am using the following code to install the certificate, which seems to be working. However I am not convinced its placing the private key in the correct place. I have tried two methods for setting permissions on the private key and the second method, which locates the private key file indicates the private key is being stored under users\my-user-account\.. Should that be a public account
Dim x As New X509Certificate2
x.Import(thisNode.Tag, Keytool_Pass, X509KeyStorageFlags.MachineKeySet And X509KeyStorageFlags.Exportable And X509KeyStorageFlags.PersistKeySet)
s = New X509Store(StoreName.My, StoreLocation.LocalMachine)
s.Open(OpenFlags.ReadWrite)
Dim certCollection As New X509Certificate2Collection
certCollection.Add(x)
s.AddRange(certCollection)
The first method I tried for setting permissions is this, which I found here:
http://stackoverflow.com/questions/425688/how-to-set-read-permission-on-the-private-key-file-of-x-509-certificate-from-ne
Dim id As New Principal.SecurityIdentifier("S-1-1-0")
Dim rsa As Cryptography.RSACryptoServiceProvider = x.PrivateKey
If rsa IsNot Nothing Then
Dim cspParams = New Cryptography.CspParameters(rsa.CspKeyContainerInfo.ProviderType, _
rsa.CspKeyContainerInfo.ProviderName, _
rsa.CspKeyContainerInfo.KeyContainerName) _
With {.Flags = Cryptography.CspProviderFlags.UseExistingKey And Cryptography.CspProviderFlags.UseMachineKeyStore, _
.CryptoKeySecurity = rsa.CspKeyContainerInfo.CryptoKeySecurity}
cspParams.CryptoKeySecurity.AddAccessRule(New CryptoKeyAccessRule(id, CryptoKeyRights.FullControl, AccessControlType.Allow))
Dim rsa2 As Cryptography.RSACryptoServiceProvider = New Cryptography.RSACryptoServiceProvider(cspParams)
End If
The second method I tried is this, which I found here:
http://www.codeproject.com/script/Forums/View.aspx?fid=1649&msg=2062983
Private Shared Sub PlaceInStore(ByVal cert As X509Certificate2)
Dim store As New X509Store(StoreName.My, StoreLocation.LocalMachine)
Try
store.Open(OpenFlags.ReadWrite)
If Not store.Certificates.Contains(cert) Then
store.Add(cert)
End If
Dim indexInStore As Integer = store.Certificates.IndexOf(cert)
cert = store.Certificates(indexInStore)
AddEveryoneAccessToCertificate(cert)
Finally
store.Close()
End Try
End Sub
Private Shared Sub AddEveryoneAccessToCertificate(ByVal cert As X509Certificate2)
Dim rsa As RSACryptoServiceProvider = TryCast(cert.PrivateKey, RSACryptoServiceProvider)
If rsa IsNot Nothing Then
Dim keyfilepath As String = FindKeyLocation(rsa.CspKeyContainerInfo.UniqueKeyContainerName)
Dim file As New FileInfo((keyfilepath & "\") + rsa.CspKeyContainerInfo.UniqueKeyContainerName)
Dim fs As FileSecurity = file.GetAccessControl()
' Dim account As New NTAccount(user)
'fs.AddAccessRule(New FileSystemAccessRule(account, FileSystemRights.FullControl, AccessControlType.Allow))
Dim id As New Principal.SecurityIdentifier("S-1-1-0")
fs.AddAccessRule(New FileSystemAccessRule(id, FileSystemRights.FullControl, AccessControlType.Allow))
file.SetAccessControl(fs)
End If
End Sub
Private Shared Function FindKeyLocation(ByVal keyFileName As String) As String
Dim text1 As String = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)
Dim text2 As String = text1 & "\Microsoft\Crypto\RSA\MachineKeys"
Dim textArray1 As String() = Directory.GetFiles(text2, keyFileName)
If textArray1.Length > 0 Then
Return text2
End If
Dim text3 As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
Dim text4 As String = text3 & "\Microsoft\Crypto\RSA\"
textArray1 = Directory.GetDirectories(text4)
If textArray1.Length > 0 Then
For Each text5 As String In textArray1
textArray1 = Directory.GetFiles(text5, keyFileName)
If textArray1.Length <> 0 Then
Return text5
End If
Next
End If
Return "Private key exists but is not accessible"
End Function
Your help and advice is appreciated.
Thanks,
Glenn
All replies (7)
Wednesday, May 2, 2012 8:08 PM ✅Answered | 1 vote
I am posting to let future problem solvers know of the solution and close this thread out. Unfortantely this was a very easy fix, if only Eric hadn't cut this thread off and let others continue to work with me, I might have saved the $250 support charge. The problem was in the initial installation of the certificate. In the .Import command, I was using And to join the X509KeyStorageFlags, where I should have been using Or.
This is my final working code to install the certificate. I am also using my first method, documented above, to set the permissions on the key.
Dim x As New X509Certificate2x.Import(thisNode.Tag, Keytool_Pass, X509KeyStorageFlags.MachineKeySet Or X509KeyStorageFlags.Exportable Or X509KeyStorageFlags.PersistKeySet)s = New X509Store(StoreName.My, StoreLocation.LocalMachine)s.Open(OpenFlags.ReadWrite)s.Add(x)
I have tested that it works for W7 and XP environments.
Thanks,
Glenn
Thursday, April 12, 2012 6:36 AM
Hi Glenn,
Welcome to the MSDN Forum.
Let's move on this issue step by step.
Would you like to tell me what it the result of this:
'This part is your code
Dim x As New X509Certificate2
x.Import(thisNode.Tag, Keytool_Pass, X509KeyStorageFlags.MachineKeySet And X509KeyStorageFlags.Exportable And X509KeyStorageFlags.PersistKeySet)
s = New X509Store(StoreName.My, StoreLocation.LocalMachine)
s.Open(OpenFlags.ReadWrite)
Dim certCollection As New X509Certificate2Collection
certCollection.Add(x)
s.AddRange(certCollection)
'your code ends
If s.Certificates.Contains(x) Then
MsgBox("Add successfully")
Else
MsgBox("Add Failed")
End If
'Close the Store
s.Close()
I look forward you.
Best regards,
Mike Feng
MSDN Community Support | Feedback to us
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Thursday, April 12, 2012 5:43 PM
Hi Mike. Thank you for working with me.
Per your suggestion I have tried just the install portion of the code and there is a problem. The code executes successfully but I am sure the issue is here. I can't say for sure on W7 but on XP when a certificate is installed through the mmc to the Local Machine store, the private key is stored under the All Users profile. I suspect something similar for W7. However when I use the code to find the Key File Location it indicates it is under my profile instead of All Users. I believe this is the issue or at least must be solved first.
Further proof is that when I go to view the private key permissions for the newly installed certificate (either with mmc > Manage Private Keys for W7, or using WSE Certificate Tool on XP) I get an error indicating the Key doesn't exist. On W7 the error is "No keys found for certificate" and on XP the error is "Keyset doesn't exist."
I have some screenshots in this word document to visualize what I am describing. http://www.box.com/s/0e09b3426e73f4b2daf9
Thanks,
Glenn
Friday, April 13, 2012 7:26 AM
Hi Glenn,
Thank you for further information. Based on this, I think I understand you very well.
You have done this:
1. Installed a certificate by your code;
2. set the permission;
3. Retrieve the physical certificate file from disk. But this step fails.
Am I right?
If so, I am performing on this issue now, and I will get back to you as soon as possible. I appreciate your patience.
Best regards,
Mike Feng
MSDN Community Support | Feedback to us
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Friday, April 13, 2012 3:03 PM
Hi Mike,
In my previous reply I did this:
- Install certificate with my code.
- use code only to get private key file location.
- use UI tool to try and check permissions on the private key.
From this I deduce the certificate install is not working as expected.
What I ultimately want to do is,
- install certificate with my code.
- use code to set permissions on private key to allow everyone read or full control
Many thanks,
Glenn
Friday, April 13, 2012 8:42 PM
I have done some further experiments with this portion of code installing the certificate in the store.
x.Import(thisNode.Tag, Keytool_Pass, X509KeyStorageFlags.MachineKeySet And X509KeyStorageFlags.Exportable And X509KeyStorageFlags.PersistKeySet)
The inclusion of either the X509KeyStorageFlags.MachineKeySet or X509KeyStorageFlags.Exportable flags causes the errors when I try to view the certificate key permissions in the mmc / wse certificate tool.
If I run this instead I am able to view the permissions and in fact the code which applys the permissions for everyone is working.
x.Import(thisNode.Tag, Keytool_Pass, X509KeyStorageFlags.PersistKeySet)
The problem I have now is the locations which this code is installing the private keys. Even though I open the Machine Key Store and .Add it there, it saves the key under my user profile. Here is what I mean...
On Windows 7
Installed in console, key is correctly located:
C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\......
Installed with code, key is incorrectly located:
C:\Users\AppData\Roaming\Microsoft\Crypto\RSA\......
On Windows XP
Installed in console, key is correctly located:
C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys\......
Installed with code, key is incorrectly located:
C:\Documents and Settings\Glenn Holden\Application Data\Microsoft\Crypto\RSA\.......
How do I get the code to install in the right place as the console does it.
Many thanks,
Glenn
Monday, April 16, 2012 3:52 AM
Dear Customer,
Your question falls into the paid support category which requires a more in-depth level of support. Please visit the below link to see the various paid support options that are available to better meet your needs.
http://support.microsoft.com/default.aspx?id=fh;en-us;offerprophone
Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
Regards,
Eric Yang
Microsoft Online Community Support