游戲開發(fā)—數(shù)據(jù)加解密

????數(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"

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末井赌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子贵扰,更是在濱河造成了極大的恐慌仇穗,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件戚绕,死亡現(xiàn)場離奇詭異纹坐,居然都是意外死亡,警方通過查閱死者的電腦和手機舞丛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門耘子,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人球切,你說我怎么就攤上這事谷誓。” “怎么了吨凑?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵捍歪,是天一觀的道長户辱。 經(jīng)常有香客問我,道長糙臼,這世上最難降的妖魔是什么庐镐? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮变逃,結(jié)果婚禮上焚鹊,老公的妹妹穿的比我還像新娘。我一直安慰自己韧献,他們只是感情好末患,可當(dāng)我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著锤窑,像睡著了一般璧针。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上渊啰,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天探橱,我揣著相機與錄音,去河邊找鬼绘证。 笑死隧膏,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嚷那。 我是一名探鬼主播胞枕,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼魏宽!你這毒婦竟也來了腐泻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤队询,失蹤者是張志新(化名)和其女友劉穎派桩,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚌斩,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡铆惑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了送膳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片员魏。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖肠缨,靈堂內(nèi)的尸體忽然破棺而出逆趋,到底是詐尸還是另有隱情盏阶,我是刑警寧澤晒奕,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響脑慧,放射性物質(zhì)發(fā)生泄漏魄眉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一闷袒、第九天 我趴在偏房一處隱蔽的房頂上張望坑律。 院中可真熱鬧,春花似錦囊骤、人聲如沸晃择。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宫屠。三九已至,卻和暖如春滑蚯,著一層夾襖步出監(jiān)牢的瞬間浪蹂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工告材, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留坤次,地道東北人。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓斥赋,卻偏偏與公主長得像缰猴,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子疤剑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,969評論 2 355