您好,登錄后才能下訂單哦!
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 * 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 個輸入量。
- 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;
- }
- }
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。