@Override
    public boolean matches(byte[] rawPassword, byte[] saltedPasswordWithSalt) {
        int length = rawPassword.length;
        if (length > BCrypt.MAX_PASSWORD_BYTES) {
            return false;
        }
        for (byte b : rawPassword) {
            if (b == NULL_TERMINATOR) {
                return false;
            }
        }
        // If the length is 40, it means the password of the first version that has no null
        // terminator.
        int saltedPasswordWithSaltLength = saltedPasswordWithSalt.length;
        if (saltedPasswordWithSaltLength == 40) {
            byte[] saltedPassword = BCRYPT.get()
                    .deriveRawKey(10, saltedPasswordWithSalt, rawPassword);
            return Arrays.equals(saltedPassword,
                    0,
                    saltedPassword.length,
                    saltedPasswordWithSalt,
                    SALT_SIZE_BYTES,
                    saltedPasswordWithSaltLength);
        }
        int cost = saltedPasswordWithSalt[saltedPasswordWithSaltLength - 1] & 0xFF;
        if (length != BCrypt.MAX_PASSWORD_BYTES) {
            rawPassword = ArrayUtil.concat(rawPassword, NULL_TERMINATOR);
        }
        byte[] saltedPassword = BCRYPT.get()
                .deriveRawKey(cost, saltedPasswordWithSalt, rawPassword);
        return Arrays.equals(saltedPassword,
                0,
                saltedPassword.length,
                saltedPasswordWithSalt,
                SALT_SIZE_BYTES,
                saltedPasswordWithSaltLength - 1);
    }
@implNote The implementation doesn't validate the null terminator in the raw password to
          avoid double checks, and it is the responsibility of the caller to ensure that no
          null terminator is in the raw password.
turms-server-common/src/main/java/im/turms/server/common/infra/security/password/BCryptPasswordEncoder.java