Advertisement
Guest User

meteotime decoder

a guest
Feb 26th, 2012
9,625
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 30.13 KB | None | 0 0
  1. using System;
  2. using System.Runtime.InteropServices;
  3.  
  4.  
  5. namespace MeteoCoder
  6. {
  7.     /// <summary>
  8.     /// Enthält alle Funktionen zum Verschlüsseln und Entschlüsseln der via DCF77 übertragenen Wetterdaten.
  9.     /// Quelle: meteocrypt_working.c
  10.     /// </summary>
  11.     public class DeEnCoder
  12.     {
  13.         #region Deklarationen, Secrets, Sboxes, etc.
  14.         /// <summary>
  15.         /// Container zum Konvertieren zwischen 4 Bytes und Uint.
  16.         /// </summary>
  17.         [StructLayout(LayoutKind.Explicit)]
  18.         private struct ByteUInt
  19.         {
  20.             [FieldOffset(0)]
  21.             public byte Byte0;
  22.  
  23.             [FieldOffset(1)]
  24.             public byte Byte1;
  25.  
  26.             [FieldOffset(2)]
  27.             public byte Byte2;
  28.  
  29.             [FieldOffset(3)]
  30.             public byte Byte3;
  31.  
  32.             [FieldOffset(0)]
  33.             public uint FullUint;
  34.         }
  35.  
  36.         /// <summary>
  37.         /// Container zum schnellen Zusammenfassen und Trennen von Key und Cipher.
  38.         /// </summary>
  39.         [StructLayout(LayoutKind.Explicit)]
  40.         unsafe private struct CipherKeyContainer
  41.         {
  42.             [FieldOffset(0)]
  43.             public fixed byte AllBytes[10];// = new Byte[10];
  44.  
  45.             [FieldOffset(0)]
  46.             public fixed byte CipherBytes[5];// = new Byte[5];
  47.  
  48.             [FieldOffset(5)]
  49.             public fixed byte KeyBytes[5];// = new Byte[5];
  50.         }
  51.  
  52.         /// <summary>
  53.         /// bit pattern for 0D,0E from 0B-0D
  54.         /// </summary>
  55.         private uint[] mUintArrBitPattern12 = new uint[12]{
  56.             0x80000, //0b10000000000000000000, /* 0D.3 */\
  57.             0x00010, //0b00000000000000010000, /* 0B.4 */\
  58.             0x00008, //0b00000000000000001000, /* 0B.3 */\
  59.             0x00100, //0b00000000000100000000, /* 0C.0 */\
  60.             0x00080, //0b00000000000010000000, /* 0B.7 */\
  61.             0x01000, //0b00000001000000000000, /* 0C.4 */\
  62.             0x00800, //0b00000000100000000000, /* 0C.3 */\
  63.             0x10000, //0b00010000000000000000, /* 0D.0 */\
  64.             0x08000, //0b00001000000000000000, /* 0C.7 */\
  65.             0x00001, //0b00000000000000000001, /* 0B.0 */\
  66.             0x00000, //0b00000000000000000000, /* xxxx */\
  67.             0x00000  //0b00000000000000000000  /* xxxx */\
  68.         };
  69.  
  70.         /// <summary>
  71.         /// 12-15 from 16-19 (time)
  72.         /// </summary>
  73.         private uint[] mUintArrBitPattern30_1 = new uint[30] {
  74.             0x00000200, //0b00000000000000000000001000000000, /* 17.1 */\
  75.             0x00000020, //0b00000000000000000000000000100000, /* 16.5 */\
  76.             0x02000000, //0b00000010000000000000000000000000, /* 19.1 */\
  77.             0x00000000, //0b00000000000000000000000000000000, /* 1A.3 */\
  78.             0x00000000, //0b00000000000000000000000000000000, /* 1A.5 */\
  79.             0x00000080, //0b00000000000000000000000010000000, /* 16.7 */\
  80.             0x40000000, //0b01000000000000000000000000000000, /* 19.6 */\
  81.             0x01000000, //0b00000001000000000000000000000000, /* 19.0 */\
  82.  
  83.             0x04000000, //0b00000100000000000000000000000000, /* 19.2 */\
  84.             0x00000000, //0b00000000000000000000000000000000, /* 1A.4 */\
  85.             0x00010000, //0b00000000000000010000000000000000, /* 18.0 */\
  86.             0x00000000, //0b00000000000000000000000000000000, /* 1A.2 */\
  87.             0x00400000, //0b00000000010000000000000000000000, /* 18.6 */\
  88.             0x00000010, //0b00000000000000000000000000010000, /* 16.4 */\
  89.             0x00200000, //0b00000000001000000000000000000000, /* 18.5 */\
  90.             0x00080000, //0b00000000000010000000000000000000, /* 18.3 */\
  91.  
  92.             0x00004000, //0b00000000000000000100000000000000, /* 17.6 */\
  93.             0x00000000, //0b00000000000000000000000000000000, /* 1A.6 */\
  94.             0x00020000, //0b00000000000000100000000000000000, /* 18.1 */\
  95.             0x00100000, //0b00000000000100000000000000000000, /* 18.4 */\
  96.             0x00008000, //0b00000000000000001000000000000000, /* 17.7 */\
  97.             0x00000040, //0b00000000000000000000000001000000, /* 16.6 */\
  98.             0x00001000, //0b00000000000000000001000000000000, /* 17.4 */\
  99.             0x00000400, //0b00000000000000000000010000000000, /* 17.2 */\
  100.  
  101.             0x00000001, //0b00000000000000000000000000000001, /* 16.0 */\
  102.             0x80000000, //0b10000000000000000000000000000000, /* 19.7 */\
  103.             0x00000008, //0b00000000000000000000000000001000, /* 16.3 */\
  104.             0x00000002, //0b00000000000000000000000000000010, /* 16.1 */\
  105.             0x00040000, //0b00000000000001000000000000000000, /* 18.2 */\
  106.             0x10000000  //0b00010000000000000000000000000000, /* 19.4 */\
  107.         };
  108.  
  109.         /// <summary>
  110.         /// bit pattern for 12-15 from 1A (time2)
  111.         /// </summary>
  112.         private uint[] mUintArrBitPattern30_2 = new uint[30] {
  113.             0x00, //0b00000000,  /* 17.1 */\
  114.             0x00, //0b00000000,  /* 16.5 */\
  115.             0x00, //0b00000000,  /* 19.1 */\
  116.             0x08, //0b00001000,  /* 1A.3 */\
  117.             0x20, //0b00100000,  /* 1A.5 */\
  118.             0x00, //0b00000000,  /* 16.7 */\
  119.             0x00, //0b00000000,  /* 19.6 */\
  120.             0x00, //0b00000000,  /* 19.0 */\
  121.  
  122.             0x00, //0b00000000,  /* 19.2 */\
  123.             0x10, //0b00010000,  /* 1A.4 */\
  124.             0x00, //0b00000000,  /* 18.0 */\
  125.             0x04, //0b00000100,  /* 1A.2 */\
  126.             0x00, //0b00000000,  /* 18.6 */\
  127.             0x00, //0b00000000,  /* 16.4 */\
  128.             0x00, //0b00000000,  /* 18.5 */\
  129.             0x00, //0b00000000,  /* 18.3 */\
  130.  
  131.             0x00, //0b00000000,  /* 17.6 */\
  132.             0x40, //0b01000000,  /* 1A.6 */\
  133.             0x00, //0b00000000,  /* 18.1 */\
  134.             0x00, //0b00000000,  /* 18.4 */\
  135.             0x00, //0b00000000,  /* 17.7 */\
  136.             0x00, //0b00000000,  /* 16.6 */\
  137.             0x00, //0b00000000,  /* 17.4 */\
  138.             0x00, //0b00000000,  /* 17.2 */\
  139.  
  140.             0x00, //0b00000000,  /* 16.0 */\
  141.             0x00, //0b00000000,  /* 19.7 */\
  142.             0x00, //0b00000000,  /* 16.3 */\
  143.             0x00, //0b00000000,  /* 16.1 */\
  144.             0x00, //0b00000000,  /* 18.2 */\
  145.             0x00  //0b00000000,  /* 19.4 */\
  146.         };
  147.  
  148.         /// <summary>
  149.         /// 12-14 from 1C-1E (result from F)
  150.         /// </summary>
  151.         private uint[] mUintArrBitPattern20 = new uint[20] {
  152.             0x000004, //0b000000000000000000000100, /* 1C.2 */\
  153.             0x002000, //0b000000000010000000000000, /* 1E.5 */\
  154.             0x008000, //0b000000001000000000000000, /* 1E.7 */\
  155.             0x400000, //0b010000000000000000000000, /* 1D.6 */\
  156.             0x000100, //0b000000000000000100000000, /* 1E.0 */\
  157.             0x100000, //0b000100000000000000000000, /* 1D.4 */\
  158.             0x000400, //0b000000000000010000000000, /* 1E.2 */\
  159.             0x800000, //0b100000000000000000000000, /* 1D.7 */\
  160.  
  161.             0x040000, //0b000001000000000000000000, /* 1D.2 */\
  162.             0x020000, //0b000000100000000000000000, /* 1D.1 */\
  163.             0x000008, //0b000000000000000000001000, /* 1C.3 */\
  164.             0x000200, //0b000000000000001000000000, /* 1E.1 */\
  165.             0x004000, //0b000000000100000000000000, /* 1E.6 */\
  166.             0x000002, //0b000000000000000000000010, /* 1C.1 */\
  167.             0x001000, //0b000000000001000000000000, /* 1E.4 */\
  168.             0x080000, //0b000010000000000000000000, /* 1D.3 */\
  169.  
  170.             0x000800, //0b000000000000100000000000, /* 1E.3 */\
  171.             0x200000, //0b001000000000000000000000, /* 1D.5 */\
  172.             0x010000, //0b000000010000000000000000, /* 1D.0 */\
  173.             0x000001  //0b000000000000000000000001  /* 1C.0 */\
  174.         };
  175.  
  176.         /// <summary>
  177.         /// bit pattern for 12-15 from 16-19 (1/3)
  178.         /// </summary>
  179.         private byte[] mByteArrLookupTable1C_1 = new byte[] {
  180.             0xBB, 0x0E, 0x22, 0xC5, 0x73, 0xDF, 0xF7, 0x6D, 0x90, 0xE9, 0xA1, 0x38, 0x1C, 0x84, 0x4A, 0x56,
  181.             0x64, 0x8D, 0x28, 0x0B, 0xD1, 0xBA, 0x93, 0x52, 0x1C, 0xC5, 0xA7, 0xF0, 0xE9, 0x7F, 0x36, 0x4E,
  182.             0xC1, 0x77, 0x3D, 0xB3, 0xAA, 0xE0, 0x0C, 0x6F, 0x14, 0x88, 0xF6, 0x2B, 0xD2, 0x99, 0x5E, 0x45,
  183.             0x1F, 0x70, 0x96, 0xD3, 0xB3, 0x0B, 0xFC, 0xEE, 0x81, 0x42, 0xCA, 0x34, 0xA5, 0x58, 0x29, 0x67
  184.         };
  185.  
  186.         /// <summary>
  187.         /// bit pattern for 12-15 from 16-19 (2/3)
  188.         /// </summary>
  189.         private byte[] mByteArrLookupTable1C_2 = new byte[] {
  190.             0xAB, 0x3D, 0xFC, 0x74, 0x65, 0xE6, 0x0E, 0x4F, 0x97, 0x11, 0xD8, 0x59, 0x83, 0xC2, 0xBA, 0x20,
  191.             0xC5, 0x1B, 0xD2, 0x58, 0x49, 0x37, 0x01, 0x7D, 0x93, 0xFA, 0xE0, 0x2F, 0x66, 0xB4, 0xAC, 0x8E,
  192.             0xB7, 0xCC, 0x43, 0xFF, 0x58, 0x66, 0xEB, 0x35, 0x82, 0x2A, 0x99, 0xDD, 0x00, 0x71, 0x14, 0xAE,
  193.             0x4E, 0xB1, 0xF7, 0x70, 0x18, 0x52, 0xAA, 0x9F, 0xD5, 0x6B, 0xCC, 0x3D, 0x04, 0x83, 0xE9, 0x26
  194.         };
  195.  
  196.         /// <summary>
  197.         /// bit pattern for 12-15 from 16-19 (3/3)
  198.         /// </summary>
  199.         private byte[] mByteArrLookupTable1C_3 = new byte[] {
  200.             0x0A, 0x02, 0x00, 0x0F, 0x06, 0x07, 0x0D, 0x08, 0x03, 0x0C, 0x0B, 0x05, 0x09, 0x01, 0x04, 0x0E,
  201.             0x02, 0x09, 0x05, 0x0D, 0x0C, 0x0E, 0x0F, 0x08, 0x06, 0x07, 0x0B, 0x01, 0x00, 0x0A, 0x04, 0x03,
  202.             0x08, 0x00, 0x0D, 0x0F, 0x01, 0x0C, 0x03, 0x06, 0x0B, 0x04, 0x09, 0x05, 0x0A, 0x07, 0x02, 0x0E,
  203.             0x03, 0x0D, 0x00, 0x0C, 0x09, 0x06, 0x0F, 0x0B, 0x01, 0x0E, 0x08, 0x0A, 0x02, 0x07, 0x04, 0x05
  204.         };
  205.  
  206.         /// <summary>
  207.         /// Container, wich contains all former global vars
  208.         /// </summary>
  209.         private struct DataContainer
  210.         {
  211.             /// <summary>
  212.             /// Registers R12 to R15
  213.             /// </summary>
  214.             public ByteUInt mByteUint1;// = new ByteUInt();
  215.  
  216.             /// <summary>
  217.             /// Registers R08 to R0A
  218.             /// </summary>
  219.             public ByteUInt mByteUint2;// = new ByteUInt();
  220.  
  221.             /// <summary>
  222.             /// Registers R0B to R0E
  223.             /// </summary>
  224.             public ByteUInt mByteUint3;// = new ByteUInt();
  225.  
  226.             /// <summary>
  227.             /// Registers R1C to R1E
  228.             /// </summary>
  229.             public ByteUInt mByteUint4;// = new ByteUInt();
  230.  
  231.             public byte mByteUpperTime2;//, mByteR1B;
  232.             public uint mUintLowerTime;
  233.         }
  234.  
  235.  
  236.         #endregion
  237.  
  238.         #region Public Methoden
  239.         /// <summary>
  240.         /// Entschlüsselt einen Datensatz.
  241.         /// </summary>
  242.         /// <param name="encodedDataset">Verschlüsselte Wetterdaten in binärer Form.</param>
  243.         /// <returns>Gibt die entschlüsselten Wetterdaten in binärer Form (untere 22 Bit + 2 Bit Status) zurück.</returns>
  244.         unsafe public uint DecodeDataset(byte[] encodedDataset)
  245.         {
  246.  
  247.             CipherKeyContainer dataCiperKey = new CipherKeyContainer();
  248.             for (int i = 0; i < 10; i++)
  249.                 if (i < encodedDataset.Length)
  250.                     dataCiperKey.AllBytes[i] = encodedDataset[i];
  251.                 else
  252.                     dataCiperKey.AllBytes[i] = 0;
  253.  
  254.             byte[] plain;
  255.  
  256.             plain = Decrypt(dataCiperKey.CipherBytes, dataCiperKey.KeyBytes);
  257.             return GetMeteoFromPlain(plain);
  258.         }
  259.  
  260.         /// <summary>
  261.         /// Entschlüsselt einen Datensatz.
  262.         /// </summary>
  263.         /// <param name="encodedDataset">Verschlüsselte Wetterdaten in Form eines Strings (Big-Endian).</param>
  264.         /// <returns>Gibt die entschlüsselten Wetterdaten in Form eines Strings (Big-Endian) zurück.</returns>
  265.         public string DecodeDataset(string encodedDataset)
  266.         {
  267.             int uiBitCnt, uiCnt;
  268.             byte ucTemp = 0;
  269.             byte[] dataCiperKey = new byte[10];
  270.             uint meteoResult;
  271.             encodedDataset = encodedDataset.PadRight(82, '0');
  272.             uiBitCnt = 0;
  273.             for (uiCnt = 1; uiCnt < 82; uiCnt++)
  274.             {
  275.                 if (uiCnt != 7)
  276.                 {
  277.                     ucTemp = (byte)(ucTemp >> 1);
  278.                     if (encodedDataset[uiCnt] == '1')
  279.                         ucTemp |= 0x80;
  280.                     uiBitCnt++;
  281.                     if ((uiBitCnt & 7) == 0)
  282.                         dataCiperKey[(uiBitCnt >> 3) - 1] = ucTemp;
  283.                 }
  284.             }
  285.  
  286.             meteoResult = DecodeDataset(dataCiperKey);
  287.  
  288.             char[] result = Convert.ToString(meteoResult, 2).PadLeft(24, '0').ToCharArray();
  289.             Array.Reverse(result);
  290.  
  291.             return new string(result);
  292.         }
  293.  
  294.         /// <summary>
  295.         /// Verschlüsselt einen Datensatz
  296.         /// </summary>
  297.         /// <param name="plain">Wetterdaten in binärer Form (untere 22 Bit werden beachtet).</param>
  298.         /// <param name="key">Schlüssel in binärer Form (üblicherweise Zeitinformationen).</param>
  299.         /// <returns>Gibt die verschlüsselten Wetterdaten inkl. des Schlüssels in binärer Form zurück.</returns>
  300.         unsafe public byte[] EncodeDataset(uint plain, byte[] key)
  301.         {
  302.             byte[] result; // = new byte[10];
  303.             CipherKeyContainer InOut = new CipherKeyContainer();
  304.  
  305.             for (int i = 0; i < 5; i++)
  306.                 if (i < key.Length)
  307.                     InOut.KeyBytes[i] = key[i];
  308.                 else
  309.                     InOut.KeyBytes[i] = 0;
  310.  
  311.             byte[] plainToEncrypt = GetPlainFromMeteo(plain & 0x003FFFFF); //nur 22 Bit
  312.  
  313.             for (int i = 0; i < 5; i++)
  314.                 InOut.CipherBytes[i] = plainToEncrypt[i];
  315.  
  316.             result = Encrypt(InOut.CipherBytes, InOut.KeyBytes);
  317.             for (int i = 0; i < 5; i++)
  318.                 InOut.CipherBytes[i] = result[i];
  319.  
  320.             result = new byte[10];
  321.  
  322.             for (int i = 0; i < 10; i++)
  323.                 result[i] = InOut.AllBytes[i];
  324.  
  325.             return result;
  326.         }
  327.  
  328.         /// <summary>
  329.         /// Verschlüsselt einen Datensatz
  330.         /// </summary>
  331.         /// <param name="plain">Wetterdaten in Form eines Strings (Big-Endian).</param>
  332.         /// <param name="key">Schlüssel in Form eines Strings (Big-Endian, üblicherweise Zeitinformationen).</param>
  333.         /// <returns>Gibt die verschlüsselten Wetterdaten inkl. des Schlüssels in Form eines Strings zurück.</returns>
  334.         unsafe public string EncodeDataset(string plain, string key)
  335.         {
  336.             byte[] resultBytes;
  337.  
  338.             key = key.PadRight(40, '0');        //If plain and key too small
  339.             plain = plain.PadRight(22, '0');
  340.  
  341.             CipherKeyContainer resultContainer = new CipherKeyContainer();
  342.             byte[] keyBytes = new byte[5];
  343.             char[] plainCharArr = plain.Substring(0, 22).ToCharArray();
  344.             Array.Reverse(plainCharArr); //Convert from Big Endian to Little Endian
  345.             uint plainData = Convert.ToUInt32(new string(plainCharArr), 2);
  346.             int uiBitCnt, uiCnt;
  347.             byte ucTemp = 0;
  348.  
  349.             uiBitCnt = 0;
  350.             for (uiCnt = 0; uiCnt < 40; uiCnt++)
  351.             {
  352.                 ucTemp = (byte)(ucTemp >> 1);
  353.                 if (key[uiCnt] == '1')
  354.                     ucTemp |= 0x80;
  355.                 uiBitCnt++;
  356.                 if ((uiBitCnt & 7) == 0)
  357.                     keyBytes[(uiBitCnt >> 3) - 1] = ucTemp;
  358.             }
  359.  
  360.             resultBytes = EncodeDataset(plainData, keyBytes);
  361.             for (int i = 0; i < 5; i++)
  362.             {
  363.                 resultContainer.CipherBytes[i] = resultBytes[i];
  364.                 resultContainer.KeyBytes[i] = keyBytes[i];
  365.             }
  366.  
  367.             return CodedBinToString(resultContainer.CipherBytes, resultContainer.KeyBytes);
  368.         }
  369.  
  370.         #endregion
  371.  
  372.         #region Private Methoden
  373.         /// <summary>
  374.         /// Fügt Binärdaten (verschlüsselte Daten und Schnlüssel) in einem String zusammen.
  375.         /// </summary>
  376.         /// <param name="cipher">Zeiger auf eine Sequenz von Bytes, welche die verschlüsselten Bytes enthält.</param>
  377.         /// <param name="key">Zeiger auf eine Sequenz von Bytes, welche die Schlüssel-Bytes enthält.</param>
  378.         /// <returns>Gibt einen String zurück, in der ein Zeichen ein Bit der Eingangsdaten repräsentiert.</returns>
  379.         unsafe private string CodedBinToString(byte* cipher, byte* key)
  380.         {
  381.             char[] result = new char[82];
  382.             uint bitCount;
  383.             byte tmp = 0;
  384.  
  385.             bitCount = 1;
  386.             result[0] = '0';
  387.  
  388.             for (int i = 0; i < 40; i++)
  389.             {
  390.                 if ((i & 7) == 0)
  391.                     tmp = *(cipher++);
  392.  
  393.                 if (bitCount == 7)
  394.                     result[bitCount++] = '0';
  395.  
  396.                 if ((tmp & 1) != 0)
  397.                     result[bitCount++] = '1';
  398.                 else
  399.                     result[bitCount++] = '0';
  400.                 tmp >>= 1;
  401.             }
  402.  
  403.             for (int i = 0; i < 40; i++)
  404.             {
  405.                 if (!((i & 7) >= 1))
  406.                     tmp = *(key++);
  407.  
  408.                 if ((tmp & 1) >= 1)
  409.                     result[bitCount++] = '1';
  410.                 else
  411.                     result[bitCount++] = '0';
  412.                 tmp >>= 1;
  413.             }
  414.  
  415.             return new string(result);
  416.         }
  417.  
  418.         /// <summary>
  419.         /// Ermittelt Wetterdaten aus den entschlüsselten Bytes und prüft auf Korrektheit.
  420.         /// </summary>
  421.         /// <param name="PlainBytes">Array mit den entschlüsselte Bytes.</param>
  422.         /// <returns>Gibt die aus dem Klartextbytes ermittelten Wetterdaten zurück</returns>
  423.         private uint GetMeteoFromPlain(byte[] PlainBytes)
  424.         {
  425.             uint result;
  426.             uint checkSum;
  427.             checkSum = PlainBytes[2] & 0x0Fu;
  428.             checkSum <<= 8;
  429.             checkSum |= PlainBytes[1];
  430.             checkSum <<= 4;
  431.             checkSum |= (uint)(PlainBytes[0] >> 4);
  432.  
  433.             result = PlainBytes[0] & 0x0Fu | 0x10u;
  434.             result <<= 8;
  435.             result |= PlainBytes[4];
  436.             result <<= 8;
  437.             result |= PlainBytes[3];
  438.             result <<= 4;
  439.             result |= (uint)(PlainBytes[2] >> 4);
  440.  
  441.             if (checkSum != 0x2501)
  442.                 result = 0x200001;
  443.             else
  444.             {
  445.                 result &= 0x3FFFFF;
  446.                 result |= 0x400000;
  447.             }
  448.             return result;
  449.         }
  450.  
  451.         /// <summary>
  452.         /// Ermittelt den Klartext aus den Wetterdaten, welcher zur Verschlüsselung benötigt wird.
  453.         /// </summary>
  454.         /// <param name="meteo">Wetterdaten in binärer Form.</param>
  455.         /// <returns>Gibt die zu verschlüsselnden Klartextbytes zurück.</returns>
  456.         unsafe private byte[] GetPlainFromMeteo(uint meteo)
  457.         {
  458.             byte[] result = new byte[5];
  459.             meteo <<= 4;
  460.             result[1] = 0x50;
  461.             result[2] = (byte)((meteo & 0xF0) | 0x02);
  462.             meteo >>= 8;
  463.             result[3] = (byte)(meteo & 0xFF);
  464.             meteo >>= 8;
  465.             result[4] = (byte)(meteo & 0xFF);
  466.             meteo >>= 8;
  467.             result[0] = (byte)(meteo & 0x0F | 0x10);
  468.             return result;
  469.         }
  470.  
  471.  
  472.         unsafe private void CopyTimeToByteUint(byte* data, byte* key, ref DataContainer container)
  473.         {
  474.             for (int i = 0; i < 4; i++)
  475.             {
  476.                 container.mUintLowerTime <<= 8;
  477.                 container.mUintLowerTime |= key[3 - i];
  478.             }
  479.             container.mByteUpperTime2 = key[4];
  480.  
  481.             // copy R
  482.             container.mByteUint3.Byte0 = data[2];
  483.             container.mByteUint3.Byte1 = data[3];
  484.             container.mByteUint3.Byte2 = data[4];
  485.             container.mByteUint3.FullUint >>= 4;
  486.  
  487.             // copy L
  488.             container.mByteUint2.Byte0 = data[0];
  489.             container.mByteUint2.Byte1 = data[1];
  490.             container.mByteUint2.Byte2 = (byte)(data[2] & 0x0F);
  491.         }
  492.  
  493.  
  494.         private void ShiftTimeRight(int round, ref DataContainer container)
  495.         {
  496.             int count;
  497.             byte tmp;
  498.  
  499.             if ((round == 16) || (round == 8) || (round == 7) || (round == 3))
  500.                 count = 2;
  501.             else
  502.                 count = 1;
  503.  
  504.             while (count-- != 0)
  505.             {
  506.                 tmp = 0;
  507.                 if ((container.mUintLowerTime & 0x00100000) != 0)                   // save time bit 20
  508.                     tmp = 1;
  509.  
  510.                 container.mUintLowerTime &= 0xFFEFFFFF;
  511.                 if ((container.mUintLowerTime & 1) != 0)
  512.                     container.mUintLowerTime |= 0x00100000;             // copy time bit 0 to time bit 19
  513.                 container.mUintLowerTime >>= 1;                         // time >>= 1
  514.  
  515.                 if ((container.mByteUpperTime2 & 1) != 0)
  516.                     container.mUintLowerTime |= 0x80000000;
  517.                 container.mByteUpperTime2 >>= 1;
  518.                 if (tmp != 0)
  519.                     container.mByteUpperTime2 |= 0x80;                  // insert time bit 20 to time bit 39
  520.             }
  521.  
  522.         }
  523.  
  524.         private void ShiftTimeLeft(int round, ref DataContainer container)
  525.         {
  526.             int count;
  527.             byte tmp;
  528.  
  529.             if ((round == 16) || (round == 8) || (round == 7) || (round == 3))
  530.                 count = 2;
  531.             else
  532.                 count = 1;
  533.  
  534.             while (count-- != 0)
  535.             {
  536.                 tmp = 0;
  537.                 if ((container.mByteUpperTime2 & 0x80) != 0)
  538.                     tmp = 1;
  539.                 container.mByteUpperTime2 <<= 1;
  540.  
  541.                 if ((container.mUintLowerTime & 0x80000000) != 0)
  542.                     container.mByteUpperTime2 |= 1;
  543.  
  544.                 container.mUintLowerTime <<= 1;
  545.                 if ((container.mUintLowerTime & 0x00100000) != 0)
  546.                     container.mUintLowerTime |= 1;
  547.  
  548.                 container.mUintLowerTime &= 0xFFEFFFFF;
  549.                 if (tmp != 0)
  550.                     container.mUintLowerTime |= 0x00100000;
  551.             }
  552.         }
  553.  
  554.         private void ExpandR(ref DataContainer container)
  555.         {
  556.             uint tmp;
  557.  
  558.             container.mByteUint3.FullUint &= 0x000FFFFF;            // clear 0D(4-7),0E
  559.             tmp = 0x00100000;                   // and set bits form 0B-0D(0-3)
  560.             for (int i = 0; i < 12; i++)
  561.             {
  562.                 if ((container.mByteUint3.FullUint & mUintArrBitPattern12[i]) != 0)
  563.                     container.mByteUint3.FullUint |= tmp;
  564.                 tmp <<= 1;
  565.             }
  566.         }
  567.  
  568.         private void ExpandL(ref DataContainer container)
  569.         {
  570.             uint tmp;
  571.  
  572.             container.mByteUint2.FullUint &= 0x000FFFFF;            // clear 0D(4-7),0E
  573.             tmp = 0x00100000;                   // and set bits form 0B-0D(0-3)
  574.             for (int i = 0; i < 12; i++)
  575.             {
  576.                 if ((container.mByteUint2.FullUint & mUintArrBitPattern12[i]) != 0)
  577.                     container.mByteUint2.FullUint |= tmp;
  578.                 tmp <<= 1;
  579.             }
  580.         }
  581.  
  582.         private void CompressKey(ref DataContainer container)
  583.         {
  584.             uint tmp;
  585.  
  586.             container.mByteUint1.FullUint = 0;                  // clear 12-15
  587.             tmp = 0x00000001;                   // and set bits from 16-1A (time)
  588.             for (int i = 0; i < 30; i++)
  589.             {
  590.                 if ((container.mUintLowerTime & mUintArrBitPattern30_1[i]) != 0 || (container.mByteUpperTime2 & mUintArrBitPattern30_2[i]) != 0)
  591.                     container.mByteUint1.FullUint |= tmp;
  592.                 tmp <<= 1;
  593.             }
  594.         }
  595.  
  596.         private void DoSbox(ref DataContainer container)
  597.         {
  598.             byte tmp, helper; //mByteR1B;
  599.  
  600.             helper = container.mByteUint1.Byte3;                          // R1B = R15;
  601.             container.mByteUint1.Byte3 = container.mByteUint1.Byte2;            // R15 = R14
  602.  
  603.             // INNER LOOP
  604.             for (int i = 5; i > 0; i--)
  605.             {
  606.                 if ((i & 1) == 0) // round 4,2
  607.                 {
  608.                     tmp = (byte)(container.mByteUint1.Byte0 >> 4);      // swap R12
  609.                     tmp |= (byte)((container.mByteUint1.Byte0 & 0x0f) << 4);
  610.                     container.mByteUint1.Byte0 = tmp;
  611.                 }
  612.                 container.mByteUint1.Byte3 &= 0xF0;                     // set R1C
  613.                 tmp = (byte)((container.mByteUint1.Byte0 & 0x0F) | container.mByteUint1.Byte3);
  614.  
  615.                 if ((i & 4) != 0)
  616.                     tmp = mByteArrLookupTable1C_1[(tmp & 0x3F)];
  617.  
  618.                 if ((i & 2) != 0)
  619.                     tmp = mByteArrLookupTable1C_2[(tmp & 0x3F)];
  620.  
  621.                 else if (i == 1)
  622.                     tmp = mByteArrLookupTable1C_3[(tmp & 0x3F)];
  623.  
  624.                 if ((i & 1) != 0)
  625.                     container.mByteUint4.Byte0 = (byte)(tmp & 0x0F);
  626.                 else
  627.                     container.mByteUint4.Byte0 |= (byte)(tmp & 0xF0);
  628.  
  629.                 if ((i & 1) == 0)                           // copy 14->13->12, 1C->1E->1D
  630.                 {
  631.                     tmp = container.mByteUint1.Byte3;
  632.                     container.mByteUint1.FullUint >>= 8;
  633.                     container.mByteUint1.Byte3 = tmp;
  634.                     container.mByteUint4.FullUint <<= 8;
  635.                 }
  636.  
  637.                 container.mByteUint1.Byte3 >>= 1;                   // rotate R1B>R15 twice
  638.                 if ((helper & 1) != 0)
  639.                     container.mByteUint1.Byte3 |= 0x80;
  640.                 helper >>= 1;
  641.  
  642.                 container.mByteUint1.Byte3 >>= 1;
  643.                 if ((helper & 1) != 0)
  644.                     container.mByteUint1.Byte3 |= 0x80;
  645.                 helper >>= 1;
  646.             } // end of inner loop
  647.         }
  648.  
  649.         private void DoPbox(ref DataContainer container)
  650.         {
  651.             uint tmp;
  652.  
  653.             container.mByteUint1.FullUint = 0xFF000000;         // clear 12-14
  654.             tmp = 0x00000001;                   // and set bits from 1C-1E (result from F)
  655.             for (int i = 0; i < 20; i++)
  656.             {
  657.                 if ((container.mByteUint4.FullUint & mUintArrBitPattern20[i]) != 0)
  658.                     container.mByteUint1.FullUint |= tmp;
  659.                 tmp <<= 1;
  660.             }
  661.         }
  662.  
  663.         /// <summary>
  664.         /// DECRYPTION
  665.         /// </summary>
  666.         /// <param name="cipher"></param>
  667.         /// <param name="key"></param>
  668.         /// <returns></returns>
  669.         unsafe private byte[] Decrypt(byte* cipher, byte* key)
  670.         {
  671.             DataContainer container = new DataContainer();
  672.  
  673.             //uint ulTemp;
  674.             //uiCnt, uiILCnt, , uiOL2Cnt, uiBitCnt
  675.             //byte ucOL2Pat, ucTemp;
  676.             byte[] plain = new byte[5];
  677.             CopyTimeToByteUint(cipher, key, ref container);
  678.  
  679.             // OUTER LOOP 1
  680.             for (int i = 16; i > 0; i--)
  681.             {
  682.                 ShiftTimeRight(i, ref container);
  683.                 ExpandR(ref container);
  684.                 CompressKey(ref container);
  685.  
  686.                 // expR XOR compr.Key
  687.                 container.mByteUint1.FullUint ^= container.mByteUint3.FullUint; // 12-15 XOR 0B-0E
  688.                 container.mByteUint3.Byte2 &= 0x0F;             // clear 0D(4-7)
  689.  
  690.                 DoSbox(ref container);
  691.                 DoPbox(ref container);
  692.  
  693.                 // L XOR P-Boxed Round-Key (L')
  694.                 container.mByteUint1.FullUint ^= container.mByteUint2.FullUint;
  695.  
  696.                 // L = R
  697.                 container.mByteUint2.FullUint = container.mByteUint3.FullUint & 0x00FFFFFF;
  698.  
  699.                 // R = L'
  700.                 container.mByteUint3.FullUint = container.mByteUint1.FullUint & 0x00FFFFFF;
  701.             } // end of outer loop 1
  702.  
  703.             container.mByteUint3.FullUint <<= 4;
  704.             container.mByteUint2.Byte2 &= 0x0F;
  705.             container.mByteUint2.Byte2 |= (byte)(container.mByteUint3.Byte0 & 0xF0);
  706.  
  707.             //R0B0C0D0E.byte.R0D |= (R08090A.byte.R08 & 0xF0);
  708.             plain[0] = container.mByteUint2.Byte0;
  709.             plain[1] = container.mByteUint2.Byte1;
  710.             plain[2] = container.mByteUint2.Byte2;
  711.             plain[3] = container.mByteUint3.Byte1;
  712.             plain[4] = container.mByteUint3.Byte2;
  713.  
  714.             return plain;
  715.         }
  716.  
  717.         /// <summary>
  718.         /// ENCRYPTION
  719.         /// </summary>
  720.         /// <param name="plain"></param>
  721.         /// <param name="key"></param>
  722.         /// <returns></returns>
  723.         unsafe private byte[] Encrypt(byte* plain, byte* key)
  724.         {
  725.             byte[] cipher = new byte[5];
  726.             DataContainer container = new DataContainer();
  727.             //uint ulTemp;
  728.             //uiCnt, uiILCnt, , uiOL2Cnt, uiBitCnt
  729.             //byte ucOL2Pat, ucTemp;
  730.  
  731.             CopyTimeToByteUint(plain, key, ref container);
  732.  
  733.             // OUTER LOOP 1
  734.             for (int i = 1; i < 17; i++)
  735.             {
  736.                 ExpandL(ref container);
  737.                 CompressKey(ref container);
  738.  
  739.                 // expR XOR compr.Key
  740.                 container.mByteUint1.FullUint ^= container.mByteUint2.FullUint;    // L' XOR compr.Key
  741.                 container.mByteUint3.Byte2 &= 0x0F;             // clear 0D(4-7)
  742.  
  743.                 DoSbox(ref container);
  744.                 DoPbox(ref container);
  745.  
  746.                 // L XOR P-Boxed Round-Key (L')
  747.                 container.mByteUint1.FullUint ^= container.mByteUint3.FullUint;
  748.                 // L = R
  749.                 container.mByteUint3.FullUint = container.mByteUint2.FullUint & 0x00FFFFFF;
  750.                 // R = L'
  751.                 container.mByteUint2.FullUint = container.mByteUint1.FullUint & 0x00FFFFFF;
  752.  
  753.                 ShiftTimeLeft(i, ref container);
  754.             } // end of outer loop 1
  755.  
  756.             container.mByteUint3.FullUint <<= 4;
  757.             container.mByteUint2.Byte2 &= 0x0F;
  758.             container.mByteUint2.Byte2 |= (byte)(container.mByteUint3.Byte0 & 0xF0);
  759.  
  760.             //R0B0C0D0E.byte.R0D |= (R08090A.byte.R08 & 0xF0);
  761.             cipher[0] = container.mByteUint2.Byte0;
  762.             cipher[1] = container.mByteUint2.Byte1;
  763.             cipher[2] = container.mByteUint2.Byte2;
  764.             cipher[3] = container.mByteUint3.Byte1;
  765.             cipher[4] = container.mByteUint3.Byte2;
  766.  
  767.             /*
  768.                 R08090A.ulFull <<= 4;
  769.                 R0B0C0D0E.byte.R0D |= (R08090A.byte.R08 & 0xF0);
  770.  
  771.                pucCipher[0] = R0B0C0D0E.byte.R0B;
  772.                pucCipher[1] = R0B0C0D0E.byte.R0C;
  773.                pucCipher[2] = R0B0C0D0E.byte.R0D;
  774.                pucCipher[3] = R08090A.byte.R09;
  775.                pucCipher[4] = R08090A.byte.R0A;
  776.             */
  777.             return cipher;
  778.         }
  779.         #endregion
  780.  
  781.     }
  782. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement