public static ScramCredential credentialFromString(String str) {
        Properties props = toProps(str);
        if (props.size() != 4 || !props.containsKey(SALT) || !props.containsKey(STORED_KEY) ||
                !props.containsKey(SERVER_KEY) || !props.containsKey(ITERATIONS)) {
            throw new IllegalArgumentException("Credentials not valid: " + str);
        }
        byte[] salt = Base64.getDecoder().decode(props.getProperty(SALT));
        byte[] storedKey = Base64.getDecoder().decode(props.getProperty(STORED_KEY));
        byte[] serverKey = Base64.getDecoder().decode(props.getProperty(SERVER_KEY));
        int iterations = Integer.parseInt(props.getProperty(ITERATIONS));
        return new ScramCredential(salt, storedKey, serverKey, iterations);
    }
@Test
    public void invalidCredential() {
        assertThrows(IllegalArgumentException.class, () -> ScramCredentialUtils.credentialFromString("abc"));
    }