views:

1097

answers:

3

I have a WCF service and client which is going to be deployed to several companies (hundreds). Some companies will run the software in their network and some will run it over the Internet (WCF server at on office, WCF client at another).

We want to encrypt the communication between the WCF server and client. We don't have any need to authenticate the cient / subscriber using WCF security, because we have our own username/password log-in which the clients will use to log on the server.

  • We can't rely on Windows auth because some of the users will run it over the Internet, and the WCF server may not be on the same domain as the WCF client.
  • If we use "real" certificates*, companies running the software would have to purchase certificates from a CA and install it, and then configure our software to use it, but this is too complicated for most of them.
  • We could auto-create certificates during installation of the WCF server, but then we would have to automatically install it into a certificate store and somehow automatically grant IIS permissions to read the certificate. This is more complicated than we would like.

In short, we want a simple solution where the encryption is just based upon a shared secret, in our case the username / password the user is logging on with. I do understand that this won't give the best available encryption, but we're willing to trade some of the security to make the software easier to deploy.

Is this possible?

*With "real" certificates, I mean certificates purchased from a certificate authority, and not one I've created myself / self-signed.

A: 

Well, with WCF you could use Password credential at message level and SSL at transport level, which I think would be enough in your case.

See here.

Philippe
Wouldn't SSL at transport level require a certificate to be installed? In that case, it wouldn't really be compatible with the requirements I listed?The page you're linking to says that Password credentials is not available on message level; just username. Password is used for transport credentails.Also, under "Message client credential types", the page you're referring to says "Note that WCF does not allow any cryptographic operations with user names, such as generating a signature or encrypting data.".Can you explain how you mean?
Martin
For the certificates, as marc_s said, there is probably no way to get around these. For the password thingy, you are absolutely right, my bad :)Perhaps you could try to encrypt the data manually before putting them in the message, or use messages inspectors to do so? I, however, think that you should think twice before using your own security mechanisms.
Philippe
> Perhaps you could try to encrypt the data manually before putting them in the messageThat thought has crossed my mind, but I ditched it. I can't write my own security mechanisms, and even if I could, I would have to intercept the message while it's still serialized which would be a pain. > For the certificates, as marc_s said, there is probably no way to get around these.The thing I was looking for here on StackOverflow was something definitive, rather than more "probably"'s. I've spent hours googling the subject, but no-one seems to know for sure.
Martin
If you put an inspector on both client and server to intercept the message and modify it's content before it released to the client/server, you could easily use your own encryption mechanism. This wouldn't be reflected in the contact, but I doesn't matter for what I can see. Or is there a reason why you can't use message inspectors?
Philippe
+2  A: 

If you want to encrypt the messages on the transport (which is a really good idea!), there has to be some shared knowledge between the sender (the client) and the server. This can be hardcoded, but that's really not a good idea at all - if that "common shared" knowledge is ever compromised, an attacker could decipher and read all your messages.

Also, since it's definitely not recommended practice, there's no support of any kind in WCF to simplify using a shared secret. You're on your own - you have to roll your own 100% of the way.

The only viable way to have a common shared secret exchanged in a safe way is to use a certificate. No way around this, sorry. The certificate doesn't even have to be used for user authentication or anything - but it establishes a shared secret between the caller and the service and thus allows the caller to encrypt the messages in such a way only the intended recipient can actually decrypt and use them.

So I really don't see any way you can get around having certificates on your servers - doesn't need to be on every client, but on every server where your service runs.

Marc

PS: if you really want to investigate the "hardcoded shared secret" approach, you'll need to think about this:

  • how do you store a shared secret safely on each and every single one of your clients?
  • how do you use information from that stored shared secret to encrypt your messages?

Typically, the approach would be two-fold:

  1. exchange some form of a private/public key pair; the server generates a key pair and keeps the private key to itself and shares the public key with the client (e.g. over a WCF message, for instance)
  2. using that private/public key pair, exchange a common shared secret, e.g. an "encryption key" that will symmetrically encrypt your messages (and since it's symmetrical, the server can use the same key to decrypt the messages)
  3. setup infrastructure on your client (e.g. a WCF extension called a behavior) to inspect the message before it goes out and encrypt it with your shared secret

All in all, it's really not trivial - anything simpler than that is not worth being called "security" at all.

If you look at all that work you will have to do - wouldn't it be easier to just use the WCF built-in certificate mechanisms??

Decent security worth its salt is hard - so why not leverage what's available instead of doing all the work yourself, or worse: come up with a half-baked solution that's so easy to crack you could just as easily send everything in cleartext..... don't under estimate the complexity and amount of code needed to handle even the most basic security scenarios - WCF does this all for you - for free and in a reliable and safe manner - use it! You won't regret it!

marc_s
As I wrote in my question, I'm already aware of the fact that I can use certificates.My question was whether there was an alternative method, based on simple username and password authentication rather than certificates. I don't see that you have answered this.
Martin
I did - I said there **IS** no other way. Either you have certificates to provide security and encryption of your messages, or you have to forgo the encryption. Take your pick.
marc_s
If you want encryption (and you **do**!), then you need a shared secret - either one that's hardcoded (not recommended) into your client's config or something, or then the other option currently available is certificates.
marc_s
Your two last comments seems to contradict eachother. First you write that the only option is using certificates. Then you write that I can either use a shared, hardcoded secret, or a certificate. I assume the latter one is the correct one. So how do I go about using the shared, hardcoded, secret?
Martin
A: 

For message security, your client provides some credentials and server provides some credentials. For this setup and with your scenario could you not use the client username and password with a Custom Username Validator, and a server certificate to provide the server credentials. This Application Scenario provides a fair chucnk of the configuration setup you would need to achieve this, except the aspNet membership sections, which you would have to replace with your custom validation config.

You would still need valid certificates on your servers (no certificates required on the clients), but I can't see any way around this.

Tanner