Генерация миллионов хэшей sha256 и случайной строки в Java

Я хотел бы как можно быстрее сгенерировать миллионы случайных строк и хэшей на Java. На данный момент @ Turing85 дал мне довольно хороший код, который был довольно быстрым всего за 5 секунд для 50M случайной строки, но следующая проблема, с которой я столкнулся, — это медленность, когда я хеширую свои пароли в своей строке. Проблема только в том, что хеш должен совпадать с сгенерированным паролем.

На данный момент я получил этот код для sha256 и случайную строку в файл.

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();
    }
}

Кстати, если вы не поняли, в чем проблема, я бы хотел увеличить скорость алгоритма sha256, чтобы сделать его более эффективным

Спасибо 🙂

1 ответ
1

«Я бы хотел увеличить скорость алгоритма SHA256»

Вы используете библиотеку для хэша, поэтому у вас действительно нет возможности сделать это быстрее. Теоретически, если вы эксперт в криптографии и информатике, возможно, вы могли бы построить что-то быстрее самостоятельно, но, скорее всего, это будет медленнее, потому что на самом деле это сложно …

Из ресурсов, которые я быстро проверил в Интернете, реализация Java sha256 должна обеспечивать скорость не менее 100 МБ / с на современном компьютере.

Вы говорите, что выполнение 50M хэшей из 7,5 символов в строке занимает 5 секунд. Получается 75 МБ / с, что примерно, но немного медленнее. Я не знаю, какой процессор вы используете, так что это могло быть нормально или могло быть медленным.

Насколько я понимаю, у вас есть несколько способов ускорить ваш код: оптимизировать генерацию строк (а не вычисление хэша) ИЛИ использовать более быструю имплантацию sha256, что, вероятно, означает использование JNI и подходящей библиотеки C / C ++. (это может привести к потере волос и принесению в жертву козла), ИЛИ, вероятно, наиболее эффективный способ — просто использовать несколько потоков, каждый из которых обрабатывает один кусок параллельно. Затем они могут записывать в один и тот же файл с синхронизацией или в отдельные файлы, если вам нужна максимальная скорость, но вам нужно будет объединить их позже, если вам понадобится один файл. Или вы можете использовать любую комбинацию из трех вышеперечисленных вариантов.

  • А как реализовать алгоритм multiThreading в моем коде для каждого хеша? Да, я использовал готовую библиотеку, поэтому, возможно, я не могу ускорить хэш для пароля

    — Forcela8

  • Изучая многопоточность для Java. В Интернете есть множество учебных пособий и руководств, которые вы можете найти.

    — Эмили Л.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *