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);
    }
SCRAM Credential persistence utility functions. Implements format conversion used
for the credential store implemented in Kafka. Credentials are persisted as a comma-separated
String of key-value pairs:
<pre>
  salt=<i>salt</i>,stored_key=<i>stored_key</i>,server_key=<i>server_key</i>,iterations=<i>iterations</i>
</pre>
clients/src/main/java/org/apache/kafka/common/security/scram/internals/ScramCredentialUtils.java