Skip to content
自定义加解密

纯nodejs使用

js
// 1. 自定义密钥(任意长度,越长越难撞)
const KEY = Buffer.from('MyQuark2025!@#', 'utf8');

// 2. 加密
function encrypt(str) {
  const buf = Buffer.from(str, 'utf8');
  const len = buf.length;
  const keyLen = KEY.length;

  for (let i = 0; i < len; i++) {
    buf[i] ^= KEY[i % keyLen];      // 异或
    buf[i] = ((buf[i] << 3) & 0xFF) | (buf[i] >> 5); // 循环左移 3 位
  }
  return buf.toString('hex');        // 返回十六进制字符串
}

// 3. 解密
function decrypt(hex) {
  const buf = Buffer.from(hex, 'hex');
  const len = buf.length;
  const keyLen = KEY.length;

  for (let i = 0; i < len; i++) {
    buf[i] = ((buf[i] >> 3) & 0xFF) | (buf[i] << 5); // 循环右移 3 位(逆运算)
    buf[i] ^= KEY[i % keyLen];      // 再异或一次就还原
  }
  return buf.toString('utf8');
}

/* 4. 自测 */
const plain = 'https://pan.quark.cn/s/abc123';
const cipher = encrypt(plain);
console.log('cipher:', cipher);          // 16进制密文
console.log('decrypt:', decrypt(cipher)); // 原文

支持nodejs和前端js使用

js
// 工具函数:兼容 Node.js 和浏览器的字节数组转换
const utils = (() => {
    const isNode = typeof Buffer !== 'undefined';

    // 字符串转字节数组
    function stringToBytes(str) {
        if (isNode) {
            return Buffer.from(str, 'utf8');
        } else {
            return new TextEncoder().encode(str);
        }
    }

    // 字节数组转字符串
    function bytesToString(bytes) {
        if (isNode) {
            return Buffer.from(bytes).toString('utf8');
        } else {
            return new TextDecoder('utf8').decode(bytes);
        }
    }

    // 十六进制字符串转字节数组
    function hexToBytes(hex) {
        const len = hex.length;
        const bytes = new Uint8Array(len / 2);
        for (let i = 0; i < len; i += 2) {
            bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
        }
        return bytes;
    }

    // 字节数组转十六进制字符串
    function bytesToHex(bytes) {
        return Array.from(bytes)
            .map(b => b.toString(16).padStart(2, '0'))
            .join('');
    }

    return { stringToBytes, bytesToString, hexToBytes, bytesToHex };
})();

// 1. 自定义密钥(任意长度,越长越难撞)
const KEY = utils.stringToBytes('MyQuark2025!@#');

// 2. 循环左移
function rol8(value, shift) {
    return ((value << shift) & 0xFF) | (value >> (8 - shift));
}

// 3. 循环右移
function ror8(value, shift) {
    return ((value >> shift) & 0xFF) | (value << (8 - shift) & 0xFF);
}

// 4. 加密
function encrypt(str) {
    const data = utils.stringToBytes(str);
    const len = data.length;
    const keyLen = KEY.length;

    for (let i = 0; i < len; i++) {
        data[i] ^= KEY[i % keyLen];      // 异或
        data[i] = rol8(data[i], 3);      // 循环左移 3 位
    }
    return utils.bytesToHex(data);     // 返回十六进制字符串
}

// 5. 解密
function decrypt(hex) {
    const data = utils.hexToBytes(hex);
    const len = data.length;
    const keyLen = KEY.length;

    for (let i = 0; i < len; i++) {
        data[i] = ror8(data[i], 3);      // 循环右移 3 位
        data[i] ^= KEY[i % keyLen];      // 再异或一次就还原
    }
    return utils.bytesToString(data);
}

/* 6. 自测 */
const plain = '测试内容';
const cipher = encrypt(plain);
console.log('cipher:', cipher);          // 16进制密文
console.log('decrypt:', decrypt(cipher)); // 原文

支持nodejs和微信小程序和前端js

js
// 工具函数:兼容 Node.js 和浏览器的字节数组转换
const utils = (() => {
    const isNode = typeof Buffer !== 'undefined';

    // 字符串转字节数组
    function stringToBytes(str) {
        if (isNode) {
            return Buffer.from(str, 'utf8');
        } else {
            // 微信小程序可用
            const arr = [];
            for (let i = 0; i < str.length; i++) {
                let c = str.charCodeAt(i);
                if (c < 0x80) {
                    arr.push(c);
                } else if (c < 0x800) {
                    arr.push(0xc0 | (c >> 6));
                    arr.push(0x80 | (c & 0x3f));
                } else if (c < 0xd800 || c >= 0xe000) {
                    arr.push(0xe0 | (c >> 12));
                    arr.push(0x80 | ((c >> 6) & 0x3f));
                    arr.push(0x80 | (c & 0x3f));
                } else {
                    // 代理对处理(UTF-16 代理对)
                    i++;
                    c = 0x10000 + (((c & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));
                    arr.push(0xf0 | (c >> 18));
                    arr.push(0x80 | ((c >> 12) & 0x3f));
                    arr.push(0x80 | ((c >> 6) & 0x3f));
                    arr.push(0x80 | (c & 0x3f));
                }
            }
            return new Uint8Array(arr);
        }
    }

    // 字节数组转字符串(微信小程序兼容版)
    function bytesToString(bytes) {
        if (isNode) {
            return Buffer.from(bytes).toString('utf8');
        } else {
            // 微信小程序兼容的 UTF-8 解码
            let str = '';
            let i = 0;
            while (i < bytes.length) {
                const b1 = bytes[i++];
                if (b1 < 0x80) {
                    str += String.fromCharCode(b1);
                } else if (b1 >= 0xC0 && b1 < 0xE0) {
                    const b2 = bytes[i++];
                    str += String.fromCharCode(((b1 & 0x1F) << 6) | (b2 & 0x3F));
                } else if (b1 >= 0xE0 && b1 < 0xF0) {
                    const b2 = bytes[i++];
                    const b3 = bytes[i++];
                    str += String.fromCharCode(((b1 & 0x0F) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F));
                } else if (b1 >= 0xF0 && b1 < 0xF8) {
                    const b2 = bytes[i++];
                    const b3 = bytes[i++];
                    const b4 = bytes[i++];
                    const codePoint = ((b1 & 0x07) << 18) | ((b2 & 0x3F) << 12) | ((b3 & 0x3F) << 6) | (b4 & 0x3F);
                    if (codePoint <= 0xFFFF) {
                        str += String.fromCharCode(codePoint);
                    } else {
                        // UTF-16 代理对
                        const offset = codePoint - 0x10000;
                        str += String.fromCharCode(0xD800 + (offset >> 10));
                        str += String.fromCharCode(0xDC00 + (offset & 0x3FF));
                    }
                }
            }
            return str;
        }
    }

    // 十六进制字符串转字节数组
    function hexToBytes(hex) {
        const len = hex.length;
        const bytes = new Uint8Array(len / 2);
        for (let i = 0; i < len; i += 2) {
            bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
        }
        return bytes;
    }

    // 字节数组转十六进制字符串
    function bytesToHex(bytes) {
        return Array.from(bytes)
            .map(b => b.toString(16).padStart(2, '0'))
            .join('');
    }

    return { stringToBytes, bytesToString, hexToBytes, bytesToHex };
})();

// 1. 自定义密钥(任意长度,越长越难撞)
const KEY = utils.stringToBytes('MyQuark2025!@#');

// 2. 循环左移
function rol8(value, shift) {
    return ((value << shift) & 0xFF) | (value >> (8 - shift));
}

// 3. 循环右移
function ror8(value, shift) {
    return ((value >> shift) & 0xFF) | (value << (8 - shift) & 0xFF);
}

// 4. 加密(保持不变)
function encrypt(str) {
    const data = utils.stringToBytes(str);
    const len = data.length;
    const keyLen = KEY.length;

    for (let i = 0; i < len; i++) {
        data[i] ^= KEY[i % keyLen];      // 异或
        data[i] = rol8(data[i], 3);      // 循环左移 3 位
    }
    return utils.bytesToHex(data);     // 返回十六进制字符串
}

// 5. 解密(使用修改后的 bytesToString)
function decrypt(hex) {
    const data = utils.hexToBytes(hex);
    const len = data.length;
    const keyLen = KEY.length;

    for (let i = 0; i < len; i++) {
        data[i] = ror8(data[i], 3);      // 循环右移 3 位
        data[i] ^= KEY[i % keyLen];      // 再异或一次就还原
    }
    return utils.bytesToString(data);  // 这里会自动使用修改后的兼容版本
}

/* 6. 自测 */
const plain = '测试版本';
const cipher = encrypt(plain);
console.log('cipher:', cipher);          // 16进制密文
console.log('decrypt:', decrypt(cipher)); // 原文