使用 Jasypt:当密码应该匹配时,checkPassword 方法返回 false。

发布于 2024-12-25 18:01:26 字数 2452 浏览 1 评论 0原文

为了向您提供一些背景知识,我和我的团队正在创建一个程序,将用户名和密码存储在数据库中。我们使用Java并通过java代码与数据库交互。

我们使用 Jasypt 来加密用户名和密码。我正在使用 Jasypt 中的 BasicPasswordEncryptor 来加密两者。用户名加密良好并存储在数据库中。但是,当检查登录并表示 BasicPasswordEncryptor 尝试根据加密密码检查明文用户名时,它始终返回 false。我进行了一系列检查,以重点确定问题发生的位置。据我所知,这是Jasypt的问题。有谁知道问题是什么,可能的解决方案,或更优化的方法?谢谢。我将发布代码。

这是加密发生的地方。

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();
    }
}

其中“e”是 BasicPasswordEncryptor 对象。这是登录检查。

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;
    }

}

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;
    }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南冥有猫 2025-01-01 18:01:26

我是 jasypt 的作者。

从您的消息中,我不清楚您在匹配用户名或密码时是否观察到此问题——您说“尝试根据加密密码检查明文用户名”,这是没有意义的。然而,像您这样的问题的最常见原因之一是您的数据库列不够大,无法存储散列用户名和/或密码。

散列结果的大小取决于所使用的算法和盐配置,但对于使用 MD5 和 8 字节盐大小的 BasicPasswordEncryptor,您应该期望散列为 16 字节(散列)加上 8 字节( salt),加上由于文本 Base64 编码而产生的 8 个额外字节。总共32个字节。

还认为许多 DBMS 以字符而不是字节来测量 varchar 字段,因此您应该根据表中使用的字符编码进行适当的转换。

我总是建议首先检查列大小,因为如果您尝试存储对于列来说太长的 varchar,许多 DBMS 不会引发错误 - 它们只是将其截断。我不知道 MySQL 的行为,但 Oracle 正是这样做的。当你尝试解密它时......它不匹配。

因此,检查色谱柱尺寸可能是一个很好的起点。请记住 jasypt 在 http://forum.jasypt.org 上有一个用户论坛

哦,顺便说一下——如果这只是临时演示代码,请原谅我,但以防万一:您应该确保在重用之前关闭“finally”块中的所有 Statement 和 ResultSet 对象...因此您应该使用不同的“statement”和“ rs 内部变量迭代块,并每次关闭它们。

问候。

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.

我一直都在从未离去 2025-01-01 18:01:26

优化1:使用WHERE子句。

Optimisation 1 : Use a WHERE clause.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文