public void Challenge3_SingleByteXorCipher() { const string cipherHex = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736"; var cipherData = Utils.HexToByteArray(cipherHex); double error; var plainText = SingleByteXorCracker.Crack(cipherData, out error); const string expected = "Cooking MC's like a pound of bacon"; Assert.AreEqual(expected, plainText); }
public void Challenge6_BreakRepeatingKeyXor() { var data = Utils.GetResourceBase64("RepeatingKeyXor.txt"); var keySizes = Enumerable.Range(2, 40); // this is slightly different than the approach described in the challenge. We // convolve the data against itself and look for the lowest "energy" step. This // is likely where the repeating keys overlap and the plaintext pattern emerges. var convolvedKeySizes = keySizes.ToDictionary(keySize => keySize, keySize => { var padding = Enumerable.Repeat((byte)0, keySize).ToArray(); return(Utils.Hamming(padding.Concat(data), data.Concat(padding))); }).OrderBy(pair => pair.Value); var topKeySizes = convolvedKeySizes.Select(pair => pair.Key).Take(1); // distribute data into bins that align with first key byte, second key byte, etc. var transposedBlocks = topKeySizes.Select( keySize => Enumerable.Range(0, keySize) .Select(keyOffset => data.Where((x, i) => i % keySize == keyOffset).ToArray())); var keySizeKeyErrors = transposedBlocks.Select(pair => pair.Select(k => { byte key; double error; var result = SingleByteXorCracker.Crack(k, out error, out key); return(new { Result = result, Key = key, Error = error }); })); var possibleKeys = keySizeKeyErrors.Select(k => k.Select(r => r.Key).ToArray()); var plaintexts = possibleKeys.ToDictionary(key => key, key => { var transform = new XorCryptoTransform(key); var stream = new MemoryStream(data); using (var cryptoStream = new CryptoStream(stream, transform, CryptoStreamMode.Read)) { using (var reader = new StreamReader(cryptoStream)) return(reader.ReadToEnd()); } }); var actual = plaintexts.First().Value; var expected = Utils.GetResourceText("Set1PlainText.txt"); Assert.AreEqual(expected, actual); }
public void Challenge4_DetectSingleCharacterXor() { var lines = Utils.GetResourceLines("DetectSingleCharacterXor.txt"); var lineData = lines.Select(Utils.HexToByteArray); var errors = lineData.Select(line => { double error; var result = SingleByteXorCracker.Crack(line, out error); return(new { Result = result, Error = error }); }).OrderBy(line => line.Error); var best = errors.First(); const string expected = "Now that the party is jumping\n"; Assert.AreEqual(expected, best.Result); }