beginner – Generating millions of hashes sha256 and random String in Java

I would like to generate Millions of Random String and Hashes in Java fast as possible. For the moment, @Turing85 gave me a pretty good code who was pretty fast only 5 sec for 50M of random String but the next problem to which I am confronted is the slowness when I hash my passwords in my String. The only problem is that the hash must match the generated password.

For the moment I got this code for sha256 and the random String into a file.

import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Random;
import java.util.concurrent.TimeUnit;

class Scratch {

    private final static String policy = "azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN1234567890";
    private final static Random random = new Random();

    private static final int MIN = '!';
    private static final int MAX = '~';
    private static final Random RANDOM = new Random();

    public static void main(final String... args) throws IOException, NoSuchAlgorithmException {
        final Path passwordFile = Path.of("passwords.txt");
        final Path hashFile = Path.of("hash.txt");
        if (!Files.exists(passwordFile)) {
            Files.createFile(passwordFile);
        }
        if (!Files.exists(hashFile)) {
            Files.createFile(hashFile);
        }
        final DecimalFormat df = new DecimalFormat();
        final DecimalFormatSymbols ds = df.getDecimalFormatSymbols();
        ds.setGroupingSeparator('_');
        df.setDecimalFormatSymbols(ds);
        final int numberOfPasswordsToGenerate = 50_000_000;
        final int chunkSize = 500_000;
        int passwordLength;
        final int min = 'A';
        final int max = 'Z';
        int generated = 0;
        int chunk = 0;

        final long start = System.nanoTime();
        while (generated < numberOfPasswordsToGenerate) {
            final StringBuilder passwords = new StringBuilder();
            final StringBuilder hashes = new StringBuilder();
            for (int index = chunk * chunkSize; index < (chunk + 1) * chunkSize && index < numberOfPasswordsToGenerate;
                    ++index) {
                final StringBuilder password = new StringBuilder();
                final StringBuilder hash = new StringBuilder();

                passwordLength = random.nextInt(9 - 6) + 6;
                for (int character = 0; character < passwordLength; ++character) {
                    //password.append(policy.charAt(random.nextInt(policy.length())));
                    password.append(fetchRandomLetterFromAlphabet());
                }
                passwords.append(password.toString()).append(System.lineSeparator());

                hash.append(toHexString(getSHA(password.toString())));
                hashes.append(hash.toString()).append(System.lineSeparator());

                ++generated;
                if (generated % 500_000 == 0) {
                    System.out.printf(
                            "%s / %s%n",
                            df.format(generated),
                            df.format(numberOfPasswordsToGenerate));
                }
            }
            ++chunk;
            Files.writeString(passwordFile, passwords.toString(), StandardOpenOption.WRITE);
            Files.writeString(hashFile, hashes.toString(), StandardOpenOption.WRITE);
        }
        final long consumed = System.nanoTime() - start;
        System.out.printf("Done. Took %d seconds%n", TimeUnit.NANOSECONDS.toSeconds(consumed));
        //System.out.printf("Done. Took %d seconds%n", TimeUnit.NANOSECONDS.toNanos(consumed)/*.toSeconds(consumed)*/);
    }

    private static char fetchRandomLetterFromAlphabet() {
        return (char) (RANDOM.nextInt(MAX - MIN + 1) + MIN);
    }

    public static byte() getSHA(String input) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        return md.digest(input.getBytes(StandardCharsets.UTF_8));
    }

    public static String toHexString(byte() hash) {
        BigInteger number = new BigInteger(1, hash);
        StringBuilder hexString = new StringBuilder(number.toString(16));
        while (hexString.length() < 32) {
            hexString.insert(0, '0');
        }
        return hexString.toString();
    }
}

btw if you didn’t understand the problematic, I would like to increase speed of the sha256 algorithm to make it more efficient

Thanks 🙂