MessageDigest по-разному хэшируется на разных машинах - PullRequest
10 голосов
/ 20 июня 2010

У меня проблема с возвратом MessageDigest разных значений хеша на разных компьютерах.

Один компьютер работает под управлением 32-битной Java в Windows Vista, а другой - под управлением 64-битной Java в Mac OS.Я не уверен, что это потому, что MessageDigest зависит от машины, или мне нужно явно указать кодировку символов где-то, или, возможно, что-то еще.Вот код:

public static boolean authenticate(String salt, String encryptedPassword, 
    char[] plainTextPassword ) throws NoSuchAlgorithmException {

    // do I need to explcitly specify character encoding here? -->
    String saltPlusPlainTextPassword = salt + new String(plainTextPassword);

    MessageDigest sha = MessageDigest.getInstance("SHA-512");

    // is this machine dependent? -->
    sha.update(saltPlusPlainTextPassword.getBytes());
    byte[] hashedByteArray = sha.digest();

    // or... perhaps theres a translation problem here? -->
    String hashed = new String(hashedByteArray);

    return hashed.equals(encryptedPassword);
}

Должен ли этот код выполняться по-разному на этих двух разных машинах?Если это зависит от машины, как я написал, есть ли другой способ хэширования этих паролей, который является более переносимым?Спасибо!

Редактировать :::::

Этот код я использую для генерации солей:

public static String getSalt() {
   int size = 16;
   byte[] bytes = new byte[size];
   new Random().nextBytes(bytes);
   return org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString(bytes);
}

Solution :::

Благодаря принятому решению я смог исправить свой код:

public static boolean authenticate_(String salt, String encryptedPassword, 
        char[] plainTextPassword ) throws NoSuchAlgorithmException, UnsupportedEncodingException {

        // This was ok
        String saltPlusPlainTextPassword = salt + new String(plainTextPassword);    

        MessageDigest sha = MessageDigest.getInstance("SHA-512");

        // must specify "UTF-8" encoding
        sha.update(saltPlusPlainTextPassword.getBytes("UTF-8"));
        byte[] hashedByteArray = sha.digest();

        // Use Base64 encoding here -->
        String hashed = org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString(hashedByteArray);

        return hashed.equals(encryptedPassword);
    }

Ответы [ 2 ]

17 голосов
/ 20 июня 2010

Кодировки вызывают у вас проблемы. Сначала здесь:

saltPlusPlainTextPassword.getBytes()

Это будет использовать кодировку по умолчанию для машины . Плохая идея. Укажите «UTF-8» как простое решение. (Присутствие гарантировано.)

Далее это вызывает проблемы:

String hashed = new String(hashedByteArray);

hashedByteArray - произвольные двоичные данные. Чтобы безопасно преобразовать его в текст, используйте кодировку base-64 или просто шестнадцатеричный код. Опять же, вы в настоящее время используете кодировку по умолчанию, которая будет варьироваться от машины к машине. Существует множество сторонних библиотек для кодирования base64 в Java.

4 голосов
/ 20 июня 2010

Вероятно, приведенное выше решение Джона Скита является причиной, и его рекомендации обязательно должны быть приняты во внимание, но другой возможной причиной является неправильное понимание соли.

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

Значения соли обычно отличаются от установки к установке.Вполне возможно, что настоящая причина заключается в том, что значения соли установлены на разных машинах по-разному.

...