C#和Javascript间互转的Xxtea加解密

简介:

很有意思的一件事情,当我想要找 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; 
}


本文转自最课程陆敏技博客园博客,原文链接:http://www.cnblogs.com/luminji/p/3406407.html,如需转载请自行联系原作者

相关文章
|
11天前
|
开发框架 前端开发 JavaScript
C# 6.0+JavaScript云LIS系统源码  云LIS实验室信息管理新型解决方案
云LIS是为区域医疗提供临床实验室信息服务的计算机应用程序,可协助区域内所有临床实验室相互协调并完成日常检验工作,对区域内的检验数据进行集中管理和共享,通过对质量控制的管理,最终实现区域内检验结果互认。其目标是以医疗服务机构为主体,以医疗资源和检验信息共享为目标,集成共性技术及医疗服务关键技术,建立区域协同检验,最大化利用有限的医疗卫生资源。
23 1
|
2月前
|
JavaScript 前端开发 安全
C#结合JavaScript实现多文件上传
C#结合JavaScript实现多文件上传
|
10天前
|
存储 开发框架 前端开发
C#开发的全套成熟的LIS系统源码JavaScript+SQLserver 2012区域云LIS系统源码
医院云LIS系统是一套成熟的实验室信息管理系统,目前已在多家三级级医院应用,并不断更新。云LIS系统是为病人为中心、以业务处理为基础、以提高检验科室管理水平和工作效率为目标,将医学检验、科室管理和财务统计等检验科室/实验室所有工作进行整合,全面改善检验科室/实验室的工作现状。
15 0
|
19天前
|
开发框架 前端开发 JavaScript
采用C#.Net +JavaScript 开发的云LIS系统源码 二级医院应用案例有演示
技术架构:Asp.NET CORE 3.1 MVC + SQLserver + Redis等 开发语言:C# 6.0、JavaScript 前端框架:JQuery、EasyUI、Bootstrap 后端框架:MVC、SQLSugar等 数 据 库:SQLserver 2012
|
开发框架 前端开发 JavaScript
医院检验信息系统LIS源码,开发语言:C# 6.0、JavaScript
云LIS系统是一种医疗实验室信息管理系统,提供全面的实验室信息管理解决方案。它的主要功能包括样本管理、检测流程管理、报告管理、质量控制、数据分析和仪器管理等。技术架构:Asp.NET CORE 3.1 MVC + SQLserver + Redis等 开发语言:C# 6.0、JavaScript 前端框架:JQuery、EasyUI、Bootstrap 后端框架:MVC、SQLSugar等 数 据 库:SQLserver 2012
|
JavaScript 数据安全/隐私保护
vue里使用crypto-js实现AES加解密
vue里使用crypto-js实现AES加解密
359 0
vue里使用crypto-js实现AES加解密
|
JavaScript 前端开发 数据安全/隐私保护
js前端使用AES加解密及在线解密工具验证
js前端使用AES加解密及在线解密工具验证
521 0
js前端使用AES加解密及在线解密工具验证
|
JavaScript PHP
php中base64和js中base64可互相加解密
php中base64和js中base64可互相加解密
384 0
|
JavaScript 前端开发 算法