Fix CTR decryption.
Off by one error in respect to the y blocks.
This commit is contained in:
parent
e04a341fc6
commit
e1c2d7df7d
7 changed files with 105 additions and 45 deletions
|
@ -4,31 +4,68 @@ import java.nio.charset.StandardCharsets;
|
|||
|
||||
import static ch.fhnw.kry.Main.BLOCK_LENGTH;
|
||||
|
||||
/**
|
||||
* Decrypt cipher text with CTR and SPN.
|
||||
* <p>
|
||||
* Some implemented functions are not as flexible as could be,
|
||||
* as everything basically assumes a block length of 16 bits.
|
||||
* For this learning exercise, this is satisfactory though.
|
||||
*/
|
||||
public class Decrypt {
|
||||
public String decrypt(String keyString, String chiffre) {
|
||||
int key = Integer.parseInt(keyString, 2);
|
||||
/**
|
||||
* Decrypt a cipher text with a key, using CTR and an SPN.
|
||||
* <p>
|
||||
* The decrypted data is interpreted as ASCII code.
|
||||
*
|
||||
* @param keyString Key as a bit string.
|
||||
* @param cipher Cipher text as a bit string.
|
||||
* @return Decrypted data, interpreted as an ASCII string.
|
||||
*/
|
||||
public String decrypt(String keyString, String cipher) {
|
||||
int key = Integer.parseInt(keyString, 2); // get the key
|
||||
|
||||
int[] data = strToArray(chiffre);
|
||||
byte[] decryptedData = new byte[data.length * 2];
|
||||
int iv = data[0];
|
||||
int[] data = strToArray(cipher);
|
||||
byte[] decryptedData =
|
||||
new byte[data.length * 2]; // as the block size is 16 bits, the byte array needs double the capacity
|
||||
int iv = data[0]; // first block is the iv
|
||||
var ctr = new CTR(iv, key);
|
||||
|
||||
for (int i = 1; i < data.length; i++) {
|
||||
for (int i = 0; i < data.length - 1; i++) {
|
||||
int block = data[i];
|
||||
int decryptedBlock = ctr.decrypt(block, i);
|
||||
int decryptedBlock = ctr.decrypt(block, i, data[i + 1]); // y is i + 1 because i = 0 is the iv
|
||||
|
||||
decryptedData[i * 2] = (byte)(decryptedBlock >>> 8);
|
||||
decryptedData[i * 2 + 1] = (byte)(decryptedBlock & 0x0000_00FF);
|
||||
decryptedData[i * 2] = (byte) (decryptedBlock >>> 8); // get the upper half of the decrypted block
|
||||
decryptedData[i * 2 + 1] = (byte) (decryptedBlock & 0xFF); // and the lower half
|
||||
}
|
||||
|
||||
String decryptedString = new String(decryptedData, StandardCharsets.US_ASCII);
|
||||
decryptedData = removePadding(decryptedData);
|
||||
|
||||
return decryptedString;
|
||||
return new String(decryptedData, StandardCharsets.US_ASCII);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the padding of data by traversing it
|
||||
* backwards until a byte != 0 s found and lop it off behind
|
||||
* the found position.
|
||||
*
|
||||
* @param data Data with padding.
|
||||
* @return Input data without the padding.
|
||||
*/
|
||||
public byte[] removePadding(byte[] data) {
|
||||
int idx = data.length - 1;
|
||||
|
||||
while (idx > 0 && data[idx] == 0) {
|
||||
idx--;
|
||||
}
|
||||
|
||||
byte[] unpaddedData = new byte[idx];
|
||||
System.arraycopy(data, 0, unpaddedData, 0, idx);
|
||||
return unpaddedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a bit string into an integer array.
|
||||
*
|
||||
* <p>
|
||||
* Because later we only ever look at the lower 16 bits,
|
||||
* we stuff every block of 16 bits into the lower half of an int
|
||||
* (meaning the igh 16 bits of the ints in the array are always 0).
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue