自用算法包

个人私用算法包

目前為 2022-10-23 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         自用算法包
// @namespace    http://tampermonkey.net/
// @version      0.1.4
// @description  个人私用算法包
// @author       Tenfond
// @match        https://*/*
// @match        http://*/*
// @license      AGPL-3.0
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // 大数精度位运算
    // const Bit = (function () {
    //     // 反码
    //     function ones_complement(a) {
    //         a = a.split("");
    //         for (let i = 1; i < a.length; i++) {
    //             if (a[0] !== a[i]) {
    //                 a[i] = "1";
    //             } else {
    //                 a[i] = "0";
    //             }
    //         }
    //         return a.join("");
    //     }
    //
    //     return {
    //         // 与
    //         and: function (a, b) {
    //             a = a.toString(2);
    //             b = b.toString(2);
    //             if (a[0] === "-") {
    //                 a = "1" + a.substring(1);
    //                 // 获取补码
    //                 a = (parseInt(ones_complement(a), 2) + 1).toString(2);
    //             } else a = "0" + a;
    //             if (b[0] === "-") {
    //                 b = "1" + b.substring(1);
    //                 // 获取补码
    //                 b = (parseInt(ones_complement(b), 2) + 1).toString(2);
    //             } else b = "0" + b;
    //             if (a.length > b.length) b = b[0] + b.substring(1).padStart(a.length - 1, b[0]);
    //             else a = a[0] + a.substring(1).padStart(b.length - 1, a[0]);
    //             a = a.split("");
    //             b = b.split("");
    //             for (let i = 0; i < a.length; i++) {
    //                 if (a[i] === "1" && b[i] === "1") {
    //                     a[i] = "1";
    //                 } else {
    //                     a[i] = "0";
    //                 }
    //             }
    //             if (a[0] === "1") {
    //                 a = ones_complement((parseInt(a.join(""), 2) - 1).toString(2));
    //                 a = "-" + a.substring(1);
    //             } else {
    //                 a = a.join("");
    //             }
    //             return parseInt(a, 2);
    //         },
    //         // 或
    //         or: function (a, b) {
    //             a = a.toString(2);
    //             b = b.toString(2);
    //             if (a[0] === "-") {
    //                 a = "1" + a.substring(1);
    //                 // 获取补码
    //                 a = (parseInt(ones_complement(a), 2) + 1).toString(2);
    //             } else a = "0" + a;
    //             if (b[0] === "-") {
    //                 b = "1" + b.substring(1);
    //                 // 获取补码
    //                 b = (parseInt(ones_complement(b), 2) + 1).toString(2);
    //             } else b = "0" + b;
    //             if (a.length > b.length) b = b[0] + b.substring(1).padStart(a.length - 1, b[0]);
    //             else a = a[0] + a.substring(1).padStart(b.length - 1, a[0]);
    //             a = a.split("");
    //             b = b.split("");
    //             for (let i = 0; i < a.length; i++) {
    //                 if (a[i] === "1" || b[i] === "1") {
    //                     a[i] = "1";
    //                 } else {
    //                     a[i] = "0";
    //                 }
    //             }
    //             if (a[0] === "1") {
    //                 a = ones_complement((parseInt(a.join(""), 2) - 1).toString(2));
    //                 a = "-" + a.substring(1);
    //             } else {
    //                 a = a.join("");
    //             }
    //             return parseInt(a, 2);
    //         },
    //         // 异或
    //         xor: function (a, b) {
    //             a = a.toString(2);
    //             b = b.toString(2);
    //             if (a[0] === "-") {
    //                 a = "1" + a.substring(1);
    //                 // 获取补码
    //                 a = (parseInt(ones_complement(a), 2) + 1).toString(2);
    //             } else a = "0" + a;
    //             if (b[0] === "-") {
    //                 b = "1" + b.substring(1);
    //                 // 获取补码
    //                 b = (parseInt(ones_complement(b), 2) + 1).toString(2);
    //             } else b = "0" + b;
    //             if (a.length > b.length) b = b[0] + b.substring(1).padStart(a.length - 1, b[0]);
    //             else a = a[0] + a.substring(1).padStart(b.length - 1, a[0]);
    //             a = a.split("");
    //             b = b.split("");
    //             for (let i = 0; i < a.length; i++) {
    //                 if (a[i] !== b[i]) {
    //                     a[i] = "1";
    //                 } else {
    //                     a[i] = "0";
    //                 }
    //             }
    //             if (a[0] === "1") {
    //                 a = ones_complement((parseInt(a.join(""), 2) - 1).toString(2));
    //                 a = "-" + a.substring(1);
    //             } else {
    //                 a = a.join("");
    //             }
    //             return parseInt(a, 2);
    //         },
    //         // 非
    //         not: function (a) {
    //             return -a - 1
    //         },
    //         // 左移
    //         shift: function (a, b) {
    //             a = a.toString(2);
    //             a = a.padEnd(a.length + b, "0");
    //             return parseInt(a, 2);
    //         },
    //         // 右移
    //         move: function (a, b) {
    //             a = a.toString(2);
    //             if (a[0] === "-") {
    //                 a = "1" + a.substring(1);
    //                 // 获取补码
    //                 a = (parseInt(ones_complement(a), 2) + 1).toString(2);
    //             } else a = "0" + a;
    //             b = Math.min(b, a.length - 1);
    //             a = a[0].padEnd(b + 1, a[0]) + a.substring(1, a.length - b);
    //             if (a[0] === "1") {
    //                 // 获取原码
    //                 a = ones_complement((parseInt(a, 2) - 1).toString(2));
    //                 a = "-" + a.substring(1);
    //             }
    //             return parseInt(a, 2);
    //         }
    //     }
    // })();

    /**
     梅森旋转算法中用到的变量如下所示:
     w:长度 生成的随机数的二进制长度
     n:寄存器长度 参与旋转的随机数个数(旋转的深度)
     m:周期参数,用作第三阶段的偏移量 旋转算法参与旋转的中间项
     r:低位掩码/低位要提取的位数 内存界限值 2 的 r 次方 - 1 x⃗ (u)kx→k(u) 和 x⃗ (l)k+1x→k+1(l) 的切分位置
     a:旋转矩阵的参数 旋转算法异或基数 矩阵 AA 的最后一行
     f:初始化梅森旋转链所需参数 旋转链异或值膨化量
     u,s,t,l: 整数参数,移位运算的移动距离
     d,b,c: 比特遮罩
     s,t:TGFSR的位移量
     b,c:TGFSR的掩码
     u,d,l:额外梅森旋转所需的掩码和位移量

     MT19937-32的参数列表如下:
     ·(w, n, m, r) = (32, 624, 397, 31)
     ·a = 9908B0DF(16)
     ·f = 1812433253
     ·(u, d) = (11, FFFFFFFF16)
     ·(s, b) = (7, 9D2C568016)
     ·(t, c) = (15, EFC6000016)
     ·l = 18

     MT19937-64的参数列表如下:
     ·(w, n, m, r) = (64, 312, 156, 31)
     ·a = B5026F5AA96619E9(16)
     ·f = 6364136223846793005
     ·(u, d) = (29, 555555555555555516)
     ·(s, b) = (17, 71D67FFFEDA6000016)
     ·(t, c) = (37, FFF7EEE00000000016)
     ·l = 43
     */
    window.MT = (function () {
        // 新方案定义私有变量。修复部分浏览器不支持 # 定义private私有变量
        const $w = Symbol(), $n = Symbol(), $m = Symbol(), $r = Symbol(),
            $a = Symbol(),
            $u = Symbol(), $d = Symbol(),
            $s = Symbol(), $b = Symbol(),
            $t = Symbol(), $c = Symbol(),
            $l = Symbol(),
            $index = Symbol(), $LinkedList = Symbol();

        // 旋转算法处理旋转链
        function generate(MT) {
            for (let i = 0n; i < MT[$n]; i++) {
                const lower_mask = -(1n << MT[$r]);
                const upper_mask = ~lower_mask;
                const y = (MT[$LinkedList][i] & upper_mask) + (MT[$LinkedList][(i + 1n) % MT[$n]] & lower_mask);
                let yA = y >> 1n;
                if ((y % 2n) !== 0n) {
                    yA = yA ^ MT[$a];
                }
                MT[$LinkedList][i] = MT[$LinkedList][(i + MT[$m]) % MT[$n]] ^ yA;
            }
        }

        class MT {
            constructor(seed = Date.now(), bit = 32) {
                const args = {
                    32: {
                        n: 624n, m: 397n, r: 31n,
                        a: 0x9908B0DFn, f: 1812433253n,
                        u: 11n, d: 0xFFFFFFFFn,
                        s: 7n, b: 0x9D2C5680n,
                        t: 15n, c: 0xEFC60000n,
                        l: 18n
                    },
                    64: {
                        n: 312n, m: 156n, r: 31n,
                        a: 0xB5026F5AA96619E9n, f: 6364136223846793005n,
                        u: 29n, d: 0x5555555555555555n,
                        s: 17n, b: 0x71D67FFFEDA60000n,
                        t: 37n, c: 0xFFF7EEE000000000n,
                        l: 43n
                    }
                };
                if (typeof args[bit] === "undefined") throw new Error("未定义" + bit.toString() + "bit的参数");
                this[$w] = BigInt(bit);
                this[$n] = args[bit].n;
                this[$m] = args[bit].m;
                this[$r] = args[bit].r;

                this[$a] = args[bit].a;

                this[$u] = args[bit].u;
                this[$d] = args[bit].d;

                this[$s] = args[bit].s;
                this[$b] = args[bit].b;

                this[$t] = args[bit].t;
                this[$c] = args[bit].c;

                this[$l] = args[bit].l;

                this[$index] = 0n;
                this[$LinkedList] = [BigInt(seed)];

                // 对数组其他元素进行初始化
                for (let i = 1n; i < this[$n]; i++) {
                    this[$LinkedList][i] = (args[bit].f * (this[$LinkedList][i - 1n] ^ (this[$LinkedList][i - 1n] >> (this[$w] - 2n))) + i & (1n << this[$w]) - 1n);
                }
            }

            // 获取随机数
            next() {
                if (this[$index] === 0n) generate(this);
                let y = this[$LinkedList][this[$index]];
                y = (y ^ ((y >> this[$u]) & this[$d]));
                y = (y ^ ((y << this[$s]) & this[$b]));
                y = (y ^ ((y << this[$s]) & this[$b]));
                y = (y ^ ((y << this[$t]) & this[$c]));
                y = (y ^ (y >> this[$l]));
                this[$index] = (this[$index] + 1n) % this[$n];
                if (this[$w] <= 53n) y = parseInt(y.toString());
                return y;
            }
        }

        return MT;
    })();
    // 未经许可禁止抄袭算法,可以私用。
    window.Key = (function () {
        // 定义private私有变量
        const $pwd = Symbol();

        // 自定义加密算法,以防数据包被破解。
        class Key {
            // _pwd;        // 火狐v68版本貌似不支持这种方式声明变量。

            constructor(pwd) {
                // num,密码偏移量
                // key,排列长度偏移量
                // charCode,防止内存频繁运动,定义在外部
                let key = 7n;
                if (typeof pwd === "string") {
                    for (let i = 0; i < pwd.length; i++) {
                        key = key * 31n + BigInt(pwd[i].charCodeAt(0));
                    }
                    pwd = key;
                    key = key & 0xFFFFFFFFFFFFn;
                } else if ((typeof pwd).match(new RegExp("(number|'bigint')"))) {
                    // 如果密码是数值型就使用此方法作为 密码偏移量 和 排列长度偏移量
                    pwd = BigInt(Math.round(pwd));
                    key = (key * 31n + pwd) & 0xFFFFFFFFFFFFn;
                } else {
                    // 如果类型不匹配就直接提出错误
                    console.error("Unsupported type '" + (typeof pwd) + "'. It only supports 'string' 'number' 'bigint'.");
                }
                // 让排列长度偏移量取第一个数字。加上密码转换成字符字符串的方式
                this[$pwd] = (pwd >= 0n ? pwd % 8n + 2n : -(pwd % 8n) + 2n).toString() + key.toString(36);
            }

            encrypt(...strings) {
                function resolve(string) {
                    if (typeof string === "string" && string.length > 0) {
                        // subStart 排列长度的起始位置。subLength 排列长度。
                        let subStart = string.length, subLength = parseInt(this[$pwd][0]),
                            // encryptPool 加密池,即去除的排列长度存放在这里。result 加密后的结果。
                            encryptPool = [], result = "";
                        // stringKey 加密种子。
                        const MTSeed = new MT(subStart + parseInt(this[$pwd].substring(1), 36));
                        // 获取加密池。
                        while (subStart > subLength) {
                            subStart -= subLength;
                            encryptPool.push(string.substring(subStart, subStart + subLength));
                        }
                        encryptPool.push(string.substring(0, subStart));
                        // 对加密池进行加密,并将加密的字符的结果放入 result 中。
                        for (let i = 0, j; i < subLength; i++) {
                            for (j = 0; j < encryptPool.length; j++) {
                                const char = encryptPool[j][i];
                                if (char) {
                                    let key = (char.charCodeAt(0) + MTSeed.next()) % 0x100000000;
                                    key = [Math.floor(key / 0x10000), key % 0x10000];
                                    result += i * j % 2 === 0 ? String.fromCharCode(key[0]) + String.fromCharCode(key[1]) : String.fromCharCode(key[1]) + String.fromCharCode(key[0]);
                                } else {
                                    break;
                                }
                            }
                        }
                        // 返回加密结果
                        return result;
                    } else if (string.constructor.name === "Array") {
                        for (let i = 0; i < string.length; i++) {
                            string[i] = resolve.call(this, string[i]);
                        }
                        return string;
                    } else {
                        // 如果加密字符串不存在就返回string
                        return string;
                    }
                }

                if (strings.length === 1) {
                    return resolve.call(this, strings[0]);
                } else {
                    return resolve.call(this, Array.from(strings));
                }
            }

            /* 假设有7个字符

             加密前 - 排列
             ( 1 )  ( 2  3  4 )  ( 5  6  7 )

             加密中 - 排列
             ︵   ︵   ︵
             5    2    1
             6    3   ︶
             7    4
             ︶   ︶
             加密后 - 排列
             ( 5  2  1 )  ( 6  3 )  ( 7  4 )

             解密中 - 排列
             ︵   ︵   ︵
             5    6   7
             2    3   4
             1   ︶   ︶
             ︶

             解密后 - 排列
             1  2  3  4  5  6  7
            */

            decrypt(...strings) {
                function resolve(string) {
                    if (typeof string === "string" && string.length > 0) {
                        // subStart 排列长度的起始位置。desubLength 反向取加密池的长度。
                        let subStart = 0,
                            desubLength = Math.ceil(string.length / 2 / parseInt(this[$pwd][0])),
                            // decryptPool 解密池。result 解密后的结果。
                            decryptPool = [], result = "";
                        // stringKey 加密种子。
                        const MTSeed = new MT(string.length / 2 + parseInt(this[$pwd].substring(1), 36));
                        (function (MT, desubLength) {
                            //NullCount 加密池中没有空位的池数
                            const NullCount = string.length / 2 % parseInt(MT[$pwd][0]);
                            // 获取解密池
                            while (string.length / 2 - subStart > desubLength) {
                                decryptPool.push(string.substring(subStart * 2, (subStart + desubLength) * 2));
                                subStart += desubLength;
                                if (decryptPool.length === NullCount) desubLength--;
                            }
                            decryptPool.push(string.substring(subStart * 2));
                        })(this, desubLength);
                        // 对解密池进行解密 并将解密结果 加入到 result(结果) 中
                        string = [];
                        for (let i = 0, j; i < decryptPool.length; i++) {
                            for (j = 0; j < desubLength; j++) {
                                const char = i * j % 2 === 0 ?
                                    decryptPool[i][j * 2] + decryptPool[i][j * 2 + 1] :
                                    decryptPool[i][j * 2 + 1] + decryptPool[i][j * 2];
                                if (char) {
                                    if (typeof string[j] === "undefined") string[j] = [];
                                    string[j][i] = String.fromCharCode((char.charCodeAt(0) * 65536 + char.charCodeAt(1) + 0x100000000 - MTSeed.next()) % 65536);
                                }
                            }
                        }
                        for (let i = string.length - 1; i >= 0; i--) {
                            result += string[i].join("");
                        }
                        // 返回解密结果
                        return result;
                    } else if (string.constructor.name === "Array") {
                        for (let i = 0; i < string.length; i++) {
                            string[i] = resolve.call(this, string[i]);
                        }
                        return string;
                    } else {
                        // 如果解密字符串不存在就返回string
                        return string;
                    }
                }

                if (strings.length === 1) {
                    return resolve.call(this, strings[0]);
                } else {
                    return resolve.call(this, Array.from(strings));
                }
            }
        }


        const KEY = new Key("Tenfond");
        Object.defineProperty(Key, "encrypt", {
            value: function () {
                return KEY.encrypt.apply(KEY, arguments);
            },
            writable: false,
            enumerable: false,
            configurable: false
        });
        Object.defineProperty(Key, "decrypt", {
            value: function () {
                return KEY.decrypt.apply(KEY, arguments);
            },
            writable: false,
            enumerable: false,
            configurable: false
        });
        return Key;
    })();
})();