C# 实现的Javascript加密算法

@老徐  February 5, 2017

不打算公开的,不过转念一想,反正又没人看,就发出来吧。
这是使用C#来实现的JS加密的,被加密的JS文件,代码需要写的规范,不能少了分号(;)等js中可能会被忽略的符号。
下面是完整代码,自己看吧

    public class JavascriptEncoder
    {
        public static string ENCODE_BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
        public bool isDebug = false;

        public string JsEncode(string filename, int offset)
        {
            string js = WebTools.FileObj.ReadFile(HttpContext.Current.Request.MapPath(string.Format("/tmp/{0}", filename)));
            int length = js.Length;

            js = RemoveAnnotation(js);

            WebTools.FileObj.WriteFile(System.Web.HttpContext.Current.Request.MapPath("tmp.js"), js);

            StringBuilder sb = new StringBuilder(js);
           
            sb.Replace(@"\r", " "); //\n替换为空格
            sb.Replace(@"\n", " "); //\n替换为空格
            sb.Replace(Environment.NewLine, " ");
            sb.Replace((char)13, (char)32);
            sb.Replace((char)10, (char)32);
            sb.Replace(@"\", @"\\");    //\替换为\\
            sb.Replace(@"'", @"\'");    // '替换为\'
            js = sb.ToString();
            Regex regex = new Regex(@"([\w\$]+)");            
            MatchCollection matches = regex.Matches(js);
            string element = "";
            List<string> dict = new List<string>();
            int index = 0;
            StringBuilder encscript = new StringBuilder(js);
            StringBuilder dicttab = new StringBuilder();

            foreach (Match match in matches)
            {
                element = match.Groups[1].Value;
                index = dict.FindIndex(m => m.Equals(element));
                if ( index < 0)
                {
                    dict.Add(element);
                    index = dict.Count - 1;
                }
                encscript.Replace(element, Base64Encode(offset + index + 1));
                //regex.Replace(js,element, Base64Encode(offset + index + 1));
            }

            foreach(string d in dict)
            {
                dicttab.AppendFormat("{0}|", d);
            }

            string dictstr = dicttab.ToString().TrimEnd('|');   //字典字符串,删除最后一个|

            string res = formatCode(encscript.ToString(), dictstr, dict.Count, offset);

            return res;
        }

        /// <summary>
        /// 仿Base64
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        private string Base64Encode(int c)
        { 
            string res="";
            if (c < 0) throw new Exception("Error:Offset必须>=0.");
            if (c > 63)
                res = Base64Encode(c >> 6) + Base64Encode(c & 63);
            else {
                //为了配合appendReplacement方法的使用,将$替换为\$
                res = c.Equals(63) ? @"\$" : ENCODE_BASE64[c].ToString();
            }
            return res;
        }

        private string formatCode(string enc, string dict, int size, int offset)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("/* Power by Shoresoft.Cn */\neval(function(E,I,A,D,J,K,L,H){function C(A){return A<62?String.fromCharCode(A+=A<26?65:A<52?71:-4):A<63?'_':A<64?'$':C(A>>6)+C(A&63)}while(A>0)K[C(D--)]=I[--A];function N(A){return K[A]==L[A]?A:K[A]}if(''.replace(/^/,String)){var M=E.match(J),B=M[0],F=E.split(J),G=0;if(E.indexOf(F[0]))F=[''].concat(F);do{H[A++]=F[G++];H[A++]=N(B)}while(B=M[G]);H[A++]=F[G]||'';return H.join('')}return E.replace(J,N)}(");
            sb.Append("'" + enc + "',");
            sb.Append("'" + dict + "'.split('|'),");
            sb.Append(size + "," + (size + offset) + ",/[\\w\\$]+/g, {}, {}, []))");
            return sb.ToString();
        }

        /// <summary>
        /// 移除块注释
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private string RemoveAnnotation(string str)
        {
            string result = str;
            int start = 0;
            int end = 0;
            start = str.IndexOf("/*");
            end = str.IndexOf("*/");
            StringBuilder sb = new StringBuilder(str);
            if (start >= 0 && end>start)
            {
                sb.Remove(start, end - start + 2);
                return RemoveAnnotation(sb.ToString());
            }
            else
                return sb.ToString();
        }
    }

添加新评论