XXTEA的返回值

时间:2009-09-26 18:12:03

标签: c# c++ cryptography

这似乎是一个愚蠢的问题,但我找不到答案......

这是来自维基百科的XXTEA代码:

#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX ((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (k[(p&3)^e] ^ z));

void btea(uint32_t *v, int n, uint32_t const k[4]) {
  uint32_t y, z, sum;
  unsigned p, rounds, e;
  if (n > 1) {          /* Coding Part */
    rounds = 6 + 52/n;
    sum = 0;
    z = v[n-1];
    do {
      sum += DELTA;
      e = (sum >> 2) & 3;
      for (p=0; p<n-1; p++)
        y = v[p+1], z = v[p] += MX;
      y = v[0];
      z = v[n-1] += MX;
    } while (--rounds);
  } else if (n < -1) {  /* Decoding Part */
    n = -n;
    rounds = 6 + 52/n;
    sum = rounds*DELTA;
    y = v[0];
    do {
      e = (sum >> 2) & 3;
      for (p=n-1; p>0; p--)
        z = v[p-1], y = v[p] -= MX;
      z = v[n-1];
      y = v[0] -= MX;
    } while ((sum -= DELTA) != 0);
  }
}

我将其移植到C#。我不知道我在忽视什么,但加密的结果存储在哪里?我假设它在v中,但是来自v的数据从未设置,只能读取。

我没看到什么?

5 个答案:

答案 0 :(得分:7)

我在谷歌搜索“XXTEA C#”时找到了这个页面。找不到任何现成的实现,所以我做了我自己的。凭借闭包的魔力,它实际上是参考代码的逐字副本。我已将它发布给到达这里的任何人。

请注意,虽然这会接受任意长度的字节数组,但返回数组的长度始终是4的倍数。并且,与参考实现不同,此实现返回修改后的数据,而不是更改原始数据。

using System;

namespace Encryption
{
    public enum XXTEAMode
    {
        Encrypt,
        Decrypt
    }

    static public class XXTEA
    {
        static public byte[] Code(byte[] data, uint[] k, XXTEAMode mode)
        {
            uint[] v = new uint[(int)Math.Ceiling((float)data.Length / 4)];
            Buffer.BlockCopy(data, 0, v, 0, data.Length);

            unchecked
            {
                const uint DELTA = 0x9e3779b9;
                uint y = 0, z = 0, sum = 0, p = 0, rounds = 0, e = 0;
                int n = v.Length;
                Func<uint> MX = () => (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (k[(p & 3) ^ e] ^ z)));

                if (mode == XXTEAMode.Encrypt)
                {
                    rounds = (uint)(6 + 52 / n);
                    z = v[n - 1];
                    do
                    {
                        sum += DELTA;
                        e = (sum >> 2) & 3;
                        for (p = 0; p < n - 1; p++)
                        {
                            y = v[p + 1];
                            z = v[p] += MX();
                        }
                        y = v[0];
                        z = v[n - 1] += MX();
                    } while (--rounds > 0);
                }
                else
                {
                    rounds = (uint)(6 + 52 / n);
                    sum = rounds * DELTA;
                    y = v[0];
                    do
                    {
                        e = (sum >> 2) & 3;
                        for (p = (uint)(n - 1); p > 0; p--)
                        {
                            z = v[p - 1];
                            y = v[p] -= MX();
                        }
                        z = v[n - 1];
                        y = v[0] -= MX();
                    } while ((sum -= DELTA) != 0);
                }
            }

            byte[] rvl = new byte[v.Length * 4];
            Buffer.BlockCopy(v, 0, rvl, 0, rvl.Length);
            return rvl;
        }
    }
}

答案 1 :(得分:2)

在编码部分:z = v[n-1] += MX;

在解码部分:y = v[p] -= MX;

这些行在v数组的元素上执行+ =,然后将新值复制到z或y中。编写代码的人优先考虑简洁而不是清晰度,这在实际应用中通常不是一件好事。

答案 2 :(得分:1)

运算符= - = + =在表达式中具有相同的优先级,并且它们根据C ++标准5.17从右到左关联(我相信在C中有相同的规则)。例如,这个:

y = v[p] -= MX;

可以替换为:

v[p] -= MX; // <<< modification of data here
y = v[p];

答案 3 :(得分:1)

v在此行中设置,例如:

y = v[0] -= MX;

这也可以写成:

v[0] = v[0] - MX;
y = v[0];

答案 4 :(得分:1)

指针v末尾的数组中的数据已更新:

v[p] += MX;
...
z = v[n-1] += MX;
...
z = v[p-1], y = v[p] -= MX;
...
y = v[0] -= MX;

是的; 引用的数据v,已更新。