2016-08-03 7 views
2

Итак, у меня есть школьный проект, с которым у меня проблемы. Нам дается метод шифрования, а затем предлагается создать для него метод дешифрования.Crypttext кража в Java

public static byte[] encrypt(byte[] plaintext, BlockCipher64 cipher, long IV) { 
    if(plaintext.length <= 8) 
     throw new IllegalArgumentException("plaintext must be longer than 8 bytes!"); 

    byte[] ciphertext = new byte[plaintext.length]; 
    int blocks = plaintext.length/8; 
    if(plaintext.length % 8 != 0) ++blocks; 

    long prev = IV; 
    for(int block = 0; block < blocks; ++block) { 
     prev = cipher.encrypt(prev^longAt(plaintext, block * 8)); 
     storeLongAt(ciphertext, prev, block * 8); 
    } 

    // copy penultimate to last, then prev to penultimate (ciphertext stealing) 
    int lastBlock = (blocks - 1) * 8; 
    int secondLastBlock = (blocks - 2) * 8; 
    storeLongAt(ciphertext, longAt(ciphertext, secondLastBlock), lastBlock); 
    storeLongAt(ciphertext, prev, secondLastBlock); 

    return ciphertext; 
} 

Таким образом, я получил метод дешифрования для работы, когда длина строки равна ровно 16 (2 блока). Другие строки с четными блоками (кратные 8) не работают, 24, 32 ... и т. Д. Также частичные блоки не работают; если я зашифрую строку длиной 18 и снова расшифрую ее, последние два символа всегда ошибочны. Любая помощь высоко ценится! Вот мой метод расшифровки:

public static byte[] decrypt(byte[] ciphertext, BlockCipher64 cipher, long IV) { 
    // code here 
    // check for an illegal argument 
    if(ciphertext.length <= 8) 
     throw new IllegalArgumentException("ciphertext must be longer than 8 bytes!"); 

    // create a byte[] for the plaintext 
    byte[] plaintext = new byte[ciphertext.length]; 

    // calculate how many blocks there are 
    int blocks = plaintext.length/8; 
    if(plaintext.length % 8 != 0) ++blocks; 

    // handle the last two blocks (which are special because of ciphertext stealing) 
    int lastBlock = (blocks - 1) * 8; 
    int secondLastBlock = (blocks - 2) * 8; 
    long lBlock = longAt(ciphertext, lastBlock); 
    int lBlockSize = ciphertext.length % 8; 
    // if block sizes are even; swap, if block size is partial; 
    if (lBlockSize != 0) { 
     //get blocks to switch 
     byte[] NLB = new byte[lBlockSize]; 
     for (int i=secondLastBlock, j=0; i<secondLastBlock + lBlockSize; i++, j++) { 
      NLB[j] = ciphertext[i]; 
     } 
     byte[] NSLB = new byte[lBlockSize]; 
     for (int i=lastBlock, j=0; i<lastBlock + lBlockSize; i++, j++) { 
      NSLB[j] = ciphertext[i]; 
     } 
     //build ciphertext 
     for (int i=secondLastBlock, j=0; i<secondLastBlock + lBlockSize; i++, j++) { 
      ciphertext[i] = NSLB[j]; 
     } 
     for (int i=lastBlock, j=0; i<lastBlock + lBlockSize; i++, j++) { 
      ciphertext[i] = NLB[j]; 
     } 
    } else { 
     storeLongAt(ciphertext, longAt(ciphertext, secondLastBlock), lastBlock); 
     storeLongAt(ciphertext, lBlock, secondLastBlock); 
    } 

    // loop over all other blocks, decrypting and xor'ing, and saving the results 
    long prev = IV; 
    for(int block = 0; block < blocks; ++block) { 
     prev = cipher.decrypt(prev^longAt(ciphertext, block * 8)); 
     storeLongAt(plaintext, prev, block * 8); 
    } 

    return plaintext; 
} 

Если какая-либо другая информация необходима, дайте мне знать ... Я реальный тупик на этом.

EDIT: Дополнительные методы и классы storeLongAt() и longAt():

public static void storeLongAt(byte[] b, long x, int pos) { 
    byte[] c = BlockCipher64.longToBytes(x); 
    for(int i = 0; i < 8 && (pos + i) < b.length; ++i) { 
     b[pos + i] = c[i]; 
    } 
} 

public static long longAt(byte[] b, int pos) { 
    return BlockCipher64.bytesToLong(Arrays.copyOfRange(b, pos, pos + 8)); 
} 

И класс BlockCipher64:

public interface BlockCipher64 { 
long encrypt(long block); 
long decrypt(long block); 

public static byte[] longToBytes(long l) { 
    byte[] result = new byte[8]; 
    for (int i = 7; i >= 0; i--) { 
     result[i] = (byte) l; 
     l >>= 8; 
    } 
    return result; 
} 

public static long bytesToLong(byte[] b) { 
    long result = 0; 
    for (int i = 0; i < 8; i++) { 
     result <<= 8; 
     result |= ((long) b[i]) & 0xffL; // notice the L 
    } 
    return result; 
} 
} 
+0

Было бы полезно, если вы отредактируете свой вопрос и включите метод 'storeLongAt (...)', а также метод 'longAt (...)'. –

+0

Добавлено вместе с сопроводительным блоком BlockCipher64 – isaac6

ответ

1

Вы обменивая зашифрованные байты вместо открытого текста байт. Обратите внимание, что при обмене происходит до шифрование последнего блока (по времени). Если вы отмените его, то он должен быть заменен после дешифрование последнего блока.

В настоящее время вы создаете недопустимый зашифрованный текст и пытаетесь его расшифровать.

+0

Буквально попробуйте следовать схеме шифрования назад и посмотрите, правильно ли реализована схема дешифрования. Эти шаги все обратимы, поэтому ваша схема должна быть точным обратным типом шифрования. –