javascript实现des算法(支持微信小程序)

概述:

本代码是本人从c++代码上转换成的javascript代码,并测试验证通过的。考虑放其他地方要么要会员要么容易关闭,不容易被需要的获取到,故直接贴在本文档下面的章节,功能代码。

测试平台:

已经在如下环境中测试通过,其他平台(浏览器)应该也不会有问题:

1、nodejs中node.exe运行

2、微信小程序

功能代码:

javascript 复制代码
function strDesCtxParams() {
  this.keybuf;
  this.keylen;
};

var PC_1 = [ //PC_1置换
  57, 49, 41, 33, 25, 17, 9,
  1, 58, 50, 42, 34, 26, 18,
  10, 2, 59, 51, 43, 35, 27,
  19, 11, 3, 60, 52, 44, 36,
  63, 55, 47, 39, 31, 23, 15,
  7, 62, 54, 46, 38, 30, 22,
  14, 6, 61, 53, 45, 37, 29,
  21, 13, 5, 28, 20, 12, 4
];

var Left_Move = [
  1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
];

var PC_2 = [
  14, 17, 11, 24, 1, 5,
  3, 28, 15, 6, 21, 10,
  23, 19, 12, 4, 26, 8,
  16, 7, 27, 20, 13, 2,
  41, 52, 31, 37, 47, 55,
  30, 40, 51, 45, 33, 48,
  44, 49, 39, 56, 34, 53,
  46, 42, 50, 36, 29, 32
];

var IP = [ //IP置换
  58, 50, 42, 34, 26, 18, 10, 2,
  60, 52, 44, 36, 28, 20, 12, 4,
  62, 54, 46, 38, 30, 22, 14, 6,
  64, 56, 48, 40, 32, 24, 16, 8,
  57, 49, 41, 33, 25, 17, 9, 1,
  59, 51, 43, 35, 27, 19, 11, 3,
  61, 53, 45, 37, 29, 21, 13, 5,
  63, 55, 47, 39, 31, 23, 15, 7
];

var Extern = [ //扩展置换
  32, 1, 2, 3, 4, 5,
  4, 5, 6, 7, 8, 9,
  8, 9, 10, 11, 12, 13,
  12, 13, 14, 15, 16, 17,
  16, 17, 18, 19, 20, 21,
  20, 21, 22, 23, 24, 25,
  24, 25, 26, 27, 28, 29,
  28, 29, 30, 31, 32, 1
];

var IP_1 = [ //IP逆置换
  40, 8, 48, 16, 56, 24, 64, 32,
  39, 7, 47, 15, 55, 23, 63, 31,
  38, 6, 46, 14, 54, 22, 62, 30,
  37, 5, 45, 13, 53, 21, 61, 29,
  36, 4, 44, 12, 52, 20, 60, 28,
  35, 3, 43, 11, 51, 19, 59, 27,
  34, 2, 42, 10, 50, 18, 58, 26,
  33, 1, 41, 9, 49, 17, 57, 25
];

var S_BOX = [ //S盒子
  /* S1 */
  14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
  0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
  4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
  15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,

  /* S2 */
  15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
  3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
  0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
  13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,

  /* S3 */
  10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
  13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
  13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
  1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,

  /* S4 */
  7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
  13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
  10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
  3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,

  /* S5 */
  2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
  14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
  4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
  11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,

  /* S6 */
  12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
  10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
  9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
  4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,

  /* S7 */
  4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
  13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
  1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
  6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,

  /* S8 */
  13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
  1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
  7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
  2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
];

var P = [ //P置换
  16, 7, 20, 21,
  29, 12, 28, 17,
  1, 15, 23, 26,
  5, 18, 31, 10,
  2, 8, 24, 14,
  32, 27, 3, 9,
  19, 13, 30, 6,
  22, 11, 4, 25
];


function des_init(keyArray, keyLen) {
  var i = 0;
  var desCtxParams = new strDesCtxParams();

  desCtxParams.keybuf = new Uint8Array(3 * (16 * 6));
  desCtxParams.keylen = keyLen;

  for (i = 0; i < keyLen; i += 8) {
    InputKey(keyArray, i, desCtxParams.keybuf, (16 * 6) * (i / 8));
  }

  //for (i = 0; i < 16 * 6 * 2; i++) {
  //console.log(i + " keybuf " + desCtxParams.keybuf[i]);
  //}
  return desCtxParams;
}

function des_encrypt(desCtxParams, byteArrayDataIn) {
  return des_crypt(desCtxParams, byteArrayDataIn, true);
}

function des_decrypt(desCtxParams, byteArrayDataIn) {
  return des_crypt(desCtxParams, byteArrayDataIn, false);
}


function des_str_to_array(strIn) {
  var bytesArray = new Uint8Array(strIn.length);
  var i = 0;

  for (i = 0; i < strIn.length; i++) {
    bytesArray[i] = strIn.charCodeAt(i);
  }

  return bytesArray;
}

function des_hex_to_array(hexStrIn) {
  var i = 0;
  var cnt = 0;
  var ele = 0;
  var bytesArray = null;

  cnt = 0;
  for (i = 0; i < hexStrIn.length; i++) {
    ele = hexStrIn.charCodeAt(i);
    if (ele >= 48 && ele < 48 + 10) {
      cnt++;
    }
    if (ele >= 65 && ele < 65 + 6) {
      cnt++;
    }
    if (ele >= 97 && ele < 97 + 6) {
      cnt++;
    }
  }
  bytesArray = new Uint8Array(parseInt((cnt + 1) / 2));
  cnt = 0;
  for (i = 0; i < hexStrIn.length; i++) {
    ele = hexStrIn.charCodeAt(i);
    if (ele >= 48 && ele < 48 + 10) {
      ele -= 48;
      cnt++;
    } else if (ele >= 65 && ele < 65 + 6) {
      ele = ele - 65 + 10;
      cnt++;
    } else if (ele >= 97 && ele < 97 + 6) {
      ele = ele - 97 + 10;
      cnt++;
    } else {
      continue;
    }
    if ((cnt % 2) == 1) {
      bytesArray[parseInt((cnt - 1) / 2)] = (ele << 4) & 0xF0;
    } else {
      bytesArray[parseInt((cnt - 1) / 2)] |= ele;
    }
  }

  return bytesArray;
}

function des_hex_to_str(data, len) {
  var sha256_hex_digits = "0123456789abcdef";
  var output = new String();
  var i = 0;

  for (i = 0; i < len; i++) {
    output += sha256_hex_digits.charAt((data[i] >>> 4) & 0x0f);
    output += sha256_hex_digits.charAt((data[i]) & 0x0f);
  }

  return output;
}

function Substitution(subIn, subLen, lpIn, lpInIndex, lpOut, lpOutIndex) {
  //置换
  var i = 0;

  for (i = 0; i < subLen; i++) {
    //console.log(i + " subIn = " + subIn[i]);
    if ((i % 8) == 0) {
      lpOut[parseInt(i / 8) + lpOutIndex] = 0x00;
    }
    /*if (i == 16) {
    	console.log("lpInIndex:" + lpInIndex);
    	console.log("subIn[i]:" + subIn[i]);
    	console.log("parseInt((subIn[i] - 1) / 8) + lpInIndex :" + (((subIn[i] - 1) / 8) + lpInIndex));
    	console.log("lpIn[parseInt((subIn[i] - 1) / 8) + lpInIndex] " + lpIn[parseInt((subIn[i] - 1) / 8) + lpInIndex]);
    	return;
    }*/
    if ((lpIn[parseInt((subIn[i] - 1) / 8) + lpInIndex] & (0x80 >>> ((subIn[i] - 1) % 8))) != 0) {
      lpOut[parseInt(i / 8) + lpOutIndex] |= (0x80 >>> (i % 8));
      //console.log("in " + i);
    }
    //console.log(i + " lpOut :" + lpOut[parseInt(i / 8) + lpOutIndex]);
  }
}

function LeftMove(buf, move) {
  var tmp;

  tmp = buf[0];
  buf[0] <<= move;
  buf[0] |= (buf[1] >> (8 - move));

  buf[1] <<= move;
  buf[1] |= (buf[2] >> (8 - move));

  buf[2] <<= move;
  buf[2] |= (buf[3] >> (8 - move));

  buf[3] &= 0xF0;
  buf[3] <<= move;
  buf[3] |= (tmp >> (8 - 4 - move));
}


function des_crypt(desCtxParams, byteArrayDataIn, isEncrypt) {
  var outResult = new Uint8Array(8);
  var tmpBuf = null;

  if (desCtxParams.keylen == 8) {
    DesCode(byteArrayDataIn, 0, outResult, 0, isEncrypt, desCtxParams.keybuf, 0);
  }
  if (desCtxParams.keylen == 16) {
    tmpBuf = new Uint8Array(16);
    DesCode(byteArrayDataIn, 0, tmpBuf, 0, isEncrypt, desCtxParams.keybuf, 0);
    DesCode(tmpBuf, 0, tmpBuf, 8, !isEncrypt, desCtxParams.keybuf, 16 * 6);
    DesCode(tmpBuf, 8, outResult, 0, isEncrypt, desCtxParams.keybuf, 0);
  }
  if (desCtxParams.keylen == 24) {
    tmpBuf = new Uint8Array(16);
    DesCode(byteArrayDataIn, 0, tmpBuf, 0, isEncrypt, desCtxParams.keybuf, isEncrypt ? 0 : (16 * 6 * 2));
    DesCode(tmpBuf, 0, tmpBuf, 8, !isEncrypt, desCtxParams.keybuf, 16 * 6);
    DesCode(tmpBuf, 8, outResult, 0, isEncrypt, desCtxParams.keybuf, isEncrypt ? (16 * 6 * 2) : 0);
  }

  return outResult;
}

function InputKey(keyIn, keyInOff, keyOutBuf, keyOutBufLen) {
  var tmpkey = new Uint8Array(32);
  var C = new Uint8Array(4);
  var D = new Uint8Array(4);
  var turns = 0;
  var i = 0;

  //console.log("keyInOff:" + keyInOff);
  Substitution(PC_1, 56, keyIn, keyInOff, tmpkey, 0);
  //console.log(des_hex(tmpkey, 32));

  for (turns = 0; turns < 16; turns++) {
    //memcpy(C, tmpkey, 4);
    //memcpy(D, &tmpkey[3], 4);
    for (i = 0; i < 4; i++) {
      C[i] = tmpkey[i];
      D[i] = tmpkey[i + 3];
    }

    D[0] <<= 4;
    D[0] &= 0xF0;
    D[0] |= ((D[1] >> 4) & 0x0F);

    D[1] <<= 4;
    D[1] &= 0xF0;
    D[1] |= ((D[2] >> 4) & 0x0F);

    D[2] <<= 4;
    D[2] &= 0xF0;
    D[2] |= ((D[3] >> 4) & 0x0F);

    D[3] <<= 4;
    D[3] &= 0xF0;

    LeftMove(C, Left_Move[turns]);
    LeftMove(D, Left_Move[turns]);

    //memcpy(tmpkey, C, 4);
    for (i = 0; i < 4; i++) {
      tmpkey[i] = C[i];
    }

    tmpkey[3] &= 0xF0;
    tmpkey[3] |= ((D[0] >> 4) & 0x0F);

    tmpkey[4] = (D[0] << 4) & 0xF0;
    tmpkey[4] |= ((D[1] >> 4) & 0x0F);

    tmpkey[5] = (D[1] << 4) & 0xF0;
    tmpkey[5] |= ((D[2] >> 4) & 0x0F);

    tmpkey[6] = (D[2] << 4) & 0xF0;
    tmpkey[6] |= ((D[3] >> 4) & 0x0F);

    //Substitution((unsigned char*)PC_2, 48, tmpkey, (unsigned char*)gTmpKey[turns]);
    Substitution(PC_2, 48,
      tmpkey, 0, keyOutBuf, keyOutBufLen + turns * 6);
  }

  //for (i = 0; i < 16 * 6; i++) {
  //console.log(i + " keybuf = %d",keyOutBuf[keyOutBufLen + i]);
  //}
}


function DesCode(lpIn, lpInIndex, lpOut, lpOutIndex,
  isEncrypt /*true:加密;false:解密*/ , keybuf, keybufIndex) {
  //unsigned char tmp[64];
  var tmp = new Uint8Array(64);
  //char L[4];
  var L = new Uint8Array(4);
  //char R[4];
  var R = new Uint8Array(4);
  //char KeepR[4];
  var KeepR = new Uint8Array(4);
  var i = 0;
  var j = 0;

  var turns = 0;
  var tmpchar = 0;

  Substitution(IP, 64, lpIn, lpInIndex, tmp, 0); /*IP置换*/

  //console.log(des_hex(tmp, 64));
  //memcpy(L, tmp, 4);
  //memcpy(R, &tmp[4], 4);
  for (i = 0; i < 4; i++) {
    L[i] = tmp[i];
    R[i] = tmp[i + 4];
  }

  if (isEncrypt) {
    turns = 0;
  } else {
    turns = 15;
  }

  while (true) {
    if (isEncrypt) {
      if (turns >= 16) {
        break;
      }
    } else {
      if (turns < 0) {
        break;
      }
    }
    //memcpy(KeepR, R, sizeof(R));
    for (i = 0; i < 4; i++) {
      KeepR[i] = R[i];
    }
    Substitution(Extern, 48, R, 0, tmp, 0);
    //console.log(des_hex(tmp, 64));
    //return;

    for (i = 0; i < 6; i++) {
      //tmp[i] = tmp[i] ^ gTmpKey[turns][i];
      tmp[i] = tmp[i] ^ keybuf[turns * 6 + i + keybufIndex];
    }
    //console.log(des_hex(tmp, 64));
    //return;


    /*S盒子计算*/
    for (i = 0; i < 8; i++) {
      /*8bit*6字节 转换成6bit*8字节*/
      tmpchar = tmp[parseInt(i * 6 / 8)];
      //console.log(parseInt(i * 6 / 8));
      //console.log("1:" + tmpchar);
      j = (i * 6) % 8;
      if (j > 2) {
        //两个字节
        tmpchar <<= (j - 2);
        tmpchar |= (tmp[parseInt(i * 6 / 8) + 1] >>> (10 - j));
        tmpchar &= 0x3F;
      } else {
        tmpchar >>>= (2 - j);
        tmpchar &= 0x3F;
      }
      //console.log("2:" + tmpchar);
      tmpchar |= ((tmpchar & 0x20) << 1);
      tmpchar &= (~0x20);
      tmpchar |= ((tmpchar & 0x01) << 5);
      tmpchar = (tmpchar >> 1) & 0x3F;
      //console.log("3:" + tmpchar);
      tmpchar = S_BOX[i * 64 + tmpchar];
      tmpchar &= 0x0F;
      //console.log("30:" + tmpchar);
      tmpchar = (tmpchar << (((i + 1) % 2) * 4));
      //console.log("4:" + tmpchar);
      tmp[parseInt(i / 2)] &= (0x0F << (((i) % 2) * 4));
      tmp[parseInt(i / 2)] |= tmpchar;
      //console.log(i + " tmp:" + tmp[parseInt(i / 2)]);
      //return;
    }
    //console.log(des_hex(tmp, 64));
    //return;
    Substitution(P, 32, tmp, 0, R, 0);

    for (j = 0; j < 4; j++) {
      R[j] ^= L[j]; /*异或运算*/
      L[j] = KeepR[j]; /*交换左右明文*/
    }

    /*合到一起*/
    //memcpy(tmp, L, sizeof(L));
    //memcpy(tmp + 4, R, sizeof(R));
    for (i = 0; i < 4; i++) {
      tmp[i] = L[i];
      tmp[i + 4] = R[i];
    }

    if (isEncrypt) {
      turns++;
    } else {
      turns--;
    }
  }

  for (i = 0; i < 4; i++) {
    tmpchar = tmp[4 + i];
    tmp[4 + i] = tmp[i];
    tmp[i] = tmpchar;
  }

  /*IP的逆置换*/
  Substitution(IP_1, 64, tmp, 0, lpOut, lpOutIndex);
}


module.exports = {
  des_init: des_init,
  des_encrypt: des_encrypt,
  des_decrypt: des_decrypt,
  des_str_to_array: des_str_to_array,
  des_hex_to_array: des_hex_to_array,
  des_hex_to_str: des_hex_to_str
}

测试代码:

如下在微信小程序中测试验证

javascript 复制代码
var js_des = require('../../crypto/des.js');

testDes() {
  var desCtx = null;
  var result = null;

  desCtx = js_des.des_init(js_des.des_hex_to_array("0011223344556677"), 8);
  result = js_des.des_encrypt(desCtx, js_des.des_hex_to_array("1234567890ABCDEF"));
  console.log("8B key des encrypt:" + js_des.des_hex_to_str(result, 8));

  desCtx = js_des.des_init(js_des.des_hex_to_array("00112233445566778888888800000000"), 16);
  result = js_des.des_encrypt(desCtx, js_des.des_hex_to_array("1234567890ABCDEF"));
  console.log("16B key des encrypt:" + js_des.des_hex_to_str(result, 8));

  desCtx = js_des.des_init(js_des.des_hex_to_array("0011223344556677888888880000000088776655AABBCCDD"), 24);
  result = js_des.des_encrypt(desCtx, js_des.des_hex_to_array("1234567890ABCDEF"));
  console.log("24B key des encrypt:" + js_des.des_hex_to_str(result, 8));

  desCtx = js_des.des_init(js_des.des_hex_to_array("0011223344556677"), 8);
  result = js_des.des_decrypt(desCtx, js_des.des_hex_to_array("1234567890ABCDEF"));
  console.log("8B key des decrypt:" + js_des.des_hex_to_str(result, 8));

  desCtx = js_des.des_init(js_des.des_hex_to_array("00112233445566778888888800000000"), 16);
  result = js_des.des_decrypt(desCtx, js_des.des_hex_to_array("1234567890ABCDEF"));
  console.log("16B key des decrypt:" + js_des.des_hex_to_str(result, 8));

  desCtx = js_des.des_init(js_des.des_hex_to_array("0011223344556677888888880000000088776655AABBCCDD"), 24);
  result = js_des.des_decrypt(desCtx, js_des.des_hex_to_array("1234567890ABCDEF"));
  console.log("24B key des decrypt:" + js_des.des_hex_to_str(result, 8));
},

测试结果:

8B key des encrypt:dabbb1cc478bffcc

16B key des encrypt:7bf2b53fc58f4069

24B key des encrypt:b2c9dae93ca6eb4b

79 8B key des decrypt:52832babfbd22b03

83 16B key des decrypt:3ad46435585e6d07

87 24B key des decrypt:8ebbe81aee99048c

经其他工具验证,结果是正确的

相关推荐
PYB32 小时前
【Web·JS·基础】函数的使用和展运算符...objs
前端·javascript
默_笙3 小时前
🚥 给 RAG 装一台心电监护仪:LangSmith 全链路观测(上)
前端·javascript
变与不变8065 小时前
js同步和异步难点重点详解
开发语言·javascript·ecmascript
Dovis(誓平步青云)5 小时前
多个链接不等于多份证据,新闻核验看板怎样合并来源
java·服务器·前端·javascript·人工智能·pdf·电脑
Dovis(誓平步青云)6 小时前
几个方案来回选不定?做一个随时切换的候选推荐页
android·java·服务器·开发语言·javascript·数据库·智能化
卓怡学长7 小时前
w192基于springboot“考研情报站”微信小程序设计与实现
java·spring boot·spring·微信小程序·intellij-idea
可乐鸡翅yeah_7 小时前
fmp4 碎片 MP4 格式 HLS 流,和传统 TS 分片有什么不一样
开发语言·javascript·ios·音视频·safari·m3u8·m3u8在线播放
ss2738 小时前
AI全栈实战 | 2.3-01 组件库实战:Element Plus 怎么搭出专业界面,过度封装为什么成维护负担
前端·javascript·elementui·vue
福兮说8 小时前
URL 编码的七个坑:c++ 传到后端变空格、%25 套娃、截断 emoji 直接报错
开发语言·前端·javascript·node.js·url
小的时候可菜了9 小时前
JS 异步的本质:从单线程到 thenable(一条进化链)
开发语言·前端·javascript