views:

241

answers:

4

I am writing a server-client application to receive user message and publish it.

Thinking about authentication method.

  1. Asymmetric encryption, probably RSA.
  2. Hash (salt+password+'msg'+'userid'), SHA256
  3. HMAC, SHA256. seems to be more secured than the method 2. Also involve hashing the password and msg data.
  4. Symmetric Encryption of the 'msg' with static password stored on both sides, probably AES.

There is no need for encryption as the msg would be publish online anyway. So I am more lean to the HMAC or PKI method.

I'm using java to send the request (including whatever authentication method to be implemented) www.mysite.com/foo?userid=12345&msg=hello&token=abc1234

python on the server side to receive request and make sure the request is from the valid user.

The problems are in integration and make sure both sides understand each other's authentication token. It is a big factor for me. And the availability of the libraries available on both language are taken into account as well.

Or I can choose to rewrite the server side into java. (Why not python? The client side application need to be in java)

What do you think?


EDIT: I would not treat this as a web application. The application does not serve any webpage. Most of the operations are not related to the web. Just the client-server communication go through internet. And sending POST/GET via HTTP is what I thought of as the simpler albeit insecure way to do it. Feel free to suggest me any other alternative.

SSL is a secure way for encryption. But it does not prevent attacker from sending message to the server impose as the user. Anyone can initiate a HTTPS connection. And the content of the communication does not need to be encrypted. It will be published online by the server anyway. What I need is a way to authenticate the message and sender.

For now I am lean to HMAC algorithm. RSA would be more secure but it comes with more developer efforts as well. Will see how it goes.

Thank you.

+1  A: 

OK, firstly, an option to consider is just going down the "enterprise solution" route and buying into the standard PKI market: buy yourself a certificate from Veri$ign etc and use boring old HTTPS (or at least TLS, the underlying protocol). Then sending the data from the client is (more or less) a doddle, and there'll be a standard library in whatever langauge you choose to interpret things at the other end. I actually think HTTPS/TLS and the whole certificate infrastructure is a complicated waste of space for applications where you know what server you're talking to and you know what encryption system you want to use. But the availability of libraries "out of the box" means it might get you up and running quickly, so it's definitely worth considering one way or the other.

In principle, you don't need a PKI-issued certificate to use HTTPS/TLS. But in practice, it may be easier to just spend the few dollars than try and persuade a standard library to accept a self-issued certificate. (In general, using HTTPS libraries may just mean you end up turning the 2-day "programming my encryption system" problem into a 2-day "why isn't this black box accepting my certificate" problem-- it also kind of depends on what problem you fancy solving...)

Even if you don't use HTTPS/TLS, you may want to read through the spec, to understand how it overcomes certain security threats (and what those threats are).

OK, so then taking your points:

  • Just to be clear, you DON'T need a certificate or PKI to use RSA or other asymmetric encryption. A PKI (attemptedly) solves the problem of a client needing to talk to a "mystery" server that it can't trust when that server says "here is my public key". If you're writing a dedicated client and you know in advance which server you're talking to, then you can just distribute the public key with your client. The client knows it's talking to the right server, because if it wasn't, that server wouldn't understand things that it encrypted with that public key.
  • The main thing you need to be careful of when using "raw" hashes is that they're vulnerable to extension attacks. So if you send "a|b|c" plus the hash code for that data, an attacker can work out the hash code for "a|b|c|d" (so in your example (2), they could substitute "userid" for "useridX" and work out a new hash code for this, based on the hash code you supplied for "a|b|c"). HMAC schemes get round this problem.
  • In any case, if you go for using "raw" encryption tools, still use standard libraries, because they'll have thought about some security issues. For example, with RSA, you have to be careful to use padding (see some info I've written on RSA encryption in Java and the cryptography section it's in-- that might be interesting for you). And when generating any encryption key, you need to be careful about "where the random data is coming from".
  • You don't have to base the AES encryption key on the password (if you do, read up on password-based encryption schemes: password generally have little entropy, so you need to take extra measures to try and protect against this). But I would go for the more standard approach of using the password to authenticate the connection, and as part of the authentication, negotiate a random AES key.
  • Make sure that you're addressing the issue of replay attacks in your scheme (generally, the client and server should each send each other a random "nonce" at the start of the communication, and authentication and future communication over that connection will depend on the nonce).
Neil Coffey
+2  A: 

Can't you just use standard SSL sockets to secure the connection, validate the user with a password, and then send the message to be published? If there won't be many clients, you can even use a self-signed certificate and put it in a KeyStore in the client app, that way you won't need to buy a certificate from Verisign or anyone else.

If you are storing the user's password hash on the server (as I think you should otherwise how are you going to validate the user's password), then you can first reproduce that hash on the client side (let's assume you hash user+pass) and then append that to the message and hash the result. You send the user id, hash and message to the server.

On the server side you receive a request with a user id, you retrieve the user's password (the server only has stored the hash of user+pass), you append that to the message and hash it again, and compare it against the hash in the request. If it matches, the user can publish the message.

Oh and you should use HTTP POST, instead of sending data on the URL. The server should not accept data on the URL for the publish request.

Chochos
alright I will look into SSL later. I wonder how difficult it is to implement this on python and java. Thanks anyway. =)
On second thought, SSL is not what I needed. I need to verify the identity of client side user rather than protect the content from eavesdropper. The message is going to be publish online anyway.
The hash user+password+message is what I thought of but seems to be less secure than HMAC algorithm. So that's what I'm heading at the moment.
A: 

RSA protocol is generally used to setup a key exchange for a faster encryption means. That's how SSL works.

If the security requirements for your applications are so sensitive that you require PKI, then it should be said (without any intent to be harsh) that if you need to ask about it on SO, then its probably something you shouldn't attempt to do (given that generally successful attacks on secure channels attack weakpoints of the implementation).

As Chochos has suggested, what's wrong with simply using the existing SSL infrastructure in Java and your server to set up a secure https connection and then simply pass the user password from client to the server?

sorry for the term "PKI". By PKI I meant asymmetric encryption rather than the full fetch implementation with Certificate Authority etc. I don't think my application is sensitive enough to require Verisign certificate.
+1  A: 

Let me just add a few random thoughts/comments to your proposals.

  1. RSA: Since you are mainly interested in authentication, I assume you'd want to use RSA signatures. This would imply that each user needs his own privat key. To me that sounds a little bit like overkill, especially when user and server already share common secrets (i.e., passwords).
  2. Using SHA256 is a good approach. I have some problems to understand why you include a salt, since a salt is commonly use to avoid that an attacker precomputes hashes of dictionaries. To be clear: dicitionary attacks are a problem here. An attacker could try to hash messages with all passwords from a dictionary. Just he has to reapeat this attack for each user and can't reuse precomputed values. One way to make such an attack a little more difficult is called key strengthening, e.g. by reapeatedly hashing the result n times and hence forcing an attacker to perform more work during a dictionary attack.
  3. I completely agree that HMAC is better than just SHA-256. After all HMAC was designed for authentication. I'm not sure why you want to hash the message before computing the HMAC. HMAC does that for you.
  4. Encryption does not always provide authentication. This is specially in cases when the attacker learns the plaintext, as he does in your case. He might be able to exploit properties of the encryption mode to manipulate the ciphertext an know exactly how the resulting plaintext will look like (E.g. the CBC mode allows these kind of manipulations). Your previous proposal (HMAC) is preferable.

Finally, if you can setup an SSL connection between user and server, as others suggest: this would be a much safer solution, since not even the dicionary attack mentioned above would be possible.

Accipitridae