After a day of long programming I want to post something useful for someone else.
Few days ago I was wondering how to handle JPasswordField
's method getPassword()
with a correct procedure to pass a value to a server and get an answer.
and this is the question:
How can I correctly get a value from a JPasswordField
in a safe way and handle it to create a login procedure with a server?
This is the solution I reached.
First of all I decided the procedure of the login that was safe enough to my purpose, I didn't want to send a plain password to the server and I didn't want to store a plain password (obviously) in my database.
The first thing to say is that a good way to secure a password is that it is never ever exchanged over a network in a plain and readable form, this is obviously because of a possible "man in the middle", that in few words is someone reading your messages in their way to the server.
The password need to be hashed, that means that it is transformed to a quite long sequence of hexadecimal characters. The good thing of the hash is that is (hopefully) one-way. You can't de-hash a password.
There are many algorithms to do this, I choose the SHA256.
The password is then hashed, but just between us, this can be not enough. If an hacker is able to steal the hash there are some techniques that can bring him to a successful "translation" of it. Just to add a variable in his equation, and to make his life harder, we can add a salt to the password prior to hash it. A salt is a piece of string that is added in any position we desire to the password. This avoids some kind of attacks based on dictionary and most used password.
But if an hacker that is better trained than me can't read the password, how can I?
The answer is simple, I don't have to.
But to understand this we need to jump for a moment in the "Registration procedure" that is the moment when a new user is added to my database. This is it:
So the login procedure will be like this:
This should be quite fine, but in this case if an hacker knows the shared secret can access the server without any problem because doing so we just changed the password, not to be readable, but still usable directly.
To avoid this behavior we just have to add a passage in our chain:
Now that the procedure is clear we have an issue to solve. If I handle any kind of String this can persist in the memory for long time, so if I put my password in a String it can be readable in a plain form for long time. This is not so good for us, but we are not the first to think about it, java indeed created a way to avoid this password persisting. The solution is use an array of characters. This is because even if the array is persisting in the memory, its datas are spread with no order in the memory and is very difficult to re-create the original password.
Re inventing hot water? Yep, just use the getPassword() method in a JPasswordField.
But this is quite difficult for newbie. We get a char[] array, and it is strange for a not expert.
The first thing that reach our mind can be to transform that array in a plain string ....... But is just what I want to avoid. So I need to handle the array as-is.
We need then a method to salt and hash the password, the result can be this:
this method create an array of bytes passing through many little strings then append the salt. Once salted it hash the result with SHA256.
Now the return can be a string because is hashed and there is no problem of security.
This give a solution for the first part of the question.
The second part is just to implements our protocol between server and client.
I will only show the code in the client that is significant enough to understand the procedure. I am using a blocking queue where the messages is put when read from the socket. this is the code:
The code, now that we have clear how the protocol works, it's easy to understand the thing that should be considered is that
this.mh.getMessage()
is a blocking method, this means that the thread will wait until something is available in the queue before trying to get it.This (almost) how I solved my problem. Let me know if there is any error in the answer or if you need some clarification. I hope this will be useful to someone. Have a nice programming