140 lines
3.7 KiB
JavaScript
140 lines
3.7 KiB
JavaScript
/**
|
||
* 加密工具
|
||
* 用于加密存储敏感信息(如产品密钥)
|
||
*
|
||
* 注意:这是一个简单的加密实现,适用于小程序场景。
|
||
* 生产环境建议使用更安全的加密算法或从服务端动态获取密钥。
|
||
*/
|
||
|
||
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,
|
||
}; |