Password4j / password4j

Java cryptographic library that supports Argon2, bcrypt, scrypt and PBKDF2 aimed to protect passwords in databases. Easy to use by design, highly customizable, secure and portable. All the implementations follow the standards and have been reviewed to perform better in the JVM.
https://password4j.com
Apache License 2.0
355 stars 26 forks source link

Argon2 Password validation not working, always showing false #72

Closed mykapps599 closed 2 years ago

mykapps599 commented 2 years ago

Describe the bug i have implemented Password Encryption with [password4j/Argon2] .

To Reproduce

Step1#: Encryption

        Hash hash=Password.hash(userEnteredPassword).addSalt(salt).addPepper(pepper).withArgon2();

Step2#: Validation

              boolean verification=Password.check(userEnteredPassword,hash..toString())
                            .addSalt(salt))
                                             .addPepper(pepper)
                                .withArgon2();

 # Details# : 
      userEnteredPassword : yesh599_33 
      salt                                : yesmykaps599
      pepper                          : 80953

Argon2() Config Details#:

hash.argon2.memory=4096 hash.argon2.iterations=99 hash.argon2.length=128 hash.argon2.parallelism=4 hash.argon2.type=id hash.argon2.version=20

Expected behavior Password verification always showing false.

Environment:

Additional context Kindly let me know, if any changes required.

firaja commented 2 years ago

Hello @mykapps599,

just use hash.getResult() instead of hash.toString().

Here you can find a quick guide on the Hash object, but in general Hash#toString() is just a string representation of that object (which contains many information). The hash itself is contained in Hash#getResult()

Using your example:

// Step2: Validation
boolean verification = Password.check(userEnteredPassword, hash.getResult())
                               .addSalt(salt)
                               .addPepper(pepper)
                               .withArgon2();

Also take in account that #addSalt() can be skipped because the salt is already contained in you hash and Password4j automatically parses the hash in search for the salt. So you can just write

// Step2: Validation
boolean verification = Password.check(userEnteredPassword, hash.getResult())
                               .addPepper(pepper)
                               .withArgon2();

Let me know if you need further information. If not, please close this issue. Thank you šŸš€

mykapps599 commented 2 years ago

Hello @mykapps599,

just use hash.getResult() instead of hash.toString().

Here you can find a quick guide on the Hash object, but in general Hash#toString() is just a string representation of that object (which contains many information). The hash itself is contained in Hash#getResult()

Using your example:

// Step2: Validation
boolean verification = Password.check(userEnteredPassword, hash.getResult())
                               .addSalt(salt)
                               .addPepper(pepper)
                               .withArgon2();

Also take in account that #addSalt() can be skipped because the salt is already contained in you hash and Password4j automatically parses the hash in search for the salt. So you can just write

// Step2: Validation
boolean verification = Password.check(userEnteredPassword, hash.getResult())
                               .addPepper(pepper)
                               .withArgon2();

Let me know if you need further information. If not, please close this issue. Thank you šŸš€

Hello @firaja ,

Thanks for sharing the details. i have tried below both cases, stil it is showing false only.

  1. boolean verification = Password.check(userEnteredPassword, hash.getResult()) .addSalt(salt) .addPepper(pepper) .withArgon2();

  2. boolean verification = Password.check(userEnteredPassword, hash.getResult()) .addPepper(pepper) .withArgon2();

Result: False Input: Same input as mentioned previously.

mykapps599 commented 2 years ago

Hello @firaja ,

Thanks for sharing the details. i have tried below both cases, stil it is showing false only.

boolean verification = Password.check(userEnteredPassword, hash.getResult()) .addSalt(salt) .addPepper(pepper) .withArgon2();

boolean verification = Password.check(userEnteredPassword, hash.getResult()) .addPepper(pepper) .withArgon2();

Result: False Input: Same input as mentioned previously.

firaja commented 2 years ago

@mykapps599 I cannot reproduce your issue. Can you please execute the following unit test?

    @Test
    public void testFromGithub()
    {
        String userEnteredPassword= "yesh599_33";
        String salt = "yesmykaps599";
        String pepper = "80953";

        Argon2Function argon2 = Argon2Function.getInstance(4096, 99, 128, 4, Argon2.ID, 20);

        Hash hash = Password.hash(userEnteredPassword).addSalt(salt).addPepper(pepper).with(argon2);
        boolean verification = Password.check(userEnteredPassword,hash.getResult()).addSalt(salt).addPepper(pepper).with(argon2);

        Hash rawHash = argon2.hash(userEnteredPassword, salt, pepper);
        boolean rawVerification = argon2.check(userEnteredPassword, hash.getResult(), salt, pepper);

        assertTrue(verification);
        assertTrue(rawVerification);
        assertEquals(rawHash, hash);
        assertTrue(slowEquals(hash.getBytes(), rawHash.getBytes()));
    }

    private boolean slowEquals(byte[] a, byte[] b)
    {
        int diff = a.length ^ b.length;
        for (int i = 0; i < a.length && i < b.length; i++)
        {
            diff |= a[i] ^ b[i];
        }
        return diff == 0;
    }

all the asserts should pass.