/// <summary> /// Apply the low level DES encryption algorithm to a WorkingSet with the calculated RoundKeys. /// </summary> /// <param name="workingSet">Contains the information needed in the encryption process</param> /// <param name="keySet">Set of the 16 RoundKeys needed for encryption</param> private void LowLevelDesAlgorithm(WorkingSet workingSet, KeySet keySet) { // Declaration of local variables int tableOffset; int arrayOffset; int permOffset; int byteOffset; int bitOffset; // Permute with byteIP for (tableOffset = 0; tableOffset < byteIP.Length; tableOffset++) { // Get perm offset permOffset = byteIP[tableOffset]; permOffset--; // Get and set bit workingSet.ip.SetBit( BitAddressToByteOffset(tableOffset, 8), BitAddressToBitOffset(tableOffset, 8), workingSet.inputBlock.GetBit( BitAddressToByteOffset(permOffset, 8), BitAddressToBitOffset(permOffset, 8) ) ); } // Create Ln[0] and Rn[0] for (arrayOffset = 0; arrayOffset < 32; arrayOffset++) { byteOffset = BitAddressToByteOffset(arrayOffset, 8); bitOffset = BitAddressToBitOffset(arrayOffset, 8); workingSet.ln[0].SetBit(byteOffset, bitOffset, workingSet.ip.GetBit(byteOffset, bitOffset)); workingSet.rn[0].SetBit(byteOffset, bitOffset, workingSet.ip.GetBit(byteOffset + 4, bitOffset)); } // Loop through 17 interations for (int blockOffset = 1; blockOffset < 17; blockOffset++) { // Get the array offset int iKeyOffset = blockOffset; // Set Ln[N] = Rn[N-1] workingSet.ln[blockOffset].Set(workingSet.rn[blockOffset - 1]); // Set Rn[N] = Ln[0] + f(R[N-1],K[N]) for (tableOffset = 0; tableOffset < byteE.Length; tableOffset++) { // Get perm offset permOffset = byteE[tableOffset]; permOffset--; // Get and set bit workingSet.rnExpand.SetBit( BitAddressToByteOffset(tableOffset, 6), BitAddressToBitOffset(tableOffset, 6), workingSet.rn[blockOffset - 1].GetBit( BitAddressToByteOffset(permOffset, 8), BitAddressToBitOffset(permOffset, 8) ) ); } //Fill String Attribute roundDetails[blockOffset - 1, 0] = workingSet.rnExpand.ToBinaryString(48, 7); // XOR expanded block with K-block workingSet.xorBlock.Xor(workingSet.rnExpand, keySet.GetAt(iKeyOffset)); //Fill String Attribute roundDetails[blockOffset - 1, 1] = workingSet.xorBlock.ToBinaryString(48, 7); // Set S-Box values workingSet.sBoxValues.Reset(); for (tableOffset = 0; tableOffset < 8; tableOffset++) { //Fill String Attribute sBoxStringDetails[blockOffset - 1, tableOffset * 4] = Convert.ToString(workingSet.xorBlock.data[tableOffset], 2).PadLeft(8, '0').Remove(6, 2); // Calculate m and n int m = ((workingSet.xorBlock.GetBit(tableOffset, 7) ? 1 : 0) << 1) | (workingSet.xorBlock.GetBit(tableOffset, 2) ? 1 : 0); int n = (workingSet.xorBlock.data[tableOffset] >> 3) & 0x0F; // Get s-box value permOffset = byteSBox[(tableOffset * 4) + m, n]; workingSet.sBoxValues.data[tableOffset] = (byte)(permOffset << 4); //Fill String Attributes sBoxNumberDetails[blockOffset - 1, tableOffset * 3] = (byte)(m); sBoxStringDetails[blockOffset - 1, (tableOffset * 4) + 1] = Convert.ToString(m, 2).PadLeft(2, '0'); sBoxNumberDetails[blockOffset - 1, (tableOffset * 3) + 1] = (byte)(n); sBoxStringDetails[blockOffset - 1, (tableOffset * 4) + 2] = Convert.ToString(n, 2).PadLeft(4, '0'); sBoxNumberDetails[blockOffset - 1, (tableOffset * 3) + 2] = (byte)(workingSet.sBoxValues.data[tableOffset] >> 4); sBoxStringDetails[blockOffset - 1, (tableOffset * 4) + 3] = Convert.ToString((byte)(workingSet.sBoxValues.data[tableOffset] >> 4), 2).PadLeft(4, '0'); } //Fill String Attributes roundDetails[blockOffset - 1, 2] = workingSet.sBoxValues.ToBinaryString(32, 5); // Permute with P -> f workingSet.f.Reset(); for (tableOffset = 0; tableOffset < byteP.Length; tableOffset++) { // Get perm offset permOffset = byteP[tableOffset]; permOffset--; // Get and set bit workingSet.f.SetBit( BitAddressToByteOffset(tableOffset, 4), BitAddressToBitOffset(tableOffset, 4), workingSet.sBoxValues.GetBit( BitAddressToByteOffset(permOffset, 4), BitAddressToBitOffset(permOffset, 4) ) ); } //Fill String Attributes roundDetails[blockOffset - 1, 3] = workingSet.f.ToBinaryString(32, 5); // Rn[N] = Ln[N-1] ^ f workingSet.rn[blockOffset].Reset(); for (tableOffset = 0; tableOffset < 8; tableOffset++) { // Get Ln[N-1] -> A byte a = workingSet.ln[blockOffset - 1].data[(tableOffset >> 1)]; if ((tableOffset % 2) == 0) { a >>= 4; } else { a &= 0x0F; } // Get f -> B byte b = Convert.ToByte(workingSet.f.data[tableOffset] >> 4); // Update Rn[N] if ((tableOffset % 2) == 0) { workingSet.rn[blockOffset].data[tableOffset >> 1] |= Convert.ToByte((a ^ b) << 4); } else { workingSet.rn[blockOffset].data[tableOffset >> 1] |= Convert.ToByte(a ^ b); } } } // X = R16 L16 workingSet.x.Reset(); for (tableOffset = 0; tableOffset < 4; tableOffset++) { workingSet.x.data[tableOffset] = workingSet.rn[16].data[tableOffset]; workingSet.x.data[tableOffset + 4] = workingSet.ln[16].data[tableOffset]; } // C = X perm IP workingSet.outputBlock.Reset(); for (tableOffset = 0; tableOffset < byteFP.Length; tableOffset++) { // Get perm offset permOffset = byteFP[tableOffset]; permOffset--; // Get and set bit workingSet.outputBlock.SetBit( BitAddressToByteOffset(tableOffset, 8), BitAddressToBitOffset(tableOffset, 8), workingSet.x.GetBit( BitAddressToByteOffset(permOffset, 8), BitAddressToBitOffset(permOffset, 8) ) ); } outputCiphertext = workingSet.outputBlock.data; //Fill String Attribute ciphertext = workingSet.outputBlock.ToBinaryString(64, 0); //Fill String Attributes if (textChanged) { for (int i = 0; i < 17; i++) { lrDataB[i, 0] = workingSet.ln[i].ToBinaryString(32, 0); lrDataB[i, 1] = workingSet.rn[i].ToBinaryString(32, 0); } //MessageBox.Show(lrDataB[1, 0] + lrDataB[1, 1]); } else { for (int i = 0; i < 17; i++) { lrData[i, 0] = workingSet.ln[i].ToBinaryString(32, 0); lrData[i, 1] = workingSet.rn[i].ToBinaryString(32, 0); } // MessageBox.Show(lrData[1, 0] + lrData[1, 1]); } }
/// <summary> /// Expand an 8 byte DES key into a set of permuted round keys. /// </summary> /// <param name="key">8 byte DES key</param> /// <returns>KeySet instance containing the round keys</returns> private KeySet ExpandKey(byte[] key) { // Declare return variable KeySet tmp = new KeySet(); // Declaration of local variables int tableOffset, arrayOffset, permOffset, byteOffset, bitOffset; bool bit; // Put key into an 8-bit block ByteBlock k = new ByteBlock(); k.Set(key, 0); //Fill String Attribute this.key = k.ToBinaryString(64, 0); // Permutate Kp with PC1 ByteBlock kp = new ByteBlock(); for (arrayOffset = 0; arrayOffset < bytePC1.Length; arrayOffset++) { // Get permute offset permOffset = bytePC1[arrayOffset]; permOffset--; // Get and set bit kp.SetBit( BitAddressToByteOffset(arrayOffset, 7), BitAddressToBitOffset(arrayOffset, 7), k.GetBit( BitAddressToByteOffset(permOffset, 8), BitAddressToBitOffset(permOffset, 8) ) ); } // Create 17 blocks of C and D from Kp ByteBlock[] kpCn = new ByteBlock[17]; ByteBlock[] kpDn = new ByteBlock[17]; for (arrayOffset = 0; arrayOffset < 17; arrayOffset++) { kpCn[arrayOffset] = new ByteBlock(); kpDn[arrayOffset] = new ByteBlock(); } for (arrayOffset = 0; arrayOffset < 32; arrayOffset++) { // Set bit in KpCn byteOffset = BitAddressToByteOffset(arrayOffset, 8); bitOffset = BitAddressToBitOffset(arrayOffset, 8); bit = kp.GetBit(byteOffset, bitOffset); kpCn[0].SetBit(byteOffset, bitOffset, bit); // Set bit in KpDn bit = kp.GetBit(byteOffset + 4, bitOffset); kpDn[0].SetBit(byteOffset, bitOffset, bit); } for (arrayOffset = 1; arrayOffset < 17; arrayOffset++) { // Shift left wrapped kpCn[arrayOffset].ShiftLeftWrapped(kpCn[arrayOffset - 1], byteShifts[arrayOffset - 1]); kpDn[arrayOffset].ShiftLeftWrapped(kpDn[arrayOffset - 1], byteShifts[arrayOffset - 1]); } // Fill Cn und Dn binary strings into KeySchedule for (arrayOffset = 0; arrayOffset < 17; arrayOffset++) { keySchedule[arrayOffset, 0] = kpCn[arrayOffset].ToBinaryString(29, 8).Remove(28, 1); keySchedule[arrayOffset, 1] = kpDn[arrayOffset].ToBinaryString(29, 8).Remove(28, 1); } // Create 17 keys Kn for (arrayOffset = 0; arrayOffset < 17; arrayOffset++) { // Loop through the bits for (tableOffset = 0; tableOffset < 48; tableOffset++) { // Get address of bit permOffset = bytePC2[tableOffset]; permOffset--; // Convert to byte and bit offsets byteOffset = BitAddressToByteOffset(permOffset, 7); bitOffset = BitAddressToBitOffset(permOffset, 7); // Get bit if (byteOffset < 4) { bit = kpCn[arrayOffset].GetBit(byteOffset, bitOffset); } else { bit = kpDn[arrayOffset].GetBit(byteOffset - 4, bitOffset); } // Set bit byteOffset = BitAddressToByteOffset(tableOffset, 6); bitOffset = BitAddressToBitOffset(tableOffset, 6); tmp.GetAt(arrayOffset).SetBit(byteOffset, bitOffset, bit); } } // Fill in binary strings into RoundKeys for (arrayOffset = 0; arrayOffset < 16; arrayOffset++) { roundKeys[arrayOffset] = tmp.GetAt(arrayOffset + 1).ToBinaryString(48, 7); } // Return filled KeySet variable tmp return(tmp); }