Алгоритм Java MessageDigest SHA1 возвращает другой результат, чем SHA1-функция php - PullRequest
11 голосов
/ 30 сентября 2011

У меня есть таблица SQL с именами пользователей и паролями.Пароли кодируются с использованием метода digest () MessageDigest.Если я кодирую пароль - скажем, «abcdef12» - с помощью метода MessageDigest digest (), а затем преобразую его в шестнадцатеричные значения, строка отличается от того, что я делаю, используя PHP-метод SHA1.Однако я ожидаю, что эти значения будут точно такими же.

Код, который используется для кодирования паролей:

MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] passbyte;
passbyte = "abcdef12".getBytes("UTF-8");
passbyte = md.digest(passbyte);

Преобразование строки в шестнадцатеричное выполняется с помощью этого метода:

public static String convertStringToHex(String str) {

    char[] chars = str.toCharArray();

    StringBuffer hex = new StringBuffer();
    for (int i = 0; i < chars.length; i++) {
        hex.append(Integer.toHexString((int) chars[i]));
    }

    return hex.toString();
}

Пароль: abcdef12

Вот пароль, возвращаемый многими онлайн-генераторами SHA1-хешей и PHP SHA1 () - функция: d253e3bd69ce1e7ce6074345fd5faa1a3c2e89

Вот пароль, закодированный MessageDigest: d253e3bd69ce1e7ce674345fd5faa1a3c2e2030ef

Я что-то забыл?

Игорь.

Редактировать: Я нашел кого-то с похожей проблемой: C # SHA-1 против PHP SHA-1 ... Различные результаты? .Решением было изменить кодировки ... но я не могу изменить кодировки на стороне сервера, поскольку пароли в этой SQL-таблице не создаются моим приложением.Я использую SHA1-кодирование на стороне клиента с использованием SHA1-класса JavaScript (точнее: Google Web Toolkit-class).Он работает и кодирует строку, как и ожидалось, но, видимо, с использованием символов ASCII? ..

Ответы [ 4 ]

6 голосов
/ 30 сентября 2011

У меня тот же дайджест, что и у PHP с моей функцией хеширования Java SHA-1:

public static String computeSha1OfString(final String message) 
    throws UnsupportedOperationException, NullPointerException {
        try {
               return computeSha1OfByteArray(message.getBytes(("UTF-8")));
        } catch (UnsupportedEncodingException ex) {
                throw new UnsupportedOperationException(ex);
        }
}

private static String computeSha1OfByteArray(final byte[] message)
    throws UnsupportedOperationException {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(message);
            byte[] res = md.digest();
            return toHexString(res);
        } catch (NoSuchAlgorithmException ex) {
            throw new UnsupportedOperationException(ex);
        }
}

Я добавил в свои модульные тесты:

String sha1Hash = StringHelper.computeSha1OfString("abcdef12");
assertEquals("d253e3bd69ce1e7ce6074345fd5faa1a3c2e89ef", sha1Hash);

Полный исходный код длякласс на github .

4 голосов
/ 27 декабря 2013

Попробуйте - у меня это работает:

MessageDigest md = MessageDigest.getInstance(algorithm);
md.update(original.getBytes());
byte[] digest = md.digest();
StringBuffer sb = new StringBuffer();
for (byte b : digest) {
    sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();

С уважением, Konki

4 голосов
/ 30 сентября 2011

Это не имеет ничего общего с кодировками. Вывод будет совсем другим.

Для начала ваша функция convertStringToHex() не выводит начальные нули, то есть 07 становится просто 7.

Остальное (изменение 89 на 2030) также, вероятно, связано с этой функцией. Попробуйте посмотреть значение passbyte после passbyte = md.digest(passbyte);.

2 голосов
/ 26 августа 2015

Или попробуйте это:

MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(clearPassword.getBytes("UTF-8"));
return new BigInteger(1 ,md.digest()).toString(16));

Приветствия Рой

...