温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Tea加密算法和XxTea加密算法

发布时间:2020-06-21 16:47:55 阅读:4048 作者:linzheng 栏目:开发技术
开发者测试专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

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)              {                  datadataBytes = 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 * 44);                  Array.Copy(ConvertUIntToByteArray(tempData[1]), 0, result, i * 4 + 44);              }              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[] DataByte[] Key)      {          if (Data.Length == 0)          {              return Data;          }          return ToByteArray(Encrypt(ToUInt32Array(Datatrue), ToUInt32Array(Keyfalse)), false);      }      public static Byte[] Decrypt(Byte[] DataByte[] Key)      {          if (Data.Length == 0)          {              return Data;          }          return ToByteArray(Decrypt(ToUInt32Array(Datafalse), ToUInt32Array(Keyfalse)), 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(Key0);              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(Key0);              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[] DataBoolean 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[] DataBoolean 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;      }  } 

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI

开发者交流群×