OK I finally learned the ins and outs of SSL certificates (very complicated but several hours of studying and I think I get it) including exporting and importing to your PC, and I cooked up a simple Hello World app following the tutorial here: (Google this): "How To Use basicHttpBinding with Certificate Authentication from Windows" I had already bought a SSL Certificate from DASP called RapidSSL. However--and this is the DASP question--I'm not sure this certificate supports encryption--it appears to lack a private key. Does it have a private key? I don't think so--and why not??? I cannot run my program without a private key (I think this is the error I'm getting, see below the output). When I go to https://www.MYCOMPANYNAME.com (the DASP account that has this RapidSSL in it), I can, when I right-click the 'padlock' icon, see everything but the private key. I see version, public key, thumbprint, etc. And I can store this certificate (import it) to the '/My' folder in Windows where such certificates are kept for users, but, no private key??? Any idea why? Do I have t pay extra for a private key version? Below are my web.config files for the WCF project and the error message. PJ <?xml version="1.0" encoding="utf-8" ?> <configuration> <system.web> <compilation debug="true" /> </system.web> <!-- When deploying the service library project, the content of the config file must be added to the host's app.config file. System.Configuration does not support config files for libraries. --> <system.serviceModel> <services> <service behaviorConfiguration="WcfServiceLibrary1Secure1.Service1Behavior" name="WcfServiceLibrary1Secure1.Service1"> <endpoint address="" binding="basicHttpBinding" bindingConfiguration="Binding1" contract="WcfServiceLibrary1Secure1.IService1"> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> <serviceHostingEnvironment> <baseAddressPrefixFilters> <add prefix="http://MYCOMPANYNAMEprogramming.com"/> </baseAddressPrefixFilters> </serviceHostingEnvironment> <bindings> <basicHttpBinding> <binding name="Binding1"> <security mode="Message"> <message clientCredentialType="Certificate"/> </security> </binding> </basicHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="WcfServiceLibrary1Secure1.Service1Behavior"> <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment --> <serviceMetadata httpGetEnabled="True"/> <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> <serviceDebug includeExceptionDetailInFaults="False" /> <serviceCredentials> <serviceCertificate findValue="MYCOMPANYNAMEprogramming.com" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/> </serviceCredentials> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration> //////////// Server Error in '/Secure10162010Website' Application. -------------------------------------------------------------------------------- Keyset does not exist 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: Keyset does not exist 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: Keyset does not exist ] System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer) +7714910 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=MYCOMPANYNAMEprogramming.com, OU=Domain Control Validated - RapidSSL(R), OU=See www.rapidssl.com/resources/cps (c)10, OU=GT55691249, O=MYCOMPANYNAMEprogramming.com, C=US, SERIALNUMBER=lFZWoksXE/ZiQtB9cvQxXx1nCG7wwQvH' must have a private key that is capable of key exchange. The process must have access rights for the private key.] // [ServiceActivationException: The service '/Secure10162010Website/WcfServiceLibrary1Secure1.svc' cannot be activated due to an exception during compilation. The exception message is: The certificate 'CN=MYCOMPANYNAMEprogramming.com, OU=Domain Control Validated - RapidSSL(R), OU=See www.rapidssl.com/resources/cps (c)10, OU=GT55691249, O=MYCOMPANYNAMEprogramming.com, C=US, SERIALNUMBER=lFZWoksXE/ZiQtB9cvQxXx1nCG7wwQvH' must have a private key that is capable of key exchange. The process must have access rights for the private key..] -------------------------------------------------------------------------------- Version Information: Microsoft .NET Framework Version:2.0.50727.4200; ASP.NET Version:2.0.50727.4209
Do I need to open a help ticket? Help. Here is what somebody else said at another forum on this problem. Should I open a help ticket or do they not have the expertise to solve this? Should I wait for an answer here? Joe, where are you? ? ;-) //from WCF Forums by MSFT...I reposted this there. Hi, I think you should also explore the second part of the error message which says "The process must have access rights for the private key". Since you are using Message security, it is likely that your WCF process does not have access to the private key of the certificate on the service side to carry out the secuity verification. You will have to work with the provider here and request them for the following - · Using FindPrivateKey tool – WCF samples ship with this utility FindPrivateKey ( http://msdn.microsoft.com/en-us/library/aa717039.aspx ) which must be used to find the location of the private key and then access must be given on this certificate using another command line tool cacls.exe (or another variant depending on the OS). · Using certificate console – Open mmc –> add certificate snap-in -> Right click the certificate to go to All Tasks -> Manage Private Key -> provide read permission to the account service is running. - Piyush
I believe the last advice you got is on the right track - the private key for the SSL cert is only accessible on the web server where the SSL cert is installed. It's created when you use the 'generate CSR' option in the DASP control panel and enables an external certification authority (RapidSSL, Verisign etc) to create a valid matching SSL certificate for the specified CN. WCF service activation is failing at the moment because the process doesn't have access rights to the key store however DASP may be preventing this for a good reason. If you find you're unable to make progress with WCF certificate security, WCF username security could be an option for you. Alternatively ASP.NET authentication coupled with the WCF authorization technique that I described here has been proven to definitely work without any server side infrastructure changes.
Thanks...but I'm curious...what do you mean? What would that 'good reason' you refer to be? I may be mistaken (and if I am, no problem, but I'd like to know so I don't keep beating my head against a wall), but I thought in order to get a secure https type connection both the app and the server have to be able to communicate as per the protocol laid out in the tutorial I followed, meaning at some point they have to be able to share the private key? So what good is (and I mean this literally, not as an insult) the SSL certificate? In other words, how do you programically use the SSL certificate issued by RapidSSL to get the cool little green padlock icon in your browser, the one with https? If there's a link to this, please let me know. Or, perhaps (and this would be incredible if true, but who knows, I'm just a noob) the only person who can do this would be somebody with control of the server, somebody at DASP, and for whatever reason DASP does not want to do this? In which case, like you say, you're out of luck. So again, why buy these SSL certificates? Is it more for web commerce rather than programmers? Yes, and though I like your solution very much (though I could not get it to compile--still, I like the source code, and I learned a few new things going through it), in Visual Studio 2010, which I will be migrating to soon, there's an WCF 'built-in' authorization technique found in the RIA Silverlight 4 business toolkit described in this tutorial here: http://msdn.microsoft.com/en-us/library/ff713719(VS.91).aspx Also Tim Heuer has a video on this toolkit: http://go.microsoft.com/fwlink/?LinkId=166921 Basically it looks very similar to what you can do in VS2008, but with one big difference: authentication is "built in", notice the attribute you can decorate your web method with called: "[RequiresAuthentication()] ". Then only logged in users can access your web method thus decorated. This solves my problem (once I migrate to VS 2010). Thank you for your help. Again, any comments about why/how I can use SSL for now (before I migrate) is greatly appreciated. Otherwise I guess I wasted $70 or so buying a SSL certificate from RapidSSL that I don't need (no big deal though, DASP has very cheap prices--I am still a happy customer)
'Good reason' - to be honest I'm not sure why DASP would choose to prevent the ASP.NET worker process access to the SSL key store but rather than me saying 'it's just plain wrong', I choose to say 'it might be like that for some good reason'. I think the only way to find out for sure will be to raise a support ticket / ask the direct question and let the DASP infrastructure support guys answer the question. To see the padlock in the browser like the one seen in the screenshot in this thread http://community.discountasp.net/showthread.php?t=11343, simply enter the correct URL in the address bar. When the padlock is displayed, all traffic between the client (browser) and the web server is SSL secured. As I mentioned in the readme.txt, build requirements to get the sample project I posted to build are Visual Studio 2010. Visual Studio 2008 will not work because there are differences between the sln and csproj file formats. Most of the code should largely lift and drop however the exception probably being the web.config. If you're seeing some sort of unexpected build problem let me know and I'll take a look at the zip I uploaded. I might have screwed something up with it. I know RIA services has been kicking around for a while but I've not done anything with it yet. I agree it looks very powerful and I've been meaning to get stuck in but it looked like it was in CTP/beta for a long time which kept putting me off and to be honest, I'm still not sure it's out of beta yet. If someone can clear that one up I'd appreciate it.
I think you may also be confusing TRANSPORT security vs. MESSAGE security. In transport security, the HTTPS protocol is used. This is where the SSL certificate that you purchased comes in. By simply accessing the WCF service through HTTPS in the URL, the data sent/received is secure. In message security, you are encrypting/decrypting only the message. Usually, the certificate used for message encryption is different from the SSL certificate that is used for HTTPS. Although you can use the SSL certificate for both, some types of SSL certificates are not multi-purposed. DASP assumes that SSL certificates are used for HTTPS and not message security. If you also want to use your SSL certificate for message security, then the application has to have access to the private key. Contact support in this case.
https means https! Yes, you are absolutely correct--I did not know about message vs transport until I read your post. And, inspired by your post, I tried an experiment that demonstrated https. Simply put (and what a shock to see this): I had a 'hello world' app like this: http://mysite.com/MyDirectory/HelloWorld.html (Silverlight). So to make it "SSL" or "TLS" secure, 128 bit AES, you change "http" to "https"! that is:https://mysite.com/MyDirectory/HelloWorld.html Similarly for any ASP.NET application. Laugh Out Loud. That's it? Great Scot. Transport security is thus trivial, once you get an SSL/TLS certificate from DASP.