I would like to know if my current implementation of BCrypt is correct, I am aware that I am not using BCrypt.checkpw()
which may lead to an issue so that is the main reason I verify it here.
Hasher.java container class:
abstract public class Hasher {
public static String hash(final char[] input) {
String output = Hasher.hash(new String(input));
for (int i = 0; i < input.length; i++) {
input[i] = 0;
}
return output;
}
public static String hash(final String input) {
return BCrypt.hashpw(input, BCrypt.gensalt());
}
}
One concern here: JPasswordField
gives me a char[]
for security reasons, however BCrypt.hashpw()
only accepts Strings. How can I avoid that String from floating around in my memory?
The client implementation of logging in:
String hashedPassword = Hasher.hash(password);
Network.getInstance().send("login " + username + " " + hashedPassword);
So the hash gets sent over the network, currently the network is not encrypted but I plan on adding that.
The server implementation on account creation:
public static Account createAccount(final String username, final String password) {
String hashedPassword = Hasher.hash(password.toCharArray());
return new Account(username, hashedPassword);
}
The server implementation of checking password:
public boolean checkPassword(final String hashedPassword) {
return this.hashedPassword.equals(hashedPassword);
}
With this.hashedPassword
being the hash that is in the server's memory (which comes from a database on bootup).
Properties of my setup:
BCrypt.gensalt()
.Please verify my assumptions.
Regards.
There are a couple problems with this setup.
1) The salt should be a value randomly generated during the hashing process (as it seems to be in your implementation. Since the client does not have access to the database of stored hashes, the client will not know what salt to use when creating a login hash.
2) This implementation is not actually checking the password passed by the client, it's checking the password hash passed by the client. That means that if someone gets your database of hashes, they can immediately use those hashes to login. Then do not need to crack them to extract passwords, since you do not check the passwords.
Both these issues can be easily solved by moving all hashing server side.
Update
Regarding the issues you mentioned.
1) If you have any intention of creating a secure system, you should be using SSL/TLS. Sending password hashes in the clear is almost as totally insecure as sending passwords in the clear. Both are a terrible idea. Use HTTPS.
2) Performing server side hashing is a pretty ordinary practice. The hashing process is computationally expensive enough to make exhaustive search impractical, but it shouldn't hinder your authentication workflow. If you're really concerned about being DoSed, keep track of how many times a given user has tried to login in the last N seconds. If they've failed a certain number of times, lock their account.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With