js壓縮、混淆和加密
最近看到有些論壇在討論js壓縮、混淆和加密的問題,特意找了些資料看了下,現在總結一下:
1.關於三者的定義與區別
壓縮:刪除 Javascript 代碼中所有註釋、跳格符號、換行符號及無用的空格,從而壓縮 JS 文件大小,優化頁面加載速度。
混淆:經過編碼將變量和函數原命名改為毫無意義的命名(如function(a,b,c,e,g)等),以防止他人窺視和竊取 Javascript 源代碼,也有一定壓縮效果。
加密:一般用eval方法加密,效果與混淆相似,也做到了壓縮的效果。
從定義中可以看出,壓縮的主要目的是消除註釋等無用字符,達到精簡js代碼,減小js文件大小的目的,這也是頁面優化的一種方式;而混淆和加密的目的比較接近,都是為了防止他人直接查看源碼,對代碼(如重要的api等)起保護作用,但這也只是增加了閱讀代碼的代價,也就是所謂的防君子不防小人。但是當混淆和加密聯合使用時,如先混淆在加密(或者先加密再混淆)時,破解時間就會增加。關於js的加密,可以參考這篇文章:http://www.cnblogs.com/top5/archive/2009/08/07/1540860.html
2.demo
下面以更直觀的方式來體會一下這四種方式(壓縮、混淆、加密、混淆&加密)的不同。
源js代碼如下:
View Code(1)經過壓縮後的代碼如下:
1 function xx(num,str){var a=num;this.aa=a;this.bb=function(){alert(str)};this.cc=function(){for(var i=0;i<10;i++){document.title=i}};this.yy=new yy();function xxf(){alert("xxf");if((/\{\d+\}/).test("a\sdf{2}ab"))alert("{\\d} is match!")}};xx.prototype.dd=function(){alert("dd");a.yy.ll();var fnx=function(i){this.ab=i;this.aa=function(){alert(this.ab)}};var f1=new fnx(1);f1.aa()};function yy(){alert(‘yy‘)};yy.prototype.ll=function(){alert("yyll")};var a=new xx(100,"hello"),b=new xx(0,"ttyp");eval("a.aa=20");a.bb();b.dd();alert(a.aa);var k=9;function kk(){var k=0;alert(k)};kk();alert(k);
壓縮後與源碼相比只是少了註釋、空格、換行等。
(2)經過混淆後的代碼如下:
1 function xx(d,e){var f=d;this.aa=f;this.bb=function(){alert(e)};this.cc=function(){for(var g=0;g<10;g++){document.title=g}};this.yy=new yy();function xxf(){alert("xxf");if((/\{\d+\}/).test("a\sdf{2}ab"))alert("{\\d} is match!")}};xx.prototype.dd=function(){alert("dd");a.yy.ll();var fnx=function(e){this.ab=e;this.aa=function(){alert(this.ab)}};var d=new fnx(1);d.aa()};function yy(){alert(‘yy‘)};yy.prototype.ll=function(){alert("yyll")};var a=new xx(100,"hello"),b=new xx(0,"ttyp");eval("a.aa=20");a.bb();b.dd();alert(a.aa);var c=9;function kk(){var d=0;alert(d)};kk();alert(c);
混淆後除了少了註釋、空格和換行等,參數也被a,b,c,d,e等字符代替,提高了閱讀的難度。
(3)經過加密後的代碼如下:
1 eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!‘‘.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return‘\\w+‘};c=1;};while(c--)if(k[c])p=p.replace(new RegExp(‘\\b‘+e(c)+‘\\b‘,‘g‘),k[c]);return p;}(‘3 e(o,l){5 a=o;6.8=a;6.p=3(){4(l)};6.B=3(){A(5 i=0;i<y;i++){x.z=i}};6.7=c 7();3 j(){4("j");t((/\\{\\d+\\}/).s("a\\u{2}g"))4("{\\\\d} w v!")}};e.r.f=3(){4("f");a.7.h();5 n=3(i){6.g=i;6.8=3(){4(6.g)}};5 m=c n(1);m.8()};3 7(){4(\‘7\‘)};7.r.h=3(){4("D")};5 a=c e(F,"H"),b=c e(0,"G");E("a.8=C");a.p();b.f();4(a.8);5 k=9;3 q(){5 k=0;4(k)};q();4(k);‘,44,44,‘|||function|alert|var|this|yy|aa||||new||xx|dd|ab|ll||xxf||str|f1|fnx|num|bb|kk|prototype|test|if|sdf|match|is|document|10|title|for|cc|20|yyll|eval|100|ttyp|hello‘.split(‘|‘),0,{}))
加密後除了有混淆的作用外,有些代碼被加密了,進一步提高了閱讀的難度。
(4)經過混淆&加密後的代碼如下
1 eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!‘‘.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return‘\\w+‘};c=1;};while(c--)if(k[c])p=p.replace(new RegExp(‘\\b‘+e(c)+‘\\b‘,‘g‘),k[c]);return p;}(‘4 i(d,e){5 f=d;6.8=f;6.p=4(){3(e)};6.s=4(){t(5 g=0;g<y;g++){G.F=g}};6.7=h 7();4 l(){3("l");x((/\\{\\d+\\}/).v("a\\u{2}j"))3("{\\\\d} w r!")}};i.o.k=4(){3("k");a.7.m();5 n=4(e){6.j=e;6.8=4(){3(6.j)}};5 d=h n(1);d.8()};4 7(){3(\‘7\‘)};7.o.m=4(){3("E")};5 a=h i(A,"z"),b=h i(0,"B");D("a.8=C");a.p();b.k();3(a.8);5 c=9;4 q(){5 d=0;3(d)};q();3(c);‘,43,43,‘|||alert|function|var|this|yy|aa|||||||||new|xx|ab|dd|xxf|ll|fnx|prototype|bb|kk|match|cc|for|sdf|test|is|if|10|hello|100|ttyp|20|eval|yyll|title|document‘.split(‘|‘),0,{}))
3.瀏覽器是怎麽解析混淆和加密後的js代碼的
其實變量名只要是Unicode字符就行了,對於js引擎來說都是一樣的,只是人類覺得他們不同而已。
4.js壓縮工具
其實js的壓縮工具網上有很多,在線和安裝版的都有,文章中使用的是HDS JSObfuscator v2.13綠色版。
在線的js壓縮工具:http://tool.chinaz.com/js.aspx
5.註意事項
源js文件一定要按照規範編寫,分號,註釋符,var等都要規範,否則很容易出錯。
6.參考文章
(1)http://m.blog.csdn.net/blog/Shb_derek/25032169
(2)http://blog.csdn.net/kof820/article/details/19345929
(3)http://www.zhihu.com/question/29169806
js壓縮、混淆和加密