/// <summary> /// expands R from 20 to 30 bit /// </summary> public static ByteUInt ExpandR(ByteUInt R) { uint tmp; // Set bits right to left, starting here: tmp = 0x00100000; // and set bits form 0B-0D(0-3) for (var i = 0; i < 10; i++) { if ((R.FullUint & expandRTable[i]) != 0) { R.FullUint |= tmp; } tmp <<= 1; } return(R); }
// Read from: sboxresult // write to: L public static ByteUInt DoPbox(ByteUInt sBoxResult) { uint tmp; ByteUInt L = new ByteUInt(); L.FullUint = 0xFF000000; // clear 12-14 tmp = 0x00000001; // and set bits from 1C-1E (result from F) for (var i = 0; i < 20; i++) { if ((sBoxResult.FullUint & mUintArrBitPattern20[i]) != 0) { L.FullUint |= tmp; } tmp <<= 1; } return(L); }
/// <summary> /// Compress 40 bit time to 30 bit key (stored in L') /// </summary> private ByteUInt CompressKey(byte timeH, uint timeL) { ByteUInt L_ = new ByteUInt(); uint tmp; L_.FullUint = 0; // clear 12-15 tmp = 0x00000001; // and set bits from 16-1A (time) for (var i = 0; i < 30; i++) { if ((timeL & timeCompression1[i]) != 0 || (timeH & timeCompression2[i]) != 0) { L_.FullUint |= tmp; } tmp <<= 1; } return(L_); }
public static ByteUInt ExpandR(ByteUInt R) { uint tmp; Console.Write("{ " + R.FullUint + ", "); R.FullUint &= 0x000FFFFF; // clear 0D(4-7),0E tmp = 0x00100000; // and set bits form 0B-0D(0-3) for (var i = 0; i < 10; i++) { if ((R.FullUint & mUintArrBitPattern12[i]) != 0) { R.FullUint |= tmp; } tmp <<= 1; } Console.WriteLine(R.FullUint + "},"); return(R); }
/// <summary> /// DECRYPTION /// </summary> /// <param name="cipher"></param> /// <param name="key"></param> /// <returns></returns> private unsafe byte[] Decrypt(byte *cipher, byte *key) { var container = new DataContainer(); var plain = new byte[5]; CopyTimeToByteUint(cipher, key, ref container); // OUTER LOOP 1 (16 Rounds) for (var round = 16; round > 0; round--) { Console.WriteLine($"Round {round}: L={container.L.FullUint:X}, R={container.R.FullUint:X}"); Console.WriteLine($"timeH=0x{container.timeH:x}, timeL=0x{container.timeL:x}"); ShiftTimeRight(round, ref container); Console.WriteLine($"Rotated Time. timeH=0x{container.timeH:x}, timeL=0x{container.timeL:x}"); ByteUInt compressedKey = CompressKey(container.timeH, container.timeL); Console.WriteLine($"Compressed key: 0x{compressedKey.FullUint:x}"); uint expandedR = ExpandR(container.R).FullUint; Console.WriteLine($"Expanded R: 0x{expandedR:x}"); uint sboxInput = compressedKey.FullUint ^ expandedR; uint bit6Group = build6bitGroups(sboxInput); Console.WriteLine($"Built 6bit groups: {bit6Group:x}"); uint sboxresult = Sbox(bit6Group); Console.WriteLine($"S Box result: {sboxresult:x}"); uint pboxResult = Pbox(sboxresult); Console.WriteLine($"Applied f: {pboxResult:x}"); pboxResult ^= container.L.FullUint; // L = R container.L.FullUint = container.R.FullUint; // R = L' container.R.FullUint = pboxResult; } Console.WriteLine($"Decrypted R = {container.R.FullUint}, L = {container.L.FullUint}"); // 4 bits from R get moved to L container.R.FullUint <<= 4; container.L.Byte2 &= 0x0F; container.L.Byte2 |= (byte)(container.R.Byte0 & 0xF0); plain[0] = container.L.Byte0; plain[1] = container.L.Byte1; plain[2] = container.L.Byte2; plain[3] = container.R.Byte1; plain[4] = container.R.Byte2; for (int i = 0; i < 5; i++) { Console.WriteLine($"plain[{i}] = 0x{plain[i]:X}"); } return(plain); }
public static ByteUInt DoSbox(ByteUInt L) { byte tmp, helper; //mByteR1B; ByteUInt result = new ByteUInt(); result.FullUint = 0; helper = L.Byte3; // R1B = R15; L.Byte3 = L.Byte2; // R15 = R14 // INNER LOOP for (var i = 5; i > 0; i--) { if ((i & 1) == 0) // round 4,2 { tmp = (byte)(L.Byte0 >> 4); // swap R12 tmp |= (byte)((L.Byte0 & 0x0f) << 4); L.Byte0 = tmp; } L.Byte3 &= 0xF0; // set R1C tmp = (byte)((L.Byte0 & 0x0F) | L.Byte3); if ((i & 4) != 0) { tmp = mByteArrLookupTable1C_1[tmp & 0x3F]; } if ((i & 2) != 0) { tmp = mByteArrLookupTable1C_2[tmp & 0x3F]; } else if (i == 1) { tmp = mByteArrLookupTable1C_3[tmp & 0x3F]; } if ((i & 1) != 0) { result.Byte0 = (byte)(tmp & 0x0F); } else { result.Byte0 |= (byte)(tmp & 0xF0); } if ((i & 1) == 0) // copy 14->13->12, 1C->1E->1D { tmp = L.Byte3; L.FullUint >>= 8; L.Byte3 = tmp; result.FullUint <<= 8; } L.Byte3 >>= 1; // rotate R1B>R15 twice if ((helper & 1) != 0) { L.Byte3 |= 0x80; } helper >>= 1; L.Byte3 >>= 1; if ((helper & 1) != 0) { L.Byte3 |= 0x80; } helper >>= 1; } // end of inner loop return(result); }