programing tip

CryptographicException '키셋이 없습니다', 그러나 WCF를 통해서만

itbloger 2020. 6. 12. 21:48
반응형

CryptographicException '키셋이 없습니다', 그러나 WCF를 통해서만


X.509 인증을 사용하여 보호되는 타사 웹 서비스를 호출하는 코드가 있습니다.

단위 테스트를 사용하여 코드를 직접 호출하면 아무런 문제없이 작동합니다.

배포되면이 코드는 WCF 서비스를 통해 호출됩니다. WCF 서비스를 호출하는 두 번째 단위 테스트를 추가했지만 타사 웹 서비스에서 메소드를 호출하면 CryptographicException, 메시지 와 함께 실패 "Keyset does not exist"합니다.

WCF 서비스가 다른 사용자를 사용하여 타사 웹 서비스를 직접 호출하려고하기 때문이라고 생각합니다.

누구든지이 문제에 대해 더 밝힐 수 있습니까?


인증서에 대한 권한 문제 일 수 있습니다.

단위 테스트를 실행하면 클라이언트 인증서가있는 저장소에 따라 자신의 사용자 컨텍스트에서 해당 인증서의 개인 키에 액세스 할 수 있는 사용자 컨텍스트에서 해당 테스트를 실행 하게됩니다.

그러나 WCF 서비스가 IIS 또는 Windows 서비스로 호스팅되는 경우 서비스 계정 (네트워크 서비스, 로컬 서비스 또는 기타 제한된 계정)에서 실행될 가능성이 있습니다.

해당 서비스 계정이 개인 키에 액세스 할 수 있도록 개인 키에 대한 적절한 권한을 설정해야합니다. MSDN 에 자세한 내용이 있습니다.


IIS 사용자가 인증서의 개인 키에 액세스 할 수 없기 때문일 수 있습니다. 다음 단계에 따라이를 설정할 수 있습니다 ...

  1. 시작-> 실행-> MMC
  2. 파일-> 스냅인 추가 / 제거
  3. 인증서 스냅인 추가
  4. 컴퓨터 계정을 선택한 후 다음을 누르십시오.
  5. 로컬 컴퓨터 (기본값)를 선택한 다음 마침을 클릭하십시오.
  6. 콘솔 루트의 왼쪽 패널에서 인증서 (로컬 컴퓨터)-> 개인-> 인증서로 이동하십시오.
  7. 귀하의 인증서가 여기에있을 것입니다.
  8. 인증서를 마우스 오른쪽 버튼으로 클릭-> 모든 작업-> 개인 키 관리
  9. 여기에서 개인 키 설정을 지정하십시오.

어젯밤에 동일한 문제가 발생했습니다. 개인 키에 대한 권한이 올바르게 설정되었으므로 Keyset에 존재하지 않는 오류를 제외하고는 모든 것이 정상이었습니다. 결국 인증서를 현재 사용자 저장소로 가져온 다음 로컬 컴퓨터 저장소로 옮겼습니다. 그러나 여전히 개인 키는 이동하지 않았습니다.

C : \ Documents and settngs \ Administrator ...

대신에

C : \ Documents and settngs \ 모든 사용자 ...

키에 대한 충분한 권한이 올바르게 설정되었으므로 ASPNET이 액세스 할 수 없습니다. 개인 키가 모든 사용자 분기에 배치되도록 인증서를 다시 가져 오면 문제가 사라졌습니다.


IIS에서 찾아 볼 때 "키셋이 존재하지 않습니다"를 해결하려면 개인 권한에 대한 것일 수 있습니다.

보고 권한을 부여하려면 다음을 수행하십시오.

  1. 실행> mmc> 예
  2. 파일을 클릭하십시오
  3. 스냅인 추가 / 제거를 클릭하십시오…
  4. 인증서를 두 번 클릭하십시오
  5. 컴퓨터 계정
  6. 다음
  7. 확인
  8. 인증서 (로컬 컴퓨터)를 클릭하십시오
  9. 개인을 클릭하십시오
  10. 인증서를 클릭하십시오

권한을 부여하려면

  1. 인증서 이름을 마우스 오른쪽 버튼으로 클릭하십시오
  2. 모든 작업> 개인 키 관리…
  3. 권한 추가 및 제공 (IIS_IUSRS 추가 및 권한 부여)

Visual Studio에서 WCF 앱을 실행하는 동안 동일한 문제가 발생했습니다. Visual Studio를 관리자 권한으로 실행하여 해결했습니다.


개인 키가 있지만이 키가 발생하는 인증서 인이 문제에 직면했습니다 ( "키 세트가 없습니다" ).

원인 : 웹 사이트가 "네트워크 서비스"계정으로 실행 중이거나 권한이 적습니다.

해결 방법 : 응용 프로그램 풀 ID를 "로컬 시스템"으로 변경하고 IIS를 재설정 한 후 다시 확인하십시오. 작동이 시작되면 권한 /리스 권한 문제이므로 다른 계정으로 가장하여 사용할 수도 있습니다.


완전히 실망 스럽지만 같은 문제가 있었고 위의 대부분을 시도했습니다. 내 보낸 인증서에는 파일을 읽을 수 C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys있는 권한이 있지만 폴더에 대한 권한이없는 것으로 나타났습니다. 그것을 추가하고 작동했습니다


나는 비슷한 문제가 있습니다. 나는 명령을 사용했다

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


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. 

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.


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


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.


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.


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.


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


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


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

참고URL : https://stackoverflow.com/questions/602345/cryptographicexception-keyset-does-not-exist-but-only-through-wcf

반응형