分享

一个类似 Base64 但真正实现了加密的 JS 文字加密算法

 昵称3884271 2014-02-12
算法的基本原理和 Base64 类似。Base64 算法请参见维基百科 http://zh./zh-cn/Base64

这里把 Base64 中使用的基本字符表进行了随机化——即用基本字符表排列的随机性作为密钥的变化性。同时,考虑编码方法的应用环境多为 Javascript,故将 Base64 规范字符表中的 “+/=” 改成了 “$_~”,便于网络传输和变量命名等。

对 “纯单字节” 字符串或 “纯双字节” 字符串,密文的长度增长 0.35 倍左右;在单/双字节混合的字符串中,因为需要在 “单/双字节序列” 间插入标识码(状态指示),故密文的长度会有所加长,但也不会增加太多。

该加密法的密文长度增加量略低于 “进制乱序法”,加密强度约为 296 位(64 的阶乘),算法中没有加入 “平移” 的二次操作,如果嫌加密强度不够,可以简单的对密文进行平移操作(详见 http://rubel./blog/891657)。

算法的编写参考了 《base64的js实现》,在此致谢!(注:该算法中未对编码串作 76 字符分段)

算法 4: Base64 变形加密法

Javascript代码 复制代码 收藏代码
  1. (function() {   
  2.     //   
  3.     // 密文字符集(size:65)。   
  4.     // [0-9A-Za-z$_~]   
  5.     //   
  6.     var _hexCHS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz$_~';   
  7.   
  8.     //   
  9.     // Base64 变形加密法   
  10.     // 算法与 Base64 类似,即将 8 位字节用 6 位表示。   
  11.     // 规则:   
  12.     // 1. 码值 <= 0xff 的用 1 个字节表示;   
  13.     // 2. 码值 > 0xff 的用 2 字节表示;   
  14.     // 3. 单/双字节序列间用 0x1d 进行分隔;   
  15.     // 4. 首字为双字节时即前置 0x1d 分隔符。   
  16.     //   
  17.     // @param array key  - [0-63] 互斥值数组,length == 64   
  18.     //    
  19.     Hex64 = function( key )   
  20.     {   
  21.         this._key = [], this._tbl = {};   
  22.   
  23.         for (var _i=0; _i<64; ++_i) {   
  24.             this._key[_i] = _hexCHS.charAt(key[_i]);   
  25.             this._tbl[this._key[_i]] = _i;   
  26.         }   
  27.   
  28.         this._pad = _hexCHS.charAt(64);   
  29.     };   
  30.   
  31.     // 加密   
  32.     Hex64.prototype.enc = function( s )   
  33.     {   
  34.         var _rs = '';   
  35.         var _c1, _c2, _c3, _n1, _n2, _n3, _n4;   
  36.         var _i = 0;   
  37.         var _a = Hex64._2to1(s);   
  38.         var _en = _a.length % 3, _sz = _a.length - _en;   
  39.         while (_i < _sz) {   
  40.             _c1 = _a[_i++];   
  41.             _c2 = _a[_i++];   
  42.             _c3 = _a[_i++];   
  43.             _n1 = _c1 >> 2;   
  44.             _n2 = ((_c1 & 3) << 4) | (_c2 >> 4);   
  45.             _n3 = ((_c2 & 15) << 2) | (_c3 >> 6);   
  46.             _n4 = _c3 & 63;   
  47.             _rs += this._key[_n1]   
  48.                 + this._key[_n2]   
  49.                 + this._key[_n3]   
  50.                 + this._key[_n4];   
  51.         }   
  52.         if (_en > 0) {   
  53.             _c1 = _a[_i++];   
  54.             _c2 = _en > 1 ? _a[_i] : 0;   
  55.             _n1 = _c1 >> 2;   
  56.             _n2 = ((_c1 & 3) << 4) | (_c2 >> 4);   
  57.             _n3 = (_c2 & 15) << 2;   
  58.             _rs += this._key[_n1] + this._key[_n2]   
  59.                 + (_n3 ? this._key[_n3] : this._pad)   
  60.                 + this._pad;   
  61.         }   
  62.         return  _rs.replace(/.{76}/g, function(s) {   
  63.             return  s + '\n';   
  64.         });   
  65.     };   
  66.   
  67.     // 解密   
  68.     Hex64.prototype.dec = function( s )   
  69.     {   
  70.         var _sa = [],   
  71.             _n1, _n2, _n3, _n4,   
  72.             _i = 0, _c = 0;   
  73.         s = s.replace(/[^0-9A-Za-z$_~]/g, '');   
  74.         while (_i < s.length) {   
  75.             _n1 = this._tbl[s.charAt(_i++)];   
  76.             _n2 = this._tbl[s.charAt(_i++)];   
  77.             _n3 = this._tbl[s.charAt(_i++)];   
  78.             _n4 = this._tbl[s.charAt(_i++)];   
  79.             _sa[_c++] = (_n1 << 2) | (_n2 >> 4);   
  80.             _sa[_c++] = ((_n2 & 15) << 4) | (_n3 >> 2);   
  81.             _sa[_c++] = ((_n3 & 3) << 6) | _n4;   
  82.         }   
  83.         var _e2 = s.slice(-2);   
  84.         if (_e2.charAt(0) == this._pad) {   
  85.             _sa.length = _sa.length - 2;   
  86.         } else if (_e2.charAt(1) == this._pad) {   
  87.             _sa.length = _sa.length - 1;   
  88.         }   
  89.         return  Hex64._1to2(_sa);   
  90.     };   
  91.   
  92.     //   
  93.     // 辅助:   
  94.     // Unicode 字符串 -> 单字节码值数组   
  95.     // 注意:   
  96.     // 原串中值为 0x1d 的字节(非字符)会被删除。   
  97.     //   
  98.     // @param string s  - 字符串(UCS-16)   
  99.     // @return array  - 单字节码值数组   
  100.     //   
  101.     Hex64._2to1 = function( s )   
  102.     {   
  103.         var _2b = false, _n = 0, _sa = [];   
  104.   
  105.         if (s.charCodeAt(0) > 0xff) {   
  106.             _2b = true;   
  107.             _sa[_n++] = 0x1d;   
  108.         }   
  109.         for (var _i=0; _i<s.length; ++_i) {   
  110.             var _c = s.charCodeAt(_i);   
  111.             if (_c == 0x1d) continue;   
  112.             if (_c <= 0xff) {   
  113.                 if (_2b) {   
  114.                     _sa[_n++] = 0x1d;   
  115.                     _2b = false;   
  116.                 }   
  117.                 _sa[_n++] = _c;   
  118.             } else {   
  119.                 if (! _2b) {   
  120.                     _sa[_n++] = 0x1d;   
  121.                     _2b = true;   
  122.                 }   
  123.                 _sa[_n++] = _c >> 8;   
  124.                 _sa[_n++] = _c & 0xff;   
  125.             }   
  126.         }   
  127.         return  _sa;   
  128.     };   
  129.   
  130.     //   
  131.     // 辅助:   
  132.     // 单字节码值数组 -> Unicode 字符串   
  133.     //   
  134.     // @param array a  - 单字节码值数组   
  135.     // @return string  - 还原后的字符串(UCS-16)   
  136.     //   
  137.     Hex64._1to2 = function( a )   
  138.     {   
  139.         var _2b = false, _rs = '';   
  140.   
  141.         for (var _i=0; _i<a.length; ++_i) {   
  142.             var _c = a[_i];   
  143.             if (_c == 0x1d) {   
  144.                 _2b = !_2b;   
  145.                 continue;   
  146.             }   
  147.             if (_2b) {   
  148.                 _rs += String.fromCharCode(_c * 256 + a[++_i]);    
  149.             } else {   
  150.                 _rs += String.fromCharCode(_c);   
  151.             }   
  152.         }   
  153.         return  _rs;   
  154.     };   
  155.   
  156. })();  


用法:
Javascript代码 复制代码 收藏代码
  1. <script language="JavaScript">   
  2.     var _str = "中文字符串和 English char string 的 JS 加密 1234. 包含一些标点符号,*@%! 等。";   
  3.     //php -r "$a=range(0,63); shuffle($a); echo join(',', $a);"   
  4.     var _k3 = [38,48,18,11,26,19,55,58,10,33,34,49,14,25,44,52,61,16,2,56,23,29,45,9,3,12,39,30,42,47,22,21,60,1,54,28,57,17,27,15,40,46,43,13,0,51,35,63,36,50,6,32,4,31,62,5,24,8,53,59,41,20,7,37];   
  5.     var _o = new Hex64(_k3);   
  6.     var _enc3 = _o.enc(_str);   
  7.     alert(_enc3)   
  8.     alert(_o.dec(_enc3));   
  9.     //wNOpC3lUT50RuSXNSm4yGj8FUtHWdImSdtJ6AwP4gRHZC6cllezlAQkuAmV2eJ_tw2coESE4nscl   
  10.     //NaTNY4Ocukpem5I8M6CuKbfEw2kcX2Qyw9pXEcA~  


附件中:
xtools.js 里包含前面几篇文章中提及的几个文字加密算法(JS 版,稍有调整),以及 Window.name 跨域实现的代码;
其它几个文件为测试用的 html 文件。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多