????數(shù)據(jù)或文件加密是游戲中常見的需求偶垮,針對重要配置文件和敏感數(shù)據(jù)铡俐,加密存儲,運行時解密使用脯倚,對游戲的安全性是很有必要的。我們項目中對個別配置文件和Lua文件也做了加密處理,加解密算法則采用廣泛使用的XXTEA算法推正,下面簡單介紹一下恍涂。
????TEA(Tiny Encryption Algorithm)是一種小型的對稱加密解密算法,最初是由劍橋計算機實驗室的 David Wheeler 和 Roger Needham 在 1994 年設(shè)計的。它支持128位密碼,可以為 64 位的信息塊進行加密植榕,每次加密/解密8字節(jié)數(shù)據(jù)再沧,需要進行 64 輪迭代。該算法使用了一個神秘常數(shù)δ作為倍數(shù)尊残,來源于黃金比率炒瘸,以保證每一輪加密都不相同,在程序中為0x9E3779B9寝衫。TEA特點是速度快顷扩、效率高,實現(xiàn)也非常簡單慰毅。TEA后續(xù)發(fā)展出XTEA隘截、Block TEA和XXTEA等版本。其中XXTE算法安全事富,非臣祭快速,也適合大文件的加解密统台,所以被項目采用雕擂。
????XXTEA代碼很簡單,網(wǎng)上也有各種版本贱勃,下附一個C#版:
public class XXTEA
{
#region Encrypt
public static string Encrypt(string source, string key)
{
byte[] sourceByteArry = Encoding.UTF8.GetBytes(base64Encode(source));
if (sourceByteArry.Length == 0)
{
return "";
}
byte[] keyByteArry = Encoding.UTF8.GetBytes(key);
return Convert.ToBase64String(ToByteArray(Encrypt(ToUintArray(sourceByteArry, true), ToUintArray(keyByteArry, false)), false));
}
public static uint[] Encrypt(uint[] v, uint[] k)
{
int n = v.Length - 1;
if (n < 1)
{
return v;
}
if (k.Length < 4)
{
uint[] Key = new uint[4];
k.CopyTo(Key, 0);
k = Key;
}
uint z = v[n], y = v[0], delta = 0x9E3779B9, sum = 0, e;
int 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;
}
private static string base64Encode(string data)
{
try
{
byte[] encData_byte = new byte[data.Length];
encData_byte = Encoding.UTF8.GetBytes(data);
string encodedData = Convert.ToBase64String(encData_byte);
return encodedData;
}
catch (Exception e)
{
throw new Exception("Error in base64Encode" + e.Message);
}
}
#endregion
#region Decrypt
public static string Decrypt(string source, string key)
{
if (source.Length == 0)
{
return "";
}
byte[] bytData = Convert.FromBase64String(source);
byte[] bytKey = Encoding.UTF8.GetBytes(key);
return base64Decode(Encoding.UTF8.GetString(ToByteArray(Decrypt(ToUintArray(bytData, false), ToUintArray(bytKey, false)), true)));
}
public static uint[] Decrypt(uint[] v, uint[] k)
{
int n = v.Length - 1;
if (n < 1)
{
return v;
}
if (k.Length < 4)
{
uint[] Key = new uint[4];
k.CopyTo(Key, 0);
k = Key;
}
uint z = v[n], y = v[0], delta = 0x9E3779B9, sum, e;
int p, q = 6 + 52 / (n + 1);
sum = unchecked((uint)(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 string base64Decode(string data)
{
try
{
byte[] todecode_byte = Convert.FromBase64String(data);
return Encoding.UTF8.GetString(todecode_byte);
}
catch (Exception e)
{
throw new Exception("Error in base64Decode" + e.Message);
}
}
#endregion
private static uint[] ToUintArray(byte[] Data, bool IncludeLength)
{
int n = (((Data.Length & 3) == 0) ? (Data.Length >> 2) : ((Data.Length >> 2) + 1));
uint[] Result;
if (IncludeLength)
{
Result = new uint[n + 1];
Result[n] = (uint)Data.Length;
}
else
{
Result = new uint[n];
}
n = Data.Length;
for (int i = 0; i < n; i++)
{
Result[i >> 2] |= (uint)Data[i] << ((i & 3) << 3);
}
return Result;
}
private static byte[] ToByteArray(uint[] Data, bool IncludeLength)
{
int n;
if (IncludeLength)
{
n = (int)Data[Data.Length - 1];
}
else
{
n = Data.Length << 2;
}
byte[] Result = new byte[n];
for (int i = 0; i < n; i++)
{
Result[i] = (byte)(Data[i >> 2] >> ((i & 3) << 3));
}
return Result;
}
}
使用方法直接調(diào)用加/解密函數(shù)即可:
class Program
{
static void Main(string[] args)
{
string content = "content_Test";
string password = "ABC123";
string encryptString = XXTEA.Encrypt(content, password);
string result = XXTEA.Decrypt(encryptString, password);
Console.WriteLine(result);
}
}
result輸出 "content_Test"