|
|
'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;
|
|
|
}; |
...
|
...
|
|