Я могу использовать Object#hashCode для хранения хеша пароля?

Чтобы сохранить файл, я определил следующий метод

public int encrypt(String fileName, String password) {
   return (fileName.concat(password)).hashCode();
}

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

Я предполагаю, что это не действительно безопасно, но насколько безопасный это? Как высоко шанс, что String#hashCode генерирует тот же хеш с двумя различными исходными данными?

Править:

Согласно Вашим ответам я изменил код:

public String encrypt(String password) {
        String hash = "";
        try {
            MessageDigest md5 = MessageDigest.getInstance("SHA-512");
            byte [] digest = md5.digest(password.getBytes("UTF-8"));
            hash = Arrays.toString(digest);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return hash;
    }

Таким образом, это должно быть лучше теперь??

8
задан 12 August 2010 в 08:33
поделиться

8 ответов

Это плохая идея - вы должны использовать обычный криптографический хеш, такой как SHA-1, как говорит NullUserException.

Однако он будет переносимым - в документации для String.hashCode () алгоритм явно указывается. Любая JRE, должным образом реализующая документы, должна выдавать один и тот же хэш-код. Однако из-за того, как работает алгоритм hashCode () , довольно легко найти строку, которая будет генерировать любой конкретный хэш-код - даже тот, который начинается с определенного префикса - поэтому злоумышленник, который знает хэш может очень легко атаковать ваше приложение. Криптографические хэши разработаны, чтобы затруднить разработку ключа, соответствующего конкретному хешу.

17
ответ дан 3 November 2019 в 13:08
поделиться

String.hashCode не подходит для хеширования паролей. Вместо этого вам понадобится криптографический хеш.

String.hashCode рассчитан на очень быстрое вычисление. Его основное использование - ключ в хеш-таблице. Для этого случая случайные столкновения не являются проблемой. Криптографические хэши вычисляются медленнее, но по определению никто не знает, как создавать коллизии для хорошей криптографии.

Что еще более важно, учитывая значение password.hashCode () , можно найти пароль (с высокой степенью уверенности, хотя и не с уверенностью, поскольку многие пароли имеют одинаковый хэш) . Это не то, чего вы когда-либо хотели. Криптографические хэши, с другой стороны, спроектированы таким образом, что невозможно найти пароль, зная хэш (математически говоря, никто не знает, как найти пароль из хеша в течение своей жизни).

Криптографические хэши доступны в стандартной библиотеке Java через java.security.MessageDigest .

ДОБАВЛЕНО : Есть еще одна сложность: напрямую хешировать пароль - плохая идея. Причина в том, что злоумышленник может попробовать все возможные пароли (например, слова из словаря, имена людей и т. Д.). Стандартное решение этой проблемы состоит в объединении пароля с случайной строкой, называемой salt ​​перед вычислением хэша: вы делаете что-то вроде sha.digest ((salt + password) .getBytes ()) . Из-за соли злоумышленник не может предварительно вычислить все хэши вероятных паролей.

Обычно соль генерируется случайным образом, когда пользователь выбирает свой пароль, и сохраняется рядом с хешем пароля в пользовательской базе данных, но судя по тому, что вы показываете в своей схеме, такого нет. Учитывая ваш дизайн, было бы разумно использовать имя файла в качестве соли: fileName.concat (encrypt (fileName + password)) .

5
ответ дан 3 November 2019 в 13:08
поделиться

Хешировать данные не так сложно, как вы думаете, и лучше использовать настоящий алгоритм хеширования. Если у вас есть массив байтов, содержащий пароль, вы можете просто сделать что-то вроде этого. Если вы получаете массив байтов из строки, не забудьте указать кодировку (например, UTF-8) при вызове getBytes ();

Вот простой пример с использованием MD5.

    try {
        MessageDigest md5 = MessageDigest.getInstance( "MD5" );

        byte [] digest = md5.digest( data );

        return digest;
    } catch( java.security.NoSuchAlgorithmException ex ) {
        // Insert error handling here.
    }
2
ответ дан 3 November 2019 в 13:08
поделиться

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

1
ответ дан 3 November 2019 в 13:08
поделиться

Вот реализация String.hashCode ():

s [0] * 31 ^ (n-1) + s [1] * 31 ^ (n-2) + ... + s [n-1]

Общедоступно здесь ...

Это фактически не зависит от виртуальной машины и не зависит от версии Java в прошлом. Реализация осталась прежней.

Защита от столкновений - это нормально, ИМХО, однако использовать ее в криптографических целях по очевидным причинам - плохая идея.

1
ответ дан 3 November 2019 в 13:08
поделиться

Проблема №1 в том, что хеш-код составляет всего 32 бита. это слишком коротко. ребенок с BASIC может сломать его за секунду.

md5 имеет длину 128 бит и сейчас считается слабым.

0
ответ дан 3 November 2019 в 13:08
поделиться

Обычно это плохая идея - полагаться на некриптографические функции для обеспечения безопасности. Поскольку вы никогда не можете быть уверены, какая реализация используется (и будет использоваться в будущем) для вычисления хэш-кода строки, вам следует предпочесть криптографически безопасный алгоритм хэш-кода. Я бы посоветовал использовать SHA-1 или SHA-256. http://www.bouncycastle.org/ имеет реализации для многих алгоритмов хэширования.

5
ответ дан 3 November 2019 в 13:08
поделиться

Честно говоря, я не знаю, насколько устойчив к столкновениям hashCode () Java. Если бы я угадал, я бы сказал, что не очень. Я тестировал его раньше и обнаружил пару коллизий после нескольких сотен тысяч входов.

Поскольку здесь вы имеете дело с паролями, вам действительно следует использовать криптографический хеш, например SHA1.

2
ответ дан 3 November 2019 в 13:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: