Строка 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);
}