Search code examples
spring-securityhashscrypt

How Spring Scrypt PasswordEncoder knows the original salt to be able to verify the password


Hashing "MYpassword" using SCrypt in Spring twice generate two different hashes which is the expected result since the salt is different.

hash 1: $100801$DBrs3RHYQafAjmY0RGGgtA==$VB1ahwEHntb36HWbAF1Eiy6FoJp1WH8xmpYY4+oHPUk=
hash 2: $100801$0EEqkaQUDzVCttua+jqu9A==$tstqjgsW5bzWXwRZKIeVy9P3jh/92QrZ8SW+8iLl7dc=

What I don't understand is that to verify the password, Scrypt needs the original salt used to hash. After searching, I found out it gets the salt from the hash field itself. So where is it exactly in the above examples? I searched for scrypt format decoded and nothing came up.


Solution

  • Per the source code,

    private String digest(CharSequence rawPassword, byte[] salt) {
        byte[] derived = SCrypt.generate(Utf8.encode(rawPassword), salt, this.cpuCost, this.memoryCost,
                this.parallelization, this.keyLength);
        String params = Long.toString(
                ((int) (Math.log(this.cpuCost) / Math.log(2)) << 16L) | this.memoryCost << 8 | this.parallelization,
                16);
        StringBuilder sb = new StringBuilder((salt.length + derived.length) * 2);
        sb.append("$").append(params).append('$');
        sb.append(encodePart(salt)).append('$');
        sb.append(encodePart(derived));
        return sb.toString();
    }
    

    The parameter, salt, and hash are appended next to each other with $ separator, so the middle value is the encoded salt.