zoukankan      html  css  js  c++  java
  • Tea加密算法和XxTea加密算法

         TEA(Tiny Encryption Algorithm)是一种小型的对称加密解密算法,支持128位密码,与BlowFish一样TEA每次只能加密/解密8字节数据。TEA特点是速度快、效率高,实现也非常简单。由于针对TEA的攻击不断出现,所以TEA也发展出几个版本,分别是XTEA、Block TEA和XXTEA。

        TEA加密和解密时都使用一个常量值,这个常量值为0x9e3779b,这个值是近似黄金分割率,注意,有些编程人员为了避免在程序中直接出现"mov 变量,0x9e3779b",以免被破解者直接搜索0x9e3779b这个常数得知使用TEA算法,所以有时会使用"sub 变量,0x61C88647"代替"mov 变量,0x9e3779b",0x61C88647=-(0x9e3779b)。

         TEA算法每一次可以操作64bit(8byte),采用128bit(16byte)作为key,算法采用迭代的形式,推荐的迭代轮数是64轮,最少32轮。 

         标准的16轮运算TEA,如果要改成标准的32轮运算TEA,只需修改code和decode中的n为32,并将decode中的delta左移4位改成左移5位即可。

    C#的实现代码:

        public static class Tea
    {

    public static byte[] Encrypt(byte[] data, byte[] key)
    {

    byte[] dataBytes;
    if (data.Length % 2 == 0)
    {
    dataBytes
    = data;

    }
    else
    {
    dataBytes
    = new byte[data.Length + 1];
    Array.Copy(data,
    0, dataBytes, 0, data.Length);
    dataBytes[data.Length]
    = 0x0;

    }
    byte[] result = new byte[dataBytes.Length * 4];
    uint[] formattedKey = FormatKey(key);
    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);
    Array.Copy(ConvertUIntToByteArray(tempData[
    0]), 0, result, i * 4, 4);
    Array.Copy(ConvertUIntToByteArray(tempData[
    1]), 0, result, i * 4 + 4, 4);
    }
    return result;
    }

    public static byte[] Decrypt(byte[] data, byte[] 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] = ConvertByteArrayToUInt(data, i);
    tempData[
    1] = ConvertByteArrayToUInt(data, i + 4);
    decode(tempData, formattedKey);
    dataBytes[x
    ++] = (byte)tempData[0];
    dataBytes[x
    ++] = (byte)tempData[1];
    }
    //修剪添加的空字符
    if (dataBytes[dataBytes.Length - 1] == 0x0)
    {
    byte[] result = new byte[dataBytes.Length - 1];
    Array.Copy(dataBytes,
    0, result, 0, dataBytes.Length - 1);
    }
    return dataBytes;

    }

    static uint[] FormatKey(byte[] key)
    {
    if (key.Length == 0)
    throw new ArgumentException("Key must be between 1 and 16 characters in length");
    byte[] refineKey = new byte[16];
    if (key.Length < 16)
    {
    Array.Copy(key,
    0, refineKey, 0, key.Length);
    for (int k = key.Length; k < 16; k++)
    {
    refineKey[k]
    = 0x20;
    }
    }
    else
    {
    Array.Copy(key,
    0, refineKey, 0, 16);
    }
    uint[] formattedKey = new uint[4];
    int j = 0;
    for (int i = 0; i < refineKey.Length; i += 4)
    formattedKey[j
    ++] = ConvertByteArrayToUInt(refineKey, i);
    return formattedKey;
    }
    #region Tea Algorithm
    static void code(uint[] v, uint[] k)
    {
    uint y = v[0];
    uint z = v[1];
    uint sum = 0;
    uint delta = 0x9e3779b9;
    uint n = 16;
    while (n-- > 0)
    {
    sum
    += delta;
    y
    += (z << 4) + k[0] ^ z + sum ^ (z >> 5) + k[1];
    z
    += (y << 4) + k[2] ^ y + sum ^ (y >> 5) + k[3];
    }
    v[
    0] = y;
    v[
    1] = z;
    }

    static void decode(uint[] v, uint[] k)
    {
    uint n = 16;
    uint sum;
    uint y = v[0];
    uint z = v[1];
    uint delta = 0x9e3779b9;
    /*
    * 由于进行16轮运算,所以将delta左移4位,减16次后刚好为0.
    */
    sum
    = delta << 4;
    while (n-- > 0)
    {
    z
    -= (y << 4) + k[2] ^ y + sum ^ (y >> 5) + k[3];
    y
    -= (z << 4) + k[0] ^ z + sum ^ (z >> 5) + k[1];
    sum
    -= delta;
    }
    v[
    0] = y;
    v[
    1] = z;
    }
    #endregion

    private static byte[] ConvertUIntToByteArray(uint v)
    {
    byte[] result = new byte[4];
    result[
    0] = (byte)(v & 0xFF);
    result[
    1] = (byte)((v >> 8) & 0xFF);
    result[
    2] = (byte)((v >> 16) & 0xFF);
    result[
    3] = (byte)((v >> 24) & 0xFF);
    return result;
    }

    private static uint ConvertByteArrayToUInt(byte[] v, int offset)
    {
    if (offset + 4 > v.Length) return 0;
    uint output;
    output
    = (uint)v[offset];
    output
    |= (uint)(v[offset + 1] << 8);
    output
    |= (uint)(v[offset + 2] << 16);
    output
    |= (uint)(v[offset + 3] << 24);
    return output;
    }
    }

         XTEA 跟 TEA 使用了相同的简单运算,但它采用了截然不同的顺序,为了阻止密钥表攻击,四个子密钥(在加密过程中,原 128 位的密钥被拆分为 4 个 32 位的子密钥)采用了一种不太正规的方式进行混合,但速度更慢了。在跟描述 XTEA 算法的同一份报告中,还介绍了另外一种被称为 Block TEA 算法的变种,它可以对 32 位大小任意倍数的变量块进行操作。该算法将 XTEA 轮循函数依次应用于块中的每个字,并且将它附加于它的邻字。该操作重复多少轮依赖于块的大小,但至少需要 6 轮。该方法的优势在于它无需操作模式(CBC,OFB,CFB 等),密钥可直接用于信息。对于长的信息它可能比 XTEA 更有效率。在 1998 年,Markku-Juhani Saarinen 给出了一个可有效攻击 Block TEA 算法的代码,但之后很快 David J. Wheeler 和 Roger M. Needham 就给出了 Block TEA 算法的修订版,这个算法被称为 XXTEA。XXTEA 使用跟 Block TEA 相似的结构,但在处理块中每个字时利用了相邻字。它利用一个更复杂的 MX 函数代替了 XTEA 轮循函数,MX 使用 2 个输入量。

         如果加密字符串长度不是 4 的整数倍,则这些实现的在加密后无法真正还原,还原以后的字符串实际上与原字符串不相等,而是后面多了一些 \0 的字符,或者少了一些 \0 的字符。原因在于 XXTEA 算法只定义了如何对 32 位的信息块数组(实际上是 32 位无符号整数数组)进行加密,而并没有定义如何来将字符串编码为这种数组。而现有的实现中在将字符串编码为整数数组时,都丢失了字符串长度信息,因此还原出现了问题。

    C#的实现代码

    using System;

    class XXTEA
    {
    public static Byte[] Encrypt(Byte[] Data, Byte[] Key)
    {
    if (Data.Length == 0)
    {
    return Data;
    }
    return ToByteArray(Encrypt(ToUInt32Array(Data, true), ToUInt32Array(Key, false)), false);
    }
    public static Byte[] Decrypt(Byte[] Data, Byte[] Key)
    {
    if (Data.Length == 0)
    {
    return Data;
    }
    return ToByteArray(Decrypt(ToUInt32Array(Data, false), ToUInt32Array(Key, false)), true);
    }

    public static UInt32[] Encrypt(UInt32[] v, UInt32[] k)
    {
    Int32 n
    = v.Length - 1;
    if (n < 1)
    {
    return v;
    }
    if (k.Length < 4)
    {
    UInt32[] Key
    = new UInt32[4];
    k.CopyTo(Key,
    0);
    k
    = Key;
    }
    UInt32 z
    = v[n], y = v[0], delta = 0x9E3779B9, sum = 0, e;
    Int32 p, q
    = 6 + 52 / (n + 1);
    while (q-- > 0)
    {
    sum
    = unchecked(sum + delta);
    e
    = sum >> 2 & 3;
    for (p = 0; p < n; p++)
    {
    y
    = v[p + 1];
    z
    = unchecked(v[p] += (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z));
    }
    y
    = v[0];
    z
    = unchecked(v[n] += (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z));
    }
    return v;
    }
    public static UInt32[] Decrypt(UInt32[] v, UInt32[] k)
    {
    Int32 n
    = v.Length - 1;
    if (n < 1)
    {
    return v;
    }
    if (k.Length < 4)
    {
    UInt32[] Key
    = new UInt32[4];
    k.CopyTo(Key,
    0);
    k
    = Key;
    }
    UInt32 z
    = v[n], y = v[0], delta = 0x9E3779B9, sum, e;
    Int32 p, q
    = 6 + 52 / (n + 1);
    sum
    = unchecked((UInt32)(q * delta));
    while (sum != 0)
    {
    e
    = sum >> 2 & 3;
    for (p = n; p > 0; p--)
    {
    z
    = v[p - 1];
    y
    = unchecked(v[p] -= (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z));
    }
    z
    = v[n];
    y
    = unchecked(v[0] -= (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z));
    sum
    = unchecked(sum - delta);
    }
    return v;
    }
    private static UInt32[] ToUInt32Array(Byte[] Data, Boolean IncludeLength)
    {
    Int32 n
    = (((Data.Length & 3) == 0) ? (Data.Length >> 2) : ((Data.Length >> 2) + 1));
    UInt32[] Result;
    if (IncludeLength)
    {
    Result
    = new UInt32[n + 1];
    Result[n]
    = (UInt32)Data.Length;
    }
    else
    {
    Result
    = new UInt32[n];
    }
    n
    = Data.Length;
    for (Int32 i = 0; i < n; i++)
    {
    Result[i
    >> 2] |= (UInt32)Data[i] << ((i & 3) << 3);
    }
    return Result;
    }
    private static Byte[] ToByteArray(UInt32[] Data, Boolean IncludeLength)
    {
    Int32 n;
    if (IncludeLength)
    {
    n
    = (Int32)Data[Data.Length - 1];
    }
    else
    {
    n
    = Data.Length << 2;
    }
    Byte[] Result
    = new Byte[n];
    for (Int32 i = 0; i < n; i++)
    {
    Result[i]
    = (Byte)(Data[i >> 2] >> ((i & 3) << 3));
    }
    return Result;
    }
    }
  • 相关阅读:
    PowerDesigner设置线风格(直线,折线。。。)
    使用PowerDesigner画ER图详细教程
    UML学习小结
    UML用例图说明
    UML类图基本画法
    Enterprise Architect与startUML表示UML常用图
    手把手教你使用startuml画用例图
    各种图(流程图,思维导图,UML,拓扑图,ER图)简介
    StartUML 各种类图的例子
    StarUML---推荐一款UML工具(很好很强大)
  • 原文地址:https://www.cnblogs.com/linzheng/p/2176767.html
Copyright © 2011-2022 走看看