/// <summary> /// Sorry, I need to comment _removePadding because I implement my own padding mechanism. So I don't need the original remove padding. /// </summary> /// <param name="bufferIn"></param> /// <param name="bufferOut"></param> /// <param name="Key"></param> /// <param name="bEncrypt"></param> public static void TripleDES(byte[] bufferIn, ref byte[] bufferOut, byte[] Key, bool bEncrypt) { // Shortcuts if (!IsValidTripleDESKey(Key)) { throw new Exception("Invalid DES key."); } // Create the output buffer _createBufferOut(bufferIn.Length, ref bufferOut, bEncrypt); // Expand the keys into Kn KEY_SET[] Kn = new KEY_SET[3] { _expandKey(Key, 0), _expandKey(Key, 8), _expandKey(Key, 16) }; // Apply DES keys _desAlgorithm(bufferIn, ref bufferOut, Kn, bEncrypt); // If decrypting... //if (!bEncrypt) // _removePadding(ref bufferOut); }
private static void _desAlgorithm(byte[] bufferIn, ref byte[] bufferOut, KEY_SET[] KeySets, byte[] iv, bool bEncrypt) { // // Apply the DES algorithm to each block // // Declare a workset set of variables WORKING_SET workingSet = new WORKING_SET(); workingSet.DecryptXorBlock.Set(iv, 0); // encode/decode blocks int iBufferPos = 0; while (true) { // Check buffer position if (bEncrypt) { // 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.m_data, 0, iRemainder); // Get the padding byte byte Padding = Convert.ToByte(KEY_BYTE_LENGTH - iRemainder); // Add padding to block for (int iByteOffset = iRemainder; iByteOffset < KEY_BYTE_LENGTH; iByteOffset++) workingSet.DataBlockIn.m_data[iByteOffset] = 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 (bEncrypt) { // Apply succession => XOR M with previous block if (iBufferPos == 0) { workingSet.DataBlockIn.Xor(workingSet.DecryptXorBlock, workingSet.DataBlockIn); } else { workingSet.DataBlockIn.Xor(workingSet.DataBlockOut, workingSet.DataBlockIn); } } // Apply the algorithm workingSet.DataBlockOut.Set(workingSet.DataBlockIn); _lowLevel_desAlgorithm(workingSet, KeySets, bEncrypt); // If decrypting... if (!bEncrypt) { // Retain the succession workingSet.DataBlockOut.Xor(workingSet.DecryptXorBlock, workingSet.DataBlockOut); // Retain the last block workingSet.DecryptXorBlock.Set(workingSet.DataBlockIn); } // Update buffer out Array.Copy(workingSet.DataBlockOut.m_data, 0, bufferOut, iBufferPos, 8); // Move on iBufferPos += 8; } // Scrub the working set workingSet.Scrub(); }
private static KEY_SET _expandKey(byte[] Key, int iOffset) { // // Expand an 8 byte DES key into a set of permuted keys // // Declare return variable KEY_SET Ftmp = new KEY_SET(); // Declaration of local variables int iTableOffset, iArrayOffset, iPermOffset, iByteOffset, iBitOffset; bool bBit; // Put key into an 8-bit block BLOCK8BYTE K = new BLOCK8BYTE(); K.Set(Key, iOffset); // Permutate Kp with PC1 BLOCK8BYTE Kp = new BLOCK8BYTE(); for (iArrayOffset = 0; iArrayOffset < bytePC1.Length; iArrayOffset++) { // Get permute offset iPermOffset = bytePC1[iArrayOffset]; iPermOffset--; // Get and set bit Kp.SetBit( _bitAddressToByteOffset(iArrayOffset, 7), _bitAddressToBitOffset(iArrayOffset, 7), K.GetBit( _bitAddressToByteOffset(iPermOffset, 8), _bitAddressToBitOffset(iPermOffset, 8) ) ); } // Create 17 blocks of C and D from Kp BLOCK8BYTE[] KpCn = new BLOCK8BYTE[17]; BLOCK8BYTE[] KpDn = new BLOCK8BYTE[17]; for (iArrayOffset = 0; iArrayOffset < 17; iArrayOffset++) { KpCn[iArrayOffset] = new BLOCK8BYTE(); KpDn[iArrayOffset] = new BLOCK8BYTE(); } for (iArrayOffset = 0; iArrayOffset < 32; iArrayOffset++) { // Set bit in KpCn iByteOffset = _bitAddressToByteOffset(iArrayOffset, 8); iBitOffset = _bitAddressToBitOffset(iArrayOffset, 8); bBit = Kp.GetBit(iByteOffset, iBitOffset); KpCn[0].SetBit(iByteOffset, iBitOffset, bBit); // Set bit in KpDn bBit = Kp.GetBit(iByteOffset + 4, iBitOffset); KpDn[0].SetBit(iByteOffset, iBitOffset, bBit); } for (iArrayOffset = 1; iArrayOffset < 17; iArrayOffset++) { // Shift left wrapped KpCn[iArrayOffset].ShiftLeftWrapped(KpCn[iArrayOffset - 1], byteShifts[iArrayOffset - 1]); KpDn[iArrayOffset].ShiftLeftWrapped(KpDn[iArrayOffset - 1], byteShifts[iArrayOffset - 1]); } // Create 17 keys Kn for (iArrayOffset = 0; iArrayOffset < 17; iArrayOffset++) { // Loop through the bits for (iTableOffset = 0; iTableOffset < 48; iTableOffset++) { // Get address if bit iPermOffset = bytePC2[iTableOffset]; iPermOffset--; // Convert to byte and bit offsets iByteOffset = _bitAddressToByteOffset(iPermOffset, 7); iBitOffset = _bitAddressToBitOffset(iPermOffset, 7); // Get bit if (iByteOffset < 4) bBit = KpCn[iArrayOffset].GetBit(iByteOffset, iBitOffset); else bBit = KpDn[iArrayOffset].GetBit(iByteOffset - 4, iBitOffset); // Set bit iByteOffset = _bitAddressToByteOffset(iTableOffset, 6); iBitOffset = _bitAddressToBitOffset(iTableOffset, 6); Ftmp.GetAt(iArrayOffset).SetBit(iByteOffset, iBitOffset, bBit); } } // Return variable return Ftmp; }
public static void TripleDES(byte[] bufferIn, ref byte[] bufferOut, byte[] Key, Byte[] iv, bool bEncrypt) { // Shortcuts if (!IsValidTripleDESKey(Key) || iv.Length != 8) throw new Exception("Invalid DES key."); // Create the output buffer _createBufferOut(bufferIn.Length, ref bufferOut, bEncrypt); // Expand the keys into Kn KEY_SET[] Kn = new KEY_SET[3] { _expandKey(Key, 0), _expandKey(Key, 8), _expandKey(Key, 16) }; // Apply DES keys _desAlgorithm(bufferIn, ref bufferOut, Kn, iv, bEncrypt); // If decrypting... if (!bEncrypt) _removePadding(ref bufferOut); }
private static void _lowLevel_desAlgorithm(WORKING_SET workingSet, KEY_SET[] KeySets, bool bEncrypt) { // // Apply 1 or 3 keys to a block of data // // Declaration of local variables int iTableOffset; int iArrayOffset; int iPermOffset; int iByteOffset; int iBitOffset; // Loop through keys for (int iKeySetOffset = 0; iKeySetOffset < KeySets.Length; iKeySetOffset++) { // Permute with byteIP workingSet.IP.Reset(); for (iTableOffset = 0; iTableOffset < byteIP.Length; iTableOffset++) { // Get perm offset iPermOffset = byteIP[iTableOffset]; iPermOffset--; // Get and set bit workingSet.IP.SetBit( _bitAddressToByteOffset(iTableOffset, 8), _bitAddressToBitOffset(iTableOffset, 8), workingSet.DataBlockOut.GetBit( _bitAddressToByteOffset(iPermOffset, 8), _bitAddressToBitOffset(iPermOffset, 8) ) ); } // Create Ln[0] and Rn[0] workingSet.Ln[0].Reset(); workingSet.Rn[0].Reset(); for (iArrayOffset = 0; iArrayOffset < 32; iArrayOffset++) { iByteOffset = _bitAddressToByteOffset(iArrayOffset, 8); iBitOffset = _bitAddressToBitOffset(iArrayOffset, 8); workingSet.Ln[0].SetBit(iByteOffset, iBitOffset, workingSet.IP.GetBit(iByteOffset, iBitOffset)); workingSet.Rn[0].SetBit(iByteOffset, iBitOffset, workingSet.IP.GetBit(iByteOffset + 4, iBitOffset)); } // 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 (iTableOffset = 0; iTableOffset < byteE.Length; iTableOffset++) { // Get perm offset iPermOffset = byteE[iTableOffset]; iPermOffset--; // Get and set bit workingSet.RnExpand.SetBit( _bitAddressToByteOffset(iTableOffset, 6), _bitAddressToBitOffset(iTableOffset, 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 (iTableOffset = 0; iTableOffset < 8; iTableOffset++) { // Calculate m and n int m = ((workingSet.XorBlock.GetBit(iTableOffset, 7) ? 1 : 0) << 1) | (workingSet.XorBlock.GetBit(iTableOffset, 2) ? 1 : 0); int n = (workingSet.XorBlock.m_data[iTableOffset] >> 3) & 0x0F; // Get s-box value iPermOffset = byteSBox[(iTableOffset * 4) + m, n]; workingSet.SBoxValues.m_data[iTableOffset] = (byte)(iPermOffset << 4); } // Permute with P -> f workingSet.f.Reset(); for (iTableOffset = 0; iTableOffset < byteP.Length; iTableOffset++) { // Get perm offset iPermOffset = byteP[iTableOffset]; iPermOffset--; // Get and set bit workingSet.f.SetBit( _bitAddressToByteOffset(iTableOffset, 4), _bitAddressToBitOffset(iTableOffset, 4), workingSet.SBoxValues.GetBit( _bitAddressToByteOffset(iPermOffset, 4), _bitAddressToBitOffset(iPermOffset, 4) ) ); } // Rn[N] = Ln[N-1] ^ f workingSet.Rn[iBlockOffset].Reset(); for (iTableOffset = 0; iTableOffset < 8; iTableOffset++) { // Get Ln[N-1] -> A byte A = workingSet.Ln[iBlockOffset - 1].m_data[(iTableOffset >> 1)]; if ((iTableOffset % 2) == 0) A >>= 4; else A &= 0x0F; // Get f -> B byte B = Convert.ToByte(workingSet.f.m_data[iTableOffset] >> 4); // Update Rn[N] if ((iTableOffset % 2) == 0) workingSet.Rn[iBlockOffset].m_data[iTableOffset >> 1] |= Convert.ToByte((A ^ B) << 4); else workingSet.Rn[iBlockOffset].m_data[iTableOffset >> 1] |= Convert.ToByte(A ^ B); } } // X = R16 L16 workingSet.X.Reset(); for (iTableOffset = 0; iTableOffset < 4; iTableOffset++) { workingSet.X.m_data[iTableOffset] = workingSet.Rn[16].m_data[iTableOffset]; workingSet.X.m_data[iTableOffset + 4] = workingSet.Ln[16].m_data[iTableOffset]; } // C = X perm IP workingSet.DataBlockOut.Reset(); for (iTableOffset = 0; iTableOffset < byteRFP.Length; iTableOffset++) { // Get perm offset iPermOffset = byteRFP[iTableOffset]; iPermOffset--; // Get and set bit workingSet.DataBlockOut.SetBit( _bitAddressToByteOffset(iTableOffset, 8), _bitAddressToBitOffset(iTableOffset, 8), workingSet.X.GetBit( _bitAddressToByteOffset(iPermOffset, 8), _bitAddressToBitOffset(iPermOffset, 8) ) ); } } // key loop }
private static KEY_SET _expandKey(byte[] Key, int iOffset) { // // Expand an 8 byte DES key into a set of permuted keys // // Declare return variable KEY_SET Ftmp = new KEY_SET(); // Declaration of local variables int iTableOffset, iArrayOffset, iPermOffset, iByteOffset, iBitOffset; bool bBit; // Put key into an 8-bit block BLOCK8BYTE K = new BLOCK8BYTE(); K.Set(Key, iOffset); // Permutate Kp with PC1 BLOCK8BYTE Kp = new BLOCK8BYTE(); for (iArrayOffset = 0; iArrayOffset < bytePC1.Length; iArrayOffset++) { // Get permute offset iPermOffset = bytePC1[iArrayOffset]; iPermOffset--; // Get and set bit Kp.SetBit( _bitAddressToByteOffset(iArrayOffset, 7), _bitAddressToBitOffset(iArrayOffset, 7), K.GetBit( _bitAddressToByteOffset(iPermOffset, 8), _bitAddressToBitOffset(iPermOffset, 8) ) ); } // Create 17 blocks of C and D from Kp BLOCK8BYTE[] KpCn = new BLOCK8BYTE[17]; BLOCK8BYTE[] KpDn = new BLOCK8BYTE[17]; for (iArrayOffset = 0; iArrayOffset < 17; iArrayOffset++) { KpCn[iArrayOffset] = new BLOCK8BYTE(); KpDn[iArrayOffset] = new BLOCK8BYTE(); } for (iArrayOffset = 0; iArrayOffset < 32; iArrayOffset++) { // Set bit in KpCn iByteOffset = _bitAddressToByteOffset(iArrayOffset, 8); iBitOffset = _bitAddressToBitOffset(iArrayOffset, 8); bBit = Kp.GetBit(iByteOffset, iBitOffset); KpCn[0].SetBit(iByteOffset, iBitOffset, bBit); // Set bit in KpDn bBit = Kp.GetBit(iByteOffset + 4, iBitOffset); KpDn[0].SetBit(iByteOffset, iBitOffset, bBit); } for (iArrayOffset = 1; iArrayOffset < 17; iArrayOffset++) { // Shift left wrapped KpCn[iArrayOffset].ShiftLeftWrapped(KpCn[iArrayOffset - 1], byteShifts[iArrayOffset - 1]); KpDn[iArrayOffset].ShiftLeftWrapped(KpDn[iArrayOffset - 1], byteShifts[iArrayOffset - 1]); } // Create 17 keys Kn for (iArrayOffset = 0; iArrayOffset < 17; iArrayOffset++) { // Loop through the bits for (iTableOffset = 0; iTableOffset < 48; iTableOffset++) { // Get address if bit iPermOffset = bytePC2[iTableOffset]; iPermOffset--; // Convert to byte and bit offsets iByteOffset = _bitAddressToByteOffset(iPermOffset, 7); iBitOffset = _bitAddressToBitOffset(iPermOffset, 7); // Get bit if (iByteOffset < 4) { bBit = KpCn[iArrayOffset].GetBit(iByteOffset, iBitOffset); } else { bBit = KpDn[iArrayOffset].GetBit(iByteOffset - 4, iBitOffset); } // Set bit iByteOffset = _bitAddressToByteOffset(iTableOffset, 6); iBitOffset = _bitAddressToBitOffset(iTableOffset, 6); Ftmp.GetAt(iArrayOffset).SetBit(iByteOffset, iBitOffset, bBit); } } // Return variable return(Ftmp); }