zoukankan      html  css  js  c++  java
  • Xxtea加解密

    转自:http://www.cnblogs.com/luminji/p/3406407.html

    很有意思的一件事情,当我想要找 Xxtea 加解密算法的时候,发现了前同事(likui318)的代码,不妨分享出来。此代码满足:

    1:Xxtea支持中文;

    2:支持 JS 和 C# 加解密之间的互转;

    一:C#部分

    class XXTEA2
    {
        public static string Encrypt(string source, string key)
        {
            System.Text.Encoding encoder = System.Text.Encoding.UTF8;
            //UTF8==>BASE64==>XXTEA==>BASE64
            byte[] bytData = encoder.GetBytes(base64Encode(source));
            byte[] bytKey = encoder.GetBytes(key);
            if (bytData.Length == 0)
            {
                return "";
            }
            return System.Convert.ToBase64String(ToByteArray(Encrypt(ToUInt32Array(bytData, true), ToUInt32Array(bytKey, false)), false));
        }
        public static string Decrypt(string source, string key)
        {
            if (source.Length == 0)
            {
                return "";
            }
            // reverse
            System.Text.Encoding encoder = System.Text.Encoding.UTF8;
            byte[] bytData = System.Convert.FromBase64String(source);
            byte[] bytKey = encoder.GetBytes(key);

            return base64Decode(encoder.GetString(ToByteArray(Decrypt(ToUInt32Array(bytData, false), ToUInt32Array(bytKey, false)), true)));
        }

        private 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;
        }

        private 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;
        }

        public static string base64Decode(string data)
        {
            try
            {
                var encoder = System.Text.Encoding.UTF8;

                byte[] todecode_byte = Convert.FromBase64String(data);
                return encoder.GetString(todecode_byte);
            }
            catch (Exception e)
            {
                throw new Exception("Error in base64Decode" + e.Message);
            }
        }

        public static string base64Encode(string data)
        {
            try
            {
                byte[] encData_byte = new byte[data.Length];
                encData_byte = System.Text.Encoding.UTF8.GetBytes(data);
                string encodedData = Convert.ToBase64String(encData_byte);
                return encodedData;
            }
            catch (Exception e)
            {
                throw new Exception("Error in base64Encode" + e.Message);
            }
        }

    二:JS部分

    //***************************************************************************************
    // Autor:Tecky
    // Date:2008-06-03
    // Desc:xxtea 算法的js加密处理类,还包含了UtfParser类,还包含了Base64类// e-mail:likui318@163.com
    //
    // var prefix = xt
    //
    //  update:
    //
    //
    //***************************************************************************************

    function Xxtea(privateKey) {
        this._keyString = privateKey;
    }

    //将长整形转换为string,private
    Xxtea.prototype._long2str = function (v, w) {
        var vl = v.length;
        var n = (vl - 1) << 2;
        if (w) {
            var m = v[vl - 1];
            if ((m < n - 3) || (m > n)) return null;
            n = m;
        }
        for (var i = 0; i < vl; i++) {
            v[i] = String.fromCharCode(v[i] & 0xff,
                                       v[i] >>> 8 & 0xff,
                                       v[i] >>> 16 & 0xff,
                                       v[i] >>> 24 & 0xff);
        }
        if (w) {
            return v.join('').substring(0, n);
        }
        else {
            return v.join('');
        }
    }

    //将string转换为long,private
    Xxtea.prototype._str2long = function (s, w) {
        var len = s.length;
        var v = [];
        for (var i = 0; i < len; i += 4) {
            v[i >> 2] = s.charCodeAt(i)
                      | s.charCodeAt(i + 1) << 8
                      | s.charCodeAt(i + 2) << 16
                      | s.charCodeAt(i + 3) << 24;
        }
        if (w) {
            v[v.length] = len;
        }
        return v;
    }

    //function: encrypt str with private key by xxtea
    Xxtea.prototype.xxtea_encrypt = function (str) {
        if (str == "") {
            return "";
        }
        str = Base64.encode64(UtfParser.utf16to8(str));
        var v = this._str2long(str, true);
        var k = this._str2long(this._keyString, false);
        if (k.length < 4) {
            k.length = 4;
        }
        var n = v.length - 1;

        var z = v[n], y = v[0], delta = 0x9E3779B9;
        var mx, e, p, q = Math.floor(6 + 52 / (n + 1)), sum = 0;
        while (0 < q--) {
            sum = sum + delta & 0xffffffff;
            e = sum >>> 2 & 3;
            for (p = 0; p < n; p++) {
                y = v[p + 1];
                mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
                z = v[p] = v[p] + mx & 0xffffffff;
            }
            y = v[0];
            mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
            z = v[n] = v[n] + mx & 0xffffffff;
        }

        return Base64.encode64(this._long2str(v, false));
    }

    //function: decrypt str with private key by xxtea
    Xxtea.prototype.xxtea_decrypt = function (str) {
        if (str == "") {
            return "";
        }
        str = Base64.decode64(str);
        var v = this._str2long(str, false);
        var k = this._str2long(this._keyString, false);
        if (k.length < 4) {
            k.length = 4;
        }
        var n = v.length - 1;

        var z = v[n - 1], y = v[0], delta = 0x9E3779B9;
        var mx, e, p, q = Math.floor(6 + 52 / (n + 1)), sum = q * delta & 0xffffffff;
        while (sum != 0) {
            e = sum >>> 2 & 3;
            for (p = n; p > 0; p--) {
                z = v[p - 1];
                mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
                y = v[p] = v[p] - mx & 0xffffffff;
            }
            z = v[n];
            mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
            y = v[0] = v[0] - mx & 0xffffffff;
            sum = sum - delta & 0xffffffff;
        }

        return UtfParser.utf8to16(Base64.decode64(this._long2str(v, true)));
    }

    //Class:utf16 to utf8, utf8 ot utf16
    //Author:Tecky
    //Date:2008-06-03
    function UtfParser() {
        //all method is static
    }

    //function:change utf16 to utf8
    //parms(str):string that you want to change
    UtfParser.utf16to8 = function (str) {
        var out, i, len, c;

        out = "";
        len = str.length;
        for (i = 0; i < len; i++) {
            c = str.charCodeAt(i);
            if ((c >= 0x0001) && (c <= 0x007F)) {
                out += str.charAt(i);
            }
            else if (c > 0x07FF) {
                out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
                out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
                out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
            }
            else {
                out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
                out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
            }
        }
        return out;
    }

    //function:change utf8 to utf16
    //parms(str):string that you want to change
    UtfParser.utf8to16 = function (str) {
        str = str.toString();

        var out, i, len, c;
        var char2, char3;

        out = "";
        len = str.length;
        i = 0;
        while (i < len) {
            c = str.charCodeAt(i++);
            switch (c >> 4) {
                case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
                    // 0xxxxxxx
                    out += str.charAt(i - 1);
                    break;
                case 12: case 13:
                    // 110x xxxx   10xx xxxx
                    char2 = str.charCodeAt(i++);
                    out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
                    break;
                case 14:
                    // 1110 xxxx  10xx xxxx  10xx xxxx
                    char2 = str.charCodeAt(i++);
                    char3 = str.charCodeAt(i++);
                    out += String.fromCharCode(((c & 0x0F) << 12) |
                                   ((char2 & 0x3F) << 6) |
                                   ((char3 & 0x3F) << 0));
                    break;
            }
        }

        return out;
    }

    // Class:base64 encode & decode
    // Autor:Tecky
    // Date:2008-06-03
    function Base64() {
        //all method is static
    }

    //static
    Base64._keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    Base64.encode64 = function (input) {
        var output = "";
        var chr1, chr2, chr3 = "";
        var enc1, enc2, enc3, enc4 = "";
        var i = 0;

        do {
            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);

            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;

            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }

            output = output +
               Base64._keyStr.charAt(enc1) +
               Base64._keyStr.charAt(enc2) +
               Base64._keyStr.charAt(enc3) +
               Base64._keyStr.charAt(enc4);
            chr1 = chr2 = chr3 = "";
            enc1 = enc2 = enc3 = enc4 = "";
        } while (i < input.length);

        return output;
    }

    Base64.decode64 = function (input) {
        var output = "";
        var chr1, chr2, chr3 = "";
        var enc1, enc2, enc3, enc4 = "";
        var i = 0;

        // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
        var base64test = /[^A-Za-z0-9\+\/\=\n]/g;
        if (base64test.exec(input)) {
            alert("There were invalid base64 characters in the input text.\n" +
                  "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
                  "Expect errors in decoding.");
        }
        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

        do {
            enc1 = Base64._keyStr.indexOf(input.charAt(i++));
            enc2 = Base64._keyStr.indexOf(input.charAt(i++));
            enc3 = Base64._keyStr.indexOf(input.charAt(i++));
            enc4 = Base64._keyStr.indexOf(input.charAt(i++));

            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;

            output = output + String.fromCharCode(chr1);

            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }

            chr1 = chr2 = chr3 = "";
            enc1 = enc2 = enc3 = enc4 = "";

        } while (i < input.length);

        return output;
    }

  • 相关阅读:
    Redis 集群
    应用系统日志采集解决方案
    Flume学习应用:Java写日志数据到MongoDB
    一次开发逻辑规范的总结
    JSP2 自定义标签
    mysql的left join、 right join和inner join
    静态网页、动态网页、apache和tomcat之间区别和联系
    spring与shiro配置详解
    maven项目在eclipse启动报错:java.lang.ClassNotFoundException
    如何修改maven的默认jdk版本
  • 原文地址:https://www.cnblogs.com/movemoon/p/5633080.html
Copyright © 2011-2022 走看看