Java MessageDigest SHA1-алгоритм возвращает другой результат, чем SHA1-функция php
У меня есть таблица SQL с именами пользователей и паролями. Пароли кодируются с помощью метода MessageDigest digest(). Если я закодирую пароль - скажем, "abcdef12" - с помощью метода MessageDigest digest(), а затем преобразуйте его в шестнадцатеричные значения, строка будет отличаться, если я сделаю то же самое с использованием метода PHP SHA1. Я бы ожидал, что эти значения будут точно такими же.
Код, который используется для кодирования паролей:
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] passbyte;
passbyte = "abcdef12".getBytes("UTF-8");
passbyte = md.digest(passbyte);
Преобразование String в шестнадцатеричное выполняется с помощью этого метода:
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() - функция: d253e3bd69ce1e7ce6074345fd5faa1a3c2e89ef
Здесь пароль, закодированный MessageDigest: d253e3bd69ce1e7ce674345fd5faa1a3c2e2030ef
Я что-то забыл?
Игорь.
Изменить: я нашел кого-то с аналогичной проблемой: С# SHA-1 против PHP SHA-1... Различные результаты?. Решение заключалось в изменении кодировок.. но я не могу изменять кодировки на стороне сервера, так как пароли в этой SQL-таблице не созданы моим приложением.
Я использую клиентскую SHA1-кодировку с использованием JavaScript SHA1-класса (точнее: класс Google Web Toolkit). Он работает и кодирует строку, как ожидалось, но, видимо, используя символы ASCII?..
Ответы
Ответ 1
Это не имеет никакого отношения к кодировкам. Результат будет совершенно другим.
Для начала ваша функция convertStringToHex()
не выводит ведущие нули, то есть 07
становится просто 7
.
Остальные (изменение 89
до 2030
) также, вероятно, будут иметь какое-то отношение к этой функции. Попробуйте посмотреть значение passbyte
после passbyte = md.digest(passbyte);
.
Ответ 2
У меня есть тот же дайджест, что и 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.
Ответ 3
Попробуйте это - он работает для меня:
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
Или попробуйте следующее:
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(clearPassword.getBytes("UTF-8"));
return new BigInteger(1 ,md.digest()).toString(16));
Приветствия Роя