We have an encryption service that we've exposed over net. tcp. Most of the time, the service is used to encrypt/decrypt strings. However, every now and then, we the need to encrypt large documents (pdf, JPG, bmp, etc.).
What are the best endpoint settings for a scenario like this? Should I accept/return a stream? I've read a lot about this, but no one gives guidance on what to do when the large file doesn't occur frequently.
MSDN describes how to enable streaming over WCF rather well.
Note, if the link between client and server needs to be encrypted, then you'll need to "roll your own" encryption mechanism. The default net.tcp encryption requires X.509 certificates, which won't work with streams as this kind of encryption needs to work on an entire message in one go rather than a stream of bytes.
This, in turn, means that you won't be able to authenticate the client using the default WCF security mechanisms as authentication requires encryption. The only work-around for this that I know of is to implement your own custom behaviour extensions on client and server to handle authentication.
A really good reference on how to add custom behaviour extensions is here: this documents how to provide custom configuration, too (something that I don't think is discussed anywhere in the MSDN documents at this time).
One pattern you could follow is to have an asynchronous service that works on files on a shared file system location:
Place the file to be encrypted on a shared location
Call the service and tell it to encrypt the file, passing both the location and name of the file, and the addres of a callback service on the client
The service would encrypt the file and place the encrypted copy in a shared location (the same as where the unencrypted was placed or different, doesn't matter)
The service would call back to the client, giving the name and location of the encrypted file
The client can retrieve the encrypted file
Related
I have a WCF service that runs on my machine and provides data to everyone.
I need to limit access to some methods only to a certain assembly, not depending on the user that is making the request.
I read about PrincipalPermission and certificates but I'm not sure if this can be useful to me, does anyone know how to make it?
You can use client certificate authentication (whether message or transport - does not matter). Add the client certificate to a trusted people store on the server side, and embed the client certificate keys (e.g PFX) in a resource.
Since not all the methods should be protected, you can create two services that expose different functionality of the same class.
I have seen one or two questions about this but no definite answers. I have a customer requirement to implement a WCF-based client/server solution using Message Encryption AND HTTPS. I understand that WCF doesn't support this as standard, and the options are HTTP with Message Encryption, HTTPS without Message Encryption, or HTTPS with Message Credentials.
None of these will satisfy the customer requirement. I have control over both the service and the desktop-based clients. The service is hosted at my location and the clients access it over the internet.
I have dug around for days (and nights :( ) trying out custom bindings and so on, but whenever I try to combine message encryption with Https, I come up against this error:
"The binding contains both a SymmetricSecurityBindingElement and a secure transport binding element. Policy export for such a binding is not supported."
I would prefer to user username/password for authentication but I am prepared to use client certificates if this makes it possible. So far I haven't found any combination which is acceptable to WCF.
Is there any way to achieve this or am I just wasting my time? I would value a quick answer because my customer's deadline is drawing very near!
Thanks!
According to this, the special both mode for security (meaning both message and transport) is only supported in the NetMsmqBinding binding, which I'm guessing, is not an option for you. Does your client happen to be the NSA? (Just wondering why anyone would need their communication encrypted twice).
OK I've found a solution ...
Using IMessageInspector I intercepted the incoming and outgoing messages so that they can be encrypted and decrypted. Encryption uses a symmetric technique - best because asymmetric only allows encryption of short strings and is very slow.
The downside is that both ends need to have the private key of the certificate - so the cert needs to be installed on both client and server machines (or the key could be placed in config). This works for me though because the number of users is limited and all are under the control of the IT dept.
If I had more time I would have looked at setting up a second SSL connection with a different cert, purely to handle the certificate negotiation and avoid placing the cert on the client machine. Using SslStream was a possibility but I wasn't sure whether I could access key information to use for my own encryption, or whether this is held privately within SslStream class.
For now I'm just pleased to have it working before my deadline (only just though :) ) ...
Here's my scenario:
I need to host a WCF web service app that will be consumed by multiple customers. Each customer is responsible for their own client app, and they will be building their client apps with different technologies. It's likely that none of their clients will be .Net (probably will be Java or something else).
I need to implement Message Level Security to abide by their policies (Transport security is not sufficient).
Given the above requirements, I am having a hard time understanding how to implement Message Security in WCF that can be used by clients that I do not control. Everything I've read discusses the scenario where I would be building my own client, and that the client would even be in my network's domain.
If I implement Message Security with Certificate, can I install one certificate on my server and have each client be responsible for installing their own certificates on their servers? Would we then be able to use Message Security by simply sharing the Public Keys?
Basically, what you're saying here in your last paragraph is true. You'd give the subscribers of your WCF service the public key (.cer) file that they'd install and register within the LocalMachine/My store of their client machines.
On the host side, you'd install the cert public key in your LocalMachine/TrustedPeople store and the private key (.pfx or .pvk) in the host LocalMachine/Personal store.
You can vary the location of where you install/registry the public and private keys a bit, but then you'd have to configure your WCF service to find those cert elements on your server. The clients would have to do the same.
This does work. I've done it.
You can automate some of this using a .bat file and the makecert.exe and certmgr.exe DOS commands to ensure everything gets installed in the correct places.
I'm in the process of designing a REST Api and we're trying to decided how to do encryption. We are currently using https for all request/responses however various logs (dns, browser, ...) will log the plain text url. This raises an issue when we're sending sensitive data in the url, such as "www.mysite.com/user/credit-card-number/". Is there a way to leverage the SSL/TLS public/private keys to encrypt path parameters? For example, "www.mysite.com/user/credit-card-number/" turns into "www.mysite.com/encryptedstring".
I would highly recommend that you not put sensitive data in the URL. If you need something identifying, you could at least use a randomly generated String/UUID/token/whatever that maps to whatever it is that is being identified.
Handling manual encryption/decryption would depend on what language/framework you are using. For example, if you were using Java, then do some google searches on JSSE, which is Java's framework for SSL/TLS.
If you're looking for something to automajically do the encryption/decryption for you, I would think that would also depend on the framework you are using.
If I understand correctly, you are asking if urls are encrypted over an SSL/TLS channel. The answer is yes as this SO question points out. Over TLS, everything is encrypted between the client and server except the IP address and port of the targeted server. (This includes the http headers as well.)
EDIT:
After reading again, I see that you are interested in stopping the the URL being logged. I'm pretty sure the only way to do this is to change the url on the server. Not much help, but my suggestion is don't put the cc number in the url or use some kind of derived key instead.
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.
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:
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)
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)
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!
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.
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.
Take a look at the following sample:
http://www.codeproject.com/KB/WCF/wcfcertificates.aspx
It uses certificates but without a certificate store - so no setup is necessary.
Hmm.. maybe something simple could be used. Move the encryption from software to hardware. VPN from each client network to your own and then you can do whatever you like for WCF transport. The line is not clear text and the problem is solved.
Of course this is easier said than done, but most network vendors provide a pretty easy VPN config and it maybe easier than trying to develop an installer for SSL certs and configure the client.
I hope it helps!