Подтвердить что ты не робот

Java - алгоритмы хеширования - самые быстрые реализации

Я хочу знать, что представляет собой наилучшую и быструю реализацию хэш-алгоритмов для Java, особенно MD5 и SHA-2 512 (SHA512) или 256. Я хочу, чтобы функция получала строку в качестве аргумента и возвращала хеш в качестве результата, Thak you.

Изменить: это для получения каждого URL-адреса для уникального хэша. Поскольку MD5 не так надежен в этой области, я больше заинтересован в поиске лучшей и быстрой реализации алгоритмов SHA-2. Обратите внимание, что я знаю, что даже SHA-2 может создавать один и тот же хэш для некоторых URL-адресов, но я могу жить с этим.

4b9b3361

Ответ 1

Первые вещи: скорость переоценена. Вы должны принять меры, прежде чем объявить, что данный алгоритм "слишком медленный". В большинстве случаев скорость хэш-функции не вызывает заметной разницы. Если у вас есть проблемы с безопасностью, сначала выберите хеш-функцию, которая достаточно безопасна, а затем беспокоится только о производительности.

Кроме того, вы хотите хэш-строки. Java String является внутренним блоком из массива значений char, которые представляют собой кодовые точки Unicode (на самом деле, Unicode 16-разрядные кодовые единицы, которые кодируют кодовые точки с использованием UTF-16). Хеш-функция принимает на входе последовательность бит или байтов. Таким образом, вам нужно будет сделать шаг преобразования, например. str.getBytes("UTF-8"), чтобы получить вашу строку как кучу байтов. Вероятно, что шаг преобразования будет иметь незначительную стоимость по сравнению с самим хешированием.

Примечание: будьте осторожны с URL-кодированием! В URL-адресе некоторые байты могут быть заменены последовательностями, начинающимися с знака '%; это предназначено для поддержки непечатаемых символов, но оно также может использоваться и для "стандартных" символов (например, для замены "a" на "%61" ). Это означает, что две строки, которые различны (в смысле String.equals()), могут фактически представлять один и тот же URL (в отношении обработки URL). В зависимости от вашей ситуации это может быть или не быть проблемой.

Сначала вы должны использовать API Java MessageDigest со стандартным (уже установленным) поставщиком JCE (т.е. вы вызываете MessageDigest.getInstance("SHA-256")) и оцениваете результат. Теоретически JCE может отображать вызов в реализацию с "родным" кодом (написанным на C или сборке), который будет быстрее, чем вы можете получить с Java.

Это сказано...

sphlib - это реализация многих криптографических хеш-функций с открытым исходным кодом в C и Java. Код был оптимизирован для скорости, и на практике версия Java оказывается быстрее, чем стандартная JRE от Sun/Oracle. Используйте эту ссылку в случае сбоя предыдущей ссылки (главный хост-сервер иногда недоступен для обслуживания, как кажется сейчас) (предупреждение: загрузка 10 МБ), Архив также содержит отчет (который был представлен на второй конференции кандидатов SHA-3 в 2010 году), которая дает некоторые измеренные показатели эффективности на нескольких платформах, для SHA-2 и 14-й раунд "кандидатов на предстоящую SHA-3.

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

Ответ 2

Изменить: Я изначально прочитал вопрос как "самый быстрый алгоритм хеширования", и было выяснено, что это "самая быстрая реализация каждого алгоритма". Это правильный вопрос, а другие указывают на более быстрые реализации. Однако, если вы не будете хешировать большие объемы данных за короткий промежуток времени, это просто не очень важно. Я сомневаюсь, что обычно стоит времени и сложности использовать что-то иное, чем то, что предоставляется стандартным JCE.

Для URL-адресов вам нужно будет хешировать SHA-256, превышающую миллион в секунду на современном оборудовании, чтобы требовать чего-то быстрее. Я не могу представить, чтобы большинство приложений нуждались в более чем тысячах в секунду (более 86 миллионов в день), а это означает, что общее время хэширования процессора будет меньше 1%. Таким образом, даже если бы у вас был бесконечно быстрый алгоритм хэширования, вы могли бы улучшить производительность всего на 1% в лучшем случае.

Исходный ответ:. Как лучшие, так и самые быстрые друг от друга. Чем лучше хеши, тем медленнее. Если вам действительно нужна скорость, и безопасность не так важна, используйте MD5. Если вам нужна лучшая безопасность, переходите к SHA-256 или даже SHA-512. Вы не упомянули, что используете, потому что трудно рекомендовать тот или иной. Вероятно, вы, вероятно, будете в безопасности с SHA-256, так как это должно быть достаточно быстро для большинства случаев использования на современном оборудовании. Вот как вы можете это сделать:

String input = "your string";
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(input.getBytes("UTF-8"));
byte[] hash = digest.digest();

Если вы используете это для целей безопасности, например, для хэширования пароля, тогда вы должны добавить соль в дайджест. Если вы хотите, чтобы печатная строка вышла из хеша, вы можете закодировать ее обратно в строку как hex:

static char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();

StringBuilder sb = new StringBuilder(hash.length * 2);
for (byte b : hash) {
    sb.append(HEX_CHARS[(b & 0xF0) >> 4]);
    sb.append(HEX_CHARS[b & 0x0F]);
}
String hex = sb.toString();

Ответ 4

Еще одна вещь, которую следует учитывать, - использовать MD4. Он не так безопасен, как MD5, но вычисляется еще быстрее. Windows до XP используется для хранения и обмена паролями в MD4, поэтому мы используем этот хеш, поскольку он по-прежнему позволяет нам предоставлять услуги аутентификации для этой платформы.

Ответ 5

Для строки просто вызовите hashCode(), потому что дешевле в служебных данных памяти.

В противном случае я рекомендую этот код для частного хэша:

public static int hash8(String val) throws UnsupportedEncodingException {
    return hash8(val.getBytes("UTF-8"));
}

public static int hash8(byte[] val) {
    int h = 1, i = 0;
    for (; i + 7 < val.length; i += 8) {
        h = 31 * 31 * 31 * 31 * 31 * 31 * 31 * 31 * h + 31 * 31 * 31 * 31
                * 31 * 31 * 31 * val[i] + 31 * 31 * 31 * 31 * 31 * 31
                * val[i + 1] + 31 * 31 * 31 * 31 * 31 * val[i + 2] + 31
                * 31 * 31 * 31 * val[i + 3] + 31 * 31 * 31 * val[i + 4]
                + 31 * 31 * val[i + 5] + 31 * val[i + 6] + val[i + 7];
    }
    for (; i + 3 < val.length; i += 4) {
        h = 31 * 31 * 31 * 31 * h + 31 * 31 * 31 * val[i] + 31 * 31
                * val[i + 1] + 31 * val[i + 2] + val[i + 3];
    }
    for (; i < val.length; i++) {
        h = 31 * h + val[i];
    }
    return h;
}

FYI: http://lemire.me/blog/2015/10/22/faster-hashing-without-effort/