public static Argon2Hash generate(
            String algorithmName,
            int argonVersion,
            ByteSource source,
            ByteSource salt,
            int iterations,
            int memoryAsKB,
            int parallelism,
            int outputLengthBits
    ) {
        final int type;
        switch (requireNonNull(algorithmName, "algorithmName")) {
            case "argon2i":
                type = Argon2Parameters.ARGON2_i;
                break;
            case "argon2d":
                type = Argon2Parameters.ARGON2_d;
                break;
            case "argon2":
                // fall through
            case "argon2id":
                type = Argon2Parameters.ARGON2_id;
                break;
            default:
                throw new IllegalArgumentException("Unknown argon2 algorithm: " + algorithmName);
        }

        final Argon2Parameters parameters = new Argon2Parameters.Builder(type)
                .withVersion(argonVersion)
                .withIterations(iterations)
                .withParallelism(parallelism)
                .withSalt(requireNonNull(salt, "salt").getBytes())
                .withMemoryAsKB(memoryAsKB)
                .build();

        final Argon2BytesGenerator gen = new Argon2BytesGenerator();
        gen.init(parameters);

        @SuppressWarnings("checkstyle:MagicNumber") final byte[] hash = new byte[outputLengthBits / 8];
        gen.generateBytes(source.getBytes(), hash);

        return new Argon2Hash(algorithmName, argonVersion, hash, new SimpleByteSource(salt), iterations, memoryAsKB, parallelism);
    }
128 bits of salt is the recommended salt length, taken from draft-irtf-cfrg-argon2-13, 4.2.
crypto/support/hashes/argon2/src/main/java/org/apache/shiro/crypto/support/hashes/argon2/Argon2Hash.java