【2024-06-03】某红书X-s分析

本文详细分析了某网站2023-02-24和2024-06-03两个版本中x-s、x-s-common、x-t等参数的获取和加密流程。通过抓包、断点调试、插桩日志分析,揭示了JSVMP加密机制,涉及到MD5、Base64和DES加密。重点在于理解JSVMP的循环执行、指令集和插桩打日志的方法,最终解密x-s的生成过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

声明:该专栏涉及的所有案例均为学习使用,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!如有侵权,请私信联系本人删帖!

一、前言

在这里插入图片描述
看看西红柿

二、【2023-02-24】版本

网址:

aHR0cHM6Ly93d3cueGlhb2hvbmdzaHUuY29tL2V4cGxvcmU=

1.网站分析

打开一篇文章,查看下请求参数有x-s和x-t
在这里插入图片描述

还有cookie中有个web_session

2.参数x-s

全局搜索,很容易定位到
在这里插入图片描述
直接断点运行,抠下sign函数
在这里插入图片描述
缺什么补什么,大概补三个函数
在这里插入图片描述
运行报错,经过和浏览器对比,浏览器生成数组,而webstorm中报错
在这里插入图片描述
在这里插入图片描述
然后发现r和浏览器中不同
在这里插入图片描述
在这里插入图片描述

r = a0_0x543e();,因此我们直接把这个列表替换成a0_0x543e的返回内容
在这里插入图片描述

再运行
在这里插入图片描述

补window
在这里插入图片描述

缺MD5

在这里插入图片描述

补上运行

在这里插入图片描述

3.web_session

而cookie中的web_session,我们将application中的这个值删掉,再刷新,就能拿到注册该cookie的接口
在这里插入图片描述

4.测试

合起来看一下文章,成功
在这里插入图片描述

三、【2024-06-03】 版本

我们抓包文章后,看到里面有x-s,x-s-common,x-t参数,这里我们分析x-s。

在这里插入图片描述

看到x-s后边的编码像base64,试一下

在这里插入图片描述

看到这里只要搞清楚payload是怎么来的就行。

1. 抓包流程

我们全局搜索x-s,找到这里

在这里插入图片描述

我们这里研究文章,所以下个文章的条件断点

在这里插入图片描述

然后开始下断,断住后,进入到里面,就会看到vmp,这里最终返回了x-s调一下,经过亿点点循环,最后返回了x-s

在这里插入图片描述

2.简单分析下jsvmp文件

上边提到了vmp,这里简单说下jsvmp。

在JSVMP逆向分析中,寄存器,循环是重要的特征,还有有一个特性,加密结果是一个一个字符生成的,基本由一个循环就是for循环或者while循环以及switch case控制。这一点至关重要,算法的分析还原就依赖这个特性。

JSVMP,一般在代码中会有一个超长字符串(指令),然后会把这个字符串decode成一个大数组,不断循环从数组中取指令,分配函数执行运算操作,运算过程会在一个数组或者对象中不断放进或取出生成的值,最后生成目标结果,这个过程会有+,/,%,*操作,会有个apply操作,这些都是插桩的关键位置。

我们通常对vmp的做法就是这么几种:

  • rpc
  • 逆向算法
  • 补环境

这里我们采用逆向算法,那么就得进行插桩打日志了。把这个vmp文件复制下来放到notepad里看一下,由于内容比较小,大概看一下流程

在这里插入图片描述

简单的分析下,刚才我们分析payload是对base64解码,先看返回值

  • 2中的的参数像上找执行了deceode,1是对decode的执行
  • 2最终返回值执行的是这个_ace_99485函数
  • 3是_ace_99485函数,按照jsvmp执行是个循环来说,该函数应该是个循环函数

在这里插入图片描述

这个循环实际上一直执行的是_ace_416e1函数和7个参数,下边的一些函数应该都是指令集,就是决定执行哪个函数

在这里插入图片描述

我们依次网上找一下这个主循环执行的方式,一步一步往上找

在这里插入图片描述

_ace_416e1  >>>  _ace_aec23 >>> _ace_1ae3c >>> _ace_b81ca

在这里插入图片描述

3.插桩

我们大概看明白这个流程,再看一下指令集,大多数是对_ace_1ae3c进行的操作

在这里插入图片描述

那么我们就在这些有计算符号的日志断点试试,这个是拼接的比较重要

在这里插入图片描述

日志断点几十万行,容易卡死浏览器,最好一个一个打。或者就是本地js替换一下,定义全局变量,最后copy下来日志到文本中看。

在这里插入图片描述

接下来看日志。

首先看到日志的url和他的参数拼接

在这里插入图片描述

然后往下看到x1,x2,x3,x4拼接的字符串

在这里插入图片描述

  • x1值就是,刚才url和好他参数拼接值的md5
  • x2是环境值,这里我们固定
  • x3是cookie中的a1值
  • x4是时间戳

拼接完该值,继续看日志,发现了一串base64,试了一下是对x1-x4值拼接出来base64。

在这里插入图片描述

再然后是对这个base64值再进行了一次加密,然后得到了payload。

看到这里生成了一开始我们解开的那个base64。中间没有找到payload是怎么生成的。

{"signSvn":"51","signType":"x1","appId":"xhs-pc-web","signVersion":"1","payload":"37b725ee4f04c180f0ff8e4f16b1c844319bbbed853da6d24e19e1e047500a3c382703f45f66f348cb47eb335cf94709c9e3bfda1faa1eb90d74aa31b54c72cd0d74aa31b54c72cdac489b9da8ce5e48f4afb9acfc3ea26fe0b266a6b4cc3cb52b9fa8540f12a90c30bdf5b8f7275117e29d380b88d5d3d18d5a29b89a8429cccd2451f5ca2f66ada151065790b0b99972fbca2a586c2af1c502dc5c4b83c1bd872cc1f0a90d588f1be60173968a5dc4a39979bf3fbae5fe1dcbcaaca46f5bae"}

但是日志里没有找到payload是怎么生成的。说明这个插桩点看不到怎么加密了。

该换地方插桩了

回到刚才会知道最后都走这里,那么我们依次把这4个参数输出,测试了一下,只有第二个参数有用

在这里插入图片描述

那么只对第二个参数输出,直接输出了一次浏览器卡死了,把干扰项Q开始的队列过滤一下,最好还是替换输出到本地,电脑不太行,老卡死

if (_ace_7e97a && _ace_7e97a[0] != 'Q' && _ace_7e97a[1] != "implementation") {
    try {
        console.log(JSON.stringify(_ace_7e97a))
    } catch (e) {}
}

然后看日志,紧接着找到刚才payload生成出来前的地方,看到包含这么一个数组值,百度上一搜是DES加密

在这里插入图片描述

那么需要找找key值,一般为16或者32位,在他周围有个数组是32的长度,就是密钥

在这里插入图片描述

找了个des的js版本代码改改,用日志的值验证一下,和日志里的一样!

在这里插入图片描述

生成出这个以后,再base64

{"signSvn":"51","signType":"x1","appId":"xhs-pc-web","signVersion":"1","payload":"a34eba1cac322a614c17453e2d9d529cf0d9c5e1e922cf1eec90561f2a9c7719c522c38dffcc733edacf5be1949c1baac9e3bfda1faa1eb90d74aa31b54c72cd0d74aa31b54c72cdac489b9da8ce5e48f4afb9acfc3ea26fe0b266a6b4cc3cb52b9fa8540f12a90c30bdf5b8f7275117e29d380b88d5d3d18d5a29b89a8429cccd2451f5ca2f66ada151065790b0b99972fbca2a586c2af1c502dc5c4b83c1bd872cc1f0a90d588fb6ce674244e11e7c87f22c522da8e733c44ef899051334f9"}

最后和XYW_拼接得到x-s,拼装代码试一下

在这里插入图片描述

4.des的代码

有好多小伙伴找不到这个des代码,这里放一下,key直接在上边15行写死成xhs的了

// https://github.com/liasica/desjs/blob/master/src/index.ts
function des(key, message, encrypt, mode, iv, padding) {
    //declaring this locally speeds things up a bit
    var spfunction1 = new Array(0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000, 0x400, 0x1010400, 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, 0x10404, 0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404, 0x1000400, 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004);
    var spfunction2 = new Array(-0x7fef7fe0, -0x7fff8000, 0x8000, 0x108020, 0x100000, 0x20, -0x7fefffe0, -0x7fff7fe0, -0x7fffffe0, -0x7fef7fe0, -0x7fef8000, -0x80000000, -0x7fff8000, 0x100000, 0x20, -0x7fefffe0, 0x108000, 0x100020, -0x7fff7fe0, 0, -0x80000000, 0x8000, 0x108020, -0x7ff00000, 0x100020, -0x7fffffe0, 0, 0x108000, 0x8020, -0x7fef8000, -0x7ff00000, 0x8020, 0, 0x108020, -0x7fefffe0, 0x100000, -0x7fff7fe0, -0x7ff00000, -0x7fef8000, 0x8000, -0x7ff00000, -0x7fff8000, 0x20, -0x7fef7fe0, 0x108020, 0x20, 0x8000, -0x80000000, 0x8020, -0x7fef8000, 0x100000, -0x7fffffe0, 0x100020, -0x7fff7fe0, -0x7fffffe0, 0x100020, 0x108000, 0, -0x7fff8000, 0x8020, -0x80000000, -0x7fefffe0, -0x7fef7fe0, 0x108000);
    var spfunction3 = new Array(0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008, 0x8000008, 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200, 0x200, 0x20200, 0x8020000, 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8, 0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, 0x8020008, 0x8000208, 0x20000, 0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, 0x8020000, 0x20208, 0x8, 0x8020008, 0x20200);
    var spfunction4 = new Array(0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001, 0, 0x802000, 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080, 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, 0, 0x802000, 0x2080, 0x800080, 0x800081, 0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, 0x2001, 0x802080, 0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080);
    var spfunction5 = new Array(0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000, 0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000, 0x40080000, 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, 0x40080000, 0x2080100, 0x40000100);
    var spfunction6 = new Array(0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000, 0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010, 0x20004010, 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010, 0x400000, 0x20004000, 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010);
    var spfunction7 = new Array(0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802, 0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, 0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800, 0x4000000, 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800, 0x200000, 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2, 0x4200802, 0, 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002);
    var spfunction8 = new Array(0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000, 0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040, 0x10001000, 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040, 0x10001000, 0x40, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000);

    //create the 16 or 48 subkeys we will need
    // var keys = des_createKeys(key);
    var keys = [187050025, 472920585, 186915882, 876157969, 255199502, 806945584, 220596020, 958210835, 757275681, 940378667, 489892883, 705504304, 354103316, 688857884, 890312192, 219096591, 622400037, 254088489, 907618332, 52759587, 907877143, 53870614, 839463457, 389417746, 975774727, 372382245, 437136414, 909246726, 168694017, 473575703, 52697872, 1010440969];


    var m = 0, i, j, temp, temp2, right1, right2, left, right, looping;
    var cbcleft, cbcleft2, cbcright, cbcright2
    var endloop, loopinc;
    var len = message.length;
    var chunk = 0;
    //set up the loops for single and triple des
    var iterations = keys.length == 32 ? 3 : 9; //single or triple des
    if (iterations == 3) {
        looping = encrypt ? new Array(0, 32, 2) : new Array(30, -2, -2);
    } else {
        looping = encrypt ? new Array(0, 32, 2, 62, 30, -2, 64, 96, 2) : new Array(94, 62, -2, 32, 64, 2, 30, -2, -2);
    }

    //pad the message depending on the padding parameter
    if (padding == 2) message += "        "; //pad the message with spaces
    else if (padding == 1) {
        temp = 8 - (len % 8);
        message += String.fromCharCode(temp, temp, temp, temp, temp, temp, temp, temp);
        if (temp == 8) len += 8;
    } //PKCS7 padding
    else if (!padding) message += "\0\0\0\0\0\0\0\0"; //pad the message out with null bytes

    //store the result here
    var result = "";
    var tempresult = "";

    if (mode == 1) { //CBC mode
        cbcleft = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++);
        cbcright = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++);
        m = 0;
    }

    //loop through each 64 bit chunk of the message
    while (m < len) {
        left = (message.charCodeAt(m++) << 24) | (message.charCodeAt(m++) << 16) | (message.charCodeAt(m++) << 8) | message.charCodeAt(m++);
        right = (message.charCodeAt(m++) << 24) | (message.charCodeAt(m++) << 16) | (message.charCodeAt(m++) << 8) | message.charCodeAt(m++);

        //for Cipher Block Chaining mode, xor the message with the previous result
        if (mode == 1) {
            if (encrypt) {
                left ^= cbcleft;
                right ^= cbcright;
            } else {
                cbcleft2 = cbcleft;
                cbcright2 = cbcright;
                cbcleft = left;
                cbcright = right;
            }
        }

        //first each 64 but chunk of the message must be permuted according to IP
        temp = ((left >>> 4) ^ right) & 0x0f0f0f0f;
        right ^= temp;
        left ^= (temp << 4);
        temp = ((left >>> 16) ^ right) & 0x0000ffff;
        right ^= temp;
        left ^= (temp << 16);
        temp = ((right >>> 2) ^ left) & 0x33333333;
        left ^= temp;
        right ^= (temp << 2);
        temp = ((right >>> 8) ^ left) & 0x00ff00ff;
        left ^= temp;
        right ^= (temp << 8);
        temp = ((left >>> 1) ^ right) & 0x55555555;
        right ^= temp;
        left ^= (temp << 1);

        left = ((left << 1) | (left >>> 31));
        right = ((right << 1) | (right >>> 31));

        //do this either 1 or 3 times for each chunk of the message
        for (j = 0; j < iterations; j += 3) {
            endloop = looping[j + 1];
            loopinc = looping[j + 2];
            //now go through and perform the encryption or decryption
            for (i = looping[j]; i != endloop; i += loopinc) { //for efficiency
                right1 = right ^ keys[i];
                right2 = ((right >>> 4) | (right << 28)) ^ keys[i + 1];
                //the result is attained by passing these bytes through the S selection functions
                temp = left;
                left = right;
                right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f]
                    | spfunction6[(right1 >>> 8) & 0x3f] | spfunction8[right1 & 0x3f]
                    | spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & 0x3f]
                    | spfunction5[(right2 >>> 8) & 0x3f] | spfunction7[right2 & 0x3f]);
            }
            temp = left;
            left = right;
            right = temp; //unreverse left and right
        } //for either 1 or 3 iterations

        //move then each one bit to the right
        left = ((left >>> 1) | (left << 31));
        right = ((right >>> 1) | (right << 31));

        //now perform IP-1, which is IP in the opposite direction
        temp = ((left >>> 1) ^ right) & 0x55555555;
        right ^= temp;
        left ^= (temp << 1);
        temp = ((right >>> 8) ^ left) & 0x00ff00ff;
        left ^= temp;
        right ^= (temp << 8);
        temp = ((right >>> 2) ^ left) & 0x33333333;
        left ^= temp;
        right ^= (temp << 2);
        temp = ((left >>> 16) ^ right) & 0x0000ffff;
        right ^= temp;
        left ^= (temp << 16);
        temp = ((left >>> 4) ^ right) & 0x0f0f0f0f;
        right ^= temp;
        left ^= (temp << 4);

        //for Cipher Block Chaining mode, xor the message with the previous result
        if (mode == 1) {
            if (encrypt) {
                cbcleft = left;
                cbcright = right;
            } else {
                left ^= cbcleft2;
                right ^= cbcright2;
            }
        }
        tempresult += String.fromCharCode((left >>> 24), ((left >>> 16) & 0xff), ((left >>> 8) & 0xff), (left & 0xff), (right >>> 24), ((right >>> 16) & 0xff), ((right >>> 8) & 0xff), (right & 0xff));

        chunk += 8;
        if (chunk == 512) {
            result += tempresult;
            tempresult = "";
            chunk = 0;
        }
    } //for every 8 characters, or 64 bits in the message

    //return the result as an array
    return result + tempresult;
} //end of des


//des_createKeys
//this takes as input a 64 bit key (even though only 56 bits are used)
//as an array of 2 integers, and returns 16 48 bit keys
function des_createKeys(key) {
    //declaring this locally speeds things up a bit
    var pc2bytes0 = new Array(0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004, 0x200, 0x204, 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204);
    var pc2bytes1 = new Array(0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001, 0x100, 0x101, 0x100100, 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101);
    var pc2bytes2 = new Array(0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808);
    var pc2bytes3 = new Array(0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000, 0x20000, 0x220000, 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000);
    var pc2bytes4 = new Array(0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010, 0x41010, 0x1000, 0x41000, 0x1010, 0x41010);
    var pc2bytes5 = new Array(0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020, 0x2000420, 0x2000000, 0x2000400, 0x2000020, 0x2000420);
    var pc2bytes6 = new Array(0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002);
    var pc2bytes7 = new Array(0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000, 0x30000, 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800);
    var pc2bytes8 = new Array(0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000, 0x2040000, 0x2000002, 0x2040002, 0x2000002, 0x2040002);
    var pc2bytes9 = new Array(0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408, 0x10000408, 0x400, 0x10000400, 0x408, 0x10000408);
    var pc2bytes10 = new Array(0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020, 0x102000, 0x102020, 0x102000, 0x102020);
    var pc2bytes11 = new Array(0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000, 0x5000000, 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200);
    var pc2bytes12 = new Array(0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010, 0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010);
    var pc2bytes13 = new Array(0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105);

    //how many iterations (1 for des, 3 for triple des)
    var iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys
    //stores the return keys
    var keys = new Array(32 * iterations);
    //now define the left shifts which need to be done
    var shifts = new Array(0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0);
    //other variables
    var lefttemp, righttemp, m = 0, n = 0, temp, left, right;

    for (var j = 0; j < iterations; j++) { //either 1 or 3 iterations
        left = (key.charCodeAt(m++) << 24) | (key.charCodeAt(m++) << 16) | (key.charCodeAt(m++) << 8) | key.charCodeAt(m++);
        right = (key.charCodeAt(m++) << 24) | (key.charCodeAt(m++) << 16) | (key.charCodeAt(m++) << 8) | key.charCodeAt(m++);

        temp = ((left >>> 4) ^ right) & 0x0f0f0f0f;
        right ^= temp;
        left ^= (temp << 4);
        temp = ((right >>> -16) ^ left) & 0x0000ffff;
        left ^= temp;
        right ^= (temp << -16);
        temp = ((left >>> 2) ^ right) & 0x33333333;
        right ^= temp;
        left ^= (temp << 2);
        temp = ((right >>> -16) ^ left) & 0x0000ffff;
        left ^= temp;
        right ^= (temp << -16);
        temp = ((left >>> 1) ^ right) & 0x55555555;
        right ^= temp;
        left ^= (temp << 1);
        temp = ((right >>> 8) ^ left) & 0x00ff00ff;
        left ^= temp;
        right ^= (temp << 8);
        temp = ((left >>> 1) ^ right) & 0x55555555;
        right ^= temp;
        left ^= (temp << 1);

        //the right side needs to be shifted and to get the last four bits of the left side
        temp = (left << 8) | ((right >>> 20) & 0x000000f0);
        //left needs to be put upside down
        left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0);
        right = temp;

        //now go through and perform these shifts on the left and right keys
        for (var i = 0; i < shifts.length; i++) {
            //shift the keys either one or two bits to the left
            if (shifts[i]) {
                left = (left << 2) | (left >>> 26);
                right = (right << 2) | (right >>> 26);
            } else {
                left = (left << 1) | (left >>> 27);
                right = (right << 1) | (right >>> 27);
            }
            left &= -0xf;
            right &= -0xf;

            //now apply PC-2, in such a way that E is easier when encrypting or decrypting
            //this conversion will look like PC-2 except only the last 6 bits of each byte are used
            //rather than 48 consecutive bits and the order of lines will be according to
            //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7
            lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf]
                | pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[(left >>> 16) & 0xf]
                | pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf]
                | pc2bytes6[(left >>> 4) & 0xf];
            righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf]
                | pc2bytes9[(right >>> 20) & 0xf] | pc2bytes10[(right >>> 16) & 0xf]
                | pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf]
                | pc2bytes13[(right >>> 4) & 0xf];
            temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff;
            keys[n++] = lefttemp ^ temp;
            keys[n++] = righttemp ^ (temp << 16);
        }
    } //for each iterations
    //return the keys we've created
    return keys;
} //end of des_createKeys

// enum Padding {
//   NULL = 0,
//   PKCS7 = 1,
//   SPACES = 2,
//   NONE = 3
// }
//
// enum Mode {
//   ECB = 0,
//   CBC = 1
// }
//
var encodeHex = function (s) {
    let r = '';
    const hexes = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
    for (let i = 0; i < s.length; i++) {
        r += hexes [s.charCodeAt(i) >> 4] + hexes [s.charCodeAt(i) & 0xf];
    }
    return r;
};

var decodeHex = function (h) {
    let r = '';
    for (let i = (h.substring(0, 2) === '0x') ? 2 : 0; i < h.length; i += 2) {
        r += String.fromCharCode(parseInt(h.substring(i, i + 2), 16));
    }
    return r;
};


function get_des(message) {
    return encodeHex(des(undefined, message, 1, 0, undefined, 0));
}


//
// export const encrypt = (key: string, message: string, iv?: string, padding: Padding = Padding.NONE): string => {
//   const mode = iv ? Mode.CBC : Mode.ECB
//   return encodeHex(des(key, message, 1, mode, iv, padding))
// }
//
// export const decrypt = (key: string, message: string, iv?: string, padding: Padding = Padding.NONE) => {
//   const mode = iv ? Mode.CBC : Mode.ECB
//   return des(key, decodeHex(message), 0, mode, iv, padding).replace(/\0/g, '')
// }

// 加密测试
var message = "eDE9NzIxYjdjODRjNWJkYmY3ZjUxYTZkMmNhYTEyZjhiNDQ7eDI9MHwwfDB8MXwwfDB8MXwwfDB8MHwxfDB8MHwwfDA7eDM9MThmYmUyNDAyYTZvNWl5c3prd29uMWl2NmduMGFkOHE2NHJiOGUyeW81MDAwMDI2ODI4MTt4ND0xNzE3MDM3Mjc2OTY1Ow==";
var aaa = encodeHex(des(undefined, message, 1, 0, undefined, 0));
console.log(aaa);

// 解密测试
// aaa='a34eba1cac322a614c17453e2d9d529cf0d9c5e1e922cf1eec90561f2a9c7719c522c38dffcc733edacf5be1949c1baac9e3bfda1faa1eb90d74aa31b54c72cd0d74aa31b54c72cdac489b9da8ce5e48f4afb9acfc3ea26fe0b266a6b4cc3cb52b9fa8540f12a90c30bdf5b8f7275117e29d380b88d5d3d18d5a29b89a8429cccd2451f5ca2f66ada151065790b0b99972fbca2a586c2af1c502dc5c4b83c1bd872cc1f0a90d588fb6ce674244e11e7c87f22c522da8e733c44ef899051334f9'
// var result = des(undefined, decodeHex(aaa), 0, 0, undefined, 0).replace(/\0/g, '');
// console.log(result);
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张烫麻辣亮。

谢谢老板,祝你生8个儿子!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值