diff --git a/src/main/java/ch/fhnw/kry/CTR.java b/src/main/java/ch/fhnw/kry/CTR.java new file mode 100644 index 0000000..7987cc9 --- /dev/null +++ b/src/main/java/ch/fhnw/kry/CTR.java @@ -0,0 +1,34 @@ +package ch.fhnw.kry; + +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; + +public class CTR { + private final SPN spn = new SPN(); + private final int iv; + private final int key; + + public CTR(int key) { + this.iv = generateIV(); + this.key = key; + } + + public int getIV() { + return iv; + } + + public int generateIV() { + Random random = ThreadLocalRandom.current(); + byte[] r = new byte[2]; + random.nextBytes(r); + + return r[0] << 8 & r[1]; + } + + public int decrypt(int block, int idx) { + int e = (iv + idx) % (1 << 16); + e = spn.decryptBlock(key, e); + + return block ^ e; + } +} diff --git a/src/main/java/ch/fhnw/kry/Decrypt.java b/src/main/java/ch/fhnw/kry/Decrypt.java new file mode 100644 index 0000000..c4c85e8 --- /dev/null +++ b/src/main/java/ch/fhnw/kry/Decrypt.java @@ -0,0 +1,49 @@ +package ch.fhnw.kry; + +import java.nio.charset.StandardCharsets; + +import static ch.fhnw.kry.Main.BLOCK_LENGTH; + +public class Decrypt { + public String decrypt(String keyString, String chiffre) { + int key = Integer.parseInt(keyString, 2); + var ctr = new CTR(key); + + int[] data = strToArray(chiffre); + byte[] decryptedData = new byte[data.length * 2]; + for (int i = 0; i < data.length; i++) { + int block = data[i]; + int decryptedBlock = ctr.decrypt(block, i); + + decryptedData[i * 2] = (byte)(decryptedBlock >>> 8); + decryptedData[i * 2 + 1] = (byte)(decryptedBlock & 0x0000_00FF); + } + + String decryptedString = new String(decryptedData, StandardCharsets.US_ASCII); + + return decryptedString; + } + + /** + * Convert a bit string into an integer array. + * + * 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). + * + * @param bits Bit string. Its length must be a multiple of 16. + * @return int array, with every int's lower 16 bits set to 16 bits of the input string. + */ + public int[] strToArray(String bits) { + int[] data = new int[bits.length() / BLOCK_LENGTH]; + + for (int i = 0; i < data.length; i++) { + int startIdx = i * BLOCK_LENGTH; + String wordBits = bits.substring(startIdx, startIdx + BLOCK_LENGTH); + int word = Integer.parseInt(wordBits, 2); + data[i] = word; + } + + return data; + } +} diff --git a/src/main/java/ch/fhnw/kry/Main.java b/src/main/java/ch/fhnw/kry/Main.java index e260c3d..20ad38f 100644 --- a/src/main/java/ch/fhnw/kry/Main.java +++ b/src/main/java/ch/fhnw/kry/Main.java @@ -5,10 +5,12 @@ package ch.fhnw.kry; */ public class Main { - private static final String KEY = "00111010100101001101011000111111"; - private static final String CHIFFRE = + static final String KEY = "00111010100101001101011000111111"; + static final String CHIFFRE = "00000100110100100000101110111000000000101000111110001110011111110110000001010001010000111010000000010011011001110010101110110000"; + static final int BLOCK_LENGTH = 16; + public static void main(String[] args) { } diff --git a/src/main/java/ch/fhnw/kry/SPN.java b/src/main/java/ch/fhnw/kry/SPN.java index 8c39bee..da2da63 100644 --- a/src/main/java/ch/fhnw/kry/SPN.java +++ b/src/main/java/ch/fhnw/kry/SPN.java @@ -3,6 +3,7 @@ package ch.fhnw.kry; import java.util.HashMap; import java.util.Map; +import static ch.fhnw.kry.Main.BLOCK_LENGTH; import static java.util.Map.entry; public class SPN { @@ -62,37 +63,9 @@ public class SPN { entry(15, 15) ); - private static final int BLOCK_LENGTH = 16; + private static final int ROUNDS = 4; - public String decrypt(int key, String chiffre) { - - return null; - } - - /** - * Convert a bit string into an integer array. - * - * 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). - * - * @param bits Bit string. Its length must be a multiple of 16. - * @return int array, with every int's lower 16 bits set to 16 bits of the input string. - */ - public int[] strToArray(String bits) { - int[] data = new int[bits.length() / BLOCK_LENGTH]; - - for (int i = 0; i < data.length; i++) { - int startIdx = i * BLOCK_LENGTH; - String wordBits = bits.substring(startIdx, startIdx + BLOCK_LENGTH); - int word = Integer.parseInt(wordBits, 2); - data[i] = word; - } - - return data; - } - /** * Encrypt a block with the defined SPN. * diff --git a/src/test/java/ch/fhnw/kry/CTRTest.java b/src/test/java/ch/fhnw/kry/CTRTest.java new file mode 100644 index 0000000..2aa54f2 --- /dev/null +++ b/src/test/java/ch/fhnw/kry/CTRTest.java @@ -0,0 +1,20 @@ +package ch.fhnw.kry; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class CTRTest { + + @Test + void generateIV() { + var ctr = new CTR(0); + + int count = 0; + while(count < Integer.MAX_VALUE) { + int iv = ctr.generateIV(); + assert (iv < 1 << 16); + count++; + } + } +} diff --git a/src/test/java/ch/fhnw/kry/DecryptTest.java b/src/test/java/ch/fhnw/kry/DecryptTest.java new file mode 100644 index 0000000..139b406 --- /dev/null +++ b/src/test/java/ch/fhnw/kry/DecryptTest.java @@ -0,0 +1,28 @@ +package ch.fhnw.kry; + +import org.junit.jupiter.api.Test; + +import static ch.fhnw.kry.Main.CHIFFRE; +import static ch.fhnw.kry.Main.KEY; +import static org.junit.jupiter.api.Assertions.*; + +class DecryptTest { + + @Test + void strToArray() { + var decrypt = new Decrypt(); + + String input = "00000100110100100000101110111000000000101000111110001110011111110110000001010001010000111010000000010011011001110010101110110000"; + int[] data = decrypt.strToArray(input); + + assertEquals(8, data.length); + assertEquals(0x04D2, data[0]); + assertEquals(0x2BB0, data[data.length - 1]); + } + + @Test + void decrypt() { + var decrypt = new Decrypt(); + String decrypted = decrypt.decrypt(KEY, CHIFFRE); + } +} diff --git a/src/test/java/ch/fhnw/kry/SPNTest.java b/src/test/java/ch/fhnw/kry/SPNTest.java index dfbccd3..4c18b3f 100644 --- a/src/test/java/ch/fhnw/kry/SPNTest.java +++ b/src/test/java/ch/fhnw/kry/SPNTest.java @@ -73,16 +73,4 @@ class SPNTest { assertEquals(y, spn.encryptBlock(key, x)); assertEquals(x, spn.decryptBlock(key, y)); } - - @Test - void strToArray() { - var spn = new SPN(); - - String input = "00000100110100100000101110111000000000101000111110001110011111110110000001010001010000111010000000010011011001110010101110110000"; - int[] data = spn.strToArray(input); - - assertEquals(8, data.length); - assertEquals(0x04D2, data[0]); - assertEquals(0x2BB0, data[data.length - 1]); - } }