fastbee/yack-mini/miniprogram/utils/crypto.js

140 lines
3.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 加密工具
* 用于加密存储敏感信息(如产品密钥)
*
* 注意:这是一个简单的加密实现,适用于小程序场景。
* 生产环境建议使用更安全的加密算法或从服务端动态获取密钥。
*/
const { CRYPTO_KEY } = require('./constants.js');
/**
* Base64 编码(兼容小程序环境)
* @param {string} str - 字符串
* @returns {string} Base64 编码字符串
*/
function base64Encode(str) {
try {
// 使用小程序提供的 ArrayBuffer 方式
const buffer = new ArrayBuffer(str.length);
const dataView = new DataView(buffer);
for (let i = 0; i < str.length; i++) {
dataView.setUint8(i, str.charCodeAt(i));
}
return wx.arrayBufferToBase64(buffer);
} catch (e) {
console.error('[Crypto] Base64 编码失败:', e);
return str;
}
}
/**
* Base64 解码(兼容小程序环境)
* @param {string} base64 - Base64 编码字符串
* @returns {string} 解码后的字符串
*/
function base64Decode(base64) {
try {
// 使用小程序提供的 ArrayBuffer 方式
const buffer = wx.base64ToArrayBuffer(base64);
const bytes = new Uint8Array(buffer);
let str = '';
for (let i = 0; i < bytes.length; i++) {
str += String.fromCharCode(bytes[i]);
}
return str;
} catch (e) {
console.error('[Crypto] Base64 解码失败:', e);
return base64;
}
}
/**
* 简单对称加密(XOR + Base64)
* @param {string} text - 明文
* @param {string} key - 密钥
* @returns {string} 密文(Base64 编码)
*/
function encrypt(text, key = CRYPTO_KEY) {
if (!text) return '';
try {
// XOR 加密
let encrypted = '';
for (let i = 0; i < text.length; i++) {
const charCode = text.charCodeAt(i) ^ key.charCodeAt(i % key.length);
encrypted += String.fromCharCode(charCode);
}
// Base64 编码
return base64Encode(encrypted);
} catch (e) {
console.error('[Crypto] 加密失败:', e);
return text;
}
}
/**
* 解密
* @param {string} ciphertext - 密文(Base64 编码)
* @param {string} key - 密钥
* @returns {string} 明文
*/
function decrypt(ciphertext, key = CRYPTO_KEY) {
if (!ciphertext) return '';
try {
// Base64 解码
const encrypted = base64Decode(ciphertext);
// XOR 解密(与加密过程相同)
let decrypted = '';
for (let i = 0; i < encrypted.length; i++) {
const charCode = encrypted.charCodeAt(i) ^ key.charCodeAt(i % key.length);
decrypted += String.fromCharCode(charCode);
}
return decrypted;
} catch (e) {
console.error('[Crypto] 解密失败:', e);
return ciphertext;
}
}
/**
* 加密对象中的指定字段
* @param {Object} obj - 对象
* @param {Array<string>} fields - 需要加密的字段名数组
* @returns {Object} 加密后的对象
*/
function encryptFields(obj, fields) {
if (!obj || typeof obj !== 'object') return obj;
const result = { ...obj };
fields.forEach(field => {
if (result[field]) {
result[field] = encrypt(result[field]);
result[`_${field}_encrypted`] = true; // 标记已加密
}
});
return result;
}
/**
* 解密对象中的指定字段
* @param {Object} obj - 对象
* @param {Array<string>} fields - 需要解密的字段名数组
* @returns {Object} 解密后的对象
*/
function decryptFields(obj, fields) {
if (!obj || typeof obj !== 'object') return obj;
const result = { ...obj };
fields.forEach(field => {
if (result[field] && result[`_${field}_encrypted`]) {
result[field] = decrypt(result[field]);
delete result[`_${field}_encrypted`]; // 移除标记
}
});
return result;
}
module.exports = {
encrypt,
decrypt,
encryptFields,
decryptFields,
};