Как человек идет об изучении Java? (преобразуйте массив байтов для преобразовывания строки в шестнадцатеричную систему),

Я знаю, что это походит на широкий вопрос, но я могу сузить его с примером. Я являюсь ОЧЕНЬ новым в Java. Для одного из моего "приобретения знаний" проектов я хотел создать внутреннюю мясорубку файла MD5 для нас для использования. Я начался очень простой путем попытки хешировать строку и затем хождения дальше в файл позже. Я создал файл под названием MD5Hasher.java и записал следующее:

import java.security.*;
import java.io.*;
public class MD5Hasher{
    public static void main(String[] args){
        String myString = "Hello, World!";
        byte[] myBA = myString.getBytes();
        MessageDigest myMD;
        try{
            myMD = MessageDigest.getInstance("MD5");
            myMD.update(myBA);
            byte[] newBA = myMD.digest();
            String output = newBA.toString();
            System.out.println("The Answer Is: " + output);
        } catch(NoSuchAlgorithmException nsae){
            // print error here
        }
    }
}

Я посетил java.sun.com для просмотра javadocs для java.security, чтобы узнать, как использовать класс MessageDigest. После чтения я знал, что должен был использовать "getInstance" метод для получения, применимый MessageDigest возражают, что я мог использовать. Javadoc продолжил "Данные, обрабатывается через него с помощью методов обновления". Таким образом, я посмотрел на методы обновления и решил, что должен был использовать тот, где я подал его массив байтов моей строки, таким образом, я добавил ту часть. Javadoc продолжил, "После того как все данные, которые будут обновлены, были обновлены, один из методов создания дайджеста нужно назвать для завершения вычисления хеша". Я, снова, посмотрел на методы и видел, что обзор возвратил массив байтов, таким образом, я добавил ту часть. Затем я использовал "toString" метод на новом массиве байтов для получения строки, которую я мог распечатать. Однако то, когда я скомпилировал и выполнил код все, что распечатало, было этим:

Ответ: [B@4cb162d5

Я сделал некоторый взгляд здесь на StackOverflow и нашел некоторую информацию здесь:

Как я могу генерировать хеш MD5?

это дало следующий пример:

String plaintext = 'your text here';
MessageDigest m = MessageDigest.getInstance("MD5");
m.reset();
m.update(plaintext.getBytes());
byte[] digest = m.digest();
BigInteger bigInt = new BigInteger(1,digest);
String hashtext = bigInt.toString(16);
// Now we need to zero pad it if you actually want the full 32 chars.
while(hashtext.length() < 32 ){
    hashtext = "0"+hashtext;
}

Кажется, что единственная первая часть МОЖЕТ отсутствовать, часть "BigInteger", но я не уверен.

Так, после того, как все это, я предполагаю то, что я спрашиваю, как Вы знаете для использования части "BigInteger"? Я неправильно предположил, что "toString" метод на моем объекте newBA преобразует его в читаемый вывод, но я был, по-видимому, неправильно. Как человек, как предполагается, знает который способ войти в Java? У меня есть знания в C, таким образом, эта вещь Java кажется довольно странной. Совет относительно того, как я могу поправиться, не имея необходимость "обманывать" путем поиска с помощью Google, как сделать что-то все время?

Спасибо всем за то, что заняли время для чтения.:-)

5
задан Community 23 May 2017 в 11:55
поделиться

10 ответов

Вы действительно успешно переварили сообщение. Вы просто не знаете, как правильно представить найденное значение дайджеста. У вас есть массив байтов. Это немного сложно для чтения, а toString массива байтов дает [B@somewhere, что совсем не полезно.

BigInteger вступает в дело как инструмент для форматирования массива байтов в одно число.

Что вы делаете:

  • создаете BigInteger с нужным значением (в данном случае это значение закодировано в виде массива байтов - ваш дайджест
  • инструктируете объект BigInteger вернуть строковое представление (например, простой, читаемый текст) этого числа, основание 16 (например, hex)

И в цикле while префиксируете это значение 0-символами, чтобы получить ширину 32. Я бы, наверное, использовал для этого String.format, но как хотите, так и делайте.)

2
ответ дан 18 December 2019 в 13:10
поделиться

Ключевым моментом в данном конкретном случае является то, что вы должны понимать, что байты не «читаются человеком», а символы - доступны. Значит, вам нужно преобразовать байты в символы определенного формата. Для произвольных байтов, таких как хэши, обычно используется шестнадцатеричный формат в качестве "удобочитаемого" формата. Затем каждый байт должен быть преобразован в двухсимвольную шестнадцатеричную строку, которую вы, в свою очередь, объедините вместе.

Это не связано с языком, который вы используете. Вам просто нужно понять / осознать, как это работает «под капотом» вне зависимости от языка. Вы должны понимать, что у вас есть (массив байтов) и что вы хотите (шестнадцатеричная строка). Язык программирования - это всего лишь инструмент для достижения желаемого результата. Вы просто Google "функциональное требование" вместе с языком программирования, который вы хотите использовать для выполнения требования. Например. « преобразовать массив байтов в шестнадцатеричную строку в java ».


Тем не менее, найденный вами пример кода неверен.Фактически вы должны определить каждый байт внутри цикла и проверить, меньше ли он 0x10 , а затем заполнить его нулем вместо того, чтобы заполнять только ноль в зависимости от длины результирующей строки (( что не обязательно может быть вызвано тем, что первый байт меньше 0x10 !).

StringBuilder hex = new StringBuilder(bytes.length * 2);
for (byte b : bytes) {
    if ((b & 0xff) < 0x10) hex.append("0");
    hex.append(Integer.toHexString(b & 0xff));
}
String hexString = hex.toString();

Обновление согласно комментариям к ответу @extraneon , использование new BigInteger (byte []) также является неправильным решением. Это не отменяет подписи байтов. Байты (как и все примитивные числа) в Java подписаны. У них отрицательный диапазон. Байт в Java варьируется от -128 до 127 , в то время как вы хотите иметь диапазон от 0 до 255 . ], чтобы получить правильную шестнадцатеричную строку. Вам просто нужно удалить знак, чтобы сделать их неподписанными. & 0xff в приведенном выше примере делает именно это.

Шестнадцатеричная строка, полученная из new BigInteger (bytes) .toString (16) , НЕ совместима с результатом всех других шестнадцатеричных генераторов MD5, о которых известно миру. Они будут отличаться, если в дайджесте MD5 будет отрицательный байт.

6
ответ дан 18 December 2019 в 13:10
поделиться

Хотя я боюсь, что у меня нет опыта использования Java для работы с хэшами MD5, я могу порекомендовать Sun's Java Tutorials как фантастический ресурс для изучения Java. Они охватывают большую часть языка и очень помогли мне, когда я изучал Java.

Также поищите другие сообщения с аналогичным вопросом и посмотрите, какие предложения там появляются.

1
ответ дан 18 December 2019 в 13:10
поделиться

Я также новичок в разработке. Для решения текущей проблемы я предлагаю книгу « Введение в криптографию с Java-апплетами » Дэвида Бишопа . Он демонстрирует, что вам нужно, и так далее ...

0
ответ дан 18 December 2019 в 13:10
поделиться

MessageDigest вычисляет байтовый массив чего-либо, строка, которую вы обычно видите (например, 1f3870be274f6c49b3e31a0c6728957f), на самом деле является просто преобразованием байтового массива в шестнадцатеричную строку.

Когда вы вызываете MessageDigest.toString(), он вызывает MessageDigest.digest().toString(), а в Java метод toString для byte[] (возвращенный MessageDigest.digest()) возвращает своего рода ссылку на байты, а не сами байты.

В коде, который вы опубликовали, массив байтов изменяется на целое число (в данном случае BigInteger, потому что оно будет очень большим), а затем преобразуется в шестнадцатеричное, чтобы быть выведенным в строку.

Массив байтов, вычисленный дайджестом, представляет собой число (128-битное число согласно http://en.wikipedia.org/wiki/MD5), и это число может быть преобразовано в любое другое основание, так что результат MD5 может быть представлен как число base-10, base-2 (как в массиве байтов) или, что наиболее распространено, как число base-16.

2
ответ дан 18 December 2019 в 13:10
поделиться

Причина использования BigInteger в том, что массив байтов очень длинный, слишком большой, чтобы поместиться в int или long. Однако, если вы хотите видеть все в байтовом массиве, есть альтернативный подход. Вы можете просто заменить строку:

String output = newBA.toString();

на:

String output = Arrays.toString(newBA);

Это выведет содержимое массива, а не адрес ссылки.

1
ответ дан 18 December 2019 в 13:10
поделиться

Использовать IDE, которая показывает, откуда берется метод "toString()". В большинстве случаев он берется из класса Object и не будет очень полезен. Обычно рекомендуется перезаписывать метод toString, чтобы обеспечить чистый вывод, но многие классы этого не делают.

0
ответ дан 18 December 2019 в 13:10
поделиться

Любые советы, как мне поправиться без "обмана" в Google как делать что-то все время?

Не начинайте с хешера MD5! Серьезно, постепенно повышайте свой уровень в программах, которые можно выполнять, не беспокоясь о предметах, относящихся к предметной области, таких как MD5.

Если вы все бросаете в main, вы не программируете Java.

В программе такого масштаба ваш main () должен делать одно: создавать объект MD5Hasher, а затем вызывать для него некоторые методы. У вас должен быть конструктор, который принимает начальную строку, метод для «выполнения работы» (обновление, дайджест) и метод для печати результата.

Получите несколько учебных пособий и потратьте время на простые традиционные упражнения (генератор Фибоначчи, программа для решения некоторой логической головоломки), чтобы вы поняли основы языка, прежде чем возиться с библиотеками, с которыми вы сейчас боретесь. Затем вы можете начать делать полезные вещи.

0
ответ дан 18 December 2019 в 13:10
поделиться

Откуда человеку знать, какой способ пойти на Java? У меня есть предыстория в C, так что эта вещь Java кажется красивой странный. Любые советы о том, как я могу получить лучше без "обмана" Погуглить, как что-то сделать все время?

Очевидные ответы: 1 - гуглить, когда у вас есть вопросы (и это не считается обманом, imo) и 2 - читать книги по предмету.

Помимо этих двоих, я бы порекомендовал найти себе наставника. Если у вас нет опытных Java-разработчиков на работе, попробуйте присоединиться к местной группе пользователей Java-разработчиков. Там вы можете найти более опытных разработчиков и, возможно, потрудиться, чтобы получить ответы на свои вопросы.

0
ответ дан 18 December 2019 в 13:10
поделиться

Я ошибочно полагал, что метод "toString" на моем объекте newBA преобразует его в удобочитаемый вывод, но, видимо, я ошибался. Как человек должен знать, в какую сторону двигаться в Java?

Вы могли бы заменить здесь Java на выбранный вами язык, который вы не знаете/не освоили. Даже если вы проработали 10 лет на определенном языке, вам все равно будут попадаться такие "Ага! Вот как это работает! "-эффекты, хотя и не так часто, как в начале.

Здесь вам нужно усвоить, что toString() возвращает не то представление, которое вы хотите/ожидаете, а то, которое выбрал исполнитель. Стандартная реализация toString() выглядит следующим образом (javadoc):

Возвращает строковое представление объекта. В общем случае метод toString возвращает строку, которая "текстуально представляет" данный объект. Результат должен быть кратким, но информативным представлением, которое легко читается человеком. Рекомендуется, чтобы все подклассы переопределяли этот метод.

Метод toString для класса Object возвращает строку, состоящую из имени класса, экземпляром которого является объект, символа at-sign `@' и беззнакового шестнадцатеричного представления хэш-кода объекта. Другими словами, этот метод возвращает строку, равную значению:

getClass().getName() + '@' + Integer.toHexString(hashCode())

0
ответ дан 18 December 2019 в 13:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: