Using Jasypt: The checkPassword method is returning false when the passwords should match.

1.5k Views Asked by At

To give you some background, my team and I are creating a program that stores usernames and passwords in a database. We are using Java and interacting with the Database through java code.

We use Jasypt to encrypt the usernames and passwords. I am using the BasicPasswordEncryptor in Jasypt to encrypt both. The usernames encrypt fine and are stored in the database fine. However, when the login is checked and said BasicPasswordEncryptor attempts to check the plaintext username against the encrypted password, it always returns false. I have done a series of checks to focus down where the problem is occuring. As far as I know, it's a problem with Jasypt. Does anyone know what the problem is, a possible solution, or a more optimal method? Thank you. I will post the code.

Here is where the encryption occurs.

public void register(String userName, String passWord){
    String encryptedUsername = e.encryptPassword(userName);
    String encryptedPassword = e.encryptPassword(passWord);
    System.out.println("Registered eU: " + encryptedUsername);
    try {
        con = DriverManager.getConnection("jdbc:mysql://localhost:3306/PandaBox", "root", "");
        statement = con.prepareStatement("insert into Users (username, password, logged) values (?,?,?)");
        statement.setString(1, encryptedUsername);
        statement.setString(2, encryptedPassword);
        statement.setInt(3, 0);
        boolean x = statement.execute();
        System.out.println("IT REGISTERED");

    } catch (SQLException o) {
        o.printStackTrace();
    }
}

Where "e" is the BasicPasswordEncryptor object. Here is the login check.

public boolean checkLogin(String inputedUsername, String inputedPassword) {
    try {
        con = DriverManager.getConnection("jdbc:mysql://localhost:3306/PandaBox", "root", "");
        statement = con.prepareStatement("select * from Users");
        rs = statement.executeQuery();
        System.out.println(inputedUsername + " / " + inputedPassword);

        while(rs.next()){
            String usernameInDatabase = rs.getString("username");
            System.out.println(usernameInDatabase);
            if (e.checkPassword(inputedUsername, usernameInDatabase)) {  
                System.out.println("Username correct.");
                statement = con.prepareStatement("select password from Users where username = ?");
                statement.setString(1, usernameInDatabase);
                rs = statement.executeQuery();
                String passwordInDatabase = rs.toString();
                if(passwordIsCorrect(inputedPassword, passwordInDatabase)){
                    return true;
                }                                               
            }                                   
        }
        return false;
    } catch (SQLException o) {
        // TODO Auto-generated catch block
        o.printStackTrace();
        return false;
    }

}
2

There are 2 best solutions below

0
On

I'm jasypt's author.

From your message, it isn't clear to me whether you are observing this issue when matching the user name or the password --you say 'attempts to check the plaintext username against the encrypted password', which makes no sense--. Nevertheless, one of the most common reasons for problems like yours is that your database columns are not big enough for storing your hashed user names and/or passwords.

The size of the hashing result will depend on the algorithm and salt configuration being used, but for a BasicPasswordEncryptor, which uses MD5 and a salt size of 8 bytes, you should expect your hashes to be 16-byte (hash) plus 8 bytes (salt), plus 8 additional bytes because of textual Base64 encoding. A total of 32 bytes.

Also think that many DBMS measure varchar fields in chars and not bytes, so you should do the appropiate conversion depending on the character encoding being used at your table.

I always recommend to check column sizes first because many DBMS's do not raise an error if you try to store a varchar which is too long for a column --they simply truncate it. I don't know MySQL's behaviour, but Oracle does exactly this. And when you try to decrypt it back... it doesn't match.

So checking your column sizes could be a good starting point. And remember jasypt has a users forum at http://forum.jasypt.org

Oh, and by the way-- forgive me if this is just ad-hoc demo code, but just in case: you should make sure you close all your Statement and ResultSet objects in 'finally' blocks before reusing them... so you should use different 'statement' and 'rs' variables in the inner iteration block, and close them each time.

Regards.

4
On

Optimisation 1 : Use a WHERE clause.