authcode.js
2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
'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;
};