public static void Do() { Console.WriteLine($"SPN: rounds {SubstitutionPermutationNetwork.RoundsCount}, blocksize {SubstitutionPermutationNetwork.BlockSizeBytes * 8 } bits"); var expectedKey = SubstitutionPermutationNetwork.GenerateRandomKey(); Console.WriteLine($"key: {expectedKey.ToHexUpperCase()}"); var spn = new SubstitutionPermutationNetwork(expectedKey); var plainTextString = new string('X', SubstitutionPermutationNetwork.BlockSizeBytes); var plainText = Encoding.ASCII.GetBytes(plainTextString); var encryptedBytes = spn.EncryptBlock(plainText); var decryptedBytes = spn.DecryptBlock(encryptedBytes); var decryptedString = Encoding.ASCII.GetString(decryptedBytes); Console.WriteLine($"{plainTextString} -> {encryptedBytes.ToHexUpperCase()} -> {decryptedString}"); HackCipher(spn, expectedKey, 6000); }
static void Main(string[] args) { // ProofOfConecpt.Do(); // return; if (args.Length < 1) { Console.WriteLine("Usage: sploit.exe <fileToDecrypt> [expectedKey]"); Environment.Exit(1); } var expectedKey = args.Length >= 2 ? File.ReadAllBytes(args[1]) : new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; byte[] imageBytes; try { imageBytes = File.ReadAllBytes(args[0]); } catch (Exception e) { Console.WriteLine($"Can't read data from file {args[0]}", e); Environment.Exit(1); return; } var spn = new SubstitutionPermutationNetwork(SubstitutionPermutationNetwork.GenerateRandomKey()); var pairs = GeneratePlainEncryptedPairs(imageBytes); var plains = pairs.Select(tuple => tuple.Item1).ToArray(); var encs = pairs.Select(tuple => tuple.Item2).ToArray(); var linearCryptoanalysis = new LinearCryptoanalysis(spn); var bestLayerApproximations = linearCryptoanalysis.ChooseBestPathsStartingFromSingleSBoxInRound0(Exploit.maxSBoxesInLastRound, Exploit.maxSBoxesInRound, Exploit.thresholdBias).ToList(); Console.WriteLine($"Total approximations: {bestLayerApproximations.Count}"); var solutions = new List <Solution>(); foreach (var approximationsGroup in bestLayerApproximations .Where(layer => layer.round0sboxNum % 8 == 3 || (layer.round0sboxNum % 8 == 4 && ((layer.round0x & 0x01) == 0))) .GroupBy(layer => layer.ActivatedSboxesNums.Aggregate("", (s, num) => s + num)) .OrderBy(group => group.Key)) { foreach (var approximation in approximationsGroup.Distinct().OrderByDescending(layer => layer.inputProbability.Bias()).Take(6)) { solutions.AddRange(Exploit.HackApproximation(plains, encs, approximation, expectedKey)); } } var solutionsDict = Exploit.OrderSolutions(solutions, expectedKey); var imageLength = imageBytes.Length - SubstitutionPermutationNetwork.GenerateRandomIV().Length; if (imageLength >= 65536) { throw new Exception("Unexpected image ciphertext length"); } Console.WriteLine("\nBruting left bits.."); var plaintextPrefixFrom4 = new byte[] { 0, 0, 0, 0, 0, 0, 0x36, 0, 0, 0 }; var hackedKey = GetFinalSolution(solutionsDict, imageBytes.Take(24).ToArray(), plaintextPrefixFrom4); if (hackedKey != null) { Console.WriteLine($"\nHACKED KEY: {hackedKey.ToHexUpperCase()}"); } else { Console.WriteLine("BAD LUCK. Key not hacked"); } }
public static List <Solution> HackApproximation(byte[][] plains, byte[][] encs, Layer bestLayerApproximation, byte[] expectedKey) { int iterationsCount = plains.Length; Console.WriteLine($"\nBEST OPTION: round0sboxNum {bestLayerApproximation.round0sboxNum}\tround0x {bestLayerApproximation.round0x}\tround0y {bestLayerApproximation.round0y}\tbias {bestLayerApproximation.inputProbability.Bias()}\toutSBoxes {string.Join(",", bestLayerApproximation.ActivatedSboxesNums)}\tLastRoundInputBits {SubstitutionPermutationNetwork.GetBitString(bestLayerApproximation.inputBits)}"); var targetPartialSubkeys = GenerateTargetPartialSubkeys(bestLayerApproximation.ActivatedSboxesNums) .Select(targetPartialSubkey => (targetPartialSubkey, SubstitutionPermutationNetwork.GetBytesBigEndian(targetPartialSubkey))) .ToList(); var keyProbabilities = targetPartialSubkeys .ToDictionary(u => u.Item1, u => 0); var hackingSubstitutionPermutationNetwork = new SubstitutionPermutationNetwork(SubstitutionPermutationNetwork.GenerateRandomKey()); for (int i = 0; i < plains.Length; i++) { if (i > 0 && i % (plains.Length / 4) == 0) { Console.WriteLine($" done {i} iterations of {iterationsCount}"); } var plain = plains[i]; var enc = encs[i]; HackIteration(plain, enc, bestLayerApproximation.round0sboxNum, bestLayerApproximation.round0x, bestLayerApproximation.inputBits, targetPartialSubkeys, hackingSubstitutionPermutationNetwork, keyProbabilities); } return(GetSolutions(bestLayerApproximation, keyProbabilities, expectedKey, iterationsCount)); }