Example #1
0
        /// <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);
        }