Authored by ccbikai(👎🏻🍜)

add authcode

  1 +'use strict';
  2 +const md5 = require('md5');
  3 +
  4 +const microtime = function() {
  5 + let unixtimeMs = new Date().getTime();
  6 + let sec = parseInt(unixtimeMs / 1000, 10);
  7 +
  8 + return (unixtimeMs - (sec * 1000)) / 1000 + ' ' + sec;
  9 +};
  10 +
  11 +const getTimestamp = function() {
  12 + let unixtimeMs = new Date().getTime();
  13 +
  14 + return parseInt(unixtimeMs / 1000, 10);
  15 +};
  16 +
  17 +module.exports = function(str, operation, key, expiry) {
  18 + operation = operation ? operation : 'encode';
  19 + key = key ? key : '';
  20 + expiry = expiry ? expiry : 0;
  21 + let tmpstr, tmp;
  22 +
  23 + let ckeyLength = 4;
  24 +
  25 + key = md5(key);
  26 +
  27 + // 密匙a会参与加解密
  28 + let keya = md5(key.substr(0, 16));
  29 +
  30 + // 密匙b会用来做数据完整性验证
  31 + let keyb = md5(key.substr(16, 16));
  32 +
  33 + // 密匙c用于变化生成的密文
  34 + let keyc = operation === 'decode' ?
  35 + str.substr(0, ckeyLength) : md5(microtime()).substr(-ckeyLength);
  36 +
  37 + // 参与运算的密匙
  38 + let cryptkey = keya + md5(keya + keyc);
  39 +
  40 + let strbuf;
  41 +
  42 + if (operation === 'decode') {
  43 + str = str.substr(ckeyLength);
  44 + strbuf = new Buffer(str, 'base64');
  45 +
  46 + // string = b.toString();
  47 + } else {
  48 + expiry = expiry ? expiry + getTimestamp() : 0;
  49 + tmpstr = expiry.toString();
  50 + if (tmpstr.length >= 10) {
  51 + str = tmpstr.substr(0, 10) + md5(str + keyb).substr(0, 16) + str;
  52 + } else {
  53 + let count = 10 - tmpstr.length;
  54 +
  55 + for (let i = 0; i < count; i++) {
  56 + tmpstr = '0' + tmpstr;
  57 + }
  58 + str = tmpstr + md5(str + keyb).substr(0, 16) + str;
  59 + }
  60 + strbuf = new Buffer(str);
  61 + }
  62 +
  63 +
  64 + let box = new Array(256);
  65 + let rndkey = [];
  66 +
  67 + for (let i = 0; i < 256; i++) {
  68 + box[i] = i;
  69 +
  70 + // 产生密匙簿
  71 + rndkey[i] = cryptkey.charCodeAt(i % cryptkey.length);
  72 + }
  73 +
  74 + // 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上对并不会增加密文的强度
  75 + for (let j = 0, i = 0; i < 256; i++) {
  76 + j = (j + box[i] + rndkey[i]) % 256;
  77 + tmp = box[i];
  78 + box[i] = box[j];
  79 + box[j] = tmp;
  80 + }
  81 +
  82 +
  83 + // 核心加解密部分
  84 + let s = '';
  85 +
  86 + for (let a = 0, j = 0, i = 0; i < strbuf.length; i++) {
  87 + a = (a + 1) % 256;
  88 + j = (j + box[a]) % 256;
  89 + tmp = box[a];
  90 + box[a] = box[j];
  91 + box[j] = tmp;
  92 +
  93 + // 从密匙簿得出密匙进行异或,再转成字符
  94 + // s += String.fromCharCode(string[i] ^ (box[(box[a] + box[j]) % 256]));
  95 + /* jshint -W016*/
  96 + strbuf[i] = strbuf[i] ^ (box[(box[a] + box[j]) % 256]);
  97 + }
  98 +
  99 + if (operation === 'decode') {
  100 + s = strbuf.toString();
  101 + if ((s.substr(0, 10) === '0'.repeat(10) ||
  102 + s.substr(0, 10) - getTimestamp() > 0) &&
  103 + s.substr(10, 16) === md5(s.substr(26) + keyb).substr(0, 16)) {
  104 + s = s.substr(26);
  105 + } else {
  106 + s = '';
  107 + }
  108 + } else {
  109 + s = strbuf.toString('base64');
  110 + let regex = new RegExp('=', 'g');
  111 +
  112 + s = s.replace(regex, '');
  113 + s = keyc + s;
  114 + }
  115 +
  116 + return s;
  117 +};
  118 +
  119 +// console.log(module.exports('abcdef123', 'encode', 'key123', 99))