public static BitString16 forwardPermutation(BitString16 bitString) { String input = bitString.BitString; String output = ""; output += input[1 - 1]; //1st bit output += input[5 - 1]; //2nd bit output += input[9 - 1]; output += input[13 - 1]; output += input[2 - 1]; output += input[6 - 1]; output += input[10 - 1]; output += input[14 - 1]; output += input[3 - 1]; output += input[7 - 1]; output += input[11 - 1]; output += input[15 - 1]; output += input[4 - 1]; output += input[8 - 1]; output += input[12 - 1]; output += input[16 - 1]; return(new BitString16(output)); }
//Decrypt a ciphertext using a key and the 4 round SPN public static BitString16 Decrypt(BitString16 ciphertext, Key key) { SBox sbox = new SBox(); //Pre BitString16 first_subkey = key.getDecryptionSubKey(1); BitString16 plaintext = Util.xor(ciphertext, first_subkey); //Round 1 BitString16 second_subkey = key.getDecryptionSubKey(2); plaintext = sbox.backwardsTransform(plaintext); plaintext = Util.xor(plaintext, second_subkey); //Rounds 2-4 for (int round = 2; round < 5; ++round) { BitString16 subkey = key.getDecryptionSubKey(round + 1); plaintext = Permutation.backwardsPermutation(plaintext); plaintext = sbox.backwardsTransform(plaintext); plaintext = Util.xor(plaintext, subkey); } return(plaintext); }
//Encrypt a message under a key using the 4 round SPN public static BitString16 Encrypt(BitString16 message, Key key) { SBox sbox = new SBox(); //Rounds 1-3 for (int round = 1; round < 4; ++round) { BitString16 subkey = key.getEncryptionSubKey(round); message = Util.xor(message, subkey); message = sbox.forwardTransform(message); message = Permutation.forwardPermutation(message); } //Round 4 BitString16 subkey_4 = key.getEncryptionSubKey(4); message = Util.xor(message, subkey_4); message = sbox.forwardTransform(message); //Post BitString16 last_subkey = key.getEncryptionSubKey(5); message = Util.xor(message, last_subkey); return(message); }
static void Main(string[] args) { Random rand = new Random(); //Random number generator which will be used to randomize the key /* * Generate the round keys. For this SPN the keys bits are random and independent. * However, we fix K5 such that [K(5,5)...K(5,8) , K(5,13)...K(5,16)] = [3,1] */ List <BitString16> keys = new List <BitString16>(); //Temporary storage container for the keys keys.Add(new BitString16(rand)); //Round 1 key (random) keys.Add(new BitString16(rand)); //Round 2 key (random) keys.Add(new BitString16(rand)); //Round 3 key (random) keys.Add(new BitString16(rand)); //Round 4 key (random) keys.Add(new BitString16("0000001100000001")); //Round 5 key (fixed) Key key = new Key(keys); //Create an instance of SBox which will be used by the SPN SBox sbox = new SBox(); Dictionary <String, String> plain_cipher_pairs = new Dictionary <string, string>(); //Plaintext/Ciphertext pairs StreamWriter writer = new StreamWriter("pairs.txt"); //Text writer //Generate 10,000 Plaintext/Ciphertext pairs while (plain_cipher_pairs.Keys.Count < 10000) { BitString16 message = new BitString16(rand); //Generate a random message to encrypt //Check if we have already encrypted this plaintext. If so, skip this iteration of the loop //Without this check we may end up with duplicate plain/ciphertext pairs if (plain_cipher_pairs.ContainsKey(message.BitString)) { continue; } //Encrypt the message via the four round SPN BitString16 encrypt_message = FourRoundSPN.Encrypt(message, key); //Extract the plaintext/ciphertext strings from the objects String plaintext = message.BitString; String ciphertext = encrypt_message.BitString; //Write the pair to the textfile and store in the dictionary for further processing writer.WriteLine("{0},{1}", plaintext, ciphertext); plain_cipher_pairs.Add(plaintext, ciphertext); } writer.Close(); //Using only the plaintext/ciphertext pairs, perform linear cryptanalysis BitString16 r5BitString = LinearCryptanalysis.PerformLinearCryptanalysis(plain_cipher_pairs); String r5Key = r5BitString.BitString; String subkey1 = r5Key.Substring(4, 4); String subkey2 = r5Key.Substring(12, 4); System.Console.WriteLine("RESULT OF LINEAR CRYPTANALYSIS:\nK[5,5]-K[5,8] = {0}\nK[5,13]-K[5,16] = {1}", subkey1, subkey2); }
static void Main(string[] args) { Random rand = new Random(); //Random number generator which will be used to randomize the key /* * Generate the round keys. For this SPN the keys bits are random and independent. * However, we fix K5 such that [K(5,5)...K(5,8) , K(5,13)...K(5,16)] = [3,1] */ List<BitString16> keys = new List<BitString16>(); //Temporary storage container for the keys keys.Add(new BitString16(rand)); //Round 1 key (random) keys.Add(new BitString16(rand)); //Round 2 key (random) keys.Add(new BitString16(rand)); //Round 3 key (random) keys.Add(new BitString16(rand)); //Round 4 key (random) keys.Add(new BitString16("0000001100000001")); //Round 5 key (fixed) Key key = new Key(keys); //Create an instance of SBox which will be used by the SPN SBox sbox = new SBox(); Dictionary<String, String> plain_cipher_pairs = new Dictionary<string, string>(); //Plaintext/Ciphertext pairs StreamWriter writer = new StreamWriter("pairs.txt"); //Text writer //Generate 10,000 Plaintext/Ciphertext pairs while (plain_cipher_pairs.Keys.Count < 10000) { BitString16 message = new BitString16(rand); //Generate a random message to encrypt //Check if we have already encrypted this plaintext. If so, skip this iteration of the loop //Without this check we may end up with duplicate plain/ciphertext pairs if (plain_cipher_pairs.ContainsKey(message.BitString)) continue; //Encrypt the message via the four round SPN BitString16 encrypt_message = FourRoundSPN.Encrypt(message, key); //Extract the plaintext/ciphertext strings from the objects String plaintext = message.BitString; String ciphertext = encrypt_message.BitString; //Write the pair to the textfile and store in the dictionary for further processing writer.WriteLine("{0},{1}", plaintext, ciphertext); plain_cipher_pairs.Add(plaintext, ciphertext); } writer.Close(); //Using only the plaintext/ciphertext pairs, perform linear cryptanalysis BitString16 r5BitString = LinearCryptanalysis.PerformLinearCryptanalysis(plain_cipher_pairs); String r5Key = r5BitString.BitString; String subkey1 = r5Key.Substring(4, 4); String subkey2 = r5Key.Substring(12, 4); System.Console.WriteLine("RESULT OF LINEAR CRYPTANALYSIS:\nK[5,5]-K[5,8] = {0}\nK[5,13]-K[5,16] = {1}", subkey1, subkey2); }
static BitString16 partial_decrypt(BitString16 ciphertext, BitString16 key) { SBox sbox = new SBox(); //Pre BitString16 plaintext = Util.xor(ciphertext, key); //Round 1 plaintext = sbox.backwardsTransform(plaintext); return plaintext; }
public BitString16 forwardTransform(BitString16 bitString) { String input = bitString.BitString; String output = ""; for (int i = 0; i < 4; ++i) { String subBlock = input.Substring(i * 4, 4); output += sBoxMapping[subBlock]; } return(new BitString16(output)); }
static BitString16 partial_decrypt(BitString16 ciphertext, BitString16 key) { SBox sbox = new SBox(); //Pre BitString16 plaintext = Util.xor(ciphertext, key); //Round 1 plaintext = sbox.backwardsTransform(plaintext); return(plaintext); }
public BitString16 forwardTransform(BitString16 bitString) { String input = bitString.BitString; String output = ""; for (int i = 0; i < 4; ++i) { String subBlock = input.Substring(i * 4, 4); output += sBoxMapping[subBlock]; } return new BitString16(output); }
public BitString16 backwardsTransform(BitString16 bitString) { String input = bitString.BitString; String output = ""; for (int i = 0; i < 4; ++i) { String subBlock = input.Substring(i * 4, 4); output += sBoxMapping.First(x => x.Value.Equals(subBlock)).Key; } return(new BitString16(output)); }
public BitString16 backwardsTransform(BitString16 bitString) { String input = bitString.BitString; String output = ""; for (int i = 0; i < 4; ++i) { String subBlock = input.Substring(i * 4, 4); output += sBoxMapping.First(x => x.Value.Equals(subBlock)).Key; } return new BitString16(output); }
static bool testPartialKey(BitString16 plaintext, BitString16 partialPlaintext) { String p = plaintext.BitString; String u = partialPlaintext.BitString; //Implementation of formula 5: U[4,6] XOR U[4,8] XOR U[4,14] XOR U[4,16] XOR P[5] XOR P[7] XOR P[8] char result = Util.bit_xor(u[5], Util.bit_xor(u[7], Util.bit_xor(u[13], Util.bit_xor(u[15], Util.bit_xor(p[4], Util.bit_xor(p[6], p[7])))))); if (result == '0') { return(true); } return(false); }
public static BitString16 xor(BitString16 bs1, BitString16 bs2) { String output = ""; String s1 = bs1.BitString; String s2 = bs2.BitString; for (int i = 0; i < s1.Length; ++i) { if (s1[i] != s2[i]) output += '1'; else output += '0'; } return new BitString16(output); }
public static BitString16 PerformLinearCryptanalysis(Dictionary <String, String> plain_cipher_pairs) { //Get the list of 256 possible subkeys List <BitString16> partialSubKeys = generateAllPartialSubkeys(); double highestBias = 0; //Keep track of the highest bias String subkey = ""; //Keep track of the subkey with the highest bias //Iterate through each possible subkey and check which has the highest bias, this is the actual subkey. foreach (BitString16 partialSubKey in partialSubKeys) { int count = 0; foreach (var x in plain_cipher_pairs) { BitString16 plaintext = new BitString16(x.Key); BitString16 ciphertext = new BitString16(x.Value); BitString16 partial_decrypted = partial_decrypt(ciphertext, partialSubKey); //Check if the partially decrypted ciphertext satisfies equation 5 if (testPartialKey(plaintext, partial_decrypted)) { count++; } } double bias = Math.Abs(count - 5000.0) / 10000.0; //Get this key's bias String _subkey = partialSubKey.BitString; //Get this subkey System.Console.WriteLine("KEY: {1}, BIAS: {0}", bias, _subkey); //If this key has the highest bias so far, store it if (bias > highestBias) { highestBias = bias; subkey = _subkey; } } //Return the best subkey we found return(new BitString16(subkey)); }
public static BitString16 xor(BitString16 bs1, BitString16 bs2) { String output = ""; String s1 = bs1.BitString; String s2 = bs2.BitString; for (int i = 0; i < s1.Length; ++i) { if (s1[i] != s2[i]) { output += '1'; } else { output += '0'; } } return(new BitString16(output)); }
public static BitString16 PerformLinearCryptanalysis(Dictionary<String, String> plain_cipher_pairs) { //Get the list of 256 possible subkeys List<BitString16> partialSubKeys = generateAllPartialSubkeys(); double highestBias = 0; //Keep track of the highest bias String subkey = ""; //Keep track of the subkey with the highest bias //Iterate through each possible subkey and check which has the highest bias, this is the actual subkey. foreach (BitString16 partialSubKey in partialSubKeys) { int count = 0; foreach (var x in plain_cipher_pairs) { BitString16 plaintext = new BitString16(x.Key); BitString16 ciphertext = new BitString16(x.Value); BitString16 partial_decrypted = partial_decrypt(ciphertext, partialSubKey); //Check if the partially decrypted ciphertext satisfies equation 5 if (testPartialKey(plaintext, partial_decrypted)) count++; } double bias = Math.Abs(count - 5000.0) / 10000.0; //Get this key's bias String _subkey = partialSubKey.BitString; //Get this subkey System.Console.WriteLine("KEY: {1}, BIAS: {0}", bias, _subkey); //If this key has the highest bias so far, store it if (bias > highestBias) { highestBias = bias; subkey = _subkey; } } //Return the best subkey we found return new BitString16(subkey); }
//Encrypt a message under a key using the 4 round SPN public static BitString16 Encrypt(BitString16 message, Key key) { SBox sbox = new SBox(); //Rounds 1-3 for (int round = 1; round < 4; ++round) { BitString16 subkey = key.getEncryptionSubKey(round); message = Util.xor(message, subkey); message = sbox.forwardTransform(message); message = Permutation.forwardPermutation(message); } //Round 4 BitString16 subkey_4 = key.getEncryptionSubKey(4); message = Util.xor(message, subkey_4); message = sbox.forwardTransform(message); //Post BitString16 last_subkey = key.getEncryptionSubKey(5); message = Util.xor(message, last_subkey); return message; }
//Decrypt a ciphertext using a key and the 4 round SPN public static BitString16 Decrypt(BitString16 ciphertext, Key key) { SBox sbox = new SBox(); //Pre BitString16 first_subkey = key.getDecryptionSubKey(1); BitString16 plaintext = Util.xor(ciphertext, first_subkey); //Round 1 BitString16 second_subkey = key.getDecryptionSubKey(2); plaintext = sbox.backwardsTransform(plaintext); plaintext = Util.xor(plaintext, second_subkey); //Rounds 2-4 for (int round = 2; round < 5; ++round) { BitString16 subkey = key.getDecryptionSubKey(round + 1); plaintext = Permutation.backwardsPermutation(plaintext); plaintext = sbox.backwardsTransform(plaintext); plaintext = Util.xor(plaintext, subkey); } return plaintext; }
static bool testPartialKey(BitString16 plaintext, BitString16 partialPlaintext) { String p = plaintext.BitString; String u = partialPlaintext.BitString; //Implementation of formula 5: U[4,6] XOR U[4,8] XOR U[4,14] XOR U[4,16] XOR P[5] XOR P[7] XOR P[8] char result = Util.bit_xor(u[5], Util.bit_xor(u[7], Util.bit_xor(u[13], Util.bit_xor(u[15], Util.bit_xor(p[4], Util.bit_xor(p[6], p[7])))))); if (result == '0') return true; return false; }