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

962

Есть ли какой-нибудь метод для генерации хэша MD5 строки в Java?

  • 2
    stackoverflow.com/questions/304268/...
  • 37
    MD5 может быть небезопасным в качестве односторонней функции безопасности, но он все еще хорош для универсальных приложений с контрольной суммой.
Теги:
hash
hashcode
md5

32 ответа

557
Лучший ответ

java.security.MessageDigest ваш друг. Вызовите getInstance("MD5") чтобы получить дайджест сообщения MD5, который вы можете использовать.

  • 127
    Одна вещь, которая здесь не упоминается, и застала меня врасплох. Классы MessageDigest НЕ являются потокобезопасными. Если они будут использоваться разными потоками, просто создайте новый, а не пытайтесь использовать их повторно.
  • 34
    Он использует несколько методов для изменения своего внутреннего состояния. Как может удивить отсутствие безопасности потоков?
Показать ещё 7 комментариев
687

Класс MessageDigest может предоставить вам экземпляр дайджеста MD5.

При работе со строками и криптографическими классами обязательно всегда укажите кодировку, в которую вы хотите включить представление байта. Если вы просто используете string.getBytes(), он будет использовать платформу по умолчанию. (Не все платформы используют одинаковые значения по умолчанию)

import java.security.*;

..

byte[] bytesOfMessage = yourString.getBytes("UTF-8");

MessageDigest md = MessageDigest.getInstance("MD5");
byte[] thedigest = md.digest(bytesOfMessage);

Если у вас много данных, посмотрите на метод .update(byte[]), который можно вызывать повторно. Затем вызовите .digest(), чтобы получить полученный хэш.

  • 0
    «LATIN1»! = «ASCII» (или «US-ASCII»). ASCII - это 7-битный набор символов, Latin1 - это 8-битный набор символов. Они не то же самое.
  • 7
    (см. joelonsoftware.com/articles/Unicode.html для лучшего объяснения и объяснения)
Показать ещё 7 комментариев
252

Вы также можете посмотреть DigestUtils класс apache commons codec, который предоставляет очень удобные методы для создания дайджестов MD5 или SHA.

  • 2
    В частности, методы, которые возвращают «безопасные» закодированные представления байтовых данных в виде строки.
  • 4
    Однако не существует простого способа вставить класс DigestUtils в ваш проект без добавления тонны библиотек или портирования класса «на руку», который требует как минимум еще двух классов.
Показать ещё 3 комментария
249

Если вы действительно хотите, чтобы ответ возвращался как строка, а не массив байтов, вы всегда можете сделать что-то вроде этого:

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;
}
  • 12
    @BalusC: Не верно, метод BigInteger.toString вернет полное число в указанной базе. 0x0606 будет напечатано как 606, только конечные нули опущены,
  • 11
    Незначительная мелочь: m.reset () не нужен сразу после вызова getInstance. Более незначительный: «ваш текст здесь» требует двойных кавычек.
158

Найдено следующее:

public String MD5(String md5) {
   try {
        java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
        byte[] array = md.digest(md5.getBytes());
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < array.length; ++i) {
          sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3));
       }
        return sb.toString();
    } catch (java.security.NoSuchAlgorithmException e) {
    }
    return null;
}

на сайте ниже, я не беру на себя ответственность за это, но это решение, которое работает! Для меня много другого кода не работало должным образом, я закончил отсутствовать 0s в хеше. Кажется, что это похоже на PHP. источник: http://m2tec.be/blog/2010/02/03/java-md5-hex-0093

  • 15
    Вы должны указать кодировку, которая будет использоваться в getBytes() , иначе ваш код получит разные результаты на разных платформах / пользовательских настройках.
  • 0
    @ PaŭloEbermann делает MessageDigest.getInstance ("MD5"); недостаточно? Я пытался добавить MD5 в getBytes (), но он вернул ошибку
Показать ещё 2 комментария
84

Вот как я его использую:

final MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.reset();
messageDigest.update(string.getBytes(Charset.forName("UTF8")));
final byte[] resultByte = messageDigest.digest();
final String result = new String(Hex.encodeHex(resultByte));

где Hex: org.apache.commons.codec.binary.Hex из проекта Apache Commons.

  • 13
    Если вы все равно используете кодек Apache Commons, вы можете использовать: commons.apache.org/codec/api-release/org/apache/commons/codec/…
  • 12
    Я бы заменил последнюю строку на это: String result = Hex.encodeHexString(resultByte);
76

Я только что загрузил commons-codec.jar и получил совершенный php, например md5. Вот руководство.

Просто импортируйте его в свой проект и используйте

String Url = "your_url";

System.out.println( DigestUtils.md5Hex( Url ) );

и там у вас есть.

  • 1
    Этот метод предоставляет то же возвращаемое значение, что и функция MySQL md5 (str). Многие другие ответы вернули другие значения.
  • 1
    Это не работает на Android, потому что Android включает в себя commons-codec 1.2, для которого вам нужен этот обходной путь: stackoverflow.com/a/9284092/2413303
61

Я нашел это наиболее понятным и сжатым способом:

MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(StandardCharsets.UTF_8.encode(string));
return String.format("%032x", new BigInteger(1, md5.digest()));
  • 1
    Отлично. Он не попадает в ловушку сокращения ведущих нулей.
  • 1
    Осторожно, это не сработает для Android, если вы используете API уровня <19, но вам просто нужно изменить вторую строку с помощью md5.update (string.getBytes ("UTF-8")); Это добавит еще одно проверенное исключение для обработки, хотя ...
31

Другая реализация:

import javax.xml.bind.DatatypeConverter;

String hash = DatatypeConverter.printHexBinary( 
           MessageDigest.getInstance("MD5").digest("SOMESTRING".getBytes("UTF-8")));
  • 2
    Я видел только одну строку, которая не использует внешнюю библиотеку.
  • 0
    Если я не ошибаюсь, это всегда возвращает в верхнем регистре, который не будет совпадать с md5, сделанным без использования hex. Даже не совсем уверен, что это настоящий MD5
Показать ещё 1 комментарий
31

Другой вариант - использовать методы Guava Hashing:

Hasher hasher = Hashing.md5().newHasher();
hasher.putString("my string");
byte[] md5 = hasher.hash().asBytes();

Удобно, если вы уже используете Guava (если это не так, вы, вероятно, должны быть).

  • 3
    или используя один из методов ярлыка: Hashing.md5().hashString("my string").asBytes();
  • 0
    Это работало отлично, потрясающе
Показать ещё 1 комментарий
31

Нашел это решение, которое намного проще с точки зрения получения строкового представления из хеша MD5.

import java.security.*;
import java.math.*;

public class MD5 {
    public static void main(String args[]) throws Exception{
        String s="This is a test";
        MessageDigest m=MessageDigest.getInstance("MD5");
        m.update(s.getBytes(),0,s.length());
        System.out.println("MD5: "+new BigInteger(1,m.digest()).toString(16));
    }
}

Код был извлечен из здесь.

  • 2
    Почему этот ответ равен -1, а другой, более короткий и менее описательный ответ имеет +146?
  • 4
    Хорошо использовать BigInteger, чтобы получить шестнадцатеричное значение +1
Показать ещё 4 комментария
26

У меня есть класс (хэш) для преобразования обычного текста в хэш в форматах: md5 или sha1, simillar, что php функции (md5, sha1):

public class Hash {
    /**
     * 
     * @param txt, text in plain format
     * @param hashType MD5 OR SHA1
     * @return hash in hashType 
     */
    public static String getHash(String txt, String hashType) {
        try {
                    java.security.MessageDigest md = java.security.MessageDigest.getInstance(hashType);
                    byte[] array = md.digest(txt.getBytes());
                    StringBuffer sb = new StringBuffer();
                    for (int i = 0; i < array.length; ++i) {
                        sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3));
                 }
                    return sb.toString();
            } catch (java.security.NoSuchAlgorithmException e) {
                //error action
            }
            return null;
    }

    public static String md5(String txt) {
        return Hash.getHash(txt, "MD5");
    }

    public static String sha1(String txt) {
        return Hash.getHash(txt, "SHA1");
    }
}

Тестирование с помощью JUnit и PHP

PHP Script:

<?php

echo 'MD5 :' . md5('Hello World') . "\n";
echo 'SHA1:' . sha1('Hello World') . "\n";

Выход PHP Script:

MD5 :b10a8db164e0754105b7a99be72e3fe5
SHA1:0a4d55a8d778e5022fab701977c5d840bbc486d0

Использование примера и Тестирование с помощью JUnit:

    public class HashTest {

    @Test
    public void test() {
        String txt = "Hello World";
        assertEquals("b10a8db164e0754105b7a99be72e3fe5", Hash.md5(txt));
        assertEquals("0a4d55a8d778e5022fab701977c5d840bbc486d0", Hash.sha1(txt));
    }

}

Код в GitHub

https://github.com/fitorec/java-hashes

  • 1
    Большое спасибо ! Это именно то, что я искал: D
  • 0
    Как сказал @CedricSimon, это именно то, что я искал. Upvote здесь .. Спасибо!
21

Мой не очень показательный ответ:

private String md5(String s) {
    try {
        MessageDigest m = MessageDigest.getInstance("MD5");
        m.update(s.getBytes(), 0, s.length());
        BigInteger i = new BigInteger(1,m.digest());
        return String.format("%1$032x", i);         
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return null;
}
  • 1
    хорошо, внешние библиотеки не требуются
  • 1
    хороший, +1 для String.format("%1$032x", i)
Показать ещё 1 комментарий
19

Не нужно делать это слишком сложным. DigestUtils отлично работает и позволяет вам комфортно работать с хэшами md5.

DigestUtils.md5Hex(_hash);

или же

DigestUtils.md5(_hash);

Либо вы можете использовать любые другие методы шифрования, такие как sha или md.

16

Ответ Bombe правильный, однако учтите, что, если вы абсолютно не должны использовать MD5 (например, принуждаете вас к взаимодействию), лучшим выбором является SHA1, поскольку MD5 имеет слабые места для долгосрочного использования.

Я должен добавить, что SHA1 также имеет теоретические уязвимости, но не столь суровые. Современное состояние хэширования состоит в том, что существует ряд альтернативных хеш-функций замены, но ни одна из них пока не стала стандартной передовой практикой для замены SHA1. Таким образом, в зависимости от ваших потребностей вам будет полезно настроить ваш алгоритм хеширования, чтобы он мог быть заменен в будущем.

  • 0
    Не могли бы вы указать мне некоторые ресурсы, где я могу прочитать об относительных достоинствах и недостатках каждого из них?
  • 0
    Вероятно, лучшее, что вы можете сделать в данный момент, это использовать SHA1 и быть готовым заменить его в будущем. Вы можете использовать новые функции, но они еще не были предметом большого количества исследований. Вы можете отслеживать ресурсы онлайн-безопасности, чтобы узнать, когда это изменится - например, блог Брюса Шнайера.
Показать ещё 1 комментарий
15

Существует класс DigestUtils в Spring:

http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/util/DigestUtils.html

Этот класс содержит метод md5DigestAsHex(), который выполняет задание.

  • 0
    Кстати: производительность этого намного лучше, чем использование BigInteger для создания представления шестнадцатеричной строки.
14

Вы можете попробовать следующее. Подробности и коды для скачивания смотрите здесь: http://jkssweetlife.com/java-hashgenerator-md5-sha-1/

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Example {

public static void main(String[] args) throws Exception {

    final String inputString = "Hello MD5";

    System.out.println("MD5 hex for '" + inputString + "' :");
    System.out.println(getMD5Hex(inputString));
}

public static String getMD5Hex(final String inputString) throws NoSuchAlgorithmException {

    MessageDigest md = MessageDigest.getInstance("MD5");
    md.update(inputString.getBytes());

    byte[] digest = md.digest();

    return convertByteToHex(digest);
}

private static String convertByteToHex(byte[] byteData) {

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < byteData.length; i++) {
        sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
    }

    return sb.toString();
}
}
10

Другая реализация: Быстрая реализация MD5 в Java

String hash = MD5.asHex(MD5.getHash(new File(filename)));
  • 1
    Это солидная, автономная библиотека с минимальными зависимостями. Хорошая вещь.
  • 0
    Я нахожу это очень полезным. Для файла 4,57 ГБ потребовалось 15357 мс, а для встроенной Java-реализации - 19094 мс.
9

Я не знаю, подходит ли это для тех, кто читает это, но у меня была проблема, которую я хотел

  • загрузите файл с заданного URL и
  • сравнить его MD5 с известным значением.

Я хотел сделать это только с классами JRE (без Apache Commons или аналогичных). Быстрый веб-поиск не показал мне фрагментов кода кода, выполняющих оба одновременно, только каждая задача отдельно. Поскольку для этого требуется дважды прочитать один и тот же файл, я решил, что стоит написать код, который объединяет обе задачи, рассчитывая контрольную сумму "на лету" при загрузке файла. Это мой результат (извините, если это не идеальная Java, но, я думаю, вы все равно получите идею):

import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.security.DigestOutputStream;        // new
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

void downloadFile(String fromURL, String toFile, BigInteger md5)
    throws IOException, NoSuchAlgorithmException
{
    ReadableByteChannel in = Channels.newChannel(new URL(fromURL).openStream());
    MessageDigest md5Digest = MessageDigest.getInstance("MD5");
    WritableByteChannel out = Channels.newChannel(
        //new FileOutputStream(toFile));  // old
        new DigestOutputStream(new FileOutputStream(toFile), md5Digest));  // new
    ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);  // 1 MB

    while (in.read(buffer) != -1) {
        buffer.flip();
        //md5Digest.update(buffer.asReadOnlyBuffer());  // old
        out.write(buffer);
        buffer.clear();
    }

    BigInteger md5Actual = new BigInteger(1, md5Digest.digest()); 
    if (! md5Actual.equals(md5))
        throw new RuntimeException(
            "MD5 mismatch for file " + toFile +
            ": expected " + md5.toString(16) +
            ", got " + md5Actual.toString(16)
        );
}
  • 0
    О, кстати, прежде чем кто-то, кроме меня, заметит, насколько плохи мои знания в области JRE: я только что открыл DigestInputStream и DigestOutputStream . Я собираюсь отредактировать свое оригинальное решение, чтобы отразить то, что я только что изучил.
6

Для чего это стоит, я наткнулся на это, потому что хочу синтезировать GUID из естественного ключа для программы, которая будет устанавливать COM-компоненты; Я хочу, чтобы syhthesize, чтобы не управлять жизненным циклом GUID. Я буду использовать MD5, а затем использовать класс UUID, чтобы получить из него строку. (http://stackoverflow.com/questions/2190890/how-can-i-generate-guid-for-a-string-values/12867439 поднимает эту проблему).

В любом случае, java.util.UUID может получить вам хорошую строку из байтов MD5.

return UUID.nameUUIDFromBytes(md5Bytes).toString();
  • 0
    на самом деле он принимает не только массив байтов MD5 (размер == 16). Вы можете передать байтовый массив любой длины. Он будет преобразован в массив байтов MD5 с помощью MD5 MessageDigest (см. Исходный код nameUUIDFromBytes () )
6

Посмотрите на следующую ссылку, Пример получает хеш-код MD5 предоставленного изображения: Хеш-код MD5 изображения

5

MD5 отлично справляется, если вам не нужна лучшая безопасность, и если вы делаете что-то вроде проверки целостности файла, тогда безопасность не рассматривается. В таком случае вы можете рассмотреть что-то более простое и быстрое, например Adler32, которое также поддерживается библиотеками Java.

  • 2
    Что заставляет вас думать, что целостность файлов не является проблемой безопасности?
4
import java.security.*;
import javax.xml.bind.*;

byte[] bytesOfMessage = yourString.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] bytesOfDigest = md.digest(bytesOfMessage);
String digest = DatatypeConverter.printHexBinary(bytesOfDigest).toLowerCase();
4

попробуйте следующее:

public static String getHashMD5(String string) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        BigInteger bi = new BigInteger(1, md.digest(string.getBytes()));
        return bi.toString(16);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(MD5Utils.class
                .getName()).log(Level.SEVERE, null, ex);

        return "";
    }
}
  • 2
    Это, вероятно, худшее решение, поскольку оно убирает лидирующие нули.
3
import java.security.MessageDigest

val digest = MessageDigest.getInstance("MD5")

//Quick MD5 of text
val text = "MD5 this text!"
val md5hash1 = digest.digest(text.getBytes).map("%02x".format(_)).mkString

//MD5 of text with updates
digest.update("MD5 ".getBytes())
digest.update("this ".getBytes())
digest.update("text!".getBytes())
val md5hash2 = digest.digest().map(0xFF & _).map("%02x".format(_)).mkString

//Output
println(md5hash1 + " should be the same as " + md5hash2)
  • 1
    Это котлинский язык?
  • 2
    @Isuru выглядит как Скала
3

этот дает точный md5, как вы получаете от функции mysql md5 или php md5 и т.д. Это тот, который я использую (вы можете изменить в соответствии с вашими потребностями)

public static String md5( String input ) {
    try {
        java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
        byte[] array = md.digest(input.getBytes( "UTF-8" ));
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < array.length; i++) {
            sb.append( String.format( "%02x", array[i]));
        }
        return sb.toString();
    } catch ( NoSuchAlgorithmException | UnsupportedEncodingException e) {
        return null;            
    }

}
2

В отличие от PHP, где вы можете выполнить хеширование md5 вашего текста, просто вызвав функцию md5($text) то есть md5($text), в Java это стало немного сложнее. Обычно я реализовывал это, вызывая функцию, которая возвращает текст хеша md5. Вот как я это реализовал. Сначала создайте функцию с именем md5encryption внутри вашего основного класса, как md5encryption ниже.

public static String md5hashing(String text)
    {   String hashtext = null;
        try 
        {
            String plaintext = text;
            MessageDigest m = MessageDigest.getInstance("MD5");
            m.reset();
            m.update(plaintext.getBytes());
            byte[] digest = m.digest();
            BigInteger bigInt = new BigInteger(1,digest);
            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;   
            }
        } catch (Exception e1) 
        {
            // TODO: handle exception
            JOptionPane.showMessageDialog(null,e1.getClass().getName() + ": " + e1.getMessage());   
        }
        return hashtext;     
    }

Теперь вызывайте функцию всякий раз, когда вам нужно, как указано ниже.

String text = textFieldName.getText();
String pass = md5hashing(text);

Здесь вы можете видеть, что к хеш-тексту добавляется ноль, чтобы он соответствовал шифрованию md5 в PHP.

  • 0
    Проголосовал, потому что вы назвали это шифрованием . MD5 - это не алгоритм шифрования, это алгоритм хеширования .
  • 0
    @ ChristianBrüggemann спасибо, что указали на ошибку. Я исправил это.
Показать ещё 1 комментарий
2

Вот что я здесь сделал для удобной функции scala, которая возвращает строку хеша MD5:

def md5(text: String) : String = java.security.MessageDigest.getInstance("MD5").digest(text.getBytes()).map(0xFF & _).map { "%02x".format(_) }.foldLeft(""){_ + _}
0
 import java.math.BigInteger;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;

/**
* MD5 encryption
*
* @author Hongten
*
*/
public class MD5 {

 public static void main(String[] args) {
     System.out.println(MD5.getMD5("123456"));
 }

 /**
  * Use md5 encoded code value
  *
  * @param sInput
  * clearly
  * @ return md5 encrypted password
  */
 public static String getMD5(String sInput) {

     String algorithm = "";
     if (sInput == null) {
         return "null";
     }
     try {
         algorithm = System.getProperty("MD5.algorithm", "MD5");
     } catch (SecurityException se) {
     }
     MessageDigest md = null;
     try {
         md = MessageDigest.getInstance(algorithm);
     } catch (NoSuchAlgorithmException e) {
         e.printStackTrace();
     }
     byte buffer[] = sInput.getBytes();

     for (int count = 0; count < sInput.length(); count++) {
         md.update(buffer, 0, count);
     }
     byte bDigest[] = md.digest();
     BigInteger bi = new BigInteger(bDigest);
     return (bi.toString(16));
 }
}

В этой статье есть статья о Кодинките. Отъезд: http://codingkit.com/a/JAVA/2013/1020/2216.html

-1
private String hashuj(String dane) throws ServletException{
    try {
        MessageDigest m = MessageDigest.getInstance("MD5");
        byte[] bufor = dane.getBytes();
        m.update(bufor,0,bufor.length);
        BigInteger hash = new BigInteger(1,m.dige`enter code here`st());
        return String.format("%1$032X", hash);

    } catch (NoSuchAlgorithmException nsae) {
        throw new ServletException("Algorytm szyfrowania nie jest obsługiwany!");
    }
}
  • 0
    Добро пожаловать в StackOverflow , вы можете прочитать, как опубликовать ответ, прежде чем сделать это. Дайте немного контекста, объясняющего, почему вы опубликовали этот код и что он делает. Также подумайте о том, чтобы найти время для форматирования вашего ответа, чтобы читатели могли легко его понять.
-2

Я сделал это... Кажется, работает нормально - я уверен, что кто-то укажет на ошибки, хотя...

public final class MD5 {
public enum SaltOption {
    BEFORE, AFTER, BOTH, NONE;
}
private static final String ALG = "MD5";
//For conversion to 2-char hex
private static final char[] digits = {
    '0' , '1' , '2' , '3' , '4' , '5' ,
    '6' , '7' , '8' , '9' , 'a' , 'b' ,
    'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
    'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
    'o' , 'p' , 'q' , 'r' , 's' , 't' ,
    'u' , 'v' , 'w' , 'x' , 'y' , 'z'
};

private SaltOption opt;

/**
 * Added the SaltOption constructor since everybody
 * has their own standards when it comes to salting
 * hashes.
 * 
 * This gives the developer the option...
 * 
 * @param option The salt option to use, BEFORE, AFTER, BOTH or NONE.
 */
public MD5(final SaltOption option) {
    //TODO: Add Char Encoding options too... I was too lazy!
    this.opt = option;
}

/**
 * 
 * Returns the salted MD5 checksum of the text passed in as an argument.
 * 
 * If the salt is an empty byte array - no salt is applied.
 * 
 * @param txt The text to run through the MD5 algorithm.
 * @param salt The salt value in bytes.
 * @return The salted MD5 checksum as a <code>byte[]</code>
 * @throws NoSuchAlgorithmException
 */
private byte[] createChecksum(final String txt, final byte[] salt) throws NoSuchAlgorithmException {
    final MessageDigest complete = MessageDigest.getInstance(ALG);
    if(opt.equals(SaltOption.BEFORE) || opt.equals(SaltOption.BOTH)) {
        complete.update(salt);
    }
    complete.update(txt.getBytes());
    if(opt.equals(SaltOption.AFTER) || opt.equals(SaltOption.BOTH)) {
        complete.update(salt);
    }
    return complete.digest();
}

/**
 * 
 * Returns the salted MD5 checksum of the file passed in as an argument.
 * 
 * If the salt is an empty byte array - no salt is applied.
 * 
 * @param fle The file to run through the MD5 algorithm.
 * @param salt The salt value in bytes.
 * @return The salted MD5 checksum as a <code>byte[]</code>
 * @throws IOException
 * @throws NoSuchAlgorithmException
 */
private byte[] createChecksum(final File fle, final byte[] salt)
        throws IOException, NoSuchAlgorithmException {
    final byte[] buffer = new byte[1024];
    final MessageDigest complete = MessageDigest.getInstance(ALG);
            if(opt.equals(SaltOption.BEFORE) || opt.equals(SaltOption.BOTH)) {
            complete.update(salt);
        }
    int numRead;
    InputStream fis = null;
    try {
        fis = new FileInputStream(fle);
        do {
            numRead = fis.read(buffer);
            if (numRead > 0) {
                complete.update(buffer, 0, numRead);
            }
        } while (numRead != -1);
    } finally {
    if (fis != null) {
            fis.close();
        }
    }
            if(opt.equals(SaltOption.AFTER) || opt.equals(SaltOption.BOTH)) {
            complete.update(salt);
        }
    return complete.digest();
}

/**
 * 
 * Efficiently converts a byte array to its 2 char per byte hex equivalent.
 * 
 * This was adapted from JDK code in the Integer class, I just didn't like
 * having to use substrings once I got the result...
 *
 * @param b The byte array to convert
 * @return The converted String, 2 chars per byte...
 */
private String convertToHex(final byte[] b) {
    int x;
    int charPos;
    int radix;
    int mask;
    final char[] buf = new char[32];
    final char[] tmp = new char[3];
    final StringBuilder md5 = new StringBuilder();
    for (int i = 0; i < b.length; i++) {
        x = (b[i] & 0xFF) | 0x100;
        charPos = 32;
        radix = 1 << 4;
        mask = radix - 1;
        do {
            buf[--charPos] = digits[x & mask];
            x >>>= 4;
        } while (x != 0);
        System.arraycopy(buf, charPos, tmp, 0, (32 - charPos));
        md5.append(Arrays.copyOfRange(tmp, 1, 3));
    }
    return md5.toString();
}

/**
 * 
 * Returns the salted MD5 checksum of the file passed in as an argument.
 * 
 * @param fle The file you want want to run through the MD5 algorithm.
 * @param salt The salt value in bytes
 * @return The salted MD5 checksum as a 2 char per byte HEX <code>String</code>
 * @throws NoSuchAlgorithmException
 * @throws IOException
 */
public String getMD5Checksum(final File fle, final byte[] salt)
        throws NoSuchAlgorithmException, IOException {
    return convertToHex(createChecksum(fle, salt));
}

/**
 * 
 * Returns the MD5 checksum of the file passed in as an argument.
 * 
 * @param fle The file you want want to run through the MD5 algorithm.
 * @return The MD5 checksum as a 2 char per byte HEX <code>String</code>
 * @throws NoSuchAlgorithmException
 * @throws IOException
 */
public String getMD5Checksum(final File fle)
        throws NoSuchAlgorithmException, IOException {
    return convertToHex(createChecksum(fle, new byte[0]));
}

/**
 * 
 * Returns the salted MD5 checksum of the text passed in as an argument.
 * 
 * @param txt The text you want want to run through the MD5 algorithm.
 * @param salt The salt value in bytes.
 * @return The salted MD5 checksum as a 2 char per byte HEX <code>String</code>
 * @throws NoSuchAlgorithmException
 * @throws IOException
 */
public String getMD5Checksum(final String txt, final byte[] salt)
        throws NoSuchAlgorithmException {
    return convertToHex(createChecksum(txt, salt));
}

/**
 * 
 * Returns the MD5 checksum of the text passed in as an argument.
 * 
 * @param txt The text you want want to run through the MD5 algorithm.
 * @return The MD5 checksum as a 2 char per byte HEX <code>String</code>
 * @throws NoSuchAlgorithmException
 * @throws IOException
 */
public String getMD5Checksum(final String txt)
        throws NoSuchAlgorithmException {

    return convertToHex(createChecksum(txt, new byte[0]));
}
}
-6

Я знаю, что вопрос касается Java, но я хотел бы перечислить здесь исходный код ActionScript 1 (здесь license), чтобы генерировать MD5 по-другому, чем ответы, перечисленные на этой странице.

Функция ниже работает хорошо и может быть преобразована в Java:

/* MD5 implementation from http://www.webtoolkit.info */

function md5(string) {

    function RotateLeft(lValue, iShiftBits) {
        return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
    }

    function AddUnsigned(lX,lY) {
        var lX4,lY4,lX8,lY8,lResult;
        lX8 = (lX & 0x80000000);
        lY8 = (lY & 0x80000000);
        lX4 = (lX & 0x40000000);
        lY4 = (lY & 0x40000000);
        lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
        if (lX4 & lY4) {
            return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
        }
        if (lX4 | lY4) {
            if (lResult & 0x40000000) {
                return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
            } else {
                return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
            }
        } else {
            return (lResult ^ lX8 ^ lY8);
        }
    }

    function F(x,y,z) { return (x & y) | ((~x) & z); }
    function G(x,y,z) { return (x & z) | (y & (~z)); }
    function H(x,y,z) { return (x ^ y ^ z); }
    function I(x,y,z) { return (y ^ (x | (~z))); }

    function FF(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    };

    function GG(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    };

    function HH(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    };

    function II(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    };

    function ConvertToWordArray(string) {
        var lWordCount;
        var lMessageLength = string.length;
        var lNumberOfWords_temp1=lMessageLength + 8;
        var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
        var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
        var lWordArray=Array(lNumberOfWords-1);
        var lBytePosition = 0;
        var lByteCount = 0;
        while ( lByteCount < lMessageLength ) {
            lWordCount = (lByteCount-(lByteCount % 4))/4;
            lBytePosition = (lByteCount % 4)*8;
            lWordArray[lWordCount] = (lWordArray[lWordCount] | 
                (string.charCodeAt(lByteCount)<<lBytePosition));
            lByteCount++;
        }
        lWordCount = (lByteCount-(lByteCount % 4))/4;
        lBytePosition = (lByteCount % 4)*8;
        lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
        lWordArray[lNumberOfWords-2] = lMessageLength<<3;
        lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
        return lWordArray;
    };

    function WordToHex(lValue) {
        var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
        for (lCount = 0;lCount<=3;lCount++) {
            lByte = (lValue>>>(lCount*8)) & 255;
            WordToHexValue_temp = "0" + lByte.toString(16);
            WordToHexValue = WordToHexValue + 
                WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
        }
        return WordToHexValue;
    };

    function Utf8Encode(string) {

        var utftext = "";

        for (var n = 0; n < string.length; n++) {

            var c = string.charCodeAt(n);

            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }

        }

        return utftext;
    };

    var x=Array();
    var k,AA,BB,CC,DD,a,b,c,d;
    var S11=7, S12=12, S13=17, S14=22;
    var S21=5, S22=9 , S23=14, S24=20;
    var S31=4, S32=11, S33=16, S34=23;
    var S41=6, S42=10, S43=15, S44=21;

    string = Utf8Encode(string);

    x = ConvertToWordArray(string);

    a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;

    for (k=0;k<x.length;k+=16) {
        AA=a; BB=b; CC=c; DD=d;
        a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
        d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
        c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
        b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
        a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
        d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
        c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
        b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
        a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
        d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
        c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
        b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
        a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
        d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
        c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
        b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
        a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
        d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
        c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
        b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
        a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
        d=GG(d,a,b,c,x[k+10],S22,0x2441453);
        c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
        b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
        a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
        d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
        c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
        b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
        a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
        d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
        c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
        b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
        a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
        d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
        c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
        b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
        a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
        d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
        c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
        b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
        a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
        d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
        c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
        b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
        a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
        d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
        c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
        b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
        a=II(a,b,c,d,x[k+0], S41,0xF4292244);
        d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
        c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
        b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
        a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
        d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
        c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
        b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
        a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
        d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
        c=II(c,d,a,b,x[k+6], S43,0xA3014314);
        b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
        a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
        d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
        c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
        b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
        a=AddUnsigned(a,AA);
        b=AddUnsigned(b,BB);
        c=AddUnsigned(c,CC);
        d=AddUnsigned(d,DD);
    }

    var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);

    return temp.toLowerCase();
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню