Строка Java для SHA1
Я пытаюсь сделать простой конвертер строки в SHA1 в Java, и это то, что у меня есть...
public static String toSHA1(byte[] convertme) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-1");
}
catch(NoSuchAlgorithmException e) {
e.printStackTrace();
}
return new String(md.digest(convertme));
}
Когда я toSHA1("password".getBytes())
его toSHA1("password".getBytes())
, я получаю [ a ɹ?? %l 3~ .
Я знаю, что это, вероятно, простое исправление кодировки, такое как UTF-8, но кто-то может сказать мне, что я должен сделать, чтобы получить то, что я хочу, 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
? Или я делаю это совершенно неправильно?
Ответы
Ответ 1
UPDATE
Вы можете использовать Apache Commons Codec (версия 1.7+), чтобы выполнить эту работу для вас.
DigestUtils.sha1Hex (stringToConvertToSHexRepresentation)
Спасибо @Jon Onstott за это предложение.
Старый ответ
Преобразуйте байт-массив в шестнадцатеричную строку. Реальный способ подсказки.
return byteArrayToHexString(md.digest(convertme))
и (скопировано из Real How To)
public static String byteArrayToHexString(byte[] b) {
String result = "";
for (int i=0; i < b.length; i++) {
result +=
Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
}
return result;
}
Кстати, вы можете получить более компактное представление с помощью Base64. Apache Commons Codec API 1.4, эта приятная утилита устраняет всю боль. см. здесь
Ответ 2
Это мое решение преобразования строки в sha1. Он хорошо работает в моем приложении для Android:
private static String encryptPassword(String password)
{
String sha1 = "";
try
{
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(password.getBytes("UTF-8"));
sha1 = byteToHex(crypt.digest());
}
catch(NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch(UnsupportedEncodingException e)
{
e.printStackTrace();
}
return sha1;
}
private static String byteToHex(final byte[] hash)
{
Formatter formatter = new Formatter();
for (byte b : hash)
{
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
Ответ 3
Использование класса Guava Hashing:
Hashing.sha1().hashString( "password", Charsets.UTF_8 ).toString()
Ответ 4
SHA-1 (и все остальные алгоритмы хэширования) возвращают двоичные данные. Это означает, что (на Java) они создают byte[]
. В этом массиве byte
не отображаются любые конкретные символы, а это означает, что вы не можете просто превратить его в String
, как вы.
Если вам нужен String
, вам нужно отформатировать этот byte[]
таким образом, который может быть представлен как String
(в противном случае просто поддерживайте byte[]
).
Двумя распространенными способами представления произвольных byte[]
в качестве печатных символов являются BASE64 или простые шестнадцатеричные строки (т.е. представляющие каждый byte
двумя шестнадцатеричными цифрами). Похоже, вы пытаетесь создать шестнадцатеричную строку.
Там также есть другая ошибка: если вы хотите получить SHA-1 Java String
, тогда вам нужно сначала преобразовать этот String
в byte[]
(так как ввод SHA-1 - это byte[]
). Если вы просто используете myString.getBytes()
, как вы показали, то он будет использовать кодировку по умолчанию для платформы и, как таковая, будет зависеть от среды, в которой вы ее запускаете (например, он может возвращать разные данные на основе языкового/локального значения вашей ОС).
Лучшим решением является определение кодировки для преобразования String
-to- byte[]
следующим образом: myString.getBytes("UTF-8")
. Выбор UTF-8 (или другого кодирования, который может представлять каждый символ Юникода) является самым безопасным выбором здесь.
Ответ 5
Просто используйте библиотеку кодеков apache commons. У них есть класс утилиты под названием DigestUtils
Не нужно вдаваться в подробности.
Ответ 6
Это простое решение, которое можно использовать при преобразовании строки в шестнадцатеричный формат:
private static String encryptPassword(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(password.getBytes("UTF-8"));
return new BigInteger(1, crypt.digest()).toString(16);
}
Ответ 7
Как упоминалось ранее, используйте кодек apache commons. Рекомендуется также ребятам Spring (см. DigestUtils в документе Spring doc). Например:.
DigestUtils.sha1Hex(b);
Определенно не использовал бы здесь наивысший рейтинг.
Ответ 8
Он не печатает правильно, потому что вам нужно использовать кодировку Base64. С помощью Java 8 вы можете кодировать, используя Base64 класс кодировщика.
public static String toSHA1(byte[] convertme) {
md = MessageDigest.getInstance("SHA-1");
return Base64.getEncoder().encodeToString((md.digest(convertme));
}
Результат
Это даст вам ожидаемый результат 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
Ответ 9
База 64 Представление SHA1
Hash:
String hashedVal = Base64.getEncoder().encodeToString(DigestUtils.sha1(stringValue.getBytes(Charset.forName("UTF-8"))));
Ответ 10
Причина, по которой это не работает, заключается в том, что при вызове String(md.digest(convertme))
вы говорите Java, чтобы интерпретировать последовательность зашифрованных байтов как строку. Вы хотите преобразовать байты в шестнадцатеричные символы.
Ответ 11
Дайджест сообщения (хеш) - это байт [] в байте [] из
Дайджест сообщения определяется как функция, которая принимает необработанный байтовый массив и возвращает необработанный байтовый массив (он же byte[]
). Например, SHA-1 (Secure Hash Algorithm 1) имеет размер дайджеста 160 бит или 20 байт. Необработанные байтовые массивы обычно не могут быть интерпретированы как кодировки символов, такие как UTF-8, потому что не каждый байт в каждом порядке является законным кодированием. Таким образом, преобразование их в String
с помощью:
new String(md.digest(subject), StandardCharsets.UTF_8)
может создавать недопустимые последовательности или иметь указатели на неопределенные отображения Unicode:
[�a�ɹ??�%l�3~��.
Двоичное в текстовое кодирование
Для этого используется двоичное кодирование текста. Для хэшей чаще всего используется HEX-кодировка или Base16. По существу, байт может иметь значение от 0
до 255
(или -128
до 127
-128
), что эквивалентно шестнадцатеричному представлению 0x00
- 0xFF
. Таким образом, шестнадцатеричный код удвоит требуемую длину выходных данных, а это означает, что 20-байтовый вывод создаст шестнадцатеричную строку длиной 40 символов, например
2fd4e1c67a2d28fced849ee1bb76e7391b93eb12
Обратите внимание, что не обязательно использовать шестнадцатеричное кодирование. Вы также можете использовать что-то вроде base64. Шестнадцатеричный кодекс часто предпочтителен, потому что он легче читается людьми и имеет определенную выходную длину без необходимости заполнения.
Вы можете преобразовать байтовый массив в шестнадцатеричный код только с помощью функции JDK:
new BigInteger(1, token).toString(16)
Однако обратите внимание, что BigInteger
будет интерпретировать данный байтовый массив как число, а не как байтовую строку. Это означает, что начальные нули не будут выводиться, а результирующая строка может быть короче 40 символов.
Использование библиотек для кодирования в HEX
Теперь вы можете скопировать и вставить непроверенный байтовый метод из Stack Overflow или использовать огромные зависимости, такие как Guava.
Чтобы получить решение для большинства проблем, связанных с байтами, я реализовал утилиту для обработки этих случаев: bytes-java (Github)
Чтобы преобразовать байтовый массив вашего сообщения, вы можете просто сделать
String hex = Bytes.wrap(md.digest(subject)).encodeHex();
или вы можете просто использовать встроенную функцию хеширования
String hex = Bytes.from(subject).hashSha1().encodeHex();
Ответ 12
Преобразование байтового массива в шестнадцатеричную строку.
public static String toSHA1(byte[] convertme) {
final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-1");
}
catch(NoSuchAlgorithmException e) {
e.printStackTrace();
}
byte[] buf = md.digest(convertme);
char[] chars = new char[2 * buf.length];
for (int i = 0; i < buf.length; ++i) {
chars[2 * i] = HEX_CHARS[(buf[i] & 0xF0) >>> 4];
chars[2 * i + 1] = HEX_CHARS[buf[i] & 0x0F];
}
return new String(chars);
}