Реализация MD5, добавить бит 1 и 0 - PullRequest
2 голосов
/ 14 августа 2011

Так что я не уверен, правильно ли я это делаю.Я собираюсь использовать псевдокод здесь: http://en.wikipedia.org/wiki/MD5

Он говорит:

//Pre-processing:
append "1" bit to message
append "0" bits until message length in bits ≡ 448 (mod 512)
append length to message

В Java я смогу преобразовать сообщение в байтовый массив.Затем получите число битов, получив длину строки * 8. Затем сделайте что-то вроде 448 - ((#bits+1) mod 512), чтобы получить число 0 битов для добавления.

Затем скопируйте этот байтовый массив в другой массив, но заполните первые байты 0 и затем 1.

Пример:

Строка - 746 бит, которые я тогда сделал бы 448 - ((746+1) mod 512) = 213

Так что мне нужно заполнить строку 213 "0" битами, а затем 1 "1" битами.

Так что тогда мой массив будет выглядеть как

byteArr[0] = 0x00
byteArr[1] = 0x00
...
byteArr[27] = 000001(Rest of message bits)
byteArr[n] = Rest of the bytes from message

Как я могу узнать, куда идет 1?В основном, как я могу узнать, собирается ли он создать короткое замыкание, если я добавлю 1 бит.

Есть ли более простой способ или какой-либо другой способ сделать это?

Ответы [ 5 ]

2 голосов
/ 14 августа 2011

Как кто-то еще поймал, «добавить» означает добавлено в конец.Так что на самом деле вы хотите получить байт 0x80 после сообщения, за которым следует набор из 0 байтов, пока общее количество байтов не станет на 8 меньше, чем кратное 64.

2 голосов
/ 14 августа 2011

Биты должны быть добавлены к концу сообщения, а не к его началу. После заполнения сообщения до 448 битов по модулю 512 необходимо добавить длину сообщения (без дополненных битов). Но пока это не упражнение, вы должны использовать алгоритм, упомянутый JB Nizet.

0 голосов
/ 14 августа 2011

Если вы реализуете криптоалгоритмы, вы должны выработать привычку, взяв официальные спецификации в качестве образца для своей реализации.Как бы ни была хороша Википедия, я бы не стал полагаться на нее при реализации критичных для безопасности алгоритмов.Конечно, хорошо использовать его в дополнение к официальной спецификации.Поэтому я бы начал с RFC 1321 и получал бы «вдохновение» из других источников.

RFC 1321 даже содержит реализацию на C, вы также можете проверить это.О шаге заполнения говорят:

3.1 Шаг 1. Добавление битов заполнения

Сообщение «дополняется» (расширяется), так что его длина (в битах) совпадает с 448по модулю 512. То есть сообщение расширяется, так что оно всего лишь на 64 бита, кратное длине 512 бит.Заполнение всегда выполняется, даже если длина сообщения уже соответствует 448 по модулю 512.

Заполнение выполняется следующим образом: к сообщению добавляется один бит «1», а затем «0»биты добавляются таким образом, что длина в битах дополненного сообщения становится равной 448 по модулю 512. Всего добавляется по меньшей мере один бит и максимум 512 бит.

Это означает, что вы должны сначала добавить 1, затем дополнить оставшимися нулями, а не наоборот.Остальные биты для заполнения (включая «1») всегда будут кратны 8, так как ваш ввод был байтами, битовая длина которых также была кратна 8. Итак, допустим, вы должны заполнить 128 битов.Это означает 1 плюс 127 0 бит.В общей сложности это 16 (16 * 8 = 128) байтов заполнения, где старший бит первого байта установлен в 1, то есть первый байт станет 0x80, остальные 0x00.Таким образом, это означает, что вы можете упростить этот шаг заполнения до

  • n = общее количество байтов для заполнения = остаток в битах, деленный на 8
  • , добавьте 0x80 к вашему сообщению
  • добавьте n-1 раз 0x00 к сообщению
0 голосов
/ 14 августа 2011

То, о чем вы говорите - это солить хеш.

Вот как я это делаю.

public static byte[] getSecure8ByteSalt(){
    SecureRandom random = null;
    try {
        random = SecureRandom.getInstance("SHA1PRNG");
        byte [] bSalt =  new byte[8];
        random.nextBytes(bSalt);
        return bSalt;
    } catch (NoSuchAlgorithmException e) {
        log.error(e.getMessage(),e);
    }
    return new byte[]{
         (byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32,
         (byte)0x56, (byte)0x34, (byte)0xE3, (byte)0x03
     };
}

Метод, который вызывает соль, называется хешем:

private void hash(String passwd, int hashType){
    byte[] bSalt = new byte[8];
    try {
        if(this.salt == null){
            bSalt = getSecure8ByteSalt();
        }
        else{ 
            bSalt = base64ToByte(salt);
        }
    } catch (IOException e1) {
        log.error(e1.getMessage(),e1);
        return;
    }


    byte[] bDigest=null;
    try {
        bDigest = getHash(ITERATION_NUMBER,passwd,bSalt,hashType);
    } catch (NoSuchAlgorithmException e) {
        log.error(e.getMessage(),e);
    }

    String sDigest = byteToBase64(bDigest);
    if(this.salt == null)
        setSalt(byteToBase64(bSalt));
setPasswordHash(sDigest);
}

Метод от байта к основанию 64:

public static byte[] base64ToByte(String data) throws IOException {
    BASE64Decoder decoder = new BASE64Decoder();
    return decoder.decodeBuffer(data);
}

public static String byteToBase64(byte[] data){
       BASE64Encoder endecoder = new BASE64Encoder();
       return endecoder.encode(data);
}

метод getHash:

    private byte[] getHash(int iterationNb, String password, byte[] salt, int hashType) throws NoSuchAlgorithmException {
       MessageDigest digest = MessageDigest.getInstance(HASH_TYPE[hashType]);
       digest.reset();
       digest.update(salt);
       byte[] input = null;
        try {
            input = digest.digest(password.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage(),e);
        }
       for (int i = 0; i < iterationNb; i++) {
           digest.reset();
           input = digest.digest(input);
       }
       return input;
   }
0 голосов
/ 14 августа 2011

Существует гораздо более простой способ сделать это: просто используйте алгоритм MD5, уже реализованный для вас API Java SE.

Примечание: строка в Java содержит символы, а не байты. Не используйте термин «строка» для обозначения двоичного сообщения. Используйте термин байтовый массив.

...