@Override
    public Hash parse(final String formatted) {
        requireNonNull(formatted, "formatted in Shiro2CryptFormat.parse(String formatted)");

        // backwards compatibility
        if (formatted.startsWith(Shiro1CryptFormat.MCF_PREFIX)) {
            return new Shiro1CryptFormat().parse(formatted);
        }

        if (!formatted.startsWith(MCF_PREFIX)) {
            final String msg = "The argument is not a valid '" + ID + "' formatted hash.";
            throw new IllegalArgumentException(msg);
        }

        final String suffix = formatted.substring(MCF_PREFIX.length());
        final String[] parts = suffix.split("\\$");
        final String algorithmName = parts[0];

        HashSpi kdfHash = HashProvider.getByAlgorithmName(algorithmName)
                .orElseThrow(() -> new UnsupportedOperationException("Algorithm " + algorithmName + " is not implemented."));
        return kdfHash.fromString("$" + suffix);
    }
Converts a Hash-extending class to a string understood by the hash class. Usually this string will follow
posix standards for passwords stored in {@code /etc/passwd}.

<p>This method should only delegate to the corresponding formatter and prepend {@code $shiro2$}.</p>

@param hash the hash instance to format into a String.
@return a string representing the hash.
crypto/hash/src/main/java/org/apache/shiro/crypto/hash/format/Shiro2CryptFormat.java