编排分类调整

This commit is contained in:
fofolee
2025-01-05 23:14:52 +08:00
parent a6cc1c8737
commit 296c231c44
31 changed files with 59 additions and 147 deletions

View File

@@ -0,0 +1,140 @@
// 创建 Buffer
function from(data, encoding = "utf8") {
try {
return Buffer.from(data, encoding);
} catch (error) {
throw new Error(`创建Buffer失败: ${error.message}`);
}
}
// 转换为字符串
function toString(buffer, encoding = "utf8", start = 0, end = buffer.length) {
try {
return buffer.toString(encoding, start, end);
} catch (error) {
throw new Error(`转换字符串失败: ${error.message}`);
}
}
// 写入数据
function write(
buffer,
string,
offset = 0,
length = buffer.length,
encoding = "utf8"
) {
try {
return buffer.write(string, offset, length, encoding);
} catch (error) {
throw new Error(`写入数据失败: ${error.message}`);
}
}
// 填充数据
function fill(
buffer,
value,
offset = 0,
end = buffer.length,
encoding = "utf8"
) {
try {
return buffer.fill(value, offset, end, encoding);
} catch (error) {
throw new Error(`填充数据失败: ${error.message}`);
}
}
// 复制数据
function copy(
source,
target,
targetStart = 0,
sourceStart = 0,
sourceEnd = source.length
) {
try {
return source.copy(target, targetStart, sourceStart, sourceEnd);
} catch (error) {
throw new Error(`复制数据失败: ${error.message}`);
}
}
// 比较数据
function compare(buf1, buf2) {
try {
return Buffer.compare(buf1, buf2);
} catch (error) {
throw new Error(`比较数据失败: ${error.message}`);
}
}
// 连接 Buffer
function concat(buffers, totalLength) {
try {
return Buffer.concat(buffers, totalLength);
} catch (error) {
throw new Error(`连接Buffer失败: ${error.message}`);
}
}
// 查找数据
function indexOf(buffer, value, byteOffset = 0, encoding = "utf8") {
try {
return buffer.indexOf(value, byteOffset, encoding);
} catch (error) {
throw new Error(`查找数据失败: ${error.message}`);
}
}
// 切片数据
function slice(buffer, start = 0, end = buffer.length) {
try {
return buffer.slice(start, end);
} catch (error) {
throw new Error(`切片数据失败: ${error.message}`);
}
}
// 交换字节序
function swap(buffer, size) {
try {
switch (size) {
case 16:
return buffer.swap16();
case 32:
return buffer.swap32();
case 64:
return buffer.swap64();
default:
throw new Error("不支持的字节大小");
}
} catch (error) {
throw new Error(`交换字节序失败: ${error.message}`);
}
}
module.exports = {
from,
toString,
write,
fill,
copy,
compare,
concat,
indexOf,
slice,
swap,
// 编码类型
encodings: [
"utf8",
"utf16le",
"latin1",
"base64",
"hex",
"ascii",
"binary",
"ucs2",
],
};

View File

@@ -0,0 +1,261 @@
const sm2 = require("sm-crypto").sm2;
const sm4 = require("sm-crypto").sm4;
const CryptoJS = require("crypto-js");
const NodeForge = require("node-forge");
const { processSecret, dataConv } = require("./utils");
const crypto = {
// 非对称加解密
asymmetricCrypto: function (config) {
const {
text,
algorithm,
operation,
format = "Base64",
publicKey = { key: "", codec: "Pem" },
privateKey = { key: "", codec: "Pem" },
padding = "RSAES-PKCS1-V1_5",
cipherMode = 1,
} = config;
if (algorithm === "SM2") {
if (operation === "encrypt") {
if (!publicKey.key) throw "缺少公钥";
// 转换公钥格式
const hexPubKey =
publicKey.codec === "Hex"
? publicKey.key
: dataConv(publicKey.key, publicKey.codec, "Hex");
// 加密
const cipher = sm2.doEncrypt(text, hexPubKey, cipherMode);
// 转换输出格式
return format === "Base64" ? dataConv(cipher, "Hex", "Base64") : cipher;
} else {
if (!privateKey.key) throw "缺少私钥";
// 转换私钥格式
const hexPriKey =
privateKey.codec === "Hex"
? privateKey.key
: dataConv(privateKey.key, privateKey.codec, "Hex");
// 转换输入格式
const hexCipher =
format === "Base64" ? dataConv(text, "Base64", "Hex") : text;
// 解密
const msg = sm2.doDecrypt(hexCipher, hexPriKey, cipherMode, {
output: "utf8",
});
if (!msg) throw "解密失败";
return msg;
}
} else if (algorithm === "RSA") {
if (operation === "encrypt") {
if (!publicKey.key) throw "缺少公钥";
// 转换公钥格式
let formattedPubKey = publicKey.key;
if (publicKey.codec !== "Pem") {
formattedPubKey =
"-----BEGIN RSA PUBLIC KEY-----\n" +
dataConv(publicKey.key, publicKey.codec, "Base64") +
"\n-----END RSA PUBLIC KEY-----";
}
formattedPubKey = formattedPubKey.replace(/\\n/g, "\n");
// 创建 RSA 公钥对象
const publicKeyObj = NodeForge.pki.publicKeyFromPem(formattedPubKey);
// 将文本转换为二进制数据
const binaryData = NodeForge.util.encodeUtf8(text);
// 使用指定的填充方式加密
const encrypted = publicKeyObj.encrypt(binaryData, padding);
// 转换输出格式
return format === "Base64"
? dataConv(encrypted, "binary", "Base64")
: dataConv(encrypted, "binary", "Hex");
} else {
if (!privateKey.key) throw "缺少私钥";
// 转换私钥格式
let formattedPriKey = privateKey.key;
if (privateKey.codec !== "Pem") {
formattedPriKey =
"-----BEGIN RSA PRIVATE KEY-----\n" +
dataConv(privateKey.key, privateKey.codec, "Base64") +
"\n-----END RSA PRIVATE KEY-----";
}
formattedPriKey = formattedPriKey.replace(/\\n/g, "\n");
// 创建 RSA 私钥对象
const privateKeyObj = NodeForge.pki.privateKeyFromPem(formattedPriKey);
// 转换输入格式
const binary =
format === "Base64"
? dataConv(text, "Base64", "binary")
: dataConv(text, "Hex", "binary");
// 解密
try {
const decrypted = privateKeyObj.decrypt(binary, padding);
// 将二进制数据转换回文本
return NodeForge.util.decodeUtf8(decrypted);
} catch (e) {
console.error(e);
throw "解密失败";
}
}
}
throw "不支持的算法";
},
// 对称加解密
symmetricCrypto: function (config) {
const {
text,
algorithm,
mode = "CBC",
padding = "Pkcs7",
key = { value: "", codec: "Utf8" },
keyLength = 128,
operation = "encrypt",
format = "Base64",
iv = { value: "", codec: "Utf8" },
} = config;
// 处理密钥和IV
const processedKey = processSecret(key.value, key.codec, keyLength / 8);
const processedIV =
mode === "ECB"
? undefined
: processSecret(iv?.value || key.value, iv?.codec || key.codec, 16);
// SM4 使用专门的库
if (algorithm === "SM4") {
const hexKey = processedKey.toString();
// 处理输入文本格式
let inputText = text;
if (operation === "decrypt") {
inputText =
format === "Base64"
? CryptoJS.enc.Base64.parse(text).toString(CryptoJS.enc.Hex)
: text;
}
if (mode === "CBC") {
const hexIv = processedIV ? processedIV.toString() : "0".repeat(32);
const result =
operation === "encrypt"
? sm4.encrypt(inputText, hexKey, {
mode: "cbc",
iv: hexIv,
padding: padding.toLowerCase(),
})
: sm4.decrypt(inputText, hexKey, {
mode: "cbc",
iv: hexIv,
padding: padding.toLowerCase(),
});
// 处理输出格式
return operation === "encrypt" && format === "Base64"
? CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(result))
: result;
}
const result =
operation === "encrypt"
? sm4.encrypt(inputText, hexKey, {
padding: padding.toLowerCase(),
})
: sm4.decrypt(inputText, hexKey, {
padding: padding.toLowerCase(),
});
// 处理输出格式
return operation === "encrypt" && format === "Base64"
? CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(result))
: result;
}
// 准备加密配置
const cryptoConfig = {
mode: CryptoJS.mode[mode],
padding: CryptoJS.pad[padding],
};
// 添加 IV如果需要
if (mode !== "ECB" && processedIV) {
cryptoConfig.iv = processedIV;
}
// 加密/解密操作
if (operation === "encrypt") {
let encrypted;
const inputText = CryptoJS.enc.Utf8.parse(text);
switch (algorithm) {
case "AES":
if (mode === "GCM") {
const cipher = NodeForge.cipher.createCipher(
"AES-GCM",
processedKey.toString()
);
cipher.start({
iv: cryptoConfig.iv ? cryptoConfig.iv.toString() : "",
tagLength: 128,
});
cipher.update(NodeForge.util.createBuffer(text, "utf8"));
cipher.finish();
return {
enc: cipher.output.toHex(),
tag: cipher.mode.tag.toHex(),
};
}
encrypted = CryptoJS.AES.encrypt(
inputText,
processedKey,
cryptoConfig
);
break;
default:
throw "不支持的算法";
}
return encrypted.ciphertext.toString(CryptoJS.enc[format]);
} else {
// 解密
if (algorithm === "AES" && mode === "GCM") {
try {
const { enc, tag } = JSON.parse(text);
const decipher = NodeForge.cipher.createDecipher(
"AES-GCM",
processedKey.toString()
);
decipher.start({
iv: cryptoConfig.iv ? cryptoConfig.iv.toString() : "",
tag: NodeForge.util.createBuffer(tag, "hex"),
});
decipher.update(NodeForge.util.createBuffer(enc, "hex"));
const pass = decipher.finish();
return pass ? decipher.output.toString() : null;
} catch (e) {
throw "解密失败";
}
}
// 将输入转换为 CipherParams 格式
const ciphertext = CryptoJS.enc[format].parse(text);
const cipherParams = CryptoJS.lib.CipherParams.create({
ciphertext: ciphertext,
});
let decrypted;
switch (algorithm) {
case "AES":
decrypted = CryptoJS.AES.decrypt(
cipherParams,
processedKey,
cryptoConfig
);
break;
default:
throw "不支持的算法";
}
return CryptoJS.enc.Utf8.stringify(decrypted);
}
},
};
module.exports = crypto;

View File

@@ -0,0 +1,48 @@
const { dataConv } = require("./utils");
const encoder = {
// base64 编码
base64Encode: function (text) {
return dataConv(text, "utf8", "base64");
},
// base64 解码
base64Decode: function (text) {
return dataConv(text, "base64", "utf8");
},
// URL 编码
urlEncode: function (text) {
return encodeURIComponent(text);
},
// URL 解码
urlDecode: function (text) {
return decodeURIComponent(text);
},
// html 编码
htmlEncode: function (text) {
return text
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;");
},
// html 解码
htmlDecode: function (text) {
return text
.replace(/&amp;/g, "&")
.replace(/&lt;/g, "<")
.replace(/&gt;/g, ">")
.replace(/&quot;/g, '"')
.replace(/&#39;/g, "'");
},
// 十六进制
hexEncode: function (text) {
return dataConv(text, "utf8", "hex");
},
// 十六进制解码
hexDecode: function (text) {
return dataConv(text, "hex", "utf8");
},
};
module.exports = encoder;

View File

@@ -0,0 +1,27 @@
const NodeForge = require("node-forge");
const sm3 = require("sm-crypto").sm3;
const hash = {
// MD5 哈希
md5Hash: function (text) {
return NodeForge.md.md5.create().update(text).digest().toHex();
},
// SHA1 哈希
sha1Hash: function (text) {
return NodeForge.md.sha1.create().update(text).digest().toHex();
},
// SHA256 哈希
sha256Hash: function (text) {
return NodeForge.md.sha256.create().update(text).digest().toHex();
},
// SHA512 哈希
sha512Hash: function (text) {
return NodeForge.md.sha512.create().update(text).digest().toHex();
},
// SM3 哈希
sm3Hash: function (text) {
return sm3(text);
},
};
module.exports = hash;

View File

@@ -0,0 +1,15 @@
const encoder = require("./encoder");
const hash = require("./hash");
const string = require("./string");
const crypto = require("./crypto");
const buffer = require("./buffer");
const zlib = require("./zlib");
module.exports = {
...encoder,
...hash,
...string,
...crypto,
buffer,
zlib,
};

View File

@@ -0,0 +1,25 @@
const string = {
// 字符串反转
reverseString: function (text) {
return text.split("").reverse().join("");
},
// 字符串替换
replaceString: function (text, oldStr, newStr) {
return text.replaceAll(oldStr, newStr);
},
// 字符串截取
substring: function (text, start, end) {
return text.substring(start, end);
},
// 正则处理
regexTransform: function (text, regex, replace) {
try {
if (replace === undefined) return text.match(regex);
return text.replace(regex, replace);
} catch (e) {
throw "正则表达式格式错误";
}
},
};
module.exports = string;

View File

@@ -0,0 +1,30 @@
const CryptoJS = require("crypto-js");
// 数据编码转换
const dataConv = (str, fromCodec, toCodec) => {
// 特殊处理 PEM 格式
if (fromCodec.toLowerCase() === "pem") {
const pemContent = str
.replace(/-----(BEGIN|END)[^-]+-----/g, "")
.replace(/[\r\n]/g, "");
return Buffer.from(pemContent, "base64").toString(toCodec.toLowerCase());
}
// 其他格式直接转换
return Buffer.from(str, fromCodec.toLowerCase()).toString(
toCodec.toLowerCase()
);
};
// 处理密钥和IV
const processSecret = (key, codec, len) => {
// 转换成 hex 并填充到指定长度
const hexStr = dataConv(key, codec, "hex")
.padEnd(len * 2, "0")
.slice(0, len * 2);
return CryptoJS.enc.Hex.parse(hexStr);
};
module.exports = {
dataConv,
processSecret,
};

View File

@@ -0,0 +1,126 @@
const zlib = require("zlib");
const { promisify } = require("util");
// 压缩方法
const gzip = promisify(zlib.gzip);
const deflate = promisify(zlib.deflate);
const brotliCompress = promisify(zlib.brotliCompress);
// 解压方法
const gunzip = promisify(zlib.gunzip);
const inflate = promisify(zlib.inflate);
const brotliDecompress = promisify(zlib.brotliDecompress);
// 同步方法
const gzipSync = zlib.gzipSync;
const gunzipSync = zlib.gunzipSync;
const deflateSync = zlib.deflateSync;
const inflateSync = zlib.inflateSync;
const brotliCompressSync = zlib.brotliCompressSync;
const brotliDecompressSync = zlib.brotliDecompressSync;
// 压缩选项
const defaultGzipOptions = {
level: zlib.constants.Z_DEFAULT_COMPRESSION,
memLevel: zlib.constants.Z_DEFAULT_MEMLEVEL,
strategy: zlib.constants.Z_DEFAULT_STRATEGY,
};
const defaultBrotliOptions = {
params: {
[zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_GENERIC,
[zlib.constants.BROTLI_PARAM_QUALITY]:
zlib.constants.BROTLI_DEFAULT_QUALITY,
[zlib.constants.BROTLI_PARAM_SIZE_HINT]: 0,
},
};
// 异步压缩函数
async function compressData(data, method, options = {}) {
try {
const buffer = Buffer.from(data);
switch (method) {
case "gzip":
return await gzip(buffer, { ...defaultGzipOptions, ...options });
case "deflate":
return await deflate(buffer, { ...defaultGzipOptions, ...options });
case "brotli":
return await brotliCompress(buffer, {
...defaultBrotliOptions,
...options,
});
default:
throw new Error("不支持的压缩方法");
}
} catch (error) {
throw new Error(`压缩失败: ${error.message}`);
}
}
// 异步解压函数
async function decompressData(data, method, options = {}) {
try {
const buffer = Buffer.from(data);
switch (method) {
case "gzip":
return await gunzip(buffer, options);
case "deflate":
return await inflate(buffer, options);
case "brotli":
return await brotliDecompress(buffer, options);
default:
throw new Error("不支持的解压方法");
}
} catch (error) {
throw new Error(`解压失败: ${error.message}`);
}
}
// 同步压缩函数
function compressDataSync(data, method, options = {}) {
try {
const buffer = Buffer.from(data);
switch (method) {
case "gzip":
return gzipSync(buffer, { ...defaultGzipOptions, ...options });
case "deflate":
return deflateSync(buffer, { ...defaultGzipOptions, ...options });
case "brotli":
return brotliCompressSync(buffer, {
...defaultBrotliOptions,
...options,
});
default:
throw new Error("不支持的压缩方法");
}
} catch (error) {
throw new Error(`压缩失败: ${error.message}`);
}
}
// 同步解压函数
function decompressDataSync(data, method, options = {}) {
try {
const buffer = Buffer.from(data);
switch (method) {
case "gzip":
return gunzipSync(buffer, options);
case "deflate":
return inflateSync(buffer, options);
case "brotli":
return brotliDecompressSync(buffer, options);
default:
throw new Error("不支持的解压方法");
}
} catch (error) {
throw new Error(`解压失败: ${error.message}`);
}
}
module.exports = {
compressData,
decompressData,
compressDataSync,
decompressDataSync,
constants: zlib.constants,
};