none
The certificate 'CN=localhost' must have a private key that is capable of key exchange.The process must have access rights for

    Question

  • Hi,

    My WCF service has following security settings:-

    at server side(web.config) :-

    <behaviors>

    <serviceBehaviors>

    <behavior name="myBehaviour" >

    <serviceDebug includeExceptionDetailInFaults="true" />

    <serviceMetadata httpGetEnabled="true" />

    <serviceCredentials>

    <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />

    </serviceCredentials>

    </behavior>

    </serviceBehaviors>

    </behaviors>

    <bindings>

    <wsHttpBinding>

    <binding name="Binding1"

    transactionFlow="true">

    <security mode="Message">

    <message clientCredentialType="UserName" />

    </security>

    </binding>

    </wsHttpBinding>

    </bindings>

    At client side(App.config)  security settings are :-

    <security mode="Message">

    <transport clientCredentialType="Windows" proxyCredentialType="None"

    realm="" />

    <message clientCredentialType="UserName" negotiateServiceCredential="true"

    algorithmSuite="Default" establishSecurityContext="true" />

    </security>

    I have create a root security certificate using :-

    makecert -n "CN=TempCA" -r -sv TempCA.pvk TempCA.cer

    And create a new certificate signed by a root authority certificate as :-

    makecert -sk SignedByCA -iv TempCA.pvk -n "CN=localhost" -ic TempCA.cer SignedByCA.cer -sr LocalMachine -ss My

    Now I installed root security certificate in Trusted Root Certification Authorities and signed certificate in Personal folder.

    I have also provided Read rights to ASPNET process for  the folder( and its parent folders)  containing private key file and also to the private key file .

    WCF service is hosted in IIS and client ( also .Net application) is running on same machine.

    But when i run the service, I am getting this error:-
    The certificate 'CN=localhost' must have a private key that is capable of key exchange. The process must have access rights for the private key.

    Pls tell what I am missing ??

    Regads

    Akshay 

     

    Friday, February 02, 2007 5:43 AM

Answers

  • Ah, I managed to narrow down my issue. I wrote some batch files that I use to generate certs using the makecert utility. I was using the wrong batch file to generate the cert, it did not specify -sky exchange.

    When I read your post about the clientCredentials value causing the cert to be validated, I interpreted it incorrectly, I guess.

    I should've just RTFS :)

     

    Monday, February 26, 2007 9:29 AM

All replies

  • It seems I already experienced this problem in the past.

    If I didn't misunderstand your post, I think you granted access to the key file on the disk and that's not necessary, as far as I know.
    You have to assign the proper access rights to the private key in the certificate store and WinHttpCertCfg.exe is a tool that let you do this, here's the link to MSDN.

    In my scenario, I had to grant access to a specific account as I'm hosting my WCF services in a Windows service, in your case you should grant access to the account used by your ASPNET application.

    HTH,
    Davide Bedin

     

    • Proposed as answer by Y2KPRABU Thursday, March 18, 2010 9:58 AM
    Friday, February 02, 2007 9:16 AM
  • Hi Davide,

    Thanks for your reply.I used winhttpcertcfg tool to grant access to private key to ASPNET account  and after this i verified th elist of users who has access to certificate private key using :- winhttpcertcfg -l -c LOCAL_MACHINE\My -s localhost

    And its show ASPNEt account in the list.Also if i try to grant acces again , i get meessage that access has already granted.

    But I still getting the same error   :(

    Am i missing anything else..?

    Thanks

    Akshay

     

     

    Monday, February 05, 2007 5:40 AM
  • Hi,

     

    I think you need to mark the certificate key as exchangeable/exportable while creating the certificate using makecert.

    So your command will probably look as under:

    makecert -sk SignedByCA -iv TempCA.pvk -n "CN=localhost" -ic TempCA.cer SignedByCA.cer -sr LocalMachine -ss My -sky exchange -pe

    Hope that helps!

    -Shalini.

     

     

    Monday, February 05, 2007 6:23 AM
  • Hi Shalini,

    Using

    makecert -sk SignedByCA -iv TempCA.pvk -n "CN=localhost" -ic TempCA.cer SignedByCA.cer -sr LocalMachine -ss My -sky exchange -pe

    give me error :- Can not create the key of the subject  ('SignedByCA')

    Regards

    Akshay

    Monday, February 05, 2007 8:36 AM
  • Hi Akshay,

    I tried these same commands on my machine and they seem to succeed on a Vista box- so the syntax seems right to me (it's just that the GUI asked me to specify Issuer/Subject passwords as well). Did you try deleting hte already created certificates on your machine first, before trying these out?

    I'll try to find out more information for you on this as well..

    -Shalini.

     

    Monday, February 05, 2007 5:58 PM
  • Hi Shalini,

    Thax for your inputs.It works ,if I set ClientCredentialType as Windows i.e

    <bindings>

    <wsHttpBinding>

    <binding name="Binding1"

    transactionFlow="true">

    <security mode="Message">

    <message clientCredentialType="Windows" />

    </security>

    </binding>

    </wsHttpBinding>

    </bindings>

    But if I set ClientCredentialType as UserName then I get the error.

    Any idea why is it ?

    Tuesday, February 06, 2007 12:19 PM
  • Cool - but I am afraid I am no expert on this issue or even why it works with one credential type and not the other - I'll  go ahead and forward this thread to someone who might know more, though ..

    -Shalini.

    Tuesday, February 06, 2007 7:00 PM
  • The ClientCredential property is confusingly named.  It controls both the client and service credentials.  Specifying Windows results in SSPI (either NTLM or Kerberos) authentication, which does not use a certificate to identify the service.  Hence, no error.  Specifying UserName results in UserNameOverTransport, UserNameForCertificate, or UserNameForSslNegotiated, depending on which way turn the security mode and negotiate service credential knobs.  All of these identify the service with a certificate, hence the error (though you won't hit WCF's private key check if https is used as the transport since the http.sys SSL port registrations are used in that case).
    Wednesday, February 07, 2007 4:38 AM
  • I have implemented a STS and obviously a STS has to be configured with a certificate.

    My STS works fine using windows authentication. But I do not want to use windows authentication, because the STS will be running outside of a domain.

    What I want to do is to let the client send through a username and password which can then be validated against an ADAM store. I would have thought that I could configure the clientCredentialType as UserName and then use that username and password to authenticate the credentials agains the ADAM store, so that I can build up a claimset for that user based on his ientity.

    What you're saying, Todd, that this isn't possible? Do I now need to embed some extra data in my RST in order to know who is doing the request. I think it's extremely weird that the binding behaves like that...

    Friday, February 23, 2007 1:09 PM
  • I don't understand the question.  Are you having a problem plugging in a custom username/password validator which checks against ADAM?
    Friday, February 23, 2007 5:28 PM
  • No,

    I guess I might've confused the issue by mentioning too much of my design in regards to federated security.

    Let me summarize my problem:

    I have a service (HomeSts) which I configure with a serviceCertificate. I would like to configure this service’s wsHttp binding with message security. The message security should be configured to “UserName”.

    The way I interpreted the binding is that it will expect a username password token in the request message from the client, but when I want to start the service I get the same error as the originator of this thread.

     

    If I do not configure my service with the certificate, I manage to get my username/password validator to work. But a soon as I configure my service behavior with a certificate, I get the error.  

     

    Additional info:

     

    I have to configure the service with a certificate, because it’s a STS service. All the examples that I’ve seen for authenticating someone in a STS service was configured with Windows (Kerberos) security, but I want to use a username/password solution, in order to authenticate against ADAM.

    Question:

    Is it possible to secure my service using a username/password validator and still have my service behavior configured to with a cert?

    Monday, February 26, 2007 8:05 AM
  • Ah, I managed to narrow down my issue. I wrote some batch files that I use to generate certs using the makecert utility. I was using the wrong batch file to generate the cert, it did not specify -sky exchange.

    When I read your post about the clientCredentials value causing the cert to be validated, I interpreted it incorrectly, I guess.

    I should've just RTFS :)

     

    Monday, February 26, 2007 9:29 AM
  • OK, cool.  For the record, client username/password authentication to a service is orthogonal to both service authentication to a client via certificate as well as federated RST/RSTRs.
    Tuesday, February 27, 2007 12:29 AM
  •  

    I'm running into the same issue. Can you provide the makcert command line?

    Thursday, March 08, 2007 10:29 PM
  • makecert -pe -ss My -sr LocalMachine -sky exchange -n "CN=YourCertName"
    Friday, March 09, 2007 7:35 AM
  • Hey Shalini May be You r not an Expert but What ever u said worked for me.

    While creating certificate U have to marked it as exportable so that the certificate can exchange the private key from the certificate authority.

    Thanks

    Parag

    Friday, March 16, 2007 6:46 AM
  • Cool :) Glad to hear that..

    Friday, March 16, 2007 3:03 PM
  • I couldn't get the makecert to work from the example in this thread, however the following steps did the trick for me .. maybe it will help others.

    1) Command: makecert -n "CN=TempCA" -r -sv TempCA.pvk TempCA.cer
    2) Command: makecert -sk SignedByCA -iv TempCA.pvk -n "CN=SignedByCA" -ic TempCA.cer SignedByCA.cer -sr localmachine -ss My
    3) Using MMC and the Certificate Snap-In for the LocalMachine, I imported "TempCA.cer" into the "Trusted Root Certification Authorities" folder.
    4) Then imported "SignedByCA.cer" into the Personal folder.

    Here is my config, I don't think the '<peer>' section is required:

    <behaviors>
     <
    serviceBehaviors>
      <
    behavior name="serviceBehavior">
      <
    serviceDebug includeExceptionDetailInFaults="true" />
      <
    serviceAuthorization principalPermissionMode="Custom" />
      <
    serviceCredentials>
        <
    peer>
          <
    messageSenderAuthentication certificateValidationMode="PeerTrust"/>
        </
    peer>
      <
    serviceCertificate storeLocation="LocalMachine" storeName="My" findValue="SignedByCA" x509FindType="FindBySubjectName" />
        <
    userNameAuthentication userNamePasswordValidationMode="MembershipProvider" includeWindowsGroups="false" membershipProviderName="CMembership"/>
      </
    serviceCredentials>
      </
    behavior>
     </
    serviceBehaviors>
    </
    behaviors>

    I placed the following security section into my netTcpBining section:

    <security mode="Message">
      <
    transport clientCredentialType="None"/>
      <
    message clientCredentialType="UserName"/>
    </
    security>

     

    Saturday, March 24, 2007 7:25 PM
  • I had a hard time to get it run also. but at last the key for this is you need the permission to access the private key.

    This link will provide the tool and description
    http://msdn2.microsoft.com/en-us/library/aa717039.aspx


    Thursday, March 29, 2007 1:46 AM
  • I am trying to do the same thing on an XP SP2 box, using the makecert that came with the Windows Vista SDK (which is the only way I see to get the .NET 3.0 SDK).  That already concerns me.

     

    If I try to set the key type as exchange or 1, I, too, get the "Can't create the key of the subject..." error.  However, if I set the key type as signature or 2, the command succeeds.  Hmmm.  Maybe the default algorithm is not strong enough for encryption, and the error message is too vague.

     

    If I set the algorithm to sha1, and the key length to 2048, and the key type to exchange, I get the same misbehavior.  Is the makecert tool designed such that it cannot be used for creating encryption keys?  I'd like to be able to make a development-use cert to create a secure (signed and encrypted) SOAP request/response between a service and a client application.

     

    Was there ever any success in accomplishing this using the PKI token model (as opposed to username/password)?

     

    Thanks.

    Tuesday, August 21, 2007 2:05 PM
  • DUH.

     

    I think the original problem in this thread is the same as mine, and that is, "how does one correctly employ WS-Security or WCF Message security using certificates and PKI?"

     

    The error was complaining about not being able to access a private key, or that the key was not usable for exchange.

     

    Well, look at http://code.google.com/support/bin/answer.py?answer=71864, under the section "Using Microsoft Visual Studio for .NET."  The problem is that when you make the "SignedByCA" service certificate according to the MSDN docs, you are not storing the private key anywhere that WCF can get at it.  So when you import the SignedByCA.cer into any keystore, it does not have a private key with it.  Then when you point a WCF service at the key store (like CurrentUser.My) via the ServiceCredentials.ServiceCertificate tag in an App.config file, the SOAP stack can't find a private key for the identity, and thus cannot sign any messages.

     

    The solution to get the service to at least run (I haven't yet intercepted the SOAP message to verify it is being signed/encrypted, and that only the sender/intended-recipient are invited to the party), is at the Google.com link, and is to create a PFX container that also stores the private key, and store the PFX in the keystore (CurrentUser.My) instead of the CER container that makecert provides.

     

    Here comes some implications as to what I did...

     

    Now I have a private key stored someplace, and potentially anyone can get/use it.  If so, then setting a password on the private key should make it useless to anyone but those savvy to the password, which should only be the service using it to sign messages.  What is the WCF App.config tag that specifies the private key password that otherwise is provided by a user via a GUI dialog?  Even if there is one, is anyone comfortable putting the private key password in a text file that might be stored on numerous hosts?  Okay, so if there is no tag, and the password must be empty for WCF code to use the private key, then access to the private key must be controlled by the keystore.  Configuring this appears to be the job of the winhttpcertcfg tool.  So now that access to the private key is restricted to only a single user by that tool, we can do signing.  How can random clients get ahold of the service's public key to encrypt requests?  I guess it must be published someplace public, separately from the PFX container holding the private key.

    Tuesday, August 21, 2007 3:05 PM
  • Hi, I am using the same tool and using the following command to get access to the private key

    winhttpcertcfg -g -c LOCAL_MACHINE\My -s MyService -a akram

    but i am getting the following error:

    Error: Access was not successfully obtained for the private key.
           This can only be done by the user who installed the certificate.

    any idea where i am going wrong?
    Friday, December 07, 2007 11:57 AM
  • Not sure what this has to do with WCF, but my bet would be you're either not running the command shell under an administrator account or running it under UAC.

    Tuesday, December 11, 2007 1:48 AM
  •  Ranju_Akram wrote:
    Hi, I am using the same tool and using the following command to get access to the private key

    winhttpcertcfg -g -c LOCAL_MACHINE\My -s MyService -a akram

    but i am getting the following error:

    Error: Access was not successfully obtained for the private key.
           This can only be done by the user who installed the certificate.

    any idea where i am going wrong?


    Could you say how you've solved your problem?

    I'm discovering the same problem when giving access to a root certificate.
    Wednesday, June 11, 2008 12:01 PM
  • first, You may need to see where is your certificate file located by use FindPrivateKey Tool (download at - http://msdn.microsoft.com/en-us/library/aa717039.aspx)

     

    then, run

    command line

    cacls.exe "C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys\8aeda5eb81555f14f8f9960745b5a40d_38f7de48-5ee9-452d-8a5a-92789d7110b1" /E /G "NETWORK SERVICE":R

     

    Friday, June 13, 2008 5:00 AM
  • Hi,

    I tried following your example. The makecert command does not work for me:

    makecert -sk SignedByCA -iv TempCA.pvk -n "CN=localhost" -ic TempCA.cer SignedByCA.cer -sr LocalMachine -ss My -sky exchange -pe

    This command is giving me the error:

    Error: Can't access the key of the issuer ('TempCA.pvk') Failed.

    Please help me finding the track...???
    Wednesday, July 02, 2008 6:15 AM
  • Hi,

    I tried following your example. The makecert command does not work for me:

    makecert -sk SignedByCA -iv TempCA.pvk -n "CN=localhost" -ic TempCA.cer SignedByCA.cer -sr LocalMachine -ss My -sky exchange -pe

    This command is giving me the error:

    Error: Can't access the key of the issuer ('TempCA.pvk') Failed.

    Please help me finding the track...???
    Wednesday, July 02, 2008 10:11 AM
  • because you don't have TempCA.pvk file.

     

    try this instead,

     

    To create cert:

    makecert.exe  -sr LocalMachine -ss MY  -pe -sky exchange -n "CN=MyServiceCert" MyServiceCert.cer

     

    To add to store:

    certmgr.exe -add -r localmachine -s My -c -n MyServiceCert -r localmachine  -s TrustedPeople

     

    Wednesday, July 02, 2008 10:37 AM
  • Hi,

    I did the same, and created a new certificate and added this to the store.

    But now I am Getting a new exception. The exception is:

    "{"The certificate 'CN=alice' must have a private key. The process must have access rights for the private key."}"

    Kindly Help me finding the solution.

    Thanks in advance.
    Wednesday, July 02, 2008 10:55 AM
  • run: FindPrivateKey My CurrentUser -n "CN=alice" -a

    to get location of the private key then you use cacls.exe to grant it permission.

     

    e.g. if you key is : abc

    then run

     

    Code Snippet
    cacls.exe "C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys\abc" /E /G "NETWORK SERVICE":R

     

     

    Wednesday, July 02, 2008 12:32 PM
  • Hi,
    I did the same and granted permission to the certificate. Mine code is related to ASPNET so I tried giving access by using this also:

    cacls.exe "C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys\abc" /E /G "ASPNET":R

    But still I am getting the same error.

    Any Loops through this???

    Kindly help me..

    Wednesday, July 02, 2008 12:38 PM
  • it depended on where is your website; I assume under IIS. then you have to see what user account run the Application Pool for your ASP.NET Application. then, you grant permission to that user. by default, it should be "Network Service"

     

    Thursday, July 03, 2008 2:51 AM
  • Yes, I know it is "ASPNET" for me.

    But still I am getting the same error.

    Any clues???
    Thursday, July 03, 2008 7:17 AM
  • can you post an error description from Event Viewer here?

     

    Thursday, July 03, 2008 7:25 AM
  • The main error is:

    [System.ServiceModel.Security.SecurityNegotiationException] = {"SOAP security negotiation failed. See inner exception for more details."}

    And the inner exception is:

    InnerException = {"The certificate 'CN=alice' must have a private key. The process must have access rights for the private key."}
    Thursday, July 03, 2008 7:47 AM
  • What is show you when you browse to your service with IE? e.g. http://localhost:8888/MyService.svc

     

    Thursday, July 03, 2008 9:02 AM
  • For test purpose, I have created just a Console application. This is not a service.

    Is it the case that WCF security can only be implemented on Service???
    Thursday, July 03, 2008 10:24 AM
  • if you use: Vista, please run it as Administor and give it a try

    if you use: VS2008, you can create Self Hosting WCF Project

    Thursday, July 03, 2008 11:29 AM
  • Okay,

    Let me give a try for this..

    I am using VS2008.

    Will tell  you as I am done with this...


    Thursday, July 03, 2008 11:33 AM
  • Hi all, I am running into this issue also when deployig my service to a windows 2003 server. I have it running on my development machine which uses Vista successfully.

    This is some relevant input:

    Here is the part of my service config that's relevant:
    Code Snippet

    <services>

    </behaviors>
      <service name="AccountManager" behaviorConfiguration="WCFBehaviour">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:26422/" />
          </baseAddresses>
        </host>
        <endpoint name="WCFEndpoint" address="/AccountManager" binding="wsHttpBinding" bindingConfiguration="WCFWSBinding" contract="Accounts.IAccountManager">
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>

    <!-- BINDINGS 524288-->
    <bindings>
      <wsHttpBinding>
        <binding name="WCFWSBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
                    receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
                    transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
                    messageEncoding="Text" textEncoding="utf-16" useDefaultWebProxy="true"
                    allowCookies="false">
          <security>

            <message clientCredentialType="Certificate"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>

    <!-- BEHAVIOURS -->
    <behaviors>
      <serviceBehaviors>
        <behavior name="WCFBehaviour">
          <serviceMetadata httpGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="True" />
          <serviceCredentials>
    <serviceCertificate findValue="WCFHost"
    x509FindType="FindBySubjectName" storeLocation="LocalMachine"
    storeName="My"/>

            <clientCertificate>
              <authentication revocationMode="NoCheck" certificateValidationMode="ChainTrust"/>
            </clientCertificate>
          </serviceCredentials>
          <serviceThrottling maxConcurrentCalls="10" maxConcurrentInstances="10"/>
        </behavior>
      </serviceBehaviors>



    I have created my cert using these commands:
    The root cert:
    makecert -n "CN=DevRootCA" -r -sv DevRootCA.pvk DevRootCA.cer

    I then imported the DevRootCA.cer file into the Certificate store "Trusted Root Certificates" using the mmc snapin for local machine.

    The client cert:
    makecert.exe -sk MyKeyName -iv DevRootCA.pvk -n "CN=TempDevCert" -ic DevRootCA.cer  -sr localmachine -ss my -sky exchange -pe TempDevCert.cer

    I then imported the TempDevCert.cer into the Certificate store Personal using the mmc snapin for local machine

    Now I have also granted access to the admin account (and the ASPNET account just in case!) under which my service runs as follows:
    winhttpcertcfg -g -c LOCAL_MACHINE\My -s WCFHost  -a admin@domain.com
    winhttpcertcfg -g -c LOCAL_MACHINE\My -s WCFHost  -a ASPNET

    The response to the command:
    winhttpcertcfg -l -c LOCAL_MACHINE\My -s TempDevCert

    is:

    Matching certificate:
    CN=TempDevCert

    Additional accounts and groups with access to the private key include:
        BUILTIN\Administrators
        NT AUTHORITY\SYSTEM
        DOMAIN\admin
        SAPP\ASPNET

    so the access rights seem correct.

    I am getting a little frustrated, since this works fine on my development machine, on which I never needed to grant access to the private key file.

    The exception I get when trying to run the service is as follows:
    Service cannot be started. System.ArgumentException: The certificate 'CN=TempDevCert' must have a private key that is capable of key exchange. The process must have access rights for the private key.
       at System.ServiceModel.Security.SecurityUtils.EnsureCertificateCanDoKeyExchange(X509Certificate2 certificate)
       at System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateServerX509TokenProvider()
       at System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateLocalSecurityTokenProvider(RecipientServiceModelSecurityTokenRequirement recipientRequirement)
       at System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateSecurityTokenProvider(SecurityTokenRequirement requirement)
       at System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateTlsnegoServerX509TokenProvider(RecipientServiceModelSecurityTokenRequirement recipientRequirement)
       at System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateTlsnegoSecurityTokenAuthenticator(RecipientServiceMod...

    For more information, see Help and Support Center at


    I hope someone can shed some light on this issue for me, what am I doing wrong here?

    Best regards
    Richard
    Thursday, September 11, 2008 2:02 PM
  •  

    Two things to verify:  1) the private key is stored in the certificate you are trying to access, and that it is not password protected, and 2) the user that runs the service has access to the private key file.

     

    With 1) you can verify the existence of the private key in the certificate by pulling up the certificate properties page from the MMC snap-in.  You should see a little key icon someplace and a note stating that you indeed have a private key for the certificate.

     

    With 2), the user name that runs a service varies depending on OS, OS version, and web container.  If you are running the service in IIS on Win2K, the process will run as a particular user like SERVICE or IUSR_MACHINENAME.  It will be different for IIS on Server 2003, IIS on WinXP, and possibly even IIS on Vista.  If you are running the service from within Visual Studio using the debug web container/web server, or the web service is "self-hosted," then the process will execute as the user you log in with.  The bottom line is you need to allow access by the appropriate user to the private key file that Windows stores the private key in behind the scenes.  There are tools to find the private key storage file for a particular certificate, but they are typically in "C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys" for "LocalMachine" certificates, and the equivalent user's AppData directory for "Current User" or "Personal" certificates.

    • Proposed as answer by Splaktar Friday, July 15, 2011 7:47 PM
    Friday, September 12, 2008 5:39 PM
  • I followed the steps Ischyrus used for creating the certs and I keep getting this error page:

    The handle is invalid.

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.Security.Cryptography.CryptographicException: The handle is invalid.

    Source Error:

    An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

    Stack Trace:

    [CryptographicException: The handle is invalid. ] System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer) +7712542 System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle) +67 System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair() +83 System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize) +226 System.Security.Cryptography.RSACryptoServiceProvider..ctor(CspParameters parameters) +9 System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey() +202 System.ServiceModel.Security.SecurityUtils.EnsureCertificateCanDoKeyExchange(X509Certificate2 certificate) +69 [ArgumentException: The certificate 'CN=SignedByCA' must have a private key that is capable of key exchange. The process must have access rights for the private key.] System.ServiceModel.Security.SecurityUtils.EnsureCertificateCanDoKeyExchange(X509Certificate2 certificate) +11594102 System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateServerX509TokenProvider() +36 System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateLocalSecurityTokenProvider(RecipientServiceModelSecurityTokenRequirement recipientRequirement) +63 System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateSecurityTokenProvider(SecurityTokenRequirement requirement) +54 System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateTlsnegoServerX509TokenProvider(RecipientServiceModelSecurityTokenRequirement recipientRequirement) +140 System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateTlsnegoSecurityTokenAuthenticator(RecipientServiceModelSecurityTokenRequirement recipientRequirement, Boolean requireClientCertificate, SecurityTokenResolver& sctResolver) +466 System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, SecurityTokenResolver& outOfBandTokenResolver) +619 System.ServiceModel.Security.SessionRenewSecurityTokenManager.CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, SecurityTokenResolver& outOfBandTokenResolver) +85 System.ServiceModel.Security.SymmetricSecurityProtocolFactory.OnOpen(TimeSpan timeout) +11298171 System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) +21 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +261 System.ServiceModel.Security.SecurityProtocolFactory.Open(Boolean actAsInitiator, TimeSpan timeout) +23 System.ServiceModel.Security.SecurityListenerSettingsLifetimeManager.Open(TimeSpan timeout) +80 System.ServiceModel.Channels.SecurityChannelListener`1.OnOpen(TimeSpan timeout) +204 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +261 System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) +72 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +261 System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +107 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +261 System.ServiceModel.Security.SecuritySessionSecurityTokenAuthenticator.OnOpen(TimeSpan timeout) +129 System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) +21 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +261 System.ServiceModel.Security.CommunicationObjectSecurityTokenAuthenticator.Open(TimeSpan timeout) +20 System.ServiceModel.Security.SecurityUtils.OpenTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout) +34 System.ServiceModel.Security.SecuritySessionServerSettings.OnOpen(TimeSpan timeout) +664 System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) +21 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +261 System.ServiceModel.Security.SecurityListenerSettingsLifetimeManager.Open(TimeSpan timeout) +133 System.ServiceModel.Channels.SecurityChannelListener`1.OnOpen(TimeSpan timeout) +204 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +261 System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) +72 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +261 System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +107 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +261 System.ServiceModel.HostingManager.ActivateService(String normalizedVirtualPath) +121 System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath) +479 [ServiceActivationException: The service '/FieldSchedulerService/FieldScheduler.svc' cannot be activated due to an exception during compilation. The exception message is: The certificate 'CN=SignedByCA' must have a private key that is capable of key exchange. The process must have access rights for the private key..] System.ServiceModel.AsyncResult.End(IAsyncResult result) +11531006 System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +194 System.ServiceModel.Activation.HostedHttpRequestAsyncResult.ExecuteSynchronous(HttpApplication context, Boolean flowContext) +176 System.ServiceModel.Activation.HttpModule.ProcessRequest(Object sender, EventArgs e) +278 System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +68 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75 

    My web.config file contains this:

    1     <system.serviceModel> 
    2         <services> 
    3             <service name="FieldSchedulerService.FieldScheduler" behaviorConfiguration="CustomValidator">  
    4                 <endpoint address="" 
    5                           binding="wsHttpBinding" 
    6                           contract="FieldSchedulerService.IFieldScheduler" 
    7                           bindingConfiguration="WSHttpBinding" /> 
    8                 <endpoint address="mex" 
    9                           binding="mexHttpBinding" 
    10                           contract="IMetadataExchange"/>  
    11                 <host> 
    12                     <baseAddresses> 
    13                         <add baseAddress="http://sqldev/FieldSchedulerService/FieldScheduler.svc"/>  
    14                     </baseAddresses> 
    15                 </host> 
    16             </service> 
    17         </services> 
    18         <bindings> 
    19             <wsHttpBinding> 
    20                 <binding name="WSHttpBinding">  
    21                     <security mode="Message">  
    22                         <message clientCredentialType="UserName" /> 
    23                         <transport clientCredentialType="None"/>  
    24                     </security> 
    25                 </binding> 
    26             </wsHttpBinding> 
    27         </bindings> 
    28         <behaviors> 
    29             <serviceBehaviors> 
    30                 <behavior name="CustomValidator">  
    31                     <serviceMetadata httpGetEnabled="true"/>  
    32                     <serviceDebug includeExceptionDetailInFaults="true"/>  
    33                     <serviceCredentials> 
    34                         <serviceCertificate storeLocation="LocalMachine" 
    35                                             x509FindType="FindByThumbprint" 
    36                                             findValue="97 ba 94 7b 92 ed 05 61 ed ba d9 e9 9c f5 cd 71 2b 68 c0 2f"/>  
    37                         <userNameAuthentication  
    38                           userNamePasswordValidationMode="Custom" 
    39                           customUserNamePasswordValidatorType="FieldSchedulerService.CustomUserNameValidator, FieldSchedulerService"/>  
    40                     </serviceCredentials> 
    41                 </behavior> 
    42             </serviceBehaviors> 
    43         </behaviors> 
    44     </system.serviceModel> 

    Could someone explain what I  need to do to support custom username validation?

    Thank you,
    Ryan Andres
    Monday, March 09, 2009 10:44 PM
  • I have tried pretty much everything on this page but still cannot get this to work, I continue to get the error:

    "The certificate 'CN=SignedByCA' must have a private key that is capable of key exchange. The process must have access rights for the private key."
    

    I have used the following commands:
    >makecert -n "CN=TempCA" -r -sv TempCA.pvk -sky exchange TempCA.cer
    Succeeded
    
    >pvk2pfx -pvk TempCA.pvk -spc TempCA.cer -pfx TempCA.pvk

    I have imported the pfx file to the Current User - Trusted Root Certification Authorities using the Certificates MMC snap-in
    >makecert -sk SignedByCA -iv TempCA.pvk -n "CN=SignedByCA" -ic TempCA.cer SignedByCA.cer -ss My -sr currentuser -pe
    Succeeded

    At this point I can look in the MMC and see that both keys have a private key corresponding to the certificate (they have the little key icon), their certification paths are valid, and they're intended for all application policies...

    Using WinHttpCertCfg I tried just granting 'Everyone' access to the key so it is now like this:

    >WinHttpCertCfg.exe -l -c CURRENT_USER\My -s SignedByCA
    Microsoft (R) WinHTTP Certificate Configuration Tool
    Copyright (C) Microsoft Corporation 2001.
    
    Matching certificate:
    CN=SignedByCA
    
    Additional accounts and groups with access to the private key include:
        KCC\JordanSoet
        NT AUTHORITY\SYSTEM
        BUILTIN\Administrators
        \Everyone

    And same thing with the key found from the findprivatekey.exe program:
    >cacls "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\261e60b18f66f34ad8c1509eced064e0_4d49b8da-5991-4410-9678-a7b0c708505f"
    C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\261e60b18f66f34ad8c1509eced064e0_4d49b8da-5991-4410-9678-a7b0c708505f
                                          NT AUTHORITY\SYSTEM:F
    
                                          BUILTIN\Administrators:F
    
                                          Everyone:F
    
                                          <Account Domain not found>R


    As far as I can tell the only thing I am doing wrong is I am not using the -sky exchange option when signing the certificate.... The problem is that I can't do this, every time I try it fails....

    So I can do this command:
    >makecert -sk SignedByCA -iv TempCA.pvk -n "CN=SignedByCA" -ic TempCA.cer SignedByCA.cer -ss My -sr currentuser -pe
    Succeeded

    But this fails:
    >makecert -sk SignedByCA -iv TempCA.pvk -n "CN=SignedByCA" -ic TempCA.cer SignedByCA.cer -ss My -sr currentuser -pe -sky exchange
    Error: Can't create the key of the subject ('SignedByCA')
    Failed


    If anyone has any suggestions I would be very appreciative :)

    Thanks,
    Jordan
    • Edited by JSoet Wednesday, January 06, 2010 12:05 AM Formatting
    Wednesday, January 06, 2010 12:02 AM
  • i think no mean for certificate in case

    clientCredentialType="Windows"

    Thursday, May 06, 2010 9:32 AM
  • Not sure whether you got it working or not. I struggled with this little bit before it is resolved...

    Here is the environment: (as things are slightly different between various windows versions)

    win-xp, visual studio2008

    Here are the commands to create/setup cert

    certmgr -del -r localmachine -s TrustedPeople -c -n MyServiceCert
    certmgr -del -r localmachine -s My -c -n MyServiceCert

    makecert.exe  -sr LocalMachine -ss MY  -pe -sky exchange -n "CN=MyServiceCert" MyServiceCert.cer
    certmgr.exe -add -r localmachine -s My -c -n MyServiceCert -r localmachine -s TrustedPeople

    After this, I was gettin that error " ...must have a private key ..." - because the service account that my WCF service is running under (<machine\aspnet>) doesn't have permissions to this certificate file.

    I tried to find the certificate file ('MyServicecert.cer') using .Netframework library class :

    X509Certificate cert = new X509Certificate(Certificate);

    But for some reason that class was not able to find it... so I found that file manually using windows explorer (i know it may be tricky with other/production environments). For my xp-machine the file is located under 'C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys\'. opened the properties for this file (had to guess based on the date created) and Added the user '<machine/aspnet>' account to it.

    then i was able to access my WCF service (through browser and through asp.net client as well).

    HTH!

    Mallik

     

    Monday, May 10, 2010 10:29 PM
  • I would like to add to this thread the solutions I found when I got this error:

     

    Error seen: It is likely that certificate 'CN=localhost' may not have a private key that is capable of key exchange or the process may not have access rights for the private key.

    I double-clicked the 2 .cer files (eg TempCA.cer and SignedByCA.cer) and chose import, putting the TempCA one under Trusted Root.. and the SignedByCA one under Personal. The problem was that running makecert already imported SignedByCA.cer only it also included the private key as well as the public key in the import. Double-clicking added a second copy without the private key.

    To check for the lack of private key in the imported SignedByCA: run certmgr.msc, private key adds a menu: choose SignedByCA, rclick>"All Tasks">"Advanced Operations" (Adv Ops menu only shows if you have the private key) and in "General" properties tab if you double-click SignedByCA it should have a "private key" line.

     

    Another Error seen: Can not create the key of the subject  ('SignedByCA')

    > try something else eg SignedByCA2 (not sure why, I might have an old one already with this name that I somehow can't find?). For me, it works to put anything here but it has to be unique.

    Tuesday, July 12, 2011 11:31 PM