/// <summary> /// Due to size, data for challenge 4 is hardcoded into the class /// </summary> /// <param name="input"></param> /// <returns></returns> public string DoChallenge04() { SingleCharXORResult bestResult = new SingleCharXORResult(); foreach (string stringToTest in workingSet) { //Do what 3 does, but keep our own high score SingleCharXORDecoder decoder = new SingleCharXORDecoder(); decoder.TestAllKeys(stringToTest); if (decoder.BestResults.Rating > bestResult.Rating) { bestResult = decoder.BestResults; } } return(string.Format("Key: {0}. Input string: {1}. Output string: {2}.", bestResult.BestKey, bestResult.InputString, bestResult.DecodedString.TrimEnd())); }
/// <summary> /// /// </summary> /// <returns></returns> public string DoChallenge06() { //Get the byte array out of the encrypted data byte[] encryptedData = Convert.FromBase64String(base64EncryptedData); int lowestKeySize = RepeatingKeyXOR.FindKeySize_CopyFromInternet(encryptedData); // //Now the encryption key's length is probably known -- lowestKeySize // int numBlocksNeeded = (int)Math.Ceiling((double)encryptedData.Length / (double)lowestKeySize); //Break up the source into blocks of this size byte[][] blocks = new byte[numBlocksNeeded][]; for (int i = 0; i < numBlocksNeeded; i++) { int blockLen = lowestKeySize; if (i == numBlocksNeeded - 1) { //special case for last block - it may be shorter blockLen = encryptedData.Length % lowestKeySize; } blocks[i] = new byte[blockLen]; Array.Copy(encryptedData, i * lowestKeySize, blocks[i], 0, blockLen); } // //Assuming we guessed the right key size, we now have a series of blocks that should each be decryptable with the full key // byte[][] transposed = new byte[lowestKeySize][]; //The first array is numBlocksNeeded arrays of lowestKeySize bytes. e.g. blocks[576][5] //The transposed array is the reverse -- lowestKeySize arrays of numBlocksNeeded bytes. e.g. blocks[5][576] int transposedBlockLength = numBlocksNeeded; //Initialize first for (int i = 0; i < lowestKeySize; i++) { transposed[i] = new byte[transposedBlockLength]; } for (int block = 0; block < numBlocksNeeded; block++) { for (int keyIndex = 0; keyIndex < lowestKeySize; keyIndex++) { //Bounds check for our possibly-truncated last block if (blocks[block].Length > keyIndex) { transposed[keyIndex][block] = blocks[block][keyIndex]; } } } // //We now have a new series of transposed blocks that are each decryptable by a single character // StringBuilder sb = new StringBuilder(); foreach (byte[] bytes in transposed) { SingleCharXORDecoder decoder = new SingleCharXORDecoder(); decoder.TestAllKeys(bytes); SingleCharXORResult result = decoder.BestResults; sb.Append(result.BestKey); } string encryptionKey = sb.ToString(); return(encryptionKey); }