deepspider 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/check.md +122 -0
- package/.claude/agents/debug.md +106 -0
- package/.claude/agents/dispatch.md +214 -0
- package/.claude/agents/implement.md +96 -0
- package/.claude/agents/plan.md +396 -0
- package/.claude/agents/research.md +120 -0
- package/.claude/commands/evolve/merge.md +80 -0
- package/.claude/commands/trellis/before-backend-dev.md +13 -0
- package/.claude/commands/trellis/before-frontend-dev.md +13 -0
- package/.claude/commands/trellis/break-loop.md +107 -0
- package/.claude/commands/trellis/check-backend.md +13 -0
- package/.claude/commands/trellis/check-cross-layer.md +153 -0
- package/.claude/commands/trellis/check-frontend.md +13 -0
- package/.claude/commands/trellis/create-command.md +154 -0
- package/.claude/commands/trellis/finish-work.md +129 -0
- package/.claude/commands/trellis/integrate-skill.md +219 -0
- package/.claude/commands/trellis/onboard.md +358 -0
- package/.claude/commands/trellis/parallel.md +193 -0
- package/.claude/commands/trellis/record-session.md +62 -0
- package/.claude/commands/trellis/start.md +280 -0
- package/.claude/commands/trellis/update-spec.md +213 -0
- package/.claude/hooks/inject-subagent-context.py +758 -0
- package/.claude/hooks/ralph-loop.py +374 -0
- package/.claude/hooks/session-start.py +126 -0
- package/.claude/settings.json +41 -0
- package/.claude/skills/deepagents-guide/SKILL.md +428 -0
- package/.cursor/commands/trellis-before-backend-dev.md +13 -0
- package/.cursor/commands/trellis-before-frontend-dev.md +13 -0
- package/.cursor/commands/trellis-break-loop.md +107 -0
- package/.cursor/commands/trellis-check-backend.md +13 -0
- package/.cursor/commands/trellis-check-cross-layer.md +153 -0
- package/.cursor/commands/trellis-check-frontend.md +13 -0
- package/.cursor/commands/trellis-create-command.md +154 -0
- package/.cursor/commands/trellis-finish-work.md +129 -0
- package/.cursor/commands/trellis-integrate-skill.md +219 -0
- package/.cursor/commands/trellis-onboard.md +358 -0
- package/.cursor/commands/trellis-record-session.md +62 -0
- package/.cursor/commands/trellis-start.md +156 -0
- package/.cursor/commands/trellis-update-spec.md +213 -0
- package/.env.example +11 -0
- package/.husky/pre-commit +1 -0
- package/.mcp.json +8 -0
- package/.trellis/.template-hashes.json +65 -0
- package/.trellis/.version +1 -0
- package/.trellis/scripts/add-session.sh +384 -0
- package/.trellis/scripts/common/developer.sh +129 -0
- package/.trellis/scripts/common/git-context.sh +263 -0
- package/.trellis/scripts/common/paths.sh +208 -0
- package/.trellis/scripts/common/phase.sh +150 -0
- package/.trellis/scripts/common/registry.sh +247 -0
- package/.trellis/scripts/common/task-queue.sh +142 -0
- package/.trellis/scripts/common/task-utils.sh +151 -0
- package/.trellis/scripts/common/worktree.sh +128 -0
- package/.trellis/scripts/create-bootstrap.sh +299 -0
- package/.trellis/scripts/get-context.sh +7 -0
- package/.trellis/scripts/get-developer.sh +15 -0
- package/.trellis/scripts/init-developer.sh +34 -0
- package/.trellis/scripts/multi-agent/cleanup.sh +396 -0
- package/.trellis/scripts/multi-agent/create-pr.sh +241 -0
- package/.trellis/scripts/multi-agent/plan.sh +207 -0
- package/.trellis/scripts/multi-agent/start.sh +310 -0
- package/.trellis/scripts/multi-agent/status.sh +828 -0
- package/.trellis/scripts/task.sh +1118 -0
- package/.trellis/spec/backend/deepagents-guide.md +337 -0
- package/.trellis/spec/backend/directory-structure.md +126 -0
- package/.trellis/spec/backend/examples/skills/deepagents-guide/README.md +11 -0
- package/.trellis/spec/backend/examples/skills/deepagents-guide/agent.js.template +20 -0
- package/.trellis/spec/backend/examples/skills/deepagents-guide/skills-config.js.template +13 -0
- package/.trellis/spec/backend/examples/skills/deepagents-guide/subagent.js.template +19 -0
- package/.trellis/spec/backend/hook-guidelines.md +178 -0
- package/.trellis/spec/backend/index.md +36 -0
- package/.trellis/spec/backend/quality-guidelines.md +201 -0
- package/.trellis/spec/backend/state-management.md +76 -0
- package/.trellis/spec/backend/tool-guidelines.md +144 -0
- package/.trellis/spec/backend/type-safety.md +71 -0
- package/.trellis/spec/guides/code-reuse-thinking-guide.md +92 -0
- package/.trellis/spec/guides/cross-layer-thinking-guide.md +94 -0
- package/.trellis/spec/guides/index.md +79 -0
- package/.trellis/tasks/archive/02-02-evolving-skills/prd.md +61 -0
- package/.trellis/tasks/archive/02-02-evolving-skills/task.json +29 -0
- package/.trellis/tasks/archive/2026-02/00-bootstrap-guidelines/prd.md +86 -0
- package/.trellis/tasks/archive/2026-02/00-bootstrap-guidelines/task.json +27 -0
- package/.trellis/tasks/archive/2026-02/02-02-skills-system/check.jsonl +3 -0
- package/.trellis/tasks/archive/2026-02/02-02-skills-system/debug.jsonl +2 -0
- package/.trellis/tasks/archive/2026-02/02-02-skills-system/implement.jsonl +5 -0
- package/.trellis/tasks/archive/2026-02/02-02-skills-system/prd.md +33 -0
- package/.trellis/tasks/archive/2026-02/02-02-skills-system/task.json +41 -0
- package/.trellis/workflow.md +407 -0
- package/.trellis/workspace/index.md +123 -0
- package/.trellis/workspace/pony/index.md +40 -0
- package/.trellis/workspace/pony/journal-1.md +7 -0
- package/.trellis/worktree.yaml +47 -0
- package/AGENTS.md +18 -0
- package/CLAUDE.md +292 -0
- package/README.md +134 -0
- package/agents/deepspider.md +142 -0
- package/docs/DEBUG.md +42 -0
- package/docs/GUIDE.md +334 -0
- package/docs/PROMPT.md +60 -0
- package/docs/USAGE.md +226 -0
- package/eslint.config.js +51 -0
- package/package.json +78 -0
- package/requirements-crypto.txt +14 -0
- package/src/agent/index.js +97 -0
- package/src/agent/logger.js +164 -0
- package/src/agent/middleware/filterTools.js +64 -0
- package/src/agent/middleware/report.js +79 -0
- package/src/agent/prompts/system.js +315 -0
- package/src/agent/run.js +575 -0
- package/src/agent/skills/anti-detect/SKILL.md +28 -0
- package/src/agent/skills/anti-detect/evolved.md +12 -0
- package/src/agent/skills/captcha/SKILL.md +37 -0
- package/src/agent/skills/captcha/evolved.md +12 -0
- package/src/agent/skills/config.js +30 -0
- package/src/agent/skills/crawler/SKILL.md +9 -0
- package/src/agent/skills/crawler/evolved.md +16 -0
- package/src/agent/skills/dynamic-analysis/SKILL.md +91 -0
- package/src/agent/skills/dynamic-analysis/evolved.md +12 -0
- package/src/agent/skills/env/SKILL.md +72 -0
- package/src/agent/skills/env/evolved.md +12 -0
- package/src/agent/skills/evolve.js +79 -0
- package/src/agent/skills/general/SKILL.md +12 -0
- package/src/agent/skills/general/evolved.md +12 -0
- package/src/agent/skills/js2python/SKILL.md +30 -0
- package/src/agent/skills/js2python/evolved.md +13 -0
- package/src/agent/skills/report/SKILL.md +21 -0
- package/src/agent/skills/report/evolved.md +12 -0
- package/src/agent/skills/sandbox/SKILL.md +22 -0
- package/src/agent/skills/sandbox/evolved.md +16 -0
- package/src/agent/skills/static-analysis/SKILL.md +93 -0
- package/src/agent/skills/static-analysis/evolved.md +12 -0
- package/src/agent/skills/xpath/SKILL.md +119 -0
- package/src/agent/subagents/anti-detect.js +45 -0
- package/src/agent/subagents/captcha.js +51 -0
- package/src/agent/subagents/crawler.js +138 -0
- package/src/agent/subagents/dynamic.js +64 -0
- package/src/agent/subagents/env-agent.js +82 -0
- package/src/agent/subagents/index.js +37 -0
- package/src/agent/subagents/js2python.js +72 -0
- package/src/agent/subagents/sandbox.js +55 -0
- package/src/agent/subagents/static.js +66 -0
- package/src/agent/tools/analysis.js +135 -0
- package/src/agent/tools/analyzer.js +85 -0
- package/src/agent/tools/anti-detect.js +89 -0
- package/src/agent/tools/antidebug.js +64 -0
- package/src/agent/tools/async.js +43 -0
- package/src/agent/tools/browser.js +324 -0
- package/src/agent/tools/captcha.js +223 -0
- package/src/agent/tools/capture.js +179 -0
- package/src/agent/tools/correlate.js +303 -0
- package/src/agent/tools/crawler.js +116 -0
- package/src/agent/tools/cryptohook.js +80 -0
- package/src/agent/tools/debug.js +246 -0
- package/src/agent/tools/deobfuscator.js +90 -0
- package/src/agent/tools/env.js +83 -0
- package/src/agent/tools/envdump.js +92 -0
- package/src/agent/tools/evolve.js +164 -0
- package/src/agent/tools/extract.js +114 -0
- package/src/agent/tools/extractor.js +54 -0
- package/src/agent/tools/file.js +224 -0
- package/src/agent/tools/hook.js +84 -0
- package/src/agent/tools/hookManager.js +178 -0
- package/src/agent/tools/index.js +137 -0
- package/src/agent/tools/nodejs.js +101 -0
- package/src/agent/tools/patch.js +46 -0
- package/src/agent/tools/preprocess.js +71 -0
- package/src/agent/tools/profile.js +122 -0
- package/src/agent/tools/python.js +627 -0
- package/src/agent/tools/report.js +124 -0
- package/src/agent/tools/runtime.js +132 -0
- package/src/agent/tools/sandbox.js +79 -0
- package/src/agent/tools/store.js +73 -0
- package/src/agent/tools/trace.js +74 -0
- package/src/agent/tools/tracing.js +201 -0
- package/src/agent/tools/utils.js +51 -0
- package/src/agent/tools/verify.js +184 -0
- package/src/agent/tools/webcrack.js +109 -0
- package/src/analyzer/ASTAnalyzer.js +387 -0
- package/src/analyzer/CallStackAnalyzer.js +379 -0
- package/src/analyzer/Deobfuscator.js +289 -0
- package/src/analyzer/EncryptionAnalyzer.js +99 -0
- package/src/analyzer/index.js +22 -0
- package/src/browser/EnvBridge.js +186 -0
- package/src/browser/cdp.js +168 -0
- package/src/browser/client.js +197 -0
- package/src/browser/collector.js +444 -0
- package/src/browser/collectors/RequestCryptoLinker.js +109 -0
- package/src/browser/collectors/ResponseSearcher.js +107 -0
- package/src/browser/collectors/ScriptCollector.js +158 -0
- package/src/browser/collectors/index.js +26 -0
- package/src/browser/defaultHooks.js +932 -0
- package/src/browser/hooks/crypto.js +55 -0
- package/src/browser/hooks/index.js +64 -0
- package/src/browser/hooks/native.js +9 -0
- package/src/browser/hooks/network.js +33 -0
- package/src/browser/index.js +42 -0
- package/src/browser/interceptors/NetworkInterceptor.js +116 -0
- package/src/browser/interceptors/ScriptInterceptor.js +76 -0
- package/src/browser/interceptors/index.js +6 -0
- package/src/browser/ui/analysisPanel.js +1782 -0
- package/src/browser/ui/confirmDialog.js +158 -0
- package/src/browser/ui/panel.html +152 -0
- package/src/browser/ui/selector.js +170 -0
- package/src/config/index.js +5 -0
- package/src/config/paths.js +71 -0
- package/src/config/patterns/crypto.js +36 -0
- package/src/config/profiles/chrome.json +71 -0
- package/src/config/profiles/firefox.json +44 -0
- package/src/config/profiles/safari.json +38 -0
- package/src/core/EnvMonitor.js +200 -0
- package/src/core/PatchGenerator.js +278 -0
- package/src/core/Sandbox.js +181 -0
- package/src/env/AntiAntiDebug.js +111 -0
- package/src/env/AsyncHook.js +68 -0
- package/src/env/BrowserAPIList.js +265 -0
- package/src/env/CookieHook.js +48 -0
- package/src/env/CryptoHook.js +205 -0
- package/src/env/EnvCodeGenerator.js +157 -0
- package/src/env/EnvDumper.js +356 -0
- package/src/env/EnvExtractor.js +220 -0
- package/src/env/HookBase.js +618 -0
- package/src/env/NetworkHook.js +159 -0
- package/src/env/modules/bom/history.js +29 -0
- package/src/env/modules/bom/location.js +26 -0
- package/src/env/modules/bom/navigator.js +70 -0
- package/src/env/modules/bom/screen.js +26 -0
- package/src/env/modules/bom/storage.js +23 -0
- package/src/env/modules/dom/document.js +110 -0
- package/src/env/modules/dom/event.js +51 -0
- package/src/env/modules/index.js +34 -0
- package/src/env/modules/webapi/fetch.js +46 -0
- package/src/env/modules/webapi/url.js +47 -0
- package/src/env/modules/webapi/xhr.js +48 -0
- package/src/index.js +27 -0
- package/src/mcp/server.js +89 -0
- package/src/store/DataStore.js +708 -0
- package/src/store/Store.js +158 -0
- package/src/store/Validator.js +24 -0
- package/test/analyze.test.js +90 -0
- package/test/envdump.test.js +74 -0
- package/test/flow.test.js +90 -0
- package/test/hooks.test.js +138 -0
- package/test/plugin.test.js +35 -0
- package/test/refactor-full.test.js +30 -0
- package/test/refactor.test.js +21 -0
- package/test/samples/obfuscated.js +61 -0
- package/test/samples/original.js +66 -0
- package/test/samples/v10_eval_chain.js +52 -0
- package/test/samples/v11_bytecode_vm.js +81 -0
- package/test/samples/v12_polymorphic.js +69 -0
- package/test/samples/v1_ob_basic.js +98 -0
- package/test/samples/v2_ob_advanced.js +99 -0
- package/test/samples/v3_jjencode.js +77 -0
- package/test/samples/v4_aaencode.js +73 -0
- package/test/samples/v5_control_flow.js +86 -0
- package/test/samples/v6_string_encryption.js +71 -0
- package/test/samples/v7_jsvmp.js +83 -0
- package/test/samples/v8_anti_debug.js +79 -0
- package/test/samples/v9_proxy_trap.js +49 -0
- package/test/samples.test.js +96 -0
- package/test/webcrack.test.js +55 -0
|
@@ -0,0 +1,627 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DeepSpider - Python 验证工具
|
|
3
|
+
* 用于验证标准加密算法并生成 Python 代码
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { tool } from '@langchain/core/tools';
|
|
8
|
+
import { spawn } from 'child_process';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 执行 Python 代码(通过 uv 管理的环境)
|
|
12
|
+
*/
|
|
13
|
+
async function executePython(code, timeout = 10000) {
|
|
14
|
+
return new Promise((resolve) => {
|
|
15
|
+
// 使用 uv run 确保在正确的环境中执行
|
|
16
|
+
const proc = spawn('uv', ['run', 'python', '-c', code], {
|
|
17
|
+
timeout,
|
|
18
|
+
env: { ...globalThis.process.env, PYTHONIOENCODING: 'utf-8' },
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
let stdout = '';
|
|
22
|
+
let stderr = '';
|
|
23
|
+
|
|
24
|
+
proc.stdout.on('data', (data) => {
|
|
25
|
+
stdout += data.toString();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
proc.stderr.on('data', (data) => {
|
|
29
|
+
stderr += data.toString();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
proc.on('close', (code) => {
|
|
33
|
+
resolve({
|
|
34
|
+
success: code === 0,
|
|
35
|
+
stdout: stdout.trim(),
|
|
36
|
+
stderr: stderr.trim(),
|
|
37
|
+
exitCode: code,
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
proc.on('error', (err) => {
|
|
42
|
+
resolve({
|
|
43
|
+
success: false,
|
|
44
|
+
stdout: '',
|
|
45
|
+
stderr: err.message,
|
|
46
|
+
exitCode: -1,
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 生成 Python 验证代码
|
|
54
|
+
*/
|
|
55
|
+
function generateVerifyCode(algorithm, params) {
|
|
56
|
+
const { plaintext, ciphertext, key, iv, mode, format, hmacKey, digestmod } = params;
|
|
57
|
+
|
|
58
|
+
const templates = {
|
|
59
|
+
// AES
|
|
60
|
+
'AES-CBC': `
|
|
61
|
+
import base64
|
|
62
|
+
from Crypto.Cipher import AES
|
|
63
|
+
from Crypto.Util.Padding import pad, unpad
|
|
64
|
+
|
|
65
|
+
key = ${JSON.stringify(key)}.encode()
|
|
66
|
+
iv = ${JSON.stringify(iv || key)}.encode()
|
|
67
|
+
plaintext = ${JSON.stringify(plaintext)}
|
|
68
|
+
expected = ${JSON.stringify(ciphertext)}
|
|
69
|
+
|
|
70
|
+
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
|
|
71
|
+
encrypted = cipher.encrypt(pad(plaintext.encode(), AES.block_size))
|
|
72
|
+
result = base64.b64encode(encrypted).decode() if ${JSON.stringify(format)} == 'base64' else encrypted.hex()
|
|
73
|
+
|
|
74
|
+
print('MATCH' if result == expected else f'MISMATCH: got {result}')
|
|
75
|
+
`,
|
|
76
|
+
'AES-ECB': `
|
|
77
|
+
import base64
|
|
78
|
+
from Crypto.Cipher import AES
|
|
79
|
+
from Crypto.Util.Padding import pad, unpad
|
|
80
|
+
|
|
81
|
+
key = ${JSON.stringify(key)}.encode()
|
|
82
|
+
plaintext = ${JSON.stringify(plaintext)}
|
|
83
|
+
expected = ${JSON.stringify(ciphertext)}
|
|
84
|
+
|
|
85
|
+
cipher = AES.new(key, AES.MODE_ECB)
|
|
86
|
+
encrypted = cipher.encrypt(pad(plaintext.encode(), AES.block_size))
|
|
87
|
+
result = base64.b64encode(encrypted).decode() if ${JSON.stringify(format)} == 'base64' else encrypted.hex()
|
|
88
|
+
|
|
89
|
+
print('MATCH' if result == expected else f'MISMATCH: got {result}')
|
|
90
|
+
`,
|
|
91
|
+
'AES-CFB': `
|
|
92
|
+
import base64
|
|
93
|
+
from Crypto.Cipher import AES
|
|
94
|
+
|
|
95
|
+
key = ${JSON.stringify(key)}.encode()
|
|
96
|
+
iv = key
|
|
97
|
+
plaintext = ${JSON.stringify(plaintext)}
|
|
98
|
+
expected = ${JSON.stringify(ciphertext)}
|
|
99
|
+
|
|
100
|
+
cipher = AES.new(key, AES.MODE_CFB, iv=iv, segment_size=128)
|
|
101
|
+
encrypted = cipher.encrypt(plaintext.encode())
|
|
102
|
+
result = base64.b64encode(encrypted).decode() if ${JSON.stringify(format)} == 'base64' else encrypted.hex()
|
|
103
|
+
|
|
104
|
+
print('MATCH' if result == expected else f'MISMATCH: got {result}')
|
|
105
|
+
`,
|
|
106
|
+
// DES
|
|
107
|
+
'DES-CBC': `
|
|
108
|
+
import base64
|
|
109
|
+
from Crypto.Cipher import DES
|
|
110
|
+
from Crypto.Util.Padding import pad, unpad
|
|
111
|
+
|
|
112
|
+
key = ${JSON.stringify(key)}.encode()
|
|
113
|
+
iv = ${JSON.stringify(iv || key)}.encode()
|
|
114
|
+
plaintext = ${JSON.stringify(plaintext)}
|
|
115
|
+
expected = ${JSON.stringify(ciphertext)}
|
|
116
|
+
|
|
117
|
+
cipher = DES.new(key, DES.MODE_CBC, iv=iv)
|
|
118
|
+
encrypted = cipher.encrypt(pad(plaintext.encode(), DES.block_size))
|
|
119
|
+
result = base64.b64encode(encrypted).decode() if ${JSON.stringify(format)} == 'base64' else encrypted.hex()
|
|
120
|
+
|
|
121
|
+
print('MATCH' if result == expected else f'MISMATCH: got {result}')
|
|
122
|
+
`,
|
|
123
|
+
'DES-ECB': `
|
|
124
|
+
import base64
|
|
125
|
+
from Crypto.Cipher import DES
|
|
126
|
+
from Crypto.Util.Padding import pad, unpad
|
|
127
|
+
|
|
128
|
+
key = ${JSON.stringify(key)}.encode()
|
|
129
|
+
plaintext = ${JSON.stringify(plaintext)}
|
|
130
|
+
expected = ${JSON.stringify(ciphertext)}
|
|
131
|
+
|
|
132
|
+
cipher = DES.new(key, DES.MODE_ECB)
|
|
133
|
+
encrypted = cipher.encrypt(pad(plaintext.encode(), DES.block_size))
|
|
134
|
+
result = base64.b64encode(encrypted).decode() if ${JSON.stringify(format)} == 'base64' else encrypted.hex()
|
|
135
|
+
|
|
136
|
+
print('MATCH' if result == expected else f'MISMATCH: got {result}')
|
|
137
|
+
`,
|
|
138
|
+
// Hash
|
|
139
|
+
'MD5': `
|
|
140
|
+
import hashlib
|
|
141
|
+
|
|
142
|
+
data = ${JSON.stringify(plaintext)}
|
|
143
|
+
expected = ${JSON.stringify(ciphertext)}
|
|
144
|
+
|
|
145
|
+
result = hashlib.md5(data.encode()).hexdigest()
|
|
146
|
+
print('MATCH' if result == expected else f'MISMATCH: got {result}')
|
|
147
|
+
`,
|
|
148
|
+
'SHA1': `
|
|
149
|
+
import hashlib
|
|
150
|
+
|
|
151
|
+
data = ${JSON.stringify(plaintext)}
|
|
152
|
+
expected = ${JSON.stringify(ciphertext)}
|
|
153
|
+
|
|
154
|
+
result = hashlib.sha1(data.encode()).hexdigest()
|
|
155
|
+
print('MATCH' if result == expected else f'MISMATCH: got {result}')
|
|
156
|
+
`,
|
|
157
|
+
'SHA256': `
|
|
158
|
+
import hashlib
|
|
159
|
+
|
|
160
|
+
data = ${JSON.stringify(plaintext)}
|
|
161
|
+
expected = ${JSON.stringify(ciphertext)}
|
|
162
|
+
|
|
163
|
+
result = hashlib.sha256(data.encode()).hexdigest()
|
|
164
|
+
print('MATCH' if result == expected else f'MISMATCH: got {result}')
|
|
165
|
+
`,
|
|
166
|
+
'SHA512': `
|
|
167
|
+
import hashlib
|
|
168
|
+
|
|
169
|
+
data = ${JSON.stringify(plaintext)}
|
|
170
|
+
expected = ${JSON.stringify(ciphertext)}
|
|
171
|
+
|
|
172
|
+
result = hashlib.sha512(data.encode()).hexdigest()
|
|
173
|
+
print('MATCH' if result == expected else f'MISMATCH: got {result}')
|
|
174
|
+
`,
|
|
175
|
+
// HMAC
|
|
176
|
+
'HMAC': `
|
|
177
|
+
import hmac
|
|
178
|
+
import hashlib
|
|
179
|
+
import base64
|
|
180
|
+
|
|
181
|
+
data = ${JSON.stringify(plaintext)}
|
|
182
|
+
key = ${JSON.stringify(hmacKey || key)}
|
|
183
|
+
expected = ${JSON.stringify(ciphertext)}
|
|
184
|
+
digestmod = ${JSON.stringify(digestmod || 'md5')}
|
|
185
|
+
|
|
186
|
+
hash_func = getattr(hashlib, digestmod)
|
|
187
|
+
hmac_obj = hmac.new(key.encode(), data.encode(), hash_func)
|
|
188
|
+
result = base64.b64encode(hmac_obj.digest()).decode() if ${JSON.stringify(format)} == 'base64' else hmac_obj.hexdigest()
|
|
189
|
+
|
|
190
|
+
print('MATCH' if result == expected else f'MISMATCH: got {result}')
|
|
191
|
+
`,
|
|
192
|
+
// SM4
|
|
193
|
+
'SM4': `
|
|
194
|
+
from gmssl import sm4
|
|
195
|
+
|
|
196
|
+
key = ${JSON.stringify(key)}
|
|
197
|
+
plaintext = ${JSON.stringify(plaintext)}
|
|
198
|
+
expected = ${JSON.stringify(ciphertext)}
|
|
199
|
+
|
|
200
|
+
gmsm4 = sm4.CryptSM4()
|
|
201
|
+
gmsm4.set_key(bytes.fromhex(key), sm4.SM4_ENCRYPT)
|
|
202
|
+
encrypted = gmsm4.crypt_ecb(plaintext.encode())
|
|
203
|
+
result = encrypted.hex()
|
|
204
|
+
|
|
205
|
+
print('MATCH' if result == expected else f'MISMATCH: got {result}')
|
|
206
|
+
`,
|
|
207
|
+
// Base64
|
|
208
|
+
'Base64': `
|
|
209
|
+
import base64
|
|
210
|
+
|
|
211
|
+
data = ${JSON.stringify(plaintext)}
|
|
212
|
+
expected = ${JSON.stringify(ciphertext)}
|
|
213
|
+
|
|
214
|
+
result = base64.b64encode(data.encode()).decode()
|
|
215
|
+
print('MATCH' if result == expected else f'MISMATCH: got {result}')
|
|
216
|
+
`,
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
return templates[algorithm] || null;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* 生成可复用的 Python 代码片段
|
|
224
|
+
*/
|
|
225
|
+
function generatePythonSnippet(algorithm, params) {
|
|
226
|
+
const { key, iv, mode, format, hmacKey, digestmod } = params;
|
|
227
|
+
|
|
228
|
+
const snippets = {
|
|
229
|
+
'AES-CBC': `
|
|
230
|
+
import base64
|
|
231
|
+
from Crypto.Cipher import AES
|
|
232
|
+
from Crypto.Util.Padding import pad, unpad
|
|
233
|
+
|
|
234
|
+
def encrypt_aes_cbc(plaintext, key="${key}", iv="${iv || key}"):
|
|
235
|
+
cipher = AES.new(key.encode(), AES.MODE_CBC, iv=iv.encode())
|
|
236
|
+
encrypted = cipher.encrypt(pad(plaintext.encode(), AES.block_size))
|
|
237
|
+
return base64.b64encode(encrypted).decode()
|
|
238
|
+
|
|
239
|
+
def decrypt_aes_cbc(ciphertext, key="${key}", iv="${iv || key}"):
|
|
240
|
+
cipher = AES.new(key.encode(), AES.MODE_CBC, iv=iv.encode())
|
|
241
|
+
decrypted = unpad(cipher.decrypt(base64.b64decode(ciphertext)), AES.block_size)
|
|
242
|
+
return decrypted.decode()
|
|
243
|
+
`,
|
|
244
|
+
'AES-ECB': `
|
|
245
|
+
import base64
|
|
246
|
+
from Crypto.Cipher import AES
|
|
247
|
+
from Crypto.Util.Padding import pad, unpad
|
|
248
|
+
|
|
249
|
+
def encrypt_aes_ecb(plaintext, key="${key}"):
|
|
250
|
+
cipher = AES.new(key.encode(), AES.MODE_ECB)
|
|
251
|
+
encrypted = cipher.encrypt(pad(plaintext.encode(), AES.block_size))
|
|
252
|
+
return base64.b64encode(encrypted).decode()
|
|
253
|
+
|
|
254
|
+
def decrypt_aes_ecb(ciphertext, key="${key}"):
|
|
255
|
+
cipher = AES.new(key.encode(), AES.MODE_ECB)
|
|
256
|
+
decrypted = unpad(cipher.decrypt(base64.b64decode(ciphertext)), AES.block_size)
|
|
257
|
+
return decrypted.decode()
|
|
258
|
+
`,
|
|
259
|
+
'AES-CFB': `
|
|
260
|
+
import base64
|
|
261
|
+
from Crypto.Cipher import AES
|
|
262
|
+
|
|
263
|
+
def encrypt_aes_cfb(plaintext, key="${key}"):
|
|
264
|
+
key_bytes = key.encode()
|
|
265
|
+
cipher = AES.new(key_bytes, AES.MODE_CFB, iv=key_bytes, segment_size=128)
|
|
266
|
+
encrypted = cipher.encrypt(plaintext.encode())
|
|
267
|
+
return base64.b64encode(encrypted).decode()
|
|
268
|
+
|
|
269
|
+
def decrypt_aes_cfb(ciphertext, key="${key}"):
|
|
270
|
+
key_bytes = key.encode()
|
|
271
|
+
cipher = AES.new(key_bytes, AES.MODE_CFB, iv=key_bytes, segment_size=128)
|
|
272
|
+
decrypted = cipher.decrypt(base64.b64decode(ciphertext))
|
|
273
|
+
return decrypted.decode()
|
|
274
|
+
`,
|
|
275
|
+
'DES-CBC': `
|
|
276
|
+
import base64
|
|
277
|
+
from Crypto.Cipher import DES
|
|
278
|
+
from Crypto.Util.Padding import pad, unpad
|
|
279
|
+
|
|
280
|
+
def encrypt_des_cbc(plaintext, key="${key}", iv="${iv || key}"):
|
|
281
|
+
cipher = DES.new(key.encode(), DES.MODE_CBC, iv=iv.encode())
|
|
282
|
+
encrypted = cipher.encrypt(pad(plaintext.encode(), DES.block_size))
|
|
283
|
+
return base64.b64encode(encrypted).decode()
|
|
284
|
+
|
|
285
|
+
def decrypt_des_cbc(ciphertext, key="${key}", iv="${iv || key}"):
|
|
286
|
+
cipher = DES.new(key.encode(), DES.MODE_CBC, iv=iv.encode())
|
|
287
|
+
decrypted = unpad(cipher.decrypt(base64.b64decode(ciphertext)), DES.block_size)
|
|
288
|
+
return decrypted.decode()
|
|
289
|
+
`,
|
|
290
|
+
'DES-ECB': `
|
|
291
|
+
import base64
|
|
292
|
+
from Crypto.Cipher import DES
|
|
293
|
+
from Crypto.Util.Padding import pad, unpad
|
|
294
|
+
|
|
295
|
+
def encrypt_des_ecb(plaintext, key="${key}"):
|
|
296
|
+
cipher = DES.new(key.encode(), DES.MODE_ECB)
|
|
297
|
+
encrypted = cipher.encrypt(pad(plaintext.encode(), DES.block_size))
|
|
298
|
+
return base64.b64encode(encrypted).decode()
|
|
299
|
+
|
|
300
|
+
def decrypt_des_ecb(ciphertext, key="${key}"):
|
|
301
|
+
cipher = DES.new(key.encode(), DES.MODE_ECB)
|
|
302
|
+
decrypted = unpad(cipher.decrypt(base64.b64decode(ciphertext)), DES.block_size)
|
|
303
|
+
return decrypted.decode()
|
|
304
|
+
`,
|
|
305
|
+
'MD5': `
|
|
306
|
+
import hashlib
|
|
307
|
+
|
|
308
|
+
def encrypt_md5(data):
|
|
309
|
+
return hashlib.md5(str(data).encode()).hexdigest()
|
|
310
|
+
`,
|
|
311
|
+
'SHA1': `
|
|
312
|
+
import hashlib
|
|
313
|
+
|
|
314
|
+
def encrypt_sha1(data):
|
|
315
|
+
return hashlib.sha1(str(data).encode()).hexdigest()
|
|
316
|
+
`,
|
|
317
|
+
'SHA256': `
|
|
318
|
+
import hashlib
|
|
319
|
+
|
|
320
|
+
def encrypt_sha256(data):
|
|
321
|
+
return hashlib.sha256(str(data).encode()).hexdigest()
|
|
322
|
+
`,
|
|
323
|
+
'SHA512': `
|
|
324
|
+
import hashlib
|
|
325
|
+
|
|
326
|
+
def encrypt_sha512(data):
|
|
327
|
+
return hashlib.sha512(str(data).encode()).hexdigest()
|
|
328
|
+
`,
|
|
329
|
+
'HMAC': `
|
|
330
|
+
import hmac
|
|
331
|
+
import hashlib
|
|
332
|
+
import base64
|
|
333
|
+
|
|
334
|
+
def encrypt_hmac(data, key="${hmacKey || key}", digestmod="${digestmod || 'md5'}", output_format="hex"):
|
|
335
|
+
hash_func = getattr(hashlib, digestmod)
|
|
336
|
+
hmac_obj = hmac.new(key.encode(), data.encode(), hash_func)
|
|
337
|
+
if output_format == "base64":
|
|
338
|
+
return base64.b64encode(hmac_obj.digest()).decode()
|
|
339
|
+
return hmac_obj.hexdigest()
|
|
340
|
+
`,
|
|
341
|
+
'SM4': `
|
|
342
|
+
from gmssl import sm4
|
|
343
|
+
|
|
344
|
+
def encrypt_sm4(plaintext, key="${key}"):
|
|
345
|
+
gmsm4 = sm4.CryptSM4()
|
|
346
|
+
gmsm4.set_key(bytes.fromhex(key), sm4.SM4_ENCRYPT)
|
|
347
|
+
encrypted = gmsm4.crypt_ecb(plaintext.encode())
|
|
348
|
+
return encrypted.hex()
|
|
349
|
+
|
|
350
|
+
def decrypt_sm4(ciphertext, key="${key}"):
|
|
351
|
+
gmsm4 = sm4.CryptSM4()
|
|
352
|
+
gmsm4.set_key(bytes.fromhex(key), sm4.SM4_DECRYPT)
|
|
353
|
+
decrypted = gmsm4.crypt_ecb(bytes.fromhex(ciphertext))
|
|
354
|
+
return decrypted.decode()
|
|
355
|
+
`,
|
|
356
|
+
'Base64': `
|
|
357
|
+
import base64
|
|
358
|
+
|
|
359
|
+
def encrypt_base64(data):
|
|
360
|
+
return base64.b64encode(str(data).encode()).decode()
|
|
361
|
+
|
|
362
|
+
def decrypt_base64(data):
|
|
363
|
+
return base64.b64decode(data).decode()
|
|
364
|
+
`,
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
return snippets[algorithm] || null;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* 验证加密算法
|
|
372
|
+
*/
|
|
373
|
+
export const verifyWithPython = tool(
|
|
374
|
+
async ({ algorithm, plaintext, ciphertext, key, iv, format, hmacKey, digestmod }) => {
|
|
375
|
+
const params = { plaintext, ciphertext, key, iv, format: format || 'base64', hmacKey, digestmod };
|
|
376
|
+
|
|
377
|
+
// 生成验证代码
|
|
378
|
+
const verifyCode = generateVerifyCode(algorithm, params);
|
|
379
|
+
if (!verifyCode) {
|
|
380
|
+
return JSON.stringify({
|
|
381
|
+
success: false,
|
|
382
|
+
error: `不支持的算法: ${algorithm}`,
|
|
383
|
+
supportedAlgorithms: [
|
|
384
|
+
'AES-CBC', 'AES-ECB', 'AES-CFB',
|
|
385
|
+
'DES-CBC', 'DES-ECB',
|
|
386
|
+
'MD5', 'SHA1', 'SHA256', 'SHA512',
|
|
387
|
+
'HMAC', 'SM4', 'Base64'
|
|
388
|
+
],
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// 执行验证
|
|
393
|
+
const result = await executePython(verifyCode);
|
|
394
|
+
|
|
395
|
+
if (!result.success) {
|
|
396
|
+
return JSON.stringify({
|
|
397
|
+
success: false,
|
|
398
|
+
error: result.stderr || '执行失败',
|
|
399
|
+
verifyCode,
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const isMatch = result.stdout.startsWith('MATCH');
|
|
404
|
+
|
|
405
|
+
// 生成可复用代码
|
|
406
|
+
const pythonSnippet = isMatch ? generatePythonSnippet(algorithm, params) : null;
|
|
407
|
+
|
|
408
|
+
return JSON.stringify({
|
|
409
|
+
success: isMatch,
|
|
410
|
+
message: result.stdout,
|
|
411
|
+
algorithm,
|
|
412
|
+
params: { key, iv, format },
|
|
413
|
+
pythonCode: pythonSnippet,
|
|
414
|
+
});
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
name: 'verify_crypto_python',
|
|
418
|
+
description: '验证标准加密算法的 Python 实现是否正确,验证成功后返回可复用的 Python 代码',
|
|
419
|
+
schema: z.object({
|
|
420
|
+
algorithm: z.string().describe('加密算法: AES-CBC, AES-ECB, AES-CFB, DES-CBC, DES-ECB, MD5, SHA1, SHA256, SHA512, HMAC, SM4, Base64'),
|
|
421
|
+
plaintext: z.string().describe('明文数据'),
|
|
422
|
+
ciphertext: z.string().describe('密文数据(用于验证)'),
|
|
423
|
+
key: z.string().optional().describe('加密密钥'),
|
|
424
|
+
iv: z.string().optional().describe('初始化向量(CBC模式需要)'),
|
|
425
|
+
format: z.string().optional().default('base64').describe('输出格式: base64 或 hex'),
|
|
426
|
+
hmacKey: z.string().optional().describe('HMAC 密钥'),
|
|
427
|
+
digestmod: z.string().optional().describe('HMAC 摘要算法: md5, sha1, sha256, sha512'),
|
|
428
|
+
}),
|
|
429
|
+
}
|
|
430
|
+
);
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* 直接生成 Python 加密代码
|
|
434
|
+
*/
|
|
435
|
+
export const generatePythonCrypto = tool(
|
|
436
|
+
async ({ algorithm, key, iv, format, hmacKey, digestmod }) => {
|
|
437
|
+
const params = { key, iv, format: format || 'base64', hmacKey, digestmod };
|
|
438
|
+
const snippet = generatePythonSnippet(algorithm, params);
|
|
439
|
+
|
|
440
|
+
if (!snippet) {
|
|
441
|
+
return JSON.stringify({
|
|
442
|
+
success: false,
|
|
443
|
+
error: `不支持的算法: ${algorithm}`,
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
return JSON.stringify({
|
|
448
|
+
success: true,
|
|
449
|
+
algorithm,
|
|
450
|
+
pythonCode: snippet.trim(),
|
|
451
|
+
});
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
name: 'generate_crypto_python_code',
|
|
455
|
+
description: '根据算法和参数生成 Python 加密/解密函数代码',
|
|
456
|
+
schema: z.object({
|
|
457
|
+
algorithm: z.string().describe('加密算法'),
|
|
458
|
+
key: z.string().optional().describe('加密密钥'),
|
|
459
|
+
iv: z.string().optional().describe('初始化向量'),
|
|
460
|
+
format: z.string().optional().default('base64').describe('输出格式'),
|
|
461
|
+
hmacKey: z.string().optional().describe('HMAC 密钥'),
|
|
462
|
+
digestmod: z.string().optional().describe('HMAC 摘要算法'),
|
|
463
|
+
}),
|
|
464
|
+
}
|
|
465
|
+
);
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* 执行 Python 加密验证代码
|
|
469
|
+
*/
|
|
470
|
+
export const executePythonCode = tool(
|
|
471
|
+
async ({ code, timeout }) => {
|
|
472
|
+
const result = await executePython(code, timeout || 10000);
|
|
473
|
+
return JSON.stringify(result);
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
name: 'run_python_crypto_test',
|
|
477
|
+
description: '运行 Python 加密/解密测试代码。仅用于验证标准加密算法(AES、DES、SM4、MD5、SHA等)的 Python 实现是否正确。不要用于执行 JS 代码或调用 subprocess。',
|
|
478
|
+
schema: z.object({
|
|
479
|
+
code: z.string().describe('纯 Python 加密验证代码,不要包含 subprocess 或调用外部程序'),
|
|
480
|
+
timeout: z.number().optional().default(10000).describe('超时时间(毫秒)'),
|
|
481
|
+
}),
|
|
482
|
+
}
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* 生成使用 execjs 执行 JS 代码的 Python 代码
|
|
487
|
+
*/
|
|
488
|
+
export const generateExecjsCode = tool(
|
|
489
|
+
async ({ jsCode, functionName, description }) => {
|
|
490
|
+
// 转义 JS 代码中的特殊字符
|
|
491
|
+
const escapedJs = jsCode
|
|
492
|
+
.replace(/\\/g, '\\\\')
|
|
493
|
+
.replace(/"""/g, '\\"\\"\\"')
|
|
494
|
+
.replace(/\n/g, '\\n');
|
|
495
|
+
|
|
496
|
+
const pythonCode = `
|
|
497
|
+
import execjs
|
|
498
|
+
|
|
499
|
+
# ${description || 'JS 代码执行'}
|
|
500
|
+
JS_CODE = """
|
|
501
|
+
${jsCode}
|
|
502
|
+
"""
|
|
503
|
+
|
|
504
|
+
# 编译 JS 代码
|
|
505
|
+
ctx = execjs.compile(JS_CODE)
|
|
506
|
+
|
|
507
|
+
def ${functionName || 'execute_js'}(*args):
|
|
508
|
+
"""
|
|
509
|
+
执行 JS 函数
|
|
510
|
+
Args: 根据 JS 函数参数传入
|
|
511
|
+
Returns: JS 函数返回值
|
|
512
|
+
"""
|
|
513
|
+
return ctx.call('${functionName || 'main'}', *args)
|
|
514
|
+
|
|
515
|
+
# 使用示例
|
|
516
|
+
# result = ${functionName || 'execute_js'}(param1, param2)
|
|
517
|
+
# print(result)
|
|
518
|
+
`.trim();
|
|
519
|
+
|
|
520
|
+
return JSON.stringify({
|
|
521
|
+
success: true,
|
|
522
|
+
pythonCode,
|
|
523
|
+
usage: `调用方式: ${functionName || 'execute_js'}(参数...)`,
|
|
524
|
+
dependencies: ['PyExecJS'],
|
|
525
|
+
});
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
name: 'generate_execjs_python',
|
|
529
|
+
description: '生成使用 execjs 库执行 JS 代码的 Python 代码。适用于复杂的、难以用纯 Python 重写的 JS 逻辑',
|
|
530
|
+
schema: z.object({
|
|
531
|
+
jsCode: z.string().describe('要执行的 JS 代码'),
|
|
532
|
+
functionName: z.string().describe('JS 中要调用的函数名'),
|
|
533
|
+
description: z.string().optional().describe('代码功能描述'),
|
|
534
|
+
}),
|
|
535
|
+
}
|
|
536
|
+
);
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* 分析 JS 代码,判断转换策略
|
|
540
|
+
*/
|
|
541
|
+
export const analyzeJsForPython = tool(
|
|
542
|
+
async ({ jsCode, cryptoPatterns }) => {
|
|
543
|
+
const analysis = {
|
|
544
|
+
canPureRewrite: true,
|
|
545
|
+
reasons: [],
|
|
546
|
+
detectedPatterns: [],
|
|
547
|
+
recommendation: '',
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
// 检测标准加密库
|
|
551
|
+
const standardCrypto = [
|
|
552
|
+
{ pattern: /CryptoJS\.AES/i, name: 'AES', rewritable: true },
|
|
553
|
+
{ pattern: /CryptoJS\.DES/i, name: 'DES', rewritable: true },
|
|
554
|
+
{ pattern: /CryptoJS\.MD5/i, name: 'MD5', rewritable: true },
|
|
555
|
+
{ pattern: /CryptoJS\.SHA(1|256|512)/i, name: 'SHA', rewritable: true },
|
|
556
|
+
{ pattern: /CryptoJS\.HmacMD5|CryptoJS\.HmacSHA/i, name: 'HMAC', rewritable: true },
|
|
557
|
+
{ pattern: /JSEncrypt|RSA/i, name: 'RSA', rewritable: true },
|
|
558
|
+
{ pattern: /sm2|sm3|sm4/i, name: 'SM国密', rewritable: true },
|
|
559
|
+
];
|
|
560
|
+
|
|
561
|
+
// 检测复杂模式(难以纯 Python 重写)
|
|
562
|
+
const complexPatterns = [
|
|
563
|
+
{ pattern: /eval\s*\(/i, name: 'eval动态执行', rewritable: false },
|
|
564
|
+
{ pattern: /Function\s*\(/i, name: 'Function构造', rewritable: false },
|
|
565
|
+
{ pattern: /\[\s*['"][a-z]+['"]\s*\]\s*\(/i, name: '动态方法调用', rewritable: false },
|
|
566
|
+
{ pattern: /window\[|document\[/i, name: 'DOM操作', rewritable: false },
|
|
567
|
+
{ pattern: /navigator|screen|canvas/i, name: '浏览器环境', rewritable: false },
|
|
568
|
+
{ pattern: /setInterval|setTimeout.*function/i, name: '异步定时器', rewritable: false },
|
|
569
|
+
{ pattern: /prototype\s*\.\s*\w+\s*=/i, name: '原型链修改', rewritable: false },
|
|
570
|
+
{ pattern: /\$_\w{2,}|\b_0x[a-f0-9]+/i, name: '混淆代码', rewritable: false },
|
|
571
|
+
];
|
|
572
|
+
|
|
573
|
+
// 检测标准加密
|
|
574
|
+
for (const crypto of standardCrypto) {
|
|
575
|
+
if (crypto.pattern.test(jsCode)) {
|
|
576
|
+
analysis.detectedPatterns.push({
|
|
577
|
+
type: 'crypto',
|
|
578
|
+
name: crypto.name,
|
|
579
|
+
rewritable: crypto.rewritable,
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// 检测复杂模式
|
|
585
|
+
for (const complex of complexPatterns) {
|
|
586
|
+
if (complex.pattern.test(jsCode)) {
|
|
587
|
+
analysis.detectedPatterns.push({
|
|
588
|
+
type: 'complex',
|
|
589
|
+
name: complex.name,
|
|
590
|
+
rewritable: complex.rewritable,
|
|
591
|
+
});
|
|
592
|
+
analysis.canPureRewrite = false;
|
|
593
|
+
analysis.reasons.push(complex.name);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// 生成建议
|
|
598
|
+
if (analysis.canPureRewrite && analysis.detectedPatterns.some(p => p.type === 'crypto')) {
|
|
599
|
+
analysis.recommendation = 'PURE_PYTHON';
|
|
600
|
+
analysis.message = '检测到标准加密算法,建议使用纯 Python 重写';
|
|
601
|
+
} else if (!analysis.canPureRewrite) {
|
|
602
|
+
analysis.recommendation = 'EXECJS';
|
|
603
|
+
analysis.message = `检测到复杂模式 (${analysis.reasons.join(', ')}),建议使用 execjs 执行原始 JS`;
|
|
604
|
+
} else {
|
|
605
|
+
analysis.recommendation = 'PURE_PYTHON';
|
|
606
|
+
analysis.message = '代码相对简单,建议尝试纯 Python 重写';
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
return JSON.stringify(analysis);
|
|
610
|
+
},
|
|
611
|
+
{
|
|
612
|
+
name: 'analyze_js_for_python',
|
|
613
|
+
description: '分析 JS 代码,判断应该用纯 Python 重写还是使用 execjs 执行',
|
|
614
|
+
schema: z.object({
|
|
615
|
+
jsCode: z.string().describe('要分析的 JS 代码'),
|
|
616
|
+
cryptoPatterns: z.array(z.string()).optional().describe('已知的加密模式'),
|
|
617
|
+
}),
|
|
618
|
+
}
|
|
619
|
+
);
|
|
620
|
+
|
|
621
|
+
export const pythonTools = [
|
|
622
|
+
verifyWithPython,
|
|
623
|
+
generatePythonCrypto,
|
|
624
|
+
executePythonCode,
|
|
625
|
+
generateExecjsCode,
|
|
626
|
+
analyzeJsForPython,
|
|
627
|
+
];
|