private void LowLevelDesAlgorithm(WorkingSet workingSet, KeySet[] keySets, bool bEncrypt) { // // Apply 1 or 3 keys to a block of data // // Loop through keys for (int iKeySetOffset = 0; iKeySetOffset < keySets.Length; iKeySetOffset++) { // Permute with byteIP workingSet.IP.Reset(); int tableOffset; int iPermOffset; for (tableOffset = 0; tableOffset < DESTables.Ip.Length; tableOffset++) { // Get perm offset iPermOffset = DESTables.Ip[tableOffset]; iPermOffset--; // Get and set bit workingSet.IP.SetBit( BitAddressToByteOffset(tableOffset, 8), BitAddressToBitOffset(tableOffset, 8), workingSet.DataBlockOut.GetBit( BitAddressToByteOffset(iPermOffset, 8), BitAddressToBitOffset(iPermOffset, 8) ) ); } // Create Ln[0] and Rn[0] workingSet.Ln[0].Reset(); workingSet.Rn[0].Reset(); int iArrayOffset; for (iArrayOffset = 0; iArrayOffset < 32; iArrayOffset++) { int byteOffset = BitAddressToByteOffset(iArrayOffset, 8); int bitOffset = BitAddressToBitOffset(iArrayOffset, 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 iBlockOffset = 1; iBlockOffset < 17; iBlockOffset++) { // Get the array offset int iKeyOffset; if (bEncrypt != (iKeySetOffset == 1)) iKeyOffset = iBlockOffset; else iKeyOffset = 17 - iBlockOffset; // Set Ln[N] = Rn[N-1] workingSet.Ln[iBlockOffset].Set(workingSet.Rn[iBlockOffset - 1]); // Set Rn[N] = Ln[0] + f(R[N-1],K[N]) for (tableOffset = 0; tableOffset < DESTables.E.Length; tableOffset++) { // Get perm offset iPermOffset = DESTables.E[tableOffset]; iPermOffset--; // Get and set bit workingSet.RnExpand.SetBit( BitAddressToByteOffset(tableOffset, 6), BitAddressToBitOffset(tableOffset, 6), workingSet.Rn[iBlockOffset - 1].GetBit( BitAddressToByteOffset(iPermOffset, 8), BitAddressToBitOffset(iPermOffset, 8) ) ); } // XOR expanded block with K-block if (bEncrypt != (iKeySetOffset == 1)) workingSet.XorBlock.Xor(workingSet.RnExpand, keySets[iKeySetOffset].GetAt(iKeyOffset)); else workingSet.XorBlock.Xor(workingSet.RnExpand, keySets[keySets.Length - 1 - iKeySetOffset].GetAt(iKeyOffset)); // Set S-Box values workingSet.SBoxValues.Reset(); for (tableOffset = 0; tableOffset < 8; tableOffset++) { // 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 iPermOffset = DESTables.SBox[(tableOffset * 4) + m, n]; workingSet.SBoxValues._data[tableOffset] = (byte)(iPermOffset << 4); } // Permute with P -> f workingSet.f.Reset(); for (tableOffset = 0; tableOffset < DESTables.P.Length; tableOffset++) { // Get perm offset iPermOffset = DESTables.P[tableOffset]; iPermOffset--; // Get and set bit workingSet.f.SetBit( BitAddressToByteOffset(tableOffset, 4), BitAddressToBitOffset(tableOffset, 4), workingSet.SBoxValues.GetBit( BitAddressToByteOffset(iPermOffset, 4), BitAddressToBitOffset(iPermOffset, 4) ) ); } // Rn[N] = Ln[N-1] ^ f workingSet.Rn[iBlockOffset].Reset(); for (tableOffset = 0; tableOffset < 8; tableOffset++) { // Get Ln[N-1] -> A byte a = workingSet.Ln[iBlockOffset - 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[iBlockOffset]._data[tableOffset >> 1] |= Convert.ToByte((a ^ b) << 4); else workingSet.Rn[iBlockOffset]._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.DataBlockOut.Reset(); for (tableOffset = 0; tableOffset < DESTables.Rfp.Length; tableOffset++) { // Get perm offset iPermOffset = DESTables.Rfp[tableOffset]; iPermOffset--; // Get and set bit workingSet.DataBlockOut.SetBit( BitAddressToByteOffset(tableOffset, 8), BitAddressToBitOffset(tableOffset, 8), workingSet.X.GetBit( BitAddressToByteOffset(iPermOffset, 8), BitAddressToBitOffset(iPermOffset, 8) ) ); } } }
protected void DESAlgorithm(byte[] bufferIn, ref byte[] bufferOut, KeySet[] keySets, bool encrypt) { // // Apply the DES algorithm to each block // // Declare a workset set of variables WorkingSet workingSet = new WorkingSet(); // encode/decode blocks int iBufferPos = 0; while (true) { // Check buffer position if (encrypt) { // If end of buffer... if (iBufferPos >= bufferOut.Length) break; // Calulate remaining bytes int iRemainder = (bufferIn.Length - iBufferPos); if (iRemainder >= 8) workingSet.DataBlockIn.Set(bufferIn, iBufferPos); else { // Copy part-block workingSet.DataBlockIn.Reset(); if (iRemainder > 0) Array.Copy(bufferIn, iBufferPos, workingSet.DataBlockIn._data, 0, iRemainder); // Get the padding byte byte padding = Convert.ToByte(KEY_BYTE_LENGTH - iRemainder); // Add padding to block for (int byteOffset = iRemainder; byteOffset < KEY_BYTE_LENGTH; byteOffset++) workingSet.DataBlockIn._data[byteOffset] = padding; } } else { // If end of buffer... if (iBufferPos >= bufferIn.Length) break; // Get the next block workingSet.DataBlockIn.Set(bufferIn, iBufferPos); } // if encrypting and not the first block... if ((encrypt) && (iBufferPos > 0)) { // Apply succession => XOR M with previous block workingSet.DataBlockIn.Xor(workingSet.DataBlockOut, workingSet.DataBlockIn); } // Apply the algorithm workingSet.DataBlockOut.Set(workingSet.DataBlockIn); LowLevelDesAlgorithm(workingSet, keySets, encrypt); // If decrypting... if (!encrypt) { // Retain the succession if (iBufferPos > 0) workingSet.DataBlockOut.Xor(workingSet.DecryptXorBlock, workingSet.DataBlockOut); // Retain the last block workingSet.DecryptXorBlock.Set(workingSet.DataBlockIn); } // Update buffer out Array.Copy(workingSet.DataBlockOut._data, 0, bufferOut, iBufferPos, 8); // Move on iBufferPos += 8; } // Scrub the working set workingSet.Scrub(); }