//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> Initializes the permutation network. </summary> /// /// <remarks> /// This is where the real work is done. The permutation network is an abstraction of a set of /// incoming wires and outgoing wires. The permutation is given in terms of those wires, but /// each indivicual wire represents a particular bit in the input. The bits represented by /// adjacent wires are separated by a value delta which is equal to 64 / (the size of the /// permutation). The first wire represents the bit indexed by phase. Thus the bit corresponding /// to wire i is phase + i * delta. Since size can be calculated by the size of the permutation /// the only thing we need to make this mapping are the phase and the permutation. Key point is /// that the permutation references wire numbers running consecutively from 0 to (size - 1), not /// actual bit positions. Darrellp, 12/7/2011. /// </remarks> /// /// <param name="permutation"> The permutation we will use to permute the bits. </param> /// <param name="phase"> The index of the first bit to be permuted. </param> //////////////////////////////////////////////////////////////////////////////////////////////////// private void Initialize(byte[] permutation, int phase) { PermutationNetwork permutationNetworkEven; PermutationNetwork permutationNetworkOdd; int size = permutation.Length; int delta = 64 / size; ulong inputMask; ulong outputMask; // Get the wiring needed for our two inner networks byte[][] permutationsInner = GetInnerPermutations(permutation, delta, phase, out inputMask, out outputMask); // Recursively create those two inner networks if (size == 4) { // The recursion ends here by creating two swappers rather than normal permutation networks permutationNetworkEven = new Swapper(permutationsInner[0], phase); permutationNetworkOdd = new Swapper(permutationsInner[1], phase + delta); } else { // For larger sizes, the inner networks are standard permutation networks permutationNetworkEven = new PermutationNetwork(permutationsInner[0], phase); permutationNetworkOdd = new PermutationNetwork(permutationsInner[1], phase + delta); } // Extract the masks from our inner permutation networks into our list of masks ExtractMasks(permutationNetworkEven, permutationNetworkOdd, inputMask, outputMask); }
public void TestPermutationNetwork() { byte[] permutation = new byte[64]; // Identity permutation for (byte i = 0; i < 64; i++) { Identity[i] = i; } for (int i1 = 0; i1 < 62; i1++) { for (int i2 = i1 + 1; i2 < 64; i2++) { TestTwoCycle(i1, i2, permutation); } } Array.Copy(Identity, permutation, 64); PermutationNetwork pnwk = new PermutationNetwork(permutation); Assert.AreEqual(56ul, pnwk.Permute(56)); // Swap unit and two's bits permutation[0] = 1; permutation[1] = 0; pnwk = new PermutationNetwork(permutation); Assert.AreEqual(1ul, pnwk.Permute(2)); Assert.AreEqual(2ul, pnwk.Permute(1)); Assert.AreEqual(3ul, pnwk.Permute(3)); Assert.AreEqual(5ul, pnwk.Permute(6)); Assert.AreEqual(6ul, pnwk.Permute(5)); // Cycle the bottom four bits permutation[0] = 1; permutation[1] = 2; permutation[2] = 3; permutation[3] = 0; pnwk = new PermutationNetwork(permutation); Assert.AreEqual(2ul, pnwk.Permute(1)); Assert.AreEqual(4ul, pnwk.Permute(2)); Assert.AreEqual(8ul, pnwk.Permute(4)); Assert.AreEqual(1ul, pnwk.Permute(8)); Assert.AreEqual(3ul, pnwk.Permute(9)); // Random permutation Random rnd = new Random(0); for (int i = 0; i < 63; i++) { int swapIndex = rnd.Next(64); byte b = permutation[i]; permutation[i] = permutation[swapIndex]; permutation[swapIndex] = b; } pnwk = new PermutationNetwork(permutation); ulong testVal = ((ulong)rnd.Next() << 32) | (uint)rnd.Next(); ulong resultVal = pnwk.Permute(testVal); TestPerm(permutation, testVal, resultVal); }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> Add this network's contribution to the mask list. </summary> /// /// <remarks> /// Extract the masks from our inner networks, interleave them and wrap the resultant list with /// our own masks. Darrellp, 12/7/2011. /// </remarks> /// /// <param name="even"> The even inner permutation network. </param> /// <param name="odd"> The odd inner permutation network. </param> /// <param name="inputMask"> Our own input mask. </param> /// <param name="outputMask"> Our own output mask. </param> //////////////////////////////////////////////////////////////////////////////////////////////////// private void ExtractMasks(PermutationNetwork even, PermutationNetwork odd, ulong inputMask, ulong outputMask) { List <ulong> masksEven = even.Masks; List <ulong> masksOdd = odd.Masks; Masks.Add(inputMask); for (int i = 0; i < masksEven.Count; i++) { Masks.Add(masksEven[i] | masksOdd[i]); } Masks.Add(outputMask); }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> Add this network's contribution to the mask list. </summary> /// /// <remarks> /// Extract the masks from our inner networks, interleave them and wrap the resultant list with /// our own masks. Darrellp, 12/7/2011. /// </remarks> /// /// <param name="even"> The even inner permutation network. </param> /// <param name="odd"> The odd inner permutation network. </param> /// <param name="inputMask"> Our own input mask. </param> /// <param name="outputMask"> Our own output mask. </param> //////////////////////////////////////////////////////////////////////////////////////////////////// private void ExtractMasks(PermutationNetwork even, PermutationNetwork odd, ulong inputMask, ulong outputMask) { List<ulong> masksEven = even.Masks; List<ulong> masksOdd = odd.Masks; Masks.Add(inputMask); for (int i = 0; i < masksEven.Count; i++) { Masks.Add(masksEven[i] | masksOdd[i]); } Masks.Add(outputMask); }
private static void TestTwoCycle(int i1, int i2, byte[] permutation) { Array.Copy(Identity, permutation, 64); permutation[i1] = (byte)i2; permutation[i2] = (byte)i1; PermutationNetwork pnwk = new PermutationNetwork(permutation); Assert.AreEqual(1UL << i2, pnwk.Permute(1UL << i1)); Assert.AreEqual(1UL << i1, pnwk.Permute(1UL << i2)); }