mtgsig

2026-04-29 10:422阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐
问题描述:

#!/usr/bin/env node 'use strict'; const crypto = require('crypto'); const fs = require('fs'); const path = require('path'); /** * 完整的单文件mtgsig纯算离线签名器 * 支持离线生成mtgsig签名,使用预设的profile参数 */ // ============= 基础MD5和XOR工具 ============= function md5Hex(input) { return crypto.createHash('md5').update(input).digest('hex'); } function xorHex(buffer, xorKeyHex) { const xorKey = Buffer.from(xorKeyHex, 'hex'); const out = Buffer.alloc(16); for (let i = 0; i < 16; i++) { out[i] = buffer[i] ^ xorKey[i]; } return out.toString('hex'); } function getSaltFromA6(a6) { const s = String(a6 || ''); if (!s.startsWith('h1.9') || s.length < 10) { throw new Error('Invalid a6 payload: expected prefix h1.9 and at least 6 salt chars'); } return s.slice(4, 10); } // ============= A3生成(从WEBDFPID) ============= function deriveA3FromWebdfpid(webdfpid) { const s = String(webdfpid || '').trim(); if (!s) { return ''; } return s.split('-')[0] || ''; } function parseCookieHeader(cookieHeader) { if (!cookieHeader) { return {}; } return String(cookieHeader) .split(';') .map((part) => part.trim()) .filter(Boolean) .reduce((cookies, part) => { const idx = part.indexOf('='); if (idx === -1) { return cookies; } const key = part.slice(0, idx).trim(); const value = part.slice(idx + 1).trim(); if (key) { cookies[key] = value; } return cookies; }, {}); } function pickCookieHeader(input) { if (!input) { return ''; } return input.cookie || input.Cookie || (input.headers && (input.headers.Cookie || input.headers.cookie)) || ''; } function resolveA3(input = {}) { if (input.a3) { return String(input.a3); } const cookies = parseCookieHeader(pickCookieHeader(input)); return deriveA3FromWebdfpid(input.webdfpid || input.dfpid || cookies.WEBDFPID); } // ============= A8生成(核心签名) ============= function generateA8({ a6, timestamp, xorKeyHex, suffix = '2' }) { const salt = getSaltFromA6(a6); const input = `h1.9${salt}${String(timestamp)}${suffix}`; const digest = crypto.createHash('md5').update(input).digest(); return xorHex(digest, xorKeyHex); } // ============= A6Key生成 ============= function generateA6Key(a8, a9, a10) { return md5Hex(`${a8}${a9}${a10}`); } // ============= D1生成 ============= function generateD1({ d1, sessionId, payload }) { if (d1 && typeof d1 === 'string' && d1.length === 32) { return d1; } if (sessionId) { return md5Hex(String(sessionId)); } return md5Hex(String(payload || '')); } // ============= A5生成(假设使用默认值或提供) ============= function generateA5({ a5, timestamp }) { if (a5) { return String(a5); } // 如果没有提供,返回空白或使用placeholder return ''; } // ============= 默认Profile(从浏览器捕获) ============= const DEFAULT_PROFILE = { a9: '4.2.0,7,39', a10: '10', a8Suffix: '2', xorKeyHex: '19f02f45fb1dee6ce3e613b8aefd6d13', // 从latest_request_20260420.json推导 description: 'Default MTGSig profile for offline signing' }; // ============= 签名生成器 ============= function createOfflineMtgsigSigner(profile = {}) { const resolvedProfile = { ...DEFAULT_PROFILE, ...profile }; function sign(request = {}, options = {}) { const timestamp = options.clock || request.a2 || request.timestamp || Date.now(); const a9 = options.a9 || request.a9 || resolvedProfile.a9; const a10 = options.a10 || request.a10 || resolvedProfile.a10; const suffix = options.suffix || resolvedProfile.a8Suffix; // 需要的数据:a6payload或从请求推导 const a6 = request.a6 || request.payload; if (!a6) { throw new Error('Missing a6 payload in request or profile'); } // 生成各个字段 const a8 = generateA8({ a6, timestamp, xorKeyHex: resolvedProfile.xorKeyHex, suffix }); const a3 = resolveA3(request); const d1 = generateD1({ d1: request.d1, sessionId: request.sessionId || request.arg23, payload: a6 }); const a6Key = generateA6Key(a8, a9, a10); const a5 = generateA5({ a5: request.a5, timestamp }); const a1 = '1.2'; const a2 = String(timestamp); return { a1, a2, a3, a5, a6, a8, a9, a10, d1, a6Key, x0: 4 // 固定值 }; } return { sign }; } // ============= 使用工具和CLI ============= function loadJsonFile(filePath) { if (!filePath) { return null; } try { const content = fs.readFileSync(path.resolve(filePath), 'utf8'); return JSON.parse(content); } catch (err) { console.error(`Failed to load ${filePath}:`, err.message); return null; } } function normalizeInput(input) { // 支持多种输入格式 if (typeof input === 'object' && input.request) { return input.request; } return input || {}; } function main() { const args = process.argv.slice(2); const requestPath = args[0]; const profilePath = args[1]; // 如果没有参数,显示帮助和演示 if (!requestPath) { console.log('══════════════════════════════════════════════════════'); console.log(' mtgsig 离线签名生成器'); console.log('══════════════════════════════════════════════════════'); console.log(''); console.log('用法:'); console.log(' node mtgsig_pure_offline_signer.js [request.json] [profile.json]'); console.log(''); console.log('示例 1 - 使用默认参数(旧版本 4.2.0,7,39):'); console.log(' node mtgsig_pure_offline_signer.js request.json'); console.log(''); console.log('示例 2 - 使用新版本参数(4.2.0,7,8):'); console.log(' node mtgsig_pure_offline_signer.js request.json new_version_profile.json'); console.log(''); console.log('request.json 格式:'); console.log(JSON.stringify({ a2: '当前时间戳(毫秒),如: ' + Date.now(), a6: 'h1.9HK1PkF...(真实的payload)', a3: '372887v7w5yu5282067xww2y1463u8wy80yw0z8xu4z9795881u44vw7', webdfpid: '372887v7w5yu5282067xww2y1463u8wy80yw0z8xu4z9795881u44vw7-...' }, null, 2)); console.log(''); console.log('══════════════════════════════════════════════════════'); console.log('执行演示(使用测试数据):'); console.log('══════════════════════════════════════════════════════'); console.log(''); // 演示模式:使用测试数据 const demoProfile = { a9: '4.2.0,7,8', a10: '98', a8Suffix: '2', xorKeyHex: 'b5ba5e10d16d19d1f2858b6497caabdd' }; const demoRequest = { a2: Date.now(), // 使用当前时间戳而不是写死的值 a6: 'h1.9HK1PkFlf4Ob8girMsbirMgPXRSgRpTkkG6ek+9XOfrTyBfz/ElmPja0cIA5BI+MVJTPmY38oUCtvWO2Caf4Eu9TsvpzGWF1/sc0go/luDfjsSIp8WN3Ngl6rBYvMeOggErpTlqvfDmGOpZ2wc+hVEHJxt5Q2kKZnPxI8E0IIdELX4+gNL0a4AF5p76g2Wn+bBLVnpvytVNKpqL/Lfr3y2Mk0asGbuqHNzmV3ivHSxnNui3ltOUB7HUGQYhMonCY0kzHlNGhCbTw3/7DQvQgck4UERlc3UrVukC9cES1kIYjxf52Rj1j4V0kfo1cf9OnWYRd9fCWmgXOIoJi5J9Da2+6R+pUtNhnnAkdgxVWWuQGieJQAOFStvImm6qjKvgPpCmBalIVenyKm79g1e6nF5w==', a3: '372887v7w5yu5282067xww2y1463u8wy80yw0z8xu4z9795881u44vw7', webdfpid: '372887v7w5yu5282067xww2y1463u8wy80yw0z8xu4z9795881u44vw7-1776843046392-1768882819070QUEUOWCfd79fef3d01d5e9aadc18ccd4d0c95072412' }; console.log('📋 演示配置 (新版本):'); console.log(` a9: ${demoProfile.a9}`); console.log(` a10: ${demoProfile.a10}`); console.log(` xorKeyHex: ${demoProfile.xorKeyHex}`); console.log(''); console.log('📋 演示请求数据:'); console.log(` timestamp: ${demoRequest.a2}`); console.log(` a3: ${demoRequest.a3.substring(0, 30)}...`); console.log(''); const signer = createOfflineMtgsigSigner(demoProfile); try { const signature = signer.sign(demoRequest); console.log('✅ 生成成功!'); console.log(''); console.log('📤 生成的签名:'); console.log(JSON.stringify(signature, null, 2)); console.log(''); console.log(`✓ a8 (关键签名): ${signature.a8}`); console.log(`✓ a6Key (验证码): ${signature.a6Key}`); } catch (err) { console.error('❌ 生成失败:', err.message); process.exitCode = 1; } return; } // 加载请求数据 const request = loadJsonFile(requestPath) || {}; console.error(`[INFO] Loaded request from: ${requestPath}`); // 加载自定义profile let customProfile = null; if (profilePath) { customProfile = loadJsonFile(profilePath); console.error(`[INFO] Loaded profile from: ${profilePath}`); } // 如果输入JSON包含request字段,使用它 const normalizedRequest = normalizeInput(request); // 创建签名器 const signer = createOfflineMtgsigSigner(customProfile); // 生成签名 try { const signature = signer.sign(normalizedRequest); console.log(JSON.stringify(signature, null, 2)); } catch (err) { console.error('[ERROR]', err.message); process.exitCode = 1; } } // ============= 导出 ============= if (require.main === module) { main(); } module.exports = { md5Hex, xorHex, getSaltFromA6, generateA8, generateA6Key, generateD1, generateA5, resolveA3, createOfflineMtgsigSigner, DEFAULT_PROFILE };

大佬勿喷,AI撕的“纯算”,大家参考,我调用了一下没问题

网友解答:
--【壹】--:

mtgsig的算法不是一样的吗?目前最新的,我没细看 好像是1.2


--【贰】--:

你这个是网页端,还是app端的? 啥版本的?

标签:算法
问题描述:

#!/usr/bin/env node 'use strict'; const crypto = require('crypto'); const fs = require('fs'); const path = require('path'); /** * 完整的单文件mtgsig纯算离线签名器 * 支持离线生成mtgsig签名,使用预设的profile参数 */ // ============= 基础MD5和XOR工具 ============= function md5Hex(input) { return crypto.createHash('md5').update(input).digest('hex'); } function xorHex(buffer, xorKeyHex) { const xorKey = Buffer.from(xorKeyHex, 'hex'); const out = Buffer.alloc(16); for (let i = 0; i < 16; i++) { out[i] = buffer[i] ^ xorKey[i]; } return out.toString('hex'); } function getSaltFromA6(a6) { const s = String(a6 || ''); if (!s.startsWith('h1.9') || s.length < 10) { throw new Error('Invalid a6 payload: expected prefix h1.9 and at least 6 salt chars'); } return s.slice(4, 10); } // ============= A3生成(从WEBDFPID) ============= function deriveA3FromWebdfpid(webdfpid) { const s = String(webdfpid || '').trim(); if (!s) { return ''; } return s.split('-')[0] || ''; } function parseCookieHeader(cookieHeader) { if (!cookieHeader) { return {}; } return String(cookieHeader) .split(';') .map((part) => part.trim()) .filter(Boolean) .reduce((cookies, part) => { const idx = part.indexOf('='); if (idx === -1) { return cookies; } const key = part.slice(0, idx).trim(); const value = part.slice(idx + 1).trim(); if (key) { cookies[key] = value; } return cookies; }, {}); } function pickCookieHeader(input) { if (!input) { return ''; } return input.cookie || input.Cookie || (input.headers && (input.headers.Cookie || input.headers.cookie)) || ''; } function resolveA3(input = {}) { if (input.a3) { return String(input.a3); } const cookies = parseCookieHeader(pickCookieHeader(input)); return deriveA3FromWebdfpid(input.webdfpid || input.dfpid || cookies.WEBDFPID); } // ============= A8生成(核心签名) ============= function generateA8({ a6, timestamp, xorKeyHex, suffix = '2' }) { const salt = getSaltFromA6(a6); const input = `h1.9${salt}${String(timestamp)}${suffix}`; const digest = crypto.createHash('md5').update(input).digest(); return xorHex(digest, xorKeyHex); } // ============= A6Key生成 ============= function generateA6Key(a8, a9, a10) { return md5Hex(`${a8}${a9}${a10}`); } // ============= D1生成 ============= function generateD1({ d1, sessionId, payload }) { if (d1 && typeof d1 === 'string' && d1.length === 32) { return d1; } if (sessionId) { return md5Hex(String(sessionId)); } return md5Hex(String(payload || '')); } // ============= A5生成(假设使用默认值或提供) ============= function generateA5({ a5, timestamp }) { if (a5) { return String(a5); } // 如果没有提供,返回空白或使用placeholder return ''; } // ============= 默认Profile(从浏览器捕获) ============= const DEFAULT_PROFILE = { a9: '4.2.0,7,39', a10: '10', a8Suffix: '2', xorKeyHex: '19f02f45fb1dee6ce3e613b8aefd6d13', // 从latest_request_20260420.json推导 description: 'Default MTGSig profile for offline signing' }; // ============= 签名生成器 ============= function createOfflineMtgsigSigner(profile = {}) { const resolvedProfile = { ...DEFAULT_PROFILE, ...profile }; function sign(request = {}, options = {}) { const timestamp = options.clock || request.a2 || request.timestamp || Date.now(); const a9 = options.a9 || request.a9 || resolvedProfile.a9; const a10 = options.a10 || request.a10 || resolvedProfile.a10; const suffix = options.suffix || resolvedProfile.a8Suffix; // 需要的数据:a6payload或从请求推导 const a6 = request.a6 || request.payload; if (!a6) { throw new Error('Missing a6 payload in request or profile'); } // 生成各个字段 const a8 = generateA8({ a6, timestamp, xorKeyHex: resolvedProfile.xorKeyHex, suffix }); const a3 = resolveA3(request); const d1 = generateD1({ d1: request.d1, sessionId: request.sessionId || request.arg23, payload: a6 }); const a6Key = generateA6Key(a8, a9, a10); const a5 = generateA5({ a5: request.a5, timestamp }); const a1 = '1.2'; const a2 = String(timestamp); return { a1, a2, a3, a5, a6, a8, a9, a10, d1, a6Key, x0: 4 // 固定值 }; } return { sign }; } // ============= 使用工具和CLI ============= function loadJsonFile(filePath) { if (!filePath) { return null; } try { const content = fs.readFileSync(path.resolve(filePath), 'utf8'); return JSON.parse(content); } catch (err) { console.error(`Failed to load ${filePath}:`, err.message); return null; } } function normalizeInput(input) { // 支持多种输入格式 if (typeof input === 'object' && input.request) { return input.request; } return input || {}; } function main() { const args = process.argv.slice(2); const requestPath = args[0]; const profilePath = args[1]; // 如果没有参数,显示帮助和演示 if (!requestPath) { console.log('══════════════════════════════════════════════════════'); console.log(' mtgsig 离线签名生成器'); console.log('══════════════════════════════════════════════════════'); console.log(''); console.log('用法:'); console.log(' node mtgsig_pure_offline_signer.js [request.json] [profile.json]'); console.log(''); console.log('示例 1 - 使用默认参数(旧版本 4.2.0,7,39):'); console.log(' node mtgsig_pure_offline_signer.js request.json'); console.log(''); console.log('示例 2 - 使用新版本参数(4.2.0,7,8):'); console.log(' node mtgsig_pure_offline_signer.js request.json new_version_profile.json'); console.log(''); console.log('request.json 格式:'); console.log(JSON.stringify({ a2: '当前时间戳(毫秒),如: ' + Date.now(), a6: 'h1.9HK1PkF...(真实的payload)', a3: '372887v7w5yu5282067xww2y1463u8wy80yw0z8xu4z9795881u44vw7', webdfpid: '372887v7w5yu5282067xww2y1463u8wy80yw0z8xu4z9795881u44vw7-...' }, null, 2)); console.log(''); console.log('══════════════════════════════════════════════════════'); console.log('执行演示(使用测试数据):'); console.log('══════════════════════════════════════════════════════'); console.log(''); // 演示模式:使用测试数据 const demoProfile = { a9: '4.2.0,7,8', a10: '98', a8Suffix: '2', xorKeyHex: 'b5ba5e10d16d19d1f2858b6497caabdd' }; const demoRequest = { a2: Date.now(), // 使用当前时间戳而不是写死的值 a6: 'h1.9HK1PkFlf4Ob8girMsbirMgPXRSgRpTkkG6ek+9XOfrTyBfz/ElmPja0cIA5BI+MVJTPmY38oUCtvWO2Caf4Eu9TsvpzGWF1/sc0go/luDfjsSIp8WN3Ngl6rBYvMeOggErpTlqvfDmGOpZ2wc+hVEHJxt5Q2kKZnPxI8E0IIdELX4+gNL0a4AF5p76g2Wn+bBLVnpvytVNKpqL/Lfr3y2Mk0asGbuqHNzmV3ivHSxnNui3ltOUB7HUGQYhMonCY0kzHlNGhCbTw3/7DQvQgck4UERlc3UrVukC9cES1kIYjxf52Rj1j4V0kfo1cf9OnWYRd9fCWmgXOIoJi5J9Da2+6R+pUtNhnnAkdgxVWWuQGieJQAOFStvImm6qjKvgPpCmBalIVenyKm79g1e6nF5w==', a3: '372887v7w5yu5282067xww2y1463u8wy80yw0z8xu4z9795881u44vw7', webdfpid: '372887v7w5yu5282067xww2y1463u8wy80yw0z8xu4z9795881u44vw7-1776843046392-1768882819070QUEUOWCfd79fef3d01d5e9aadc18ccd4d0c95072412' }; console.log('📋 演示配置 (新版本):'); console.log(` a9: ${demoProfile.a9}`); console.log(` a10: ${demoProfile.a10}`); console.log(` xorKeyHex: ${demoProfile.xorKeyHex}`); console.log(''); console.log('📋 演示请求数据:'); console.log(` timestamp: ${demoRequest.a2}`); console.log(` a3: ${demoRequest.a3.substring(0, 30)}...`); console.log(''); const signer = createOfflineMtgsigSigner(demoProfile); try { const signature = signer.sign(demoRequest); console.log('✅ 生成成功!'); console.log(''); console.log('📤 生成的签名:'); console.log(JSON.stringify(signature, null, 2)); console.log(''); console.log(`✓ a8 (关键签名): ${signature.a8}`); console.log(`✓ a6Key (验证码): ${signature.a6Key}`); } catch (err) { console.error('❌ 生成失败:', err.message); process.exitCode = 1; } return; } // 加载请求数据 const request = loadJsonFile(requestPath) || {}; console.error(`[INFO] Loaded request from: ${requestPath}`); // 加载自定义profile let customProfile = null; if (profilePath) { customProfile = loadJsonFile(profilePath); console.error(`[INFO] Loaded profile from: ${profilePath}`); } // 如果输入JSON包含request字段,使用它 const normalizedRequest = normalizeInput(request); // 创建签名器 const signer = createOfflineMtgsigSigner(customProfile); // 生成签名 try { const signature = signer.sign(normalizedRequest); console.log(JSON.stringify(signature, null, 2)); } catch (err) { console.error('[ERROR]', err.message); process.exitCode = 1; } } // ============= 导出 ============= if (require.main === module) { main(); } module.exports = { md5Hex, xorHex, getSaltFromA6, generateA8, generateA6Key, generateD1, generateA5, resolveA3, createOfflineMtgsigSigner, DEFAULT_PROFILE };

大佬勿喷,AI撕的“纯算”,大家参考,我调用了一下没问题

网友解答:
--【壹】--:

mtgsig的算法不是一样的吗?目前最新的,我没细看 好像是1.2


--【贰】--:

你这个是网页端,还是app端的? 啥版本的?

标签:算法