1

I'm having problems with an algorithm I'm doing to decrypt data. The is problems every time that I try to run an overflow error happened in line:

uint sum=(numberOfRounds*Delta);

The file I'm reading just has the array in hexadecimal: 3D 00 01 12 02 CC F8 FD 33 3B 44 01 00 92 00 03 03 00 CB 44 6D 38 01 12 00 24 D6 23 02 04 E9 65 F7 44 00 00 00 00 00 5B D2 D6 ED 3A 81 03 DD 00 00 00 00 00 00 AC 87 B0 51 0F 27 01 00 D9

The code is bellow:

 private const int EncryptedDataBlockSizeInBytes = 4;

  private static readonly uint[] Key = new uint[] { 0xA50DADD1, 0xFEAD1276, 0x03948029, 0x49493095 };
  private const uint Delta = 0x9E3779B9;

  public static int headersize = 13;
  public static int crcsize = 1;


  public static byte[] Decrypt(byte[] data, int offset, int count, uint[] key)
  {
   if (count % EncryptedDataBlockSizeInBytes != 0)
   {
    throw new ArgumentException("The count of the data to be decrypted must be divisible by 4.");
   }

   // Convert the byte array into a uint array
   uint[] dataInUints = ConvertBytesToUints(data, offset, count);

   uint numberOfRounds = (uint)(6 + (52 / dataInUints.Length));
   uint n = (uint)(dataInUints.Length - 1);
   uint sum = numberOfRounds * Delta;
   uint y = dataInUints[0];

   do
   {
        uint e = (sum >> 2) & 3;

        uint z;
        for (uint i = n; i > 0; i--)
        {
         z = dataInUints[i - 1];
         dataInUints[i] -= XxteaMx(z, y, e, sum, key, i);
         y = dataInUints[i];
        }

        z = dataInUints[n];
        dataInUints[0] -= XxteaMx(z, y, e, sum, key, 0);
        y = dataInUints[0];

        sum -= Delta;
   }
   while (sum != 0);

   // Convert the decrypted data back into a byte array and return the result
   return ConvertUintsToBytes(dataInUints);
  }




  private static uint XxteaMx(uint z, uint y, uint e, uint sum, uint[] key, uint i)
  {
   return (((((z) >> 5) ^ ((y) << 2)) + (((y) >> 3) ^ ((z) << 4))) ^ (((sum) ^ y) + ((key)[((i) & 3U) ^ (e)] ^ (z))));
  }



  private static uint[] ConvertBytesToUints(byte[] data, int offset, int count)
  {
   uint[] result = new uint[count / 4];

   // Run through the data and create the uints from
   // the array of bytes
   for (int i = offset, j = 0; i < offset + count; i += 4, j++)
   {
    result[j] = ((uint)data[i + 3] << 24) | ((uint)data[i + 2] << 16) | ((uint)data[i + 1] << 8) | (data[i]);
   }

   // Return the array of uints
   return result;
  }


  private static byte[] ConvertUintsToBytes(uint[] data)
  {
   byte[] result = new byte[data.Length * 4];

   // Run through the data and create the bytes from
   // the array of uints
   for (int i = 0, j = 0; i < data.Length; i++, j += 4)
   {
    result[j] = (byte)(data[i]);
    result[j + 1] = (byte)(data[i] >> 8);
    result[j + 2] = (byte)(data[i] >> 16);
    result[j + 3] = (byte)(data[i] >> 24);
   }

   // Return the array of bytes
   return result;
  }




        void Button1Click(object sender, EventArgs e)
        {


                FileStream file = new FileStream("arquivobin.dat", FileMode.Open);
                BinaryReader br = new BinaryReader(file);

                byte[] data = new byte[br.BaseStream.Length];

                data = br.ReadBytes((int)br.BaseStream.Length);

                string s = "";
                richTextBox1.Text = "My binary file data:" + "\n";
                for(int i =0; i< data.Length; i++){
                    s = data[i].ToString();
                    richTextBox1.Text += s + " ";
                }

                richTextBox1.Text += "\n\n\n" ;

                richTextBox1.Text += "My HEADER:" + "\n";
                for (int i = 0; i < headersize; i++)
                {
                    s = data[i].ToString();
                    richTextBox1.Text += s + " ";
                }

                richTextBox1.Text += "\n\n\n";  

                richTextBox1.Text += "My payload:" + "\n";
                for(int i = headersize; i < data.Length - crcsize; i++){
                    s = data[i].ToString();
                    richTextBox1.Text += s + " ";
                }

                richTextBox1.Text += "\n\n\n";
                richTextBox1.Text += "My CheckSum:" + "\n";
                s = printhex(data[data.Length - crcsize]);
                richTextBox1.Text += s;

                int offset = headersize;
                int count = data.Length - crcsize - headersize;


                byte[] result = Decrypt(data, headersize, count, Key);

                richTextBox1.Text += "\n\n\n";
                richTextBox1.Text += "My Decrypted:" + "\n";

                for (int i = headersize; i < data.Length - crcsize; i++)
                {
                    s = result[i].ToString();
                    richTextBox1.Text += s + " ";
                }
                file.Close();

        }


    }

1 Answers1

0

If I'm reading your code right... that line will always overflow insofar as numberOfRounds is greater than 1. uint in C# is just an alias for uint32 as such with Delta being so large (the most significant bit is 1) the calculation will always overflow when you multiply Delta against anything. However If I'm reading your code correctly that calculation is supposed to be an addition instead of the multiplication it currently is, if that is not correct I would suggest changing sum to being uint64.

Mgetz
  • 5,108
  • 2
  • 33
  • 51