CryptographicException „Keyset nie istnieje”, ale tylko za pośrednictwem WCF

157

Mam kod, który wywołuje usługę internetową innej firmy, która jest zabezpieczona certyfikatem X.509.

Jeśli zadzwonię bezpośrednio do kodu (za pomocą testu jednostkowego), działa to bez żadnych problemów.

Po wdrożeniu ten kod zostanie wywołany za pośrednictwem usługi WCF. Dodałem drugi test jednostkowy, który wywołuje usługę WCF, jednak kończy się to niepowodzeniem z CryptographicExceptionkomunikatem, "Keyset does not exist"gdy wywołuję metodę w usłudze sieci Web innej firmy.

Zakładam, że dzieje się tak, ponieważ moja usługa WCF będzie próbowała wywołać usługę sieci Web innej firmy przy użyciu innego użytkownika.

Czy ktoś może rzucić dodatkowe światło na tę kwestię?

Richard Ev
źródło

Odpowiedzi:

168

Prawdopodobnie będzie to problem z uprawnieniami na certyfikacie.

Podczas przeprowadzania testu jednostkowego zamierzasz wykonywać je w ramach własnego kontekstu użytkownika, który (w zależności od tego, w jakim magazynie znajduje się certyfikat klienta ) będzie miał dostęp do klucza prywatnego tego certyfikatu.

Jeśli jednak usługa WCF jest hostowana w ramach usług IIS lub jako usługa systemu Windows, prawdopodobnie będzie działać na koncie usługi (usługa sieciowa, usługa lokalna lub inne ograniczone konto).

Będziesz musiał ustawić odpowiednie uprawnienia do klucza prywatnego, aby umożliwić dostęp do niego temu kontu usługi. MSDN zawiera szczegóły

strzałka do dmuchawki
źródło
Bieganie calcs pomogło mi w zupełnie innym problemie, dzięki
Jan
3
Uruchamiam aplikację jako administrator, problem zniknął.
derek
1
+1 dla dokumentacji MSDN, a wymienione kroki odnoszą się nawet do aplikacji sieciowej
Naren
Dodanie „USŁUGA SIECIOWA” do uprawnień bezpieczeństwa certyfikatu rozwiązało ten problem. Dzięki!
OpMt
276

Jest to najprawdopodobniej spowodowane tym, że użytkownik usług IIS nie ma dostępu do klucza prywatnego Twojego certyfikatu. Możesz to ustawić, wykonując następujące kroki ...

  1. Start -> Uruchom -> MMC
  2. Plik -> Dodaj / Usuń Snapin
  3. Dodaj przystawkę certyfikatów
  4. Wybierz Konto komputera, a następnie kliknij Dalej
  5. Wybierz opcję Komputer lokalny (ustawienie domyślne), a następnie kliknij przycisk Zakończ
  6. W lewym panelu z katalogu głównego konsoli przejdź do opcji Certyfikaty (komputer lokalny) -> Osobiste -> Certyfikaty
  7. Twój certyfikat najprawdopodobniej będzie tutaj.
  8. Kliknij prawym przyciskiem myszy swój certyfikat -> Wszystkie zadania -> Zarządzaj kluczami prywatnymi
  9. Ustaw tutaj ustawienia klucza prywatnego.
Steve Sheldon
źródło
1
Warto zauważyć, że nie jest to opcja na serwerze 2003, chyba że moje środowisko jest skonfigurowane nieprawidłowo. Ale mogę to zrobić na Windows 7.
Shawn Hubbard
co masz na myśli z ustawieniem klucza prywatnego tutaj? Chodzi mi o to, że możesz dodać tylko użytkownika z prawem dostępu !?
mastervv
10
Dzięki, chciałem tylko zwrócić uwagę, że jeśli używasz iis7.5, a pula aplikacji działa jako applicationpoolidentity, będziesz musiał nadać IIS AppPool \ DefaultAppPool uprawnienia użytkownika do pliku. To rozwiązało problem.
Ronen Festinger,
25
Musiałem dać pozwolenie IIS_IUSRS, aby działał dla mnie.
TrueEddie
1
jeśli otrzymujesz to podczas korzystania z usług IIS Express, musisz podać własne uprawnienia logowania.
Jez
38

Miałem identyczny problem zeszłej nocy. Uprawnienia do klucza prywatnego zostały ustawione poprawnie, wszystko było w porządku, z wyjątkiem błędu Keyset nie istnieje. Ostatecznie okazało się, że certyfikat został najpierw zaimportowany do bieżącego magazynu użytkowników, a następnie przeniesiony do lokalnego magazynu maszynowego. Jednak - to nie spowodowało przeniesienia klucza prywatnego, który nadal znajdował się w

C: \ Documents and settings \ Administrator ...

zamiast

C: \ Dokumenty i ustawienia \ Wszyscy użytkownicy ...

Mimo że uprawnienia do klucza zostały ustawione poprawnie, ASPNET nie mógł uzyskać do niego dostępu. Gdy ponownie zaimportowaliśmy certyfikat, aby klucz prywatny został umieszczony w gałęzi Wszyscy użytkownicy, problem zniknął.

Željko Tanović
źródło
Taki sam problem. Microsoft musi przestać pozwalać ochroniarzom na prowadzenie azylu.
Paul Stovell
2
Po 3 straconych godzinach to rozwiązuje mój problem - dziękuję. Użyłem FindPrivateKey próbkę, i zmieszał się, dlaczego pojawił się w magazynie kluczy mojego użytkownika, nawet wtedy, gdy pojawiła się w LocalMachine przez MMC.
Rob Potter
Postawiłbym ci piwo za stracone godziny, majstrując przy pozwoleniach, jak każda inna odpowiedź, którą mi kazała.
Scott Scowden
Dziekuję Dziekuję Dziękuję! Straciłem około 2,5 godziny życia dzięki temu okropnemu problemowi i jestem pewien, że straciłbym 2,5 dnia, gdybym tego nie widział.
Frank Tzanabetis
Miałem ten sam problem w odwrotnej kolejności. Najpierw zainstalowany na komputerze lokalnym, a następnie w bieżącym użytkowniku. Usunięcie wszystkich certyfikatów z obu sklepów i ponowna instalacja w obszarze Bieżący użytkownik rozwiązało problem.
Bart Verkoeijen
24

Aby rozwiązać problem „Zestaw kluczy nie istnieje” podczas przeglądania z poziomu usług IIS: Może to być za pozwoleniem prywatnym

Aby wyświetlić i przyznać uprawnienia:

  1. Uruchom> mmc> tak
  2. kliknij plik
  3. Kliknij Dodaj / usuń przystawkę…
  4. Kliknij dwukrotnie certyfikat
  5. Konto komputera
  6. Kolejny
  7. koniec
  8. Dobrze
  9. Kliknij Certyfikaty (komputer lokalny)
  10. Kliknij Osobiste
  11. Kliknij Certyfikaty

Aby udzielić pozwolenia:

  1. Kliknij prawym przyciskiem myszy nazwę certyfikatu
  2. Wszystkie zadania> Zarządzaj kluczami prywatnymi…
  3. Dodaj i nadaj uprawnienie (dodanie IIS_IUSRS i nadanie mu uprawnienia działa u mnie)
Md. Ilyas Hasan Mamun
źródło
1
Jeśli korzystasz z puli aplikacji, dodaj tego użytkownika zamiast „IIS AppPool \ DefaultAppPool”
Sameer Alibhai
To też mi pomogło. Jak tylko nadałem IIS_IUSRS uprawnienia, zaczęło działać.
Andrej Mohar
18

Wystąpił ten sam problem podczas próby uruchomienia aplikacji WCF z programu Visual Studio. Rozwiązałem to, uruchamiając Visual Studio jako administrator.

desegel
źródło
11

Napotkałem ten problem, moje certyfikaty miały klucz prywatny, ale otrzymywałem ten błąd ( „Zestaw kluczy nie istnieje” )

Przyczyna: Twoja witryna internetowa działa na koncie „Usługi sieciowe” lub ma mniejsze uprawnienia.

Rozwiązanie : Zmień tożsamość puli aplikacji na „System lokalny”, zresetuj usługi IIS i sprawdź ponownie. Jeśli zacznie działać, jest to problem z uprawnieniami / mniejszymi uprawnieniami, możesz podszywać się pod inne konta, a następnie używać innych kont.

Vaibhav. Zainspirowany
źródło
8

Całkowicie frustrujące, miałem ten sam problem i próbowałem większości z powyższych. Wyeksportowany certyfikat poprawnie miał uprawnienia do odczytu pliku C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys, jednak okazuje się, że nie ma uprawnień do folderu. Dodałem i zadziałało

błazen
źródło
Próbowałem tylu rzeczy, aby rozwiązać ten problem, ale ten załatwił sprawę!
Gyum Fox
wow - NIE spodziewałem się, że to zadziała, ale tak się stało. Dodałem, IISAPPPool\www.mywebsite.comktóra jest nazwą użytkownika Windows dla mojego appoola i zadziałało :-)
Simon_Weaver
ktoś wie, dlaczego to działa? jest coś
zepsutego,
Nie rób tego! Serwer przechodzi w „zły stan”, w którym certyfikaty są importowane i pojawia się z typem dostawcy „Microsoft Software KSP”, gdy folder ..RSA \ MachineKeys ma zmienione uprawnienia podstawowe. Więcej szczegółów reddit.com/r/sysadmin/comments/339ogk/… .
Dhanuka777
3

Ja też mam dokładnie podobny problem. Użyłem polecenia

findprivatekey root localmachine -n "CN="CertName" 

wynik pokazuje, że klucz prywatny znajduje się w folderze c: \ ProgramData zamiast C: \ Documents and settings \ All users ..

Kiedy usuwam klucz z folderu c: \ ProgramData, ponownie uruchamiam polecenie findPrivatekey nie powiedzie się. to znaczy. nie znajduje klucza.

Ale jeśli wyszukam ten sam klucz zwrócony przez wcześniejsze polecenie, nadal mogę znaleźć klucz w

C: \ Dokumenty i ustawienia \ Wszyscy użytkownicy ..

Tak więc, zgodnie z moim zrozumieniem, usługi IIS lub hostowane WCF nie znajdują klucza prywatnego z C: \ Documents and settings \ All users ...

user1773822
źródło
2
Cześć ten link pokaże Ci, jak rozwiązać ten problem, a także zlokalizować findprivatekey narzędzia: blogs.msdn.microsoft.com/dsnotes/2015/08/13/...
Tahir Khalid
3

Otrzymałem błąd: CryptographicException „Keyset nie istnieje”, kiedy uruchamiam aplikację MVC.

Rozwiązanie było następujące: aby przyznać dostęp do certyfikatów osobistych kontu, na którym działa pula aplikacji. W moim przypadku było to dodanie IIS_IUSRS i wybranie odpowiedniej lokalizacji rozwiązało ten problem.

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. 
Dev
źródło
2

Odpowiedź Steve'a Sheldona rozwiązała problem za mnie, jednak ponieważ piszę uprawnienia certyfikatów w skryptach bez interfejsu GUI, potrzebowałem rozwiązania skryptowego. Starałem się znaleźć miejsce przechowywania mojego klucza prywatnego. Nie było klucza prywatnego -C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys, w końcu odkryłem, że faktycznie był C:\ProgramData\Microsoft\Crypto\Keys. Poniżej opisuję, jak się tego dowiedziałem:

Próbowałem, FindPrivateKeyale nie udało mi się znaleźć klucza prywatnego, a przy użyciu programu PowerShell $cert.privatekey.cspkeycontainerinfo.uniquekeycontainernamebył pusty / pusty.

Na szczęście certutil -store mywymieniłem certyfikat i podałem szczegóły potrzebne do napisania scenariusza rozwiązania.

================ 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.

Następnie przeskanowałem c\ProgramData\Microsoft\Crypto\folder i znalazłem plik 8787033f8ccb5836115b87acb_ca96c65a-4b42-a145-eee62128a w C: \ ProgramData \ Microsoft \ Crypto \ Keys .

Przyznanie mojemu kontu usługi dostępu do odczytu tego pliku rozwiązało problemy

Dai Bok
źródło
1
Korzystanie z „certutil -store my” było kluczem do rozwiązania mojego problemu. Użyłem „Unikalnej nazwy kontenera”, aby zlokalizować plik, a Sysinternals Process Monitor do rozwiązania problemu z błędem „Odmowa dostępu” w pliku certyfikatu. W moim przypadku musiałem zapewnić dostęp do pliku certyfikatu dla użytkownika NT Authority \ IUSR.
hsop
1

Znalazłem brakujące informacje, które pomogły mi w uzyskaniu mojej usługi WCF z zabezpieczeniami na poziomie wiadomości poza „Zestaw kluczy nie istnieje”, na który natrafiłem pomimo przyznania uprawnień do wszystkich kluczy wygenerowanych na podstawie przykładów w Internecie.

W końcu zaimportowałem klucz prywatny do magazynu zaufanych osób na komputerze lokalnym, a następnie nadałem kluczowi prywatnemu odpowiednie uprawnienia.

To wypełniło dla mnie puste miejsca i ostatecznie pozwoliło mi zaimplementować usługę WCF z zabezpieczeniami na poziomie wiadomości. Buduję WCF, który musi być zgodny z HIPPA.

user1483373
źródło
1

Właśnie ponownie zainstalowałem certyfikat na komputerze lokalnym i wszystko działa poprawnie

Muni Chittem
źródło
0

Jeśli używasz ApplicationPoolIdentity dla swojej puli aplikacji, możesz mieć problem z określeniem uprawnień dla tego „wirtualnego” użytkownika w edytorze rejestru (nie ma takiego użytkownika w systemie).

Więc użyj subinacl - narzędzia wiersza poleceń, które umożliwia ustawienie listy ACL rejestru lub czegoś podobnego.

tyger
źródło
0

Chciałem tylko dodać odpowiedź sprawdzającą poczytalność. Otrzymałem dokładnie ten sam błąd, nawet po zainstalowaniu certyfikatów we właściwych sklepach na moich komputerach i posiadaniu wszystkich odpowiednich uprawnień bezpieczeństwa dla klienta. Okazuje się, że pomyliłem certyfikat klienta i certyfikat usługi. Jeśli wypróbowałeś wszystkie powyższe, dwukrotnie sprawdziłbym, czy masz te dwa proste. Kiedy to zrobiłem, moja aplikacja pomyślnie wywołała usługę sieciową. Ponownie, tylko test poczytalności.

SoftwareSavant
źródło
0

Otrzymałem ten błąd podczas używania openAM Fedlet w IIS7

Zmiana konta użytkownika dla domyślnej witryny sieci Web rozwiązała problem. Idealnie byłoby, gdyby było to konto usługi. Może nawet konto IUSR. Zasugeruj wyszukanie metod utwardzania usług IIS, aby całkowicie je ustalić.

Jeff Minder
źródło
0

Udało mi się to w moim projekcie sieci szkieletowej usług po tym, jak certyfikat używany do uwierzytelniania w naszym magazynie kluczy wygasł i został obrócony, co zmieniło odcisk palca. Otrzymałem ten błąd, ponieważ przegapiłem aktualizację odcisku palca w pliku applicationManifest.xml w tym bloku, co dokładnie robi to, co sugerowały inne odpowiedzi - do danej USŁUGI SIECIOWEJ (którą wszystkie moje exes działają jako standardowa konfiguracja dla klastra Azure servicefabric) do uzyskać dostęp do lokalizacji magazynu LOCALMACHINE \ MY cert.

Zwróć uwagę na wartość atrybutu „X509FindValue”.

<!-- 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 -->

Sat Thiru
źródło
0

To jedyne rozwiązanie, które u mnie zadziałało.

    // 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));

Odniesienie 1

Odniesienie 2

CharithJ
źródło
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.
yuvraj
źródło