Как хешировать строку с помощью sha256 в Java?

Как я могу хешировать строку с sha256 в Java? Кто-нибудь знает какую-нибудь бесплатную библиотеку для этого?


person Ivana    schedule 03.04.2011    source источник
comment
возможный дубликат хеш-строки через SHA-256 в Java   -  person mmmmmm    schedule 11.08.2014
comment
baeldung.com/sha-256-hashing-java   -  person Barett    schedule 01.04.2020


Ответы (15)


SHA-256 - это не «кодировка» - это односторонний хэш.

Вы в основном преобразовываете строку в байты (например, используя text.getBytes(StandardCharsets.UTF_8)), а затем хешируете байты. Обратите внимание, что результатом хеширования также будут произвольные двоичные данные, и если вы хотите представить это в строке, вы должны использовать base64 или шестнадцатеричный ... не попробуйте использовать конструктор String(byte[], String).

e.g.

MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));
person Jon Skeet    schedule 03.04.2011
comment
SHA-256 не является кодировкой, но я должен сказать, что предпочитаю заголовок текущего вопроса, а не то, как зашифровать с помощью sha (многие, кажется, думают, что это шифрование). Возможно, нам следует рассматривать это как кодировку, а не как-то связанное с криптографией, потому что на практике это ближе к тому, как она используется. - person Luc; 10.06.2014
comment
@Luc: Ну, это криптографический хеш, поэтому я не думаю, что было бы необоснованно говорить, что он имеет какое-то отношение к криптографии ... шифрование и криптография не взаимозаменяемы ... - person Jon Skeet; 10.06.2014
comment
Примечание. Рекомендуется использовать StandardCharsets.UTF_8 вместо литерала "UTF-8" в Java 7+: на одно проверенное исключение меньше поводов для беспокойства. - person kryger; 02.12.2015
comment
@kryger: Согласовано, отредактировано. О радостях ответов до выхода Java 7 ... - person Jon Skeet; 02.12.2015
comment
Почему вам следует избегать конструктора String (byte [], String) при работе с результатом хеширования? - person Isaac van Bakel; 18.04.2016
comment
@IsaacvanBakel: Потому что хеш не закодирован для текста. Это произвольные двоичные данные. - person Jon Skeet; 18.04.2016
comment
Правильный способ назвать это должно заключаться в том, как я хеширую текст с помощью SHA 256, потому что, наконец, то, что у вас есть, является результатом применения алгоритма хеширования, вы НЕ шифруете текст, так как вы не можете его расшифровать - person Carlos de Luna Saenz; 27.02.2018
comment
@IsaacvanBakel: хэш обычно является результатом преобразования из исходной строки - и это преобразование является односторонним, подгоняя результат в указанное количество битов и воспроизводимо (один и тот же ввод дает одинаковый результат). Представьте себе синусоидальную форму волны - вы выбираете точку на оси X и получаете ее высоту по оси Y. Y - это хэш, этот X всегда дает это Y. Но многие X делают это, поэтому Y = ›X. Кодирование (и / или сжатие без потерь) - это обратимое преобразование - там вы можете получить входную строку путем обработки выходных данных, и она может быть или нет воспроизводимой (есть много способов правильно написать даже base64). - person Jim Klimov; 08.12.2020

Я думаю, что самое простое решение - использовать Общий кодек Apache:

String sha256hex = org.apache.commons.codec.digest.DigestUtils.sha256Hex(stringText);   
person seba    schedule 13.07.2013
comment
Лучший ответ, простой в использовании, чистый. Спасибо! - person fl0w; 16.01.2020

Другой альтернативой является Guava, который имеет простой в использовании набор Хеширование утилит. Например, для хеширования строки с использованием SHA256 в качестве шестнадцатеричной строки вы просто выполните:

final String hashed = Hashing.sha256()
        .hashString("your input", StandardCharsets.UTF_8)
        .toString();
person Jonathan    schedule 20.08.2013

Полный пример хеша для преобразования в другую строку.

public static String sha256(final String base) {
    try{
        final MessageDigest digest = MessageDigest.getInstance("SHA-256");
        final byte[] hash = digest.digest(base.getBytes("UTF-8"));
        final StringBuilder hexString = new StringBuilder();
        for (int i = 0; i < hash.length; i++) {
            final String hex = Integer.toHexString(0xff & hash[i]);
            if(hex.length() == 1) 
              hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString();
    } catch(Exception ex){
       throw new RuntimeException(ex);
    }
}
person user1452273    schedule 13.06.2012
comment
Чтобы закодировать результаты Джона в шестнадцатеричном формате, рассмотрите возможность использования существующей библиотеки, например apache commons вместо того, чтобы создавать собственные. - person Leigh; 14.06.2012
comment
Почему StringBuffer? (не stringBuilder)? и, может быть, было бы лучше установить размер конструктора строк по умолчанию? - person Bogdan; 09.10.2013
comment
@Leigh: некоторые люди не хотят добавлять целую зависимость lib только потому, что им нужна одна ее функция, поэтому иногда неплохо было бы использовать собственную. - person Chris; 04.09.2014
comment
@Chris - Верно. Вот почему я сказал рассмотреть возможность его использования ;-) Существующие библиотеки могут увеличить объем. С другой стороны, они обычно более проверены, чем домашний спан-код, и, конечно же, экономят время. Но не существует универсального ответа для всех. - person Leigh; 13.09.2014
comment
Вы также можете прочитать исходный код из библиотеки и скопировать его код! - person Olav Grønås Gjerde; 10.05.2016
comment
вы спасаете мне жизнь .. Я хочу преобразовать хеш-функцию php $ key = hash ('sha256', '1234567890'); в android это дает мне точный результат .. Большое вам спасибо - person shubomb; 12.02.2020
comment
Однако есть ли причина, по которой он может выйти из строя и вызвать исключение (или иметь дайджест, равный нулю)? - person android developer; 14.03.2021

Если вы используете Java 8, вы можете закодировать byte[], выполнив

MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));
String encoded = Base64.getEncoder().encodeToString(hash);
person Eduardo Dennis    schedule 08.04.2017
comment
Мне этот способ удобен. Однако вы должны использовать следующий код Base64.encodeToString (hash, Base64.DEFAULT); - person Motassem Jalal; 27.06.2017
comment
@MotassemJalal Base64.DEFAULT недоступен в последней версии Java8, в настоящее время я использую jdk1.8.0_144. Не могли бы вы рассказать мне, как вы его создали? - person rajadilipkolli; 01.12.2017
comment
@rajadilipkolli Я думаю, что это реализация Android: developer.android.com/reference/android/util / Base64 - person dbm; 11.06.2018
comment
Почему-то я получаю от этого неправильный результат. Пример: для ввода теста я получил n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg= вместо 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08. Как придешь? - person android developer; 14.03.2021

Я проследил код Apache через DigestUtils, и sha256, похоже, по умолчанию возвращается к java.security.MessageDigest для расчета. Apache не реализует независимое sha256 решение. Я искал независимую реализацию для сравнения с библиотекой java.security. Только к сведению.

person garyn    schedule 05.11.2015

Вот несколько более эффективный способ превратить дайджест в шестнадцатеричную строку:

private static final char[] hexArray = "0123456789abcdef".toCharArray();

public static String getSHA256(String data) {
    StringBuilder sb = new StringBuilder();
    try {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(data.getBytes());
        byte[] byteData = md.digest();
        sb.append(bytesToHex(byteData);
    } catch(Exception e) {
        e.printStackTrace();
    }
    return sb.toString();
}

private static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    for ( int j = 0; j < bytes.length; j++ ) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return String.valueOf(hexChars);
}

Кто-нибудь знает более быстрый способ на Java?

person andi    schedule 31.03.2018

Это был мой подход с использованием Kotlin:

private fun getHashFromEmailString(email : String) : String{
    val charset = Charsets.UTF_8
    val byteArray = email.toByteArray(charset)
    val digest = MessageDigest.getInstance("SHA-256")
    val hash = digest.digest(byteArray)

    return hash.fold("", { str, it -> str + "%02x".format(it)})
}
person Samuel Luís    schedule 12.03.2019
comment
Привет, я только что попробовал ваш код, потому что мне нужно хешировать пароль в Android Studio, и ваш код возвращает что-то вроде этого: [B@188363e, а не зашифрованный пароль. Кроме того, каждый раз, когда вызывается эта функция, кажется, что все меняется. - person Adrian2895; 31.10.2019
comment
Исправлено: вы забыли return hash.fold("", { str, it -> str + "%02x".format(it)}), который возвращает зашифрованный пароль, а не сам объект. - person Adrian2895; 31.10.2019
comment
да, вы правы, позвольте мне дополнить ответ вашим исправлением. Спасибо :) - person Samuel Luís; 31.10.2019

В Java 8

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Scanner;
import javax.xml.bind.DatatypeConverter;


Scanner scanner = new Scanner(System.in);
String password = scanner.nextLine();
scanner.close();

MessageDigest digest = null;
try {
    digest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
byte[] hash = digest.digest(password.getBytes(StandardCharsets.UTF_8));
String encoded = DatatypeConverter.printHexBinary(hash);        
System.out.println(encoded.toLowerCase());
person Mimu Saha Tishan    schedule 02.04.2020
comment
Почему у вас такая попытка / уловка? - person dragi; 21.08.2020

Вы можете использовать MessageDigest следующим образом:

public static String getSHA256(String data){
    StringBuffer sb = new StringBuffer();
    try{
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(data.getBytes());
        byte byteData[] = md.digest();

        for (int i = 0; i < byteData.length; i++) {
         sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
        }
    } catch(Exception e){
        e.printStackTrace();
    }
    return sb.toString();
}
person thatman    schedule 08.06.2017

Вот что я использовал для хеширования:

String pass = "password";

MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
byte hashBytes[] = messageDigest.digest(pass.getBytes(StandardCharsets.UTF_8));
BigInteger noHash = new BigInteger(1, hashBytes);
String hashStr = noHash.toString(16);

Выход: 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

person MrBitwise    schedule 16.06.2020

В Java для вычисления значения криптографического хеширования используется класс MessageDigest. Этот класс предоставляет криптографическую хеш-функцию (MD5, SHA-1 и SHA-256) для поиска хеш-значения текста.

Пример кода для использования алгоритма SHA-256.

public void printHash(String str) throws NoSuchAlgorithmException {

MessageDigest md=MessageDigest.getInstance("SHA-256");

byte[] sha256=md.digest(str.getBytes(StandardCharsets.UTF_8));

   for(byte b : sha256){

      System.out.printf("%02x",b);

  }
}
person Ravi    schedule 04.03.2020

Вот метод, который возвращает String:

public static String sha256(final String data) {
    try {
        final byte[] hash = MessageDigest.getInstance("SHA-256").digest(data.getBytes(StandardCharsets.UTF_8));
        final StringBuilder hashStr = new StringBuilder(hash.length);

        for (byte hashByte : hash)
            hashStr.append(Integer.toHexString(255 & hashByte));

        return hashStr.toString();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        return null;
    }
}
person YektaDev    schedule 01.05.2021

private static String getMessageDigest(String message, String algorithm) {
 MessageDigest digest;
 try {
  digest = MessageDigest.getInstance(algorithm);
  byte data[] = digest.digest(message.getBytes("UTF-8"));
  return convertByteArrayToHexString(data);
 } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 }
 return null;
}

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

getMessageDigest(message, "MD5");
getMessageDigest(message, "SHA-256");
getMessageDigest(message, "SHA-1");

Вы можете сослаться на это ссылка для полной заявки.

person Hari Krishna    schedule 12.12.2019

person    schedule
comment
В чем смысл побитового & - байтового значения с 0xff? Это ничего не дает, не так ли? - person yktoo; 27.01.2017
comment
@yktoo: преобразует его в положительное целое число (к сожалению, байты подписаны в Java) stackoverflow.com/questions/11380062/ - person leonbloy; 15.03.2017
comment
StringBuffer можно заменить на StringBuilder - person User8461; 23.06.2018