CryptographicException 'Keyset does not exist', but only through WCF
Asked Answered
P

25

186

I have some code that makes a call to a third party web service that is secured using X.509 certification.

If I call the code directly (using a unit test) it works without any problems.

When deployed, this code will be called via a WCF Service. I have added a second unit test that calls the WCF Service, however this fails with a CryptographicException, message "Keyset does not exist" when I call a method on the third party web service.

I presume that this is because my WCF Service will be attempting to call the third party web service using a different user to myself.

Can anyone shed any additional light on this issue?

Policlinic answered 2/3, 2009 at 13:25 Comment(0)
G
182

It will probably be a permissions problem on the certificate.

When running a unit test you are going to be executing those under your own user context, which (depending on what store the client certificate is in) will have access to that certificate's private key.

However if your WCF service is hosted under IIS, or as a Windows Service it's likely it will be running under a service account (Network Service, Local Service or some other restricted account).

You will need to set the appropriate permissions on the private key to allow that service account access to it. MSDN has the details

Gentry answered 2/3, 2009 at 13:40 Comment(4)
Running calcs helped me for a completely different issue thanksMustee
I run my APP as administrator the the issue is gone.Ileanaileane
+1 for the MSDN documentation and the steps listed applies even to a Web ApplicationBriquet
Adding "NETWORK SERVICE" to the certificate security permissions resolved this for me, thanks!Dittography
A
316

This is most likely because the IIS user doesn't have access to the private key for your certificate. You can set this by following these steps...

  1. Start → Run → MMC
  2. File → Add/Remove Snapin
  3. Add the Certificates Snap In
  4. Select Computer Account, then hit next
  5. Select Local Computer (the default), then click Finish
  6. On the left panel from Console Root, navigate to Certificates (Local Computer) → Personal → Certificates
  7. Your certificate will most likely be here.
  8. Right click on your certificate → All Tasks → Manage Private Keys
  9. Set your private key settings here.
Aspectual answered 4/7, 2010 at 21:18 Comment(10)
Worth noting that this isn't an option on Server 2003, unless my environment is configured wacky. I can do this on Windows 7 though.Vetiver
what you mean with set private key here?? I mean you can only add the user with access right!?Sava
Thanks, just wanted to point out that if you use iis7.5 and the application pool runs as applicationpoolidentity, you will have to give IIS AppPool\DefaultAppPool user permissions to the file. This fixed the problem for me.Jerrine
I had to give permission to IIS_IUSRS to get it to work for me.Turk
if you are getting this while running IIS express you need to give your own login permissions.Human
I had to give permissions to IUSR. My scenario is like I'm calling with php a method from a registered .Net dll.Oceanid
I had to give permission to NETWORK SERVICE user to work!Salol
I was using ApplicationPoolIdentity but on Windows 10 I needed to grant permissions to IIS_IUSRS and then perform an iisreset, then it worked!Swot
Thanks! I have to add the "Authenticated Users" to get the IIS accesing the Private Keys, I supposed that was my problem, because now it´s working.Montherlant
In windows 10, steps 1-5 are replaced by "hit the windows key and start typing "manage computer certificates", select it when found.Greensand
G
182

It will probably be a permissions problem on the certificate.

When running a unit test you are going to be executing those under your own user context, which (depending on what store the client certificate is in) will have access to that certificate's private key.

However if your WCF service is hosted under IIS, or as a Windows Service it's likely it will be running under a service account (Network Service, Local Service or some other restricted account).

You will need to set the appropriate permissions on the private key to allow that service account access to it. MSDN has the details

Gentry answered 2/3, 2009 at 13:40 Comment(4)
Running calcs helped me for a completely different issue thanksMustee
I run my APP as administrator the the issue is gone.Ileanaileane
+1 for the MSDN documentation and the steps listed applies even to a Web ApplicationBriquet
Adding "NETWORK SERVICE" to the certificate security permissions resolved this for me, thanks!Dittography
D
41

I've had identical issue last night. Permissions on private key were set correctly, everything was apparently fine except the Keyset doesn't exist error. In the end it turned out that certificate was imported to the current user store first and then moved to local machine store. However - that didn't move the private key, which was still in the

C:\Documents and settngs\Administrator...

instead of

C:\Documents and settngs\All users...

Altough permissions on the key were set correctly, ASPNET couldn't access it. When we re-imported certificate so that private key is placed in the All users branch, the problem disappeared.

Duester answered 7/12, 2009 at 10:52 Comment(5)
Same problem. Microsoft need to stop letting the security bozos run the asylum.Cowey
After 3 lost hours, this solves my problem - Thank you. I used the FindPrivateKey sample, and was confused why it appeared to be in my user's keystore, even when it appeared in LocalMachine through the MMC snap-in.Haustorium
I'd buy you a beer for the hours wasted messing with permissions like every other answer told me to.Flaunt
Thankyou thankyou thankyou! I've lost about 2.5 hours of my life thanks to this horrid issue and i'm sure i would have lost 2.5 days if i didn't see this.Boutin
I had the same issue in reverse. First installed in Local Machine, then in Current User. Removing all certs from both stores and reinstalling under Current User fixed it.Exudation
A
35

To solve the “Keyset does not exist” when browsing from IIS: It may be for the private permission

To view and give the permission:

  1. Run>mmc>yes
  2. click on file
  3. Click on Add/remove snap-in…
  4. Double click on certificate
  5. Computer Account
  6. Next
  7. Finish
  8. Ok
  9. Click on Certificates(Local Computer)
  10. Click on Personal
  11. Click Certificates

To give the permission:

  1. Right Click on the name of certificate
  2. All Tasks>Manage Private Keys…
  3. Add and give the privilege( adding IIS_IUSRS and giving it the privilege works for me )
Aloisia answered 30/8, 2016 at 9:9 Comment(2)
If you are running under an app pool, add this user instead "IIS AppPool\DefaultAppPool"Dizzy
This has helped me, too. As soon as I gave IIS_IUSRS the permissions, it started working.Pout
S
22

Had the same problem while trying to run WCF app from Visual Studio. Solved it by running Visual Studio as administrator.

Subequatorial answered 11/1, 2014 at 21:51 Comment(0)
M
12

I have faced this issue, my certificates where having private key but i was getting this error("Keyset does not exist")

Cause: Your web site is running under "Network services" account or having less privileges.

Solution: Change Application pool identity to "Local System", reset IIS and check again. If it starts working it is permission/Less privilege issue, you can impersonate then using other accounts too.

Mixer answered 9/7, 2013 at 14:7 Comment(0)
C
10

Totally frustrating, I had the same issue and tried most of the above. The exported certificate correctly had permissions to read the file in C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys, however as it turns out it didn't have permission on the folder. Added it and it worked

Crewel answered 17/7, 2013 at 13:29 Comment(4)
I tried so many things to solve this issue, but this one did the trick!Grunion
wow - was NOT expecting that to work but it did. I added IISAPPPool\www.mywebsite.com which is the windows username for my appool and it worked :-)Placencia
anybody know why this works? is something corrupted because this is pretty obscurePlacencia
Don't do this! The server gets into the "bad state" where certs are being imported and showing up with the "Microsoft Software KSP" provider type when the folder ..RSA\MachineKeys has its base permissions changed. More details reddit.com/r/sysadmin/comments/339ogk/….Animalist
A
4

I was getting the error : CryptographicException 'Keyset does not exist' when i run the MVC application.

Solution was : to give access to the personal certificates to the account that application pool is running under. In my case it was to add IIS_IUSRS and choosing the right location resolved this issue.

RC on the Certificate - > All tasks -> Manage Private Keys -> Add->  
For the From this location : Click on Locations and make sure to select the Server name. 
In the Enter the object names to select : IIS_IUSRS and click ok. 
Amoebic answered 23/8, 2016 at 16:4 Comment(0)
O
3

I have exactly similar problem too. I have used the command

findprivatekey root localmachine -n "CN="CertName" 

the result shows that the private key is in c:\ProgramData folder instead of C:\Documents and settngs\All users..

When I delete the key from c:\ProgramData folder, again run the findPrivatekey command does not succeed. ie. it does not find the key.

But if i search the same key returned by earlier command, i can still find the key in

C:\Documents and settngs\All users..

So to my understanding, IIS or the hosted WCF is not finding the private key from C:\Documents and settngs\All users..

Odiliaodille answered 25/10, 2012 at 10:9 Comment(1)
Hi this link will tell you how to resolve this issue and also locate the findprivatekey tool: blogs.msdn.microsoft.com/dsnotes/2015/08/13/…Abhorrence
X
2

The Answer from Steve Sheldon fixed the problem for me, however, as I am scripting certificate permissions with out a gui, I needed a scriptable solution. I struggled to find where my private key was stored . The private key was not in -C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys , eventually I found that it was actually in C:\ProgramData\Microsoft\Crypto\Keys. Below I describe how I found that out:

I tried FindPrivateKey but it could not find the private key, and using powershell the $cert.privatekey.cspkeycontainerinfo.uniquekeycontainername was null/empty.

Luckily, certutil -store my listed the certificate and gave me the details I needed to script the solution.

================ Certificate 1 ================ Serial Number: 162f1b54fe78c7c8fa9df09 Issuer: CN=*.internal.xxxxxxx.net NotBefore: 23/08/2019 14:04 NotAfter: 23/02/2020 14:24 Subject: CN=*.xxxxxxxnet Signature matches Public Key Root Certificate: Subject matches Issuer Cert Hash(sha1): xxxxa5f0e9f0ac8b7dd634xx Key Container = {407EC7EF-8701-42BF-993F-CDEF8328DD} Unique container name: 8787033f8ccb5836115b87acb_ca96c65a-4b42-a145-eee62128a ##* ^-- filename for private key*## Provider = Microsoft Software Key Storage Provider Private key is NOT plain text exportable Encryption test passed CertUtil: -store command completed successfully.

I then scanned c\ProgramData\Microsoft\Crypto\ folder and found the file 8787033f8ccb5836115b87acb_ca96c65a-4b42-a145-eee62128a in C:\ProgramData\Microsoft\Crypto\Keys .

Giving my service account read access this file fixed the issues for me

Xl answered 1/10, 2019 at 8:28 Comment(1)
Using "certutil -store my" was the key to solve my problem. I used the "Unique container name" to locate the file and Sysinternals Process Monitor to troubleshoot an "Access Denied" error on the certificate file. In my case I had to provide read access to the certificate file for the NT Authority\IUSR user.Belle
S
2

I was getting this same error in my PowerShell scripts. The fix for me was simply to run the script as administrator. So make sure whatever app you're running that attempts to retrieve the certificate is running as admin.

Sexist answered 2/9, 2021 at 19:42 Comment(0)
C
2

Here's the fix for in Azure.

Instead of fiddling with different KeyStorageFlags ( which describes how to store the private key on the OS) and different web.config settings.

Use EphemeralKeySet, which will load the private key in memory ( https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509keystorageflags?view=netframework-4.7.2 )

Test it out and it will work every time :)

Tip: If you need more info or other methods, read https://github.com/projectkudu/kudu/wiki/Best-X509Certificate2-Practices

Connor answered 19/6, 2023 at 11:37 Comment(0)
P
1

I found some missing information that helped me get my WCF service with Message level security past the "Keyset does not exist" that I kept running into despite granting permissions to all the keys generated from the examples on the internet.

I finally imported the private key into the trusted people store on local machine and then granted the private key the correct permissions.

This filled in the blanks for me and finally allowed me to implement the WCF service with Message level security. I am building a WCF that must be HIPPA compliant.

Ppm answered 26/6, 2012 at 16:18 Comment(0)
U
1

I just reinstalled my certificate in local machine and then it is working fine

Unbelt answered 31/7, 2018 at 16:24 Comment(0)
B
1

In my case, the issue was something different. Adding any permission through MMC did not change anything. I ran this in PowerShell to find out where this private key file is:

[System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey((Get-ChildItem $certStorePath | Where thumbprint -eq <YourCertThumbprint>)).key.UniqueName

Here, you should change "YourCertThumbprint" to your own certificate thumbprint. This returns the unique name of your key. I searched for this key in Windows and found out that it's stored in: "C:/ProgramData/Microsoft/Crypto/RSA/MachineKeys" Now, I right-click this file, go to permissions, and viola, I don't see any of the permissions I gave in MMC for this file, so it means MMC did not work. After I only added IIS_IUSRS permission to this file, it fixed the issue.

So, you should not always count on MMC and Microsoft Windows; you should always check that the file actually has permission.

Behka answered 21/3, 2023 at 22:34 Comment(0)
C
0

If you use ApplicationPoolIdentity for your application pool, you may have problem with specifying permission for that "virtual" user in registry editor (there is not such user in system).

So, use subinacl - command-line tool that enables set registry ACL's, or something like this.

Canvas answered 9/8, 2011 at 13:38 Comment(0)
T
0

I just wanted to add a sanity check answer. I was getting the exact same error even after installing the certificates to the right stores on my machines and having all the right security privileges for the client. Turns out I mixed up my clientCertificate and my Service Certificate. If you have tried all of the above, I would double check that you have those two straight. Once I did that, my application successfully called the web service. Again, just a sanity checker.

Touchstone answered 2/1, 2013 at 16:44 Comment(0)
T
0

Received this error while using the openAM Fedlet on IIS7

Changing the user account for the default website resolved the issue. Ideally, you would want this to be a service account. Perhaps even the IUSR account. Suggest looking up methods for IIS hardening to nail it down completely.

Taction answered 26/9, 2013 at 20:51 Comment(0)
C
0

I hit this in my service fabric project after the cert used to authenticate against our key vault expired and was rotated, which changed the thumbprint. I got this error because I had missed updating the thumbprint in the applicationManifest.xml file in this block which precisely does what other answers have suggested - to given NETWORK SERVICE (which all my exes run as, standard config for azure servicefabric cluster) permissions to access the LOCALMACHINE\MY cert store location.

Note the "X509FindValue" attribute value.

<!-- this block added to allow low priv processes (such as service fabric processes) that run as NETWORK SERVICE to read certificates from the store -->
  <Principals>
    <Users>
      <User Name="NetworkService" AccountType="NetworkService" />
    </Users>
  </Principals>
  <Policies>
    <SecurityAccessPolicies>
      <SecurityAccessPolicy ResourceRef="AzureKeyvaultClientCertificate" PrincipalRef="NetworkService" GrantRights="Full" ResourceType="Certificate" />
    </SecurityAccessPolicies>
  </Policies>
  <Certificates>
    <SecretsCertificate X509FindValue="[[THIS KEY ALSO NEEDS TO BE UPDATED]]" Name="AzureKeyvaultClientCertificate" />
  </Certificates>
  <!-- end block -->
Conveyance answered 2/4, 2018 at 2:30 Comment(0)
C
0

This is the only solution worked for me.

    // creates the CspParameters object and sets the key container name used to store the RSA key pair
    CspParameters cp = new CspParameters();
    cp.KeyContainerName = "MyKeyContainerName"; //Eg: Friendly name

    // instantiates the rsa instance accessing the key container MyKeyContainerName
    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp);
    // add the below line to delete the key entry in MyKeyContainerName
    // rsa.PersistKeyInCsp = false;

    //writes out the current key pair used in the rsa instance
    Console.WriteLine("Key is : \n" + rsa.ToXmlString(true));

Reference 1

Reference 2

Clavus answered 27/8, 2019 at 4:42 Comment(0)
A
0
This issue is got resolved after adding network service role.

CERTIFICATE ISSUES 
Error :Keyset does not exist means System might not have access to private key
Error :Enveloped data … 
Step 1:Install certificate in local machine not in current user store
Step 2:Run certificate manager
Step 3:Find your certificate in the local machine tab and right click manage privatekey and check in allowed personnel following have been added:
a>Administrators
b>yourself
c>'Network service'
And then provide respective permissions.

## You need to add 'Network Service' and then it will start working.
Anneliese answered 25/2, 2020 at 7:7 Comment(0)
K
0

This issue is old but it surfaced to me today and all the readings I did refer to permission, but that wasn't the case with me. It turned out that the new (Windows Service) project I created had this option enabled by default. Properties-->Build-->Prefer 32-bit.

By unchecking this option and re-deploying this error went away and everything worked fine.

Hope this helps someone whose issue isn't permission-related.

Kalil answered 17/11, 2021 at 0:23 Comment(0)
U
0

I was having this exception when signing a file using SNK data. The trick is to set the KeyNumber to 2 (Signature) in the CspParameters, e.g.:

$params = New-Object System.Security.Cryptography.CspParameters
$params.KeyNumber = 2

$rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider($params)
$rsa.ImportCspBlob($snk)
$signature = $rsa.SignData($inputBytes, [Security.Cryptography.HashAlgorithmName]::SHA256, [Security.Cryptography.RSASignaturePadding]::Pkcs1)

Urbana answered 23/12, 2021 at 12:31 Comment(0)
T
0

I experienced this exception in a race condition. I used the same PFX file about 10k times in parallel processes (maybe 50 processes in parallel) and the exception appeared in about 1 % of the cases. I assume that the processes share the same private key file and the handle counter sometimes counts wrong or something the like, and then the key file is deleted although another process still needs it.

Catching the exception and retrying to use the same X509Certificate2 object didn't help. I didn't investigate further for now, but I believe it would help to leave out the parallelization.

Turret answered 23/3, 2022 at 12:28 Comment(0)
F
0

I'd also suggest the solution discussed here. As explained there:

The PFX has the friendlyName attribute on the key. Windows PFXImportCertStore has a race condition where opening two PFXes (including "the same PFX") that have identical friendlyName values in parallel may result in the two objects becoming inter-linked, and deleting one deletes the key out from under the other.

So, the problem was solved by removing the friendlyName attribute from the PFX file before loading it to X509Certificate2.

This code worked for me:

 public static void Foo( byte[] certificate, string pin)
    {
        using (X509Certificate2 cert = new X509Certificate2(certificate, pin,
                X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable))
        {
            if (!string.IsNullOrEmpty(cert.FriendlyName))
            {
                cert.FriendlyName = null;
                var bytesCert = cert.Export(X509ContentType.Pkcs12, pin);
                Foo(bytesCert , pin); //To reopen the certificate without the FriendlyName
                return;
            }
            cert.GetRSAPrivateKey() //It works!
        }
    }
Forbid answered 10/1, 2024 at 22:30 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.