How can I secure socket.io on the client-side? - node.js

Note: This is not a duplicate. Please read the question carefully.
I'm building a chat app with socket.io; however, I have a lot of concerns about the security. Basically, anyone can connect to my namespace and get messages that are sent from the server. After reading many SO posts and looking over the web, I concluded that I need to encrypt the data.
The problem: Encryptions and decryptions need keys. I can store a private key on the server, but since everything client-side is visible to the client, how do I keep some malicious hacker from seeing the key on the client side?
I’ve looked at socket.io-encrypt, but that just confuses me even more, because it seems like the client side is also written in Node.js. The other answers on SO I either can't understand why it helps or they don't solve my problem

Related

Messaging between users with node application

I want to implement in-app messaging in my iOS and Android application, and I am unsure about how the backend functionality should be created. From before my backend is running with Node.js and users etc. are stored with MongoDB.
I figure that I quite easily could implement messaging just by saving the messages in the database and sending a push to the recipient with the new message and also showing it in the app, but I do not want the messages to be readable on the server. It would therefore be necessary to encrypt them in the database and decrypt them on the clients.
Do anyone have any suggestions for either how the encryption could be implemented or about node frameworks to use? I have looked at socket.io, but this seem to be created for real time chatting applications, which is not exactly what I'm looking for. I have also looked at RabbitMQ, but I don't really understand if it suits my requirements or not.
Many thanks in advance!
You are talking about end to end encryption. Your encryption would be easy to break if the key for the encryption is hardcoded inside the application. In order to implement something like this, you'll need a library for iOS and a library for Android.
For iOS, I recommend using OpenSSL and implementing a encryption scheme(Public key Cryptography). For Android, you can use the Spongy Castle library.
Due to limitations with iOS push notification size, it is not a great idea to send data via PUSH.
You will also (probably)need to implement a authentication mechanism for users to login.
You can go on two paths here..
Have the server generate a secret for the clients to decrypt
Separate keys, (hashed password on database, and public/privatekeys on client)
I have not used socket.io/rabbitmq, so unfortunately I cannot help you there. It seems like you are new to this, I would take a good look & reading on public key cryptography. http://en.wikipedia.org/wiki/Public-key_cryptography#Examples

API authentication without SSL

I'm writing an API that will be hosted without SSL support and I need a way to authenticate the requests. Each client would have a different ID, but if requests were authorised with that, anyone with a packet sniffer could forge requests. Is it possible to make a secure system WITHOUT relying on SSL?
(Some thoughts I had included OAuth, could that be implemented?)
Many thanks
Have each client cryptographically sign its requests with a client-specific key. Verify the signature on the server.
Using cryptography pretty simple. The main challenge is setting up the clients' keys. It'll be hard to do that securely without using SSL. There's no information in the question about how you set up client IDs, so I don't know if it's secure enough to set up keys at that point as well.
It's also going to be a problem if you serve the client code without SSL.
But hey, it's just an API you're building. Maybe the code that interacts with it is served over HTTPS. Or maybe the code is stored locally on the client.
I feel like a lot of people are going to complain about this answer though.

How to do server-side validation of a client application?

I've got a Windows client (desktop) application that when run for the first time will hit a server and request a client ID. A short time later that client will call back up to the server with additional requests. The server can hand out client IDs all day long, but it's important that the server be able to know that any future requests are coming from a valid client.
This means verifying that it's the client application making the request, and not someone/something else pretending to be the client application. Ideally it would also involve verifying that the client ID of a client application hasn't changed.
I thought about including a hash of the salted client ID with future requests, but it doesn't seem like it would be terribly hard for a determined person to disassemble the client enough to figure out the salt value.
Thanks in advance for any solutions, tips or pointers!
Can't be done sensibly without a heavy dose of cryptography. As long as the other end has complete control, there just is no way they can't fake the answers. Something vaguely similar is what Kerberos does, the protocols are quite involved. Ross Anderson's "Security Engineering" would be my first stop to take a look at how to do it.

Can I make my own secure HTTP connection to a specific server

I am thinking about writing a secure connection between a specific client and a specific server over HTTP. Of course SSL is the best and most obvious choice. But I keep thinking I could do the do the cryptography myself.
Note that this isn't about connecting any client to a specific server, but a specific client (e.g. a Java client app on my PC) to a specific server (my website hosted somewhere else). SO third-party certification doesnt seem necessary, since the server knows exactly which client to look out for and the cleint knows exactly which server to find.
If I want to upload a file from client to server. I could encrypt it manually (AES or other) and have the key hardcoded into the client app and also put in a file on the server, out of public view.
Please tell me if I'm crazy, stupid or pushing at windmills. Is my idea possible?
The short answer is, "No you can't." You can write some code that you think implements a secure connection, but actually it will be insecure. Designing and implementing a secure connection is a very skilled job; just see what a security consultant would charge you for doing that.
Since you are asking the question here, it is reasonable to assume that you are not such a person. Since you do not have the required skills and experience, anything you produce would be insecure.
Use existing standards where all the obvious errors, and a lot of the not so obvious ones, have been avoided for you.
Your idea possible, and really, if you just need to send file to specific URL, it would be easier to make a POST request with encrypted data (if URL/headers don't need to be secure for you).
Trying to roll your own replacement for SSL is a bad idea. Don't roll your own crypto. Instead, you should use SSL. It does what you need.
Given that you need to authenticate both the client and the server, you should use SSL with client certificates (as well as server certificates, which are standard).

I need resources for API security basics. Any suggestions?

I've done a little googling but have been a bit overwhelmed by the amount of information. Until now, I've been considering asking for a valid md5 hash for every API call but I realized that it wouldn't be a difficult task to hijack such a system. Would you guys be kind enough to provide me with a few links that might help me in my search? Thanks.
First, consider OAuth. It's somewhat of a standard for web-based APIs nowadays.
Second, some other potential resources -
A couple of decent blog entries:
http://blog.sonoasystems.com/detail/dont_roll_your_own_api_security_recommendations1/
http://blog.sonoasystems.com/detail/more_api_security_choices_oauth_ssl_saml_and_rolling_your_own/
A previous question:
Good approach for a web API token scheme?
I'd like to add some clarifying information to this question. The "use OAuth" answer is correct, but also loaded (given the spec is quite long and people who aren't familiar with it typically want to kill themselves after seeing it).
I wrote up a story-style tutorial on how to go from no security to HMAC-based security when designing a secure REST API here:
http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/
This ends up being basically what is known as "2-legged OAuth"; because OAuth was originally intended to verifying client applications, the flow is 3-parts involving the authenticating service, the user staring at the screen and the service that wants to use the client's credentials.
2-legged OAuth (and what I outline in depth in that article) is intended for service APIs to authenticate between each other. For example, this is the approach Amazon Web Services uses for all their API calls.
The gist is that with any request over HTTP you have to consider the attack vector where some malicious man-in-the-middle is recording and replaying or changing your requests.
For example, you issue a POST to /user/create with name 'bob', well the man-in-the-middle can issue a POST to /user/delete with name 'bob' just to be nasty.
The client and server need some way to trust each other and the only way that can happen is via public/private keys.
You can't just pass the public/private keys back and forth NOR can you simply provide a unique token signed with the private key (which is typically what most people do and think that makes them safe), while that will identify the original request coming from the real client, it still leaves the arguments to the comment open to change.
For example, if I send:
/chargeCC?user=bob&amt=100.00&key=kjDSLKjdasdmiUDSkjh
where the key is my public key signed by my private key only a man-in-the-middle can intercept this call, and re-submit it to the server with an "amt" value of "10000.00" instead.
The key is that you have to include ALL the parameters you send in the hash calculation, so when the server gets it, it re-vets all the values by recalculating the same hash on its side.
REMINDER: Only the client and server know the private key.
This style of verification is called an "HMAC"; it is a checksum verifying the contents of the request.
Because hash generation is SO touchy and must be done EXACTLY the same on both the client and server in order to get the same hash, there are super-strict rules on exactly how all the values should be combined.
For example, these two lines provides VERY different hashes when you try and sign them with SHA-1:
/chargeCC&user=bob&amt=100
/chargeCC&amt=100&user=bob
A lot of the OAuth spec is spent describing that exact method of combination in excruciating detail, using terminology like "natural byte ordering" and other non-human-readable garbage.
It is important though, because if you get that combination of values wrong, the client and server cannot correctly vet each other's requests.
You also can't take shortcuts and just concatonate everything into a huge String, Amazon tried this with AWS Signature Version 1 and it turned out wrong.
I hope all of that helps, feel free to ask questions if you are stuck.

Resources