2010-07-13 2 views
5

Я знаю, что это звучит как широкий вопрос, но я могу сузить его на примере. Я ОЧЕНЬ новый на Java. Для одного из моих «обучающих» проектов я хотел создать собственный хэш-файл MD5 для использования нами. Я начал очень просто, пытаясь хешировать строку, а затем перейти к файлу позже. Я создал файл с именем MD5Hasher.java и написал следующее:Как человек изучает 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 продолжил: «Данные обрабатываются с помощью методов обновления». Поэтому я просмотрел методы обновления и решил, что мне нужно использовать тот, где я подал ему байтовый массив моей строки, поэтому я добавил эту часть. Далее Джавадок сказал: «Как только все данные, которые будут обновляться, будут обновлены, один из методов дайджеста должен быть вызван для завершения вычисления хэша». Я снова посмотрел на методы и увидел, что дайджест вернул массив байтов, поэтому я добавил эту часть. Затем я использовал метод «toString» для нового байтового массива, чтобы получить строку, которую я мог бы распечатать. Однако, когда я составил и побежал код все, что распечатаны было это:

Отвечаю: [B @ 4cb162d5

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

How can I generate an MD5 hash?

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

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; 
} 

Это кажется только часть I МАЙ будет отсутствовать часть «BigInteger», но я не уверен.

Итак, после всего этого, я думаю, что я спрашиваю, откуда вы знаете, как использовать часть «BigInteger»? Я ошибочно предположил, что метод toString для моего объекта newBA преобразует его в читаемый вывод, но я, по-видимому, ошибался. Как человек должен знать, куда идти на Java? У меня есть фон в C, поэтому эта вещь Java кажется довольно странной. Любые советы о том, как я могу стать лучше, не «обманывать» Googling, как делать что-то все время?

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

+1

трудный путь :) – Bozho

+2

Часть того, чтобы быть хорошим программистом, изучает, кто и что ваши ресурсы, и когда и как их использовать. Google - это ресурс, и нет никакого стыда в использовании и злоупотреблении им, чтобы сделать себя более опытным разработчиком. Другие ресурсы - ваши коллеги-разработчики и/или книги для самостоятельного обучения. – Jagd

+0

Возможный дубликат [Каковы наилучшие ресурсы для изучения Java (книги, веб-сайты и т. Д.)?] (Http://stackoverflow.com/questions/77839/what-are-the-best-resources-for-learning- java-books-websites-etc) – gnovice

ответ

2

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

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

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

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

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

+0

Очень круто ... спасибо. Я добавил следующие строки, и он выплюнул, что я искал: BigInteger newBI = новый BigInteger (newBA); String outupt = newBI.toString (16); – Brian

+0

@Brian: это тоже неправильное решение. Он вернет отрицательную (!!!) шестую строку, когда старший байт отрицательный. См. Мой ответ для правильного подхода преобразования hexstring. Вы также увидите, что некоторые пользователи могут предложить вместо этого использовать новый BigInteger (байты) .abs(). ToString (16) ', но это также принципиально неправильно. С отрицательным ведущим байтом это приводит к неправильной hexstring, которая не конвертируется обратно в * те же * байты. И, следовательно, нельзя использовать кросс-общий/используемый с другими генераторами MD5, генерирующими шестую строку, о которых известно миру. – BalusC

+0

Я не уверен, в какой части я ошибаюсь. Я построил BigInteger с «BigInteger newBI = новый BigInteger (newBA)»; и затем я использовал toString (16), чтобы вернуть человеко-читаемую шестнадцатеричную строку. Где я сходил? – Brian

2

Это нормально Google за ответы до тех пор, как вы (в конце концов) понять, что вы копию вставили в приложение :-)

В общем, я рекомендую начать с хорошей Java вводной книгой, или веб-учебник. Смотрите эти темы больше советов:

+0

И причина для downvote ...? –

2

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

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

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

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

0

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

+0

О да ... Я использую NetBeans. Мне было полезно помогать мне, насколько я могу. – Brian

1

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

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

1

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

String output = newBA.toString(); 

с:

String output = Arrays.toString(newBA); 

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

+0

«Строковый вывод = Arrays.toString (newBA)» - не очень полезно. Он отображает содержимое массива в виде ряда байтовых значений, например. «[-33, 1, 93, -104, ...» вместо DF015D98 ... –

+0

@ Джейсон: Вы правы, в этом конкретном приложении 'Arrays.toString()' не обеспечивает лучшего представления. Я оставлю свой ответ, потому что он * полезен для большинства случаев печати массивов. –

6

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

Это не относится к используемому вами языку. Вам просто нужно понять/понять, как это работает «под капотами» в языке агностическим способом. Вы должны понять, что у вас есть (массив байтов) и что вы хотите (шестнадцатеричная строка). Язык программирования - это всего лишь инструмент для достижения желаемого результата. Вы просто рекламируете «функциональное требование» вместе с языком программирования, который вы хотели бы использовать для достижения этого требования. Например. "convert byte array to hex string in 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(); 

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

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

0

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

Здесь вы можете заменить Java языком, который вы еще не знаете/еще не освоили. Даже если вы проработали 10 лет на определенном языке, вы все равно получите «Aha! Это так, как он работает!» «Эффекты, хотя и не так часто, как в начале.

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

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

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

GetClass() GetName() + '@' + Integer.toHexString (хэш-код())

0

Я также новичок в разработке. Для текущей проблемы я предлагаю книгу «Введение в криптографию с апплетами Java» by David Bishop. Это демонстрирует то, что вам нужно, и так далее ...

0

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

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

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

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

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

0

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

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

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

Смежные вопросы