n8n-nodes-zola-fake
Version:
Các node hỗ trợ Zalo cho n8n Thong
370 lines (334 loc) • 18.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ZaloDecrypt = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const ZaloDecryptDescription_1 = require("./ZaloDecryptDescription");
const utils_1 = require("../zalo-sdk/utils");
const cryptojs = require("crypto-js");
class ZaloDecrypt {
constructor() {
this.description = {
displayName: 'Zalo Decrypt',
name: 'zaloDecrypt',
icon: 'file:../shared/zalo.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Giải mã chuỗi đã được mã hóa bằng AES',
defaults: {
name: 'Zalo Decrypt',
},
inputs: ['main'],
outputs: ['main'],
properties: [
...ZaloDecryptDescription_1.zaloDecryptResources,
...ZaloDecryptDescription_1.zaloDecryptOperations,
{
displayName: 'Chuỗi đã mã hóa',
name: 'encryptedString',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
resource: ['zaloDecrypt'],
operation: ['decryptAES', 'decryptLoginInfo'],
},
},
description: 'Chuỗi đã được mã hóa cần giải mã',
},
{
displayName: 'Secret Key',
name: 'secretKey',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
resource: ['zaloDecrypt'],
operation: ['decryptAES', 'decryptLoginInfo'],
},
},
description: 'Secret key dùng để giải mã (Base64)',
},
{
displayName: 'Cookie',
name: 'cookie',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
resource: ['zaloDecrypt'],
operation: ['decryptLoginInfo'],
},
},
description: 'Cookie zpw_sek để trích xuất key giải mã',
},
// Thêm trường nhập cho getEncryptKey
{
displayName: 'ZCID',
name: 'zcid',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
resource: ['zaloDecrypt'],
operation: ['getEncryptKey'],
},
},
description: 'Giá trị zcid đã lưu từ phiên đăng nhập',
},
{
displayName: 'ZCID EXT',
name: 'zcid_ext',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
resource: ['zaloDecrypt'],
operation: ['getEncryptKey'],
},
},
description: 'Giá trị zcid_ext đã lưu từ phiên đăng nhập',
},
],
};
}
async execute() {
const items = this.getInputData();
const returnData = [];
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
for (let i = 0; i < items.length; i++) {
try {
// Thêm xử lý cho operation getEncryptKey
if (resource === 'zaloDecrypt' && operation === 'getEncryptKey') {
const zcid = this.getNodeParameter('zcid', i);
const zcid_ext = this.getNodeParameter('zcid_ext', i);
// Hàm tách ký tự chẵn/lẻ
function processStr(str) {
const even = [];
const odd = [];
for (let i = 0; i < str.length; i++) {
(i % 2 === 0 ? even : odd).push(str[i]);
}
return { even, odd };
}
// Tính MD5 zcid_ext (chữ hoa)
const md5_zcid_ext = cryptojs.MD5(zcid_ext).toString().toUpperCase();
const n = processStr(md5_zcid_ext).even;
const { even: a, odd: s } = processStr(zcid);
const part1 = n.slice(0, 8).join('');
const part2 = a.slice(0, 12).join('');
const part3 = s.reverse().slice(0, 12).join('');
const encryptKey = part1 + part2 + part3;
returnData.push({
json: {
success: true,
zcid,
zcid_ext,
encryptKey,
},
});
continue;
}
if (resource === 'zaloDecrypt') {
if (operation === 'decryptLoginInfo') {
const encryptedString = this.getNodeParameter('encryptedString', i);
const secretKey = this.getNodeParameter('secretKey', i);
const cookie = this.getNodeParameter('cookie', i);
this.logger.info('Đang giải mã dữ liệu getLoginInfo');
try {
// Thử giải mã với các phương pháp khác nhau
let decryptedData = null;
let method = '';
// Phương pháp 1: Sử dụng decryptResp từ utils (như trong login.js)
try {
decryptedData = utils_1.decryptResp(secretKey, encryptedString);
method = 'decryptResp';
this.logger.info('Giải mã thành công với decryptResp');
} catch (error) {
this.logger.info('Không thể giải mã với decryptResp:', error.message);
}
// Phương pháp 2: Sử dụng decodeAES nếu phương pháp 1 thất bại
if (!decryptedData) {
try {
const decoded = utils_1.decodeAES(secretKey, encryptedString);
if (decoded) {
try {
decryptedData = JSON.parse(decoded);
method = 'decodeAES';
this.logger.info('Giải mã thành công với decodeAES');
} catch (parseError) {
this.logger.info('Giải mã thành công nhưng không phải JSON hợp lệ');
decryptedData = decoded;
method = 'decodeAES (raw string)';
}
}
} catch (error) {
this.logger.info('Không thể giải mã với decodeAES:', error.message);
}
}
// Phương pháp 3: Thử trực tiếp với crypto-js
if (!decryptedData) {
try {
// Kiểm tra định dạng key và data
const isBase64Key = /^[A-Za-z0-9+/=]+$/.test(secretKey);
const isBase64Data = /^[A-Za-z0-9+/=]+$/.test(encryptedString);
this.logger.info(`Key là base64: ${isBase64Key}, Data là base64: ${isBase64Data}`);
if (isBase64Key && isBase64Data) {
let keyBytes = cryptojs.enc.Base64.parse(secretKey);
let decrypted = cryptojs.AES.decrypt({
ciphertext: cryptojs.enc.Base64.parse(encryptedString)
}, keyBytes, {
iv: cryptojs.enc.Hex.parse("00000000000000000000000000000000"),
mode: cryptojs.mode.CBC,
padding: cryptojs.pad.Pkcs7
});
const decryptedStr = decrypted.toString(cryptojs.enc.Utf8);
if (decryptedStr) {
try {
decryptedData = JSON.parse(decryptedStr);
method = 'crypto-js';
this.logger.info('Giải mã thành công với crypto-js');
} catch (parseError) {
this.logger.info('Giải mã thành công nhưng không phải JSON hợp lệ');
decryptedData = decryptedStr;
method = 'crypto-js (raw string)';
}
}
} else {
this.logger.info('Key hoặc data không phải base64, không thể giải mã với crypto-js');
}
} catch (error) {
this.logger.info('Không thể giải mã với crypto-js:', error.message);
}
}
// Phương pháp 4: Thử trích xuất key từ cookie và giải mã
if (!decryptedData && cookie) {
try {
// Trích xuất key từ cookie
let extractedKey = cookie;
if (cookie.includes('zpw_sek=')) {
extractedKey = cookie.split('zpw_sek=')[1].split(';')[0];
}
this.logger.info('Đang thử với key từ cookie:', extractedKey.substring(0, 20) + '...');
// Thử giải mã với key từ cookie
const decrypted = utils_1.decryptResp(extractedKey, encryptedString);
if (decrypted) {
decryptedData = decrypted;
method = 'decryptResp with cookie key';
this.logger.info('Giải mã thành công với key từ cookie');
}
} catch (error) {
this.logger.info('Không thể giải mã với key từ cookie:', error.message);
}
}
if (decryptedData) {
returnData.push({
json: {
success: true,
method,
data: decryptedData,
secretKey: decryptedData.zpw_enk || null,
uid: decryptedData.uid || null
},
});
} else {
throw new Error('Không thể giải mã dữ liệu với các phương pháp đã thử');
}
} catch (error) {
this.logger.error('Lỗi khi giải mã getLoginInfo:', error.message);
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Không thể giải mã dữ liệu getLoginInfo: ${error.message}`);
}
}
else if (operation === 'decryptAES') {
const encryptedString = this.getNodeParameter('encryptedString', i);
const secretKey = this.getNodeParameter('secretKey', i);
this.logger.info('Đang giải mã chuỗi với secret key');
try {
// Sử dụng hàm decodeAES từ utils
const decrypted = utils_1.decodeAES(secretKey, encryptedString);
// Nếu kết quả là chuỗi JSON, thử parse thành đối tượng
let parsedResult = decrypted;
try {
parsedResult = JSON.parse(decrypted);
} catch (parseError) {
// Nếu không phải JSON, giữ nguyên chuỗi
this.logger.info('Kết quả không phải JSON, giữ nguyên dạng chuỗi');
}
this.logger.info('Giải mã thành công');
returnData.push({
json: {
success: true,
data: parsedResult,
raw: decrypted
},
});
} catch (decryptError) {
this.logger.error('Lỗi khi giải mã:', decryptError);
// Thử phương pháp giải mã thứ hai sử dụng decryptResp
try {
const decrypted = utils_1.decryptResp(secretKey, encryptedString);
this.logger.info('Giải mã thành công với phương pháp thứ hai');
returnData.push({
json: {
success: true,
data: decrypted,
method: 'decryptResp'
},
});
} catch (error) {
this.logger.error('Không thể giải mã với cả hai phương pháp:', error);
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Không thể giải mã chuỗi: ${error.message}`);
}
}
}
else if (operation === 'getEncryptKey') {
const zcid = this.getNodeParameter('zcid', i);
const zcid_ext = this.getNodeParameter('zcid_ext', i);
function processStr(str) {
const even = [];
const odd = [];
for (let i = 0; i < str.length; i++) {
(i % 2 === 0 ? even : odd).push(str[i]);
}
return { even, odd };
}
const md5_zcid_ext = cryptojs.MD5(zcid_ext).toString().toUpperCase();
const n = processStr(md5_zcid_ext).even;
const { even: a, odd: s } = processStr(zcid);
const part1 = n.slice(0, 8).join('');
const part2 = a.slice(0, 12).join('');
const part3 = s.reverse().slice(0, 12).join('');
const encryptKey = part1 + part2 + part3;
returnData.push({
json: {
success: true,
zcid,
zcid_ext,
encryptKey,
},
});
}
}
} catch (error) {
if (this.continueOnFail()) {
returnData.push({
json: {
success: false,
error: error.message,
},
});
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];
}
}
exports.ZaloDecrypt = ZaloDecrypt;