65.9K
CodeProject 正在变化。 阅读更多。
Home

Compact Framework 的 Tiny Encryption Algorithm (TEA)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.57/5 (35投票s)

2004 年 2 月 19 日

CPOL

3分钟阅读

viewsIcon

301497

downloadIcon

3008

了解如何使用 TEA 加密来保护敏感数据。

Sample Image - teaencryption.jpg

引言

Compact Framework 省略了 Cryptography 命名空间中的主要加密功能,以便为更重要的功能腾出空间。 幸运的是,实现某种加密来隐藏您的敏感数据并非难事。 我想找到一种安全且可移植的小型算法。 经过一番搜索,我偶然发现了微型加密算法 (TEA)。 该算法由剑桥大学的 David Wheeler 和 Roger Needham 于 1994 年开发。 该算法非常便携且速度快。 原始 TEA 算法已经成功进行了密码分析,导致原始作者修改了 TEA 算法。 修改后的算法称为 XTEA。 关于此算法的信息不多,因此无法保证 XTEA 算法也未被破解。 但是,对于不需要最高安全性的应用程序,此算法仍然有用。 原始算法是用 C 语言开发的,但构造方式使其易于移植到其他语言,如 C#。 我能够以最小的更改将原始 C 算法移植到 C#。 我在完整的 .NET Framework 以及 .NET Compact Framework 上测试了该算法,它在两个平台上都运行良好,无需任何更改。
有关 TEA 加密如何工作的更多信息,请参阅本文底部的链接。

背景

微型加密算法基于成对的数据块的原理。 这使得准备用于加密的字符串更具挑战性,因为您需要将无符号整数对传递给算法,然后以某种方式存储它们,以便可以在以后的某个时间点恢复数据。 我使用一些位移来在整数和字符串之间进行转换,因此对数字系统的一些了解将对您有所帮助。

使用代码

将代码移植到 C# 很容易。 将 C 算法移植到 C# 后,我最终得到以下加密函数

private void code(uint[] v, uint[] k)
{
    uint y = v[0];
    uint z = v[1];
    uint sum = 0;
    uint delta=0x9e3779b9;
    uint n=32;

    while(n-->0)
    {
        y += (z << 4 ^ z >> 5) + z ^ sum + k[sum & 3];
        sum += delta;
        z += (y << 4 ^ y >> 5) + y ^ sum + k[sum >> 11 & 3];
    }

    v[0]=y;
    v[1]=z;
}

简单吧? 它们不是没有理由称之为微型! 这是解密函数

private void decode(uint[] v, uint[] k)
{
    uint n=32;
    uint sum;
    uint y=v[0];
    uint z=v[1];
    uint delta=0x9e3779b9;

    sum = delta << 5 ;

    while(n-->0)
    {
        z -= (y << 4 ^ y >> 5) + y ^ sum + k[sum >> 11 & 3];
        sum -= delta;
        y -= (z << 4 ^ z >> 5) + z ^ sum + k[sum & 3];
    }

    v[0]=y;
    v[1]=z;
}

注意:我只修改了编译代码所需的内容。 我还格式化了代码,使其更易于阅读。 在原始算法中,他们使用 unsigned long 作为变量。 在 C 中,unsigned 是一个 32 位无符号整数。 在 .NET 领域中,等效的是一个无符号整数。

现在我们已经到了具有挑战性的部分。 要将该算法与字符串一起使用,我们必须将字符串转换为可接受的格式。 这是我为使用该算法所做工作的基本过程

  • 如有必要,通过在字符串末尾添加空格,使字符串的长度为偶数。 我们需要这样做,因为该算法期望成对的数据。
  • 将字符串转换为字节数组。
  • 循环遍历数组并将一对值传递给加密函数。
  • 将两个密码值转换为字符串并附加到一个长字符串。

我的 Encrypt 函数看起来像这样

public string Encrypt(string Data, string Key)
{
    uint[] formattedKey = FormatKey(Key);

    if(Data.Length%2!=0) Data += '\0'; // Make sure array is even in length.
    byte[] dataBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(Data);

    string cipher = string.Empty;
    uint[] tempData = new uint[2];
    for(int i=0; i<dataBytes.Length; i+=2)
    {
        tempData[0] = dataBytes[i];
        tempData[1] = dataBytes[i+1];
        code(tempData, formattedKey);
        cipher += ConvertUIntToString(tempData[0]) + 
                          ConvertUIntToString(tempData[1]);
    }

    return cipher;
}

Decrypt 函数基本上只是加密函数的反向操作

public string Decrypt(string Data, string Key)
{
    uint[] formattedKey = FormatKey(Key);

    int x = 0;
    uint[] tempData = new uint[2];
    byte[] dataBytes = new byte[Data.Length / 8 * 2];
    for(int i=0; i<Data.Length; i+=8)
    {
        tempData[0] = ConvertStringToUInt(Data.Substring(i, 4));
        tempData[1] = ConvertStringToUInt(Data.Substring(i+4, 4));
        decode(tempData, formattedKey);
        dataBytes[x++] = (byte)tempData[0];
        dataBytes[x++] = (byte)tempData[1];
    }

    string decipheredString = 
            System.Text.ASCIIEncoding.ASCII.GetString(dataBytes, 
                                                      0, dataBytes.Length);

    // Strip the null char if it was added.
    if(decipheredString[decipheredString.Length - 1] == '\0')
        decipheredString = decipheredString.Substring(0, 
                                                decipheredString.Length - 1);
    return decipheredString;
}
ConvertUIntToString 函数利用一些移位和按位与 (&) 将 32 位无符号整数转换为长度为 4 的字符串。 由于一个字符的长度为 1 字节,我们可以组合 4 个字符来生成 4 个字节或 32 位。 哇,这将很好地保存一个 32 位无符号整数 (uint)! 哇!
private string ConvertUIntToString(uint Input)
{
    System.Text.StringBuilder output = new System.Text.StringBuilder();
    output.Append((char)((Input & 0xFF)));
    output.Append((char)((Input >> 8) & 0xFF));
    output.Append((char)((Input >> 16) & 0xFF));
    output.Append((char)((Input >> 24) & 0xFF));
    return output.ToString();
}

这是撤消 ConvertUIntToString 操作的函数

private uint ConvertStringToUInt(string Input)
{
    uint output;
    output =  ((uint)Input[0]);
    output += ((uint)Input[1] << 8);
    output += ((uint)Input[2] << 16);
    output += ((uint)Input[3] << 24);
    return output;
}

将移位的输入与 0xFF 进行与运算将仅返回 1 个字节。
示例代码包括 .NET Framework 和 .NET Compact Framework 的示例应用程序。

关注点

  • 可以在这里找到原始的微型加密算法。
  • 可以在这里找到另一个包含有关此算法信息的站点。
  • 关于TEA 框架的深入文章

历史

  • 2004 年 2 月 29 日 - 将 XTEA 算法添加到文章和源代码。
  • 2004 年 2 月 19 日 - 原始文章。
© . All rights reserved.