'use strict'; const md5 = require('md5'); const microtime = function() { let unixtimeMs = new Date().getTime(); let sec = parseInt(unixtimeMs / 1000, 10); return (unixtimeMs - (sec * 1000)) / 1000 + ' ' + sec; }; const getTimestamp = function() { let unixtimeMs = new Date().getTime(); return parseInt(unixtimeMs / 1000, 10); }; module.exports = function(str, key, expiry, operation) { operation = operation ? operation : 'decode'; key = key ? key : ''; expiry = expiry ? expiry : 0; let tmpstr, tmp; let ckeyLength = 4; key = md5(key); // 密匙a会参与加解密 let keya = md5(key.substr(0, 16)); // 密匙b会用来做数据完整性验证 let keyb = md5(key.substr(16, 16)); // 密匙c用于变化生成的密文 let keyc = operation === 'decode' ? str.substr(0, ckeyLength) : md5(microtime()).substr(-ckeyLength); // 参与运算的密匙 let cryptkey = keya + md5(keya + keyc); let strbuf; if (operation === 'decode') { str = str.substr(ckeyLength); strbuf = new Buffer(str, 'base64'); // string = b.toString(); } else { expiry = expiry ? expiry + getTimestamp() : 0; tmpstr = expiry.toString(); if (tmpstr.length >= 10) { str = tmpstr.substr(0, 10) + md5(str + keyb).substr(0, 16) + str; } else { let count = 10 - tmpstr.length; for (let i = 0; i < count; i++) { tmpstr = '0' + tmpstr; } str = tmpstr + md5(str + keyb).substr(0, 16) + str; } strbuf = new Buffer(str); } let box = new Array(256); let rndkey = []; for (let i = 0; i < 256; i++) { box[i] = i; // 产生密匙簿 rndkey[i] = cryptkey.charCodeAt(i % cryptkey.length); } // 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上对并不会增加密文的强度 for (let j = 0, i = 0; i < 256; i++) { j = (j + box[i] + rndkey[i]) % 256; tmp = box[i]; box[i] = box[j]; box[j] = tmp; } // 核心加解密部分 let s = ''; for (let a = 0, j = 0, i = 0; i < strbuf.length; i++) { a = (a + 1) % 256; j = (j + box[a]) % 256; tmp = box[a]; box[a] = box[j]; box[j] = tmp; // 从密匙簿得出密匙进行异或,再转成字符 // s += String.fromCharCode(string[i] ^ (box[(box[a] + box[j]) % 256])); /* jshint -W016*/ strbuf[i] = strbuf[i] ^ (box[(box[a] + box[j]) % 256]); } if (operation === 'decode') { s = strbuf.toString(); if ((s.substr(0, 10) === '0'.repeat(10) || s.substr(0, 10) - getTimestamp() > 0) && s.substr(10, 16) === md5(s.substr(26) + keyb).substr(0, 16)) { s = s.substr(26); } else { s = ''; } } else { s = strbuf.toString('base64'); let regex = new RegExp('=', 'g'); s = s.replace(regex, ''); s = keyc + s; } return s; };