none
How to properly use X509FindType.FindBySubjectKeyIdentifier with WCF RRS feed

  • Question

  • Hello,

    We are creating a WCF client that uses certificate authentication,  and I cannot seem to be able to find out which value needs to be passed for the "find" value when when the FindType is X509FindType.FindBySubjectKeyIdentifier using either the "findValue" attribute in the client credentials 

    <system.serviceModel>
      <behaviors>
        <endpointBehaviors>
           <clientCredentials findValue="AAAAAA">
        <endpointBehaviors>
      <behaviors>
    <system.serviceModel>

    Or the ClientCredentials.ClientCertificate.SetCertificate of the System.ServiceModel.Description class:

    proxy.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectKeyIdentifier, "AAAAA")


    When trying to retrieve a certificate to use as a client certificate.

    As per documentation (https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509findtype(v=vs.110).aspx) the FindBySubjectKeyIdentifier says that this should be: 
    "The findValue parameter for the Find method must be a string representing the subject key identifier in hexadecimal, such as "F3E815D45E83B8477B9284113C64EF208E897112", as displayed in the UI."

    Without explictly stating what the UI is... assuming that this is the Details tab when opening a certificate from the MMC certificate snap-in

    When viewing a certificate in with the snap in, when a certificate (in local machine\personal store), has a subject key identifier of "AAAAAA" (simplified for example purposes only), our client proxy classes (generated by adding service reference) are unable to find the certificate with a config set as: 

     <clientCredentials>
                  <clientCertificate findValue="AAAAAA"
                                  storeLocation="LocalMachine"
                                  x509FindType="FindBySubjectKeyIdentifier" storeName="My"/>              
    </clientCredentials>

    or trying to add it via code using 

    proxy.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectKeyIdentifier, "AAAAAA")

    Each scenario produces the error: 

    Cannot find the X.509 certificate using the following search criteria: StoreName 'My', StoreLocation 'LocalMachine', FindType 'FindBySubjectKeyIdentifier', FindValue 

    However, in an attempt to prove that this certificate is in that store and accessible, running this code block in the same application which uses an X509Store to retreive the certificate, returns a certificate successfully using the exact same FindType and FindValue


    Private Function getCertificate() As X509Certificate2
            Dim clientStore As X509Store = New X509Store(StoreName.My, StoreLocation.LocalMachine)        
            Try    
                Dim cert2 As X509Certificate2 = (From c In clientStore.Certificates.Find(X509FindType.FindBySubjectKeyIdentifier, "AAAAAA", False)).FirstOrDefault
                Return cert2
            Catch ex As Exception
                Throw ex
            Finally
                clientStore.Close()
            End Try
        End Function


    Any help would be appreciated... thanks




    • Edited by _MikeG Wednesday, July 6, 2016 5:34 PM corrected the example in config to use the right FindType
    Wednesday, July 6, 2016 3:54 PM

Answers

  • Thanks Zhiqing, 

    With the help of support services, have found the ClientCredentials.ClientCertificate.Certificate property, which when combined with a retrieval using the System.Security.Cryptography libraries the example above, you can then set the client certificate of the proxy class.

    proxy.ClientCredentials.ClientCertificate.Certificate = getCertificate(certificateSubjectName)
    
    Private Function getCertificate(ByVal certificateName As String) As X509Certificate2
            Dim clientStore As X509Store = New X509Store(StoreName.My, StoreLocation.LocalMachine)        
            Try
                clientStore.Open(OpenFlags.ReadOnly)
                Dim cert As X509Certificate2 = (From c In clientStore.Certificates.Find(X509FindType.FindBySubjectKeyIdentifier, certificateName, False)).FirstOrDefault
                Return cert
            Catch ex As Exception
                Throw ex
            Finally
                clientStore.Close()
            End Try
    End Function


    • Edited by _MikeG Tuesday, August 9, 2016 8:50 PM
    • Marked as answer by _MikeG Tuesday, August 9, 2016 8:50 PM
    Tuesday, August 9, 2016 2:28 PM

All replies

  • Hello,

    Based on your description, I know that when you are using the following config, you can not find the certificate:

     <clientCredentials>
                  <clientCertificate findValue="AAAAAA"
                                  storeLocation="LocalMachine"
                                  x509FindType="FindBySubjectKeyIdentifier" storeName="My"/>              
    </clientCredentials>

    I wonder have you tired any others type for the x509FindType, for the detailed information about the types for the x509FindType, please check:
    https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509findtype(v=vs.110).aspx .

    For example you can use the FindBySubjectName x509FindType as following to see if it works:

    <clientCredentials>
                  <clientCertificate findValue="******"
                                  storeLocation="LocalMachine"
                                  x509FindType="FindBySubjectName" storeName="My"/>              
    </clientCredentials>

    Best Regards,
    Amy Peng


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, July 8, 2016 4:23 AM
    Moderator
  • Hi Amy, 

    Thanks for your reply, yes searching by subject name works... however this is not the approach we want to take unless we have to, as we want to use the SKI for other reasons.

    Thanks

    Friday, July 8, 2016 1:15 PM
  • Hi MikeG,

    I could reproduce your issue, I will keep pay attention to this issue.

    Best Regards,

    Edward


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Wednesday, July 20, 2016 11:04 AM
  • Dear MikeG,

    I can also reproduce this issue.

    Currently there are two workarounds:

    1. Use FindBySubjectName in the web.config
    2. Write source codes in the WCF project to retrieve the certificate by FindBySubjectKeyIdentifier

    Besides there two workarounds, then your question falls into a category which requires a more in-depth level of support.  Please visit the below link to see the various free and paid support options that are available to better meet your needs. http://support.microsoft.com/default.aspx?id=fh;en-us;offerprophone

    Best regards,

    Zhiqing


    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.

    Tuesday, August 9, 2016 5:30 AM
  • Thanks Zhiqing, 

    With the help of support services, have found the ClientCredentials.ClientCertificate.Certificate property, which when combined with a retrieval using the System.Security.Cryptography libraries the example above, you can then set the client certificate of the proxy class.

    proxy.ClientCredentials.ClientCertificate.Certificate = getCertificate(certificateSubjectName)
    
    Private Function getCertificate(ByVal certificateName As String) As X509Certificate2
            Dim clientStore As X509Store = New X509Store(StoreName.My, StoreLocation.LocalMachine)        
            Try
                clientStore.Open(OpenFlags.ReadOnly)
                Dim cert As X509Certificate2 = (From c In clientStore.Certificates.Find(X509FindType.FindBySubjectKeyIdentifier, certificateName, False)).FirstOrDefault
                Return cert
            Catch ex As Exception
                Throw ex
            Finally
                clientStore.Close()
            End Try
    End Function


    • Edited by _MikeG Tuesday, August 9, 2016 8:50 PM
    • Marked as answer by _MikeG Tuesday, August 9, 2016 8:50 PM
    Tuesday, August 9, 2016 2:28 PM