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.
Files changed (261) hide show
  1. package/.claude/agents/check.md +122 -0
  2. package/.claude/agents/debug.md +106 -0
  3. package/.claude/agents/dispatch.md +214 -0
  4. package/.claude/agents/implement.md +96 -0
  5. package/.claude/agents/plan.md +396 -0
  6. package/.claude/agents/research.md +120 -0
  7. package/.claude/commands/evolve/merge.md +80 -0
  8. package/.claude/commands/trellis/before-backend-dev.md +13 -0
  9. package/.claude/commands/trellis/before-frontend-dev.md +13 -0
  10. package/.claude/commands/trellis/break-loop.md +107 -0
  11. package/.claude/commands/trellis/check-backend.md +13 -0
  12. package/.claude/commands/trellis/check-cross-layer.md +153 -0
  13. package/.claude/commands/trellis/check-frontend.md +13 -0
  14. package/.claude/commands/trellis/create-command.md +154 -0
  15. package/.claude/commands/trellis/finish-work.md +129 -0
  16. package/.claude/commands/trellis/integrate-skill.md +219 -0
  17. package/.claude/commands/trellis/onboard.md +358 -0
  18. package/.claude/commands/trellis/parallel.md +193 -0
  19. package/.claude/commands/trellis/record-session.md +62 -0
  20. package/.claude/commands/trellis/start.md +280 -0
  21. package/.claude/commands/trellis/update-spec.md +213 -0
  22. package/.claude/hooks/inject-subagent-context.py +758 -0
  23. package/.claude/hooks/ralph-loop.py +374 -0
  24. package/.claude/hooks/session-start.py +126 -0
  25. package/.claude/settings.json +41 -0
  26. package/.claude/skills/deepagents-guide/SKILL.md +428 -0
  27. package/.cursor/commands/trellis-before-backend-dev.md +13 -0
  28. package/.cursor/commands/trellis-before-frontend-dev.md +13 -0
  29. package/.cursor/commands/trellis-break-loop.md +107 -0
  30. package/.cursor/commands/trellis-check-backend.md +13 -0
  31. package/.cursor/commands/trellis-check-cross-layer.md +153 -0
  32. package/.cursor/commands/trellis-check-frontend.md +13 -0
  33. package/.cursor/commands/trellis-create-command.md +154 -0
  34. package/.cursor/commands/trellis-finish-work.md +129 -0
  35. package/.cursor/commands/trellis-integrate-skill.md +219 -0
  36. package/.cursor/commands/trellis-onboard.md +358 -0
  37. package/.cursor/commands/trellis-record-session.md +62 -0
  38. package/.cursor/commands/trellis-start.md +156 -0
  39. package/.cursor/commands/trellis-update-spec.md +213 -0
  40. package/.env.example +11 -0
  41. package/.husky/pre-commit +1 -0
  42. package/.mcp.json +8 -0
  43. package/.trellis/.template-hashes.json +65 -0
  44. package/.trellis/.version +1 -0
  45. package/.trellis/scripts/add-session.sh +384 -0
  46. package/.trellis/scripts/common/developer.sh +129 -0
  47. package/.trellis/scripts/common/git-context.sh +263 -0
  48. package/.trellis/scripts/common/paths.sh +208 -0
  49. package/.trellis/scripts/common/phase.sh +150 -0
  50. package/.trellis/scripts/common/registry.sh +247 -0
  51. package/.trellis/scripts/common/task-queue.sh +142 -0
  52. package/.trellis/scripts/common/task-utils.sh +151 -0
  53. package/.trellis/scripts/common/worktree.sh +128 -0
  54. package/.trellis/scripts/create-bootstrap.sh +299 -0
  55. package/.trellis/scripts/get-context.sh +7 -0
  56. package/.trellis/scripts/get-developer.sh +15 -0
  57. package/.trellis/scripts/init-developer.sh +34 -0
  58. package/.trellis/scripts/multi-agent/cleanup.sh +396 -0
  59. package/.trellis/scripts/multi-agent/create-pr.sh +241 -0
  60. package/.trellis/scripts/multi-agent/plan.sh +207 -0
  61. package/.trellis/scripts/multi-agent/start.sh +310 -0
  62. package/.trellis/scripts/multi-agent/status.sh +828 -0
  63. package/.trellis/scripts/task.sh +1118 -0
  64. package/.trellis/spec/backend/deepagents-guide.md +337 -0
  65. package/.trellis/spec/backend/directory-structure.md +126 -0
  66. package/.trellis/spec/backend/examples/skills/deepagents-guide/README.md +11 -0
  67. package/.trellis/spec/backend/examples/skills/deepagents-guide/agent.js.template +20 -0
  68. package/.trellis/spec/backend/examples/skills/deepagents-guide/skills-config.js.template +13 -0
  69. package/.trellis/spec/backend/examples/skills/deepagents-guide/subagent.js.template +19 -0
  70. package/.trellis/spec/backend/hook-guidelines.md +178 -0
  71. package/.trellis/spec/backend/index.md +36 -0
  72. package/.trellis/spec/backend/quality-guidelines.md +201 -0
  73. package/.trellis/spec/backend/state-management.md +76 -0
  74. package/.trellis/spec/backend/tool-guidelines.md +144 -0
  75. package/.trellis/spec/backend/type-safety.md +71 -0
  76. package/.trellis/spec/guides/code-reuse-thinking-guide.md +92 -0
  77. package/.trellis/spec/guides/cross-layer-thinking-guide.md +94 -0
  78. package/.trellis/spec/guides/index.md +79 -0
  79. package/.trellis/tasks/archive/02-02-evolving-skills/prd.md +61 -0
  80. package/.trellis/tasks/archive/02-02-evolving-skills/task.json +29 -0
  81. package/.trellis/tasks/archive/2026-02/00-bootstrap-guidelines/prd.md +86 -0
  82. package/.trellis/tasks/archive/2026-02/00-bootstrap-guidelines/task.json +27 -0
  83. package/.trellis/tasks/archive/2026-02/02-02-skills-system/check.jsonl +3 -0
  84. package/.trellis/tasks/archive/2026-02/02-02-skills-system/debug.jsonl +2 -0
  85. package/.trellis/tasks/archive/2026-02/02-02-skills-system/implement.jsonl +5 -0
  86. package/.trellis/tasks/archive/2026-02/02-02-skills-system/prd.md +33 -0
  87. package/.trellis/tasks/archive/2026-02/02-02-skills-system/task.json +41 -0
  88. package/.trellis/workflow.md +407 -0
  89. package/.trellis/workspace/index.md +123 -0
  90. package/.trellis/workspace/pony/index.md +40 -0
  91. package/.trellis/workspace/pony/journal-1.md +7 -0
  92. package/.trellis/worktree.yaml +47 -0
  93. package/AGENTS.md +18 -0
  94. package/CLAUDE.md +292 -0
  95. package/README.md +134 -0
  96. package/agents/deepspider.md +142 -0
  97. package/docs/DEBUG.md +42 -0
  98. package/docs/GUIDE.md +334 -0
  99. package/docs/PROMPT.md +60 -0
  100. package/docs/USAGE.md +226 -0
  101. package/eslint.config.js +51 -0
  102. package/package.json +78 -0
  103. package/requirements-crypto.txt +14 -0
  104. package/src/agent/index.js +97 -0
  105. package/src/agent/logger.js +164 -0
  106. package/src/agent/middleware/filterTools.js +64 -0
  107. package/src/agent/middleware/report.js +79 -0
  108. package/src/agent/prompts/system.js +315 -0
  109. package/src/agent/run.js +575 -0
  110. package/src/agent/skills/anti-detect/SKILL.md +28 -0
  111. package/src/agent/skills/anti-detect/evolved.md +12 -0
  112. package/src/agent/skills/captcha/SKILL.md +37 -0
  113. package/src/agent/skills/captcha/evolved.md +12 -0
  114. package/src/agent/skills/config.js +30 -0
  115. package/src/agent/skills/crawler/SKILL.md +9 -0
  116. package/src/agent/skills/crawler/evolved.md +16 -0
  117. package/src/agent/skills/dynamic-analysis/SKILL.md +91 -0
  118. package/src/agent/skills/dynamic-analysis/evolved.md +12 -0
  119. package/src/agent/skills/env/SKILL.md +72 -0
  120. package/src/agent/skills/env/evolved.md +12 -0
  121. package/src/agent/skills/evolve.js +79 -0
  122. package/src/agent/skills/general/SKILL.md +12 -0
  123. package/src/agent/skills/general/evolved.md +12 -0
  124. package/src/agent/skills/js2python/SKILL.md +30 -0
  125. package/src/agent/skills/js2python/evolved.md +13 -0
  126. package/src/agent/skills/report/SKILL.md +21 -0
  127. package/src/agent/skills/report/evolved.md +12 -0
  128. package/src/agent/skills/sandbox/SKILL.md +22 -0
  129. package/src/agent/skills/sandbox/evolved.md +16 -0
  130. package/src/agent/skills/static-analysis/SKILL.md +93 -0
  131. package/src/agent/skills/static-analysis/evolved.md +12 -0
  132. package/src/agent/skills/xpath/SKILL.md +119 -0
  133. package/src/agent/subagents/anti-detect.js +45 -0
  134. package/src/agent/subagents/captcha.js +51 -0
  135. package/src/agent/subagents/crawler.js +138 -0
  136. package/src/agent/subagents/dynamic.js +64 -0
  137. package/src/agent/subagents/env-agent.js +82 -0
  138. package/src/agent/subagents/index.js +37 -0
  139. package/src/agent/subagents/js2python.js +72 -0
  140. package/src/agent/subagents/sandbox.js +55 -0
  141. package/src/agent/subagents/static.js +66 -0
  142. package/src/agent/tools/analysis.js +135 -0
  143. package/src/agent/tools/analyzer.js +85 -0
  144. package/src/agent/tools/anti-detect.js +89 -0
  145. package/src/agent/tools/antidebug.js +64 -0
  146. package/src/agent/tools/async.js +43 -0
  147. package/src/agent/tools/browser.js +324 -0
  148. package/src/agent/tools/captcha.js +223 -0
  149. package/src/agent/tools/capture.js +179 -0
  150. package/src/agent/tools/correlate.js +303 -0
  151. package/src/agent/tools/crawler.js +116 -0
  152. package/src/agent/tools/cryptohook.js +80 -0
  153. package/src/agent/tools/debug.js +246 -0
  154. package/src/agent/tools/deobfuscator.js +90 -0
  155. package/src/agent/tools/env.js +83 -0
  156. package/src/agent/tools/envdump.js +92 -0
  157. package/src/agent/tools/evolve.js +164 -0
  158. package/src/agent/tools/extract.js +114 -0
  159. package/src/agent/tools/extractor.js +54 -0
  160. package/src/agent/tools/file.js +224 -0
  161. package/src/agent/tools/hook.js +84 -0
  162. package/src/agent/tools/hookManager.js +178 -0
  163. package/src/agent/tools/index.js +137 -0
  164. package/src/agent/tools/nodejs.js +101 -0
  165. package/src/agent/tools/patch.js +46 -0
  166. package/src/agent/tools/preprocess.js +71 -0
  167. package/src/agent/tools/profile.js +122 -0
  168. package/src/agent/tools/python.js +627 -0
  169. package/src/agent/tools/report.js +124 -0
  170. package/src/agent/tools/runtime.js +132 -0
  171. package/src/agent/tools/sandbox.js +79 -0
  172. package/src/agent/tools/store.js +73 -0
  173. package/src/agent/tools/trace.js +74 -0
  174. package/src/agent/tools/tracing.js +201 -0
  175. package/src/agent/tools/utils.js +51 -0
  176. package/src/agent/tools/verify.js +184 -0
  177. package/src/agent/tools/webcrack.js +109 -0
  178. package/src/analyzer/ASTAnalyzer.js +387 -0
  179. package/src/analyzer/CallStackAnalyzer.js +379 -0
  180. package/src/analyzer/Deobfuscator.js +289 -0
  181. package/src/analyzer/EncryptionAnalyzer.js +99 -0
  182. package/src/analyzer/index.js +22 -0
  183. package/src/browser/EnvBridge.js +186 -0
  184. package/src/browser/cdp.js +168 -0
  185. package/src/browser/client.js +197 -0
  186. package/src/browser/collector.js +444 -0
  187. package/src/browser/collectors/RequestCryptoLinker.js +109 -0
  188. package/src/browser/collectors/ResponseSearcher.js +107 -0
  189. package/src/browser/collectors/ScriptCollector.js +158 -0
  190. package/src/browser/collectors/index.js +26 -0
  191. package/src/browser/defaultHooks.js +932 -0
  192. package/src/browser/hooks/crypto.js +55 -0
  193. package/src/browser/hooks/index.js +64 -0
  194. package/src/browser/hooks/native.js +9 -0
  195. package/src/browser/hooks/network.js +33 -0
  196. package/src/browser/index.js +42 -0
  197. package/src/browser/interceptors/NetworkInterceptor.js +116 -0
  198. package/src/browser/interceptors/ScriptInterceptor.js +76 -0
  199. package/src/browser/interceptors/index.js +6 -0
  200. package/src/browser/ui/analysisPanel.js +1782 -0
  201. package/src/browser/ui/confirmDialog.js +158 -0
  202. package/src/browser/ui/panel.html +152 -0
  203. package/src/browser/ui/selector.js +170 -0
  204. package/src/config/index.js +5 -0
  205. package/src/config/paths.js +71 -0
  206. package/src/config/patterns/crypto.js +36 -0
  207. package/src/config/profiles/chrome.json +71 -0
  208. package/src/config/profiles/firefox.json +44 -0
  209. package/src/config/profiles/safari.json +38 -0
  210. package/src/core/EnvMonitor.js +200 -0
  211. package/src/core/PatchGenerator.js +278 -0
  212. package/src/core/Sandbox.js +181 -0
  213. package/src/env/AntiAntiDebug.js +111 -0
  214. package/src/env/AsyncHook.js +68 -0
  215. package/src/env/BrowserAPIList.js +265 -0
  216. package/src/env/CookieHook.js +48 -0
  217. package/src/env/CryptoHook.js +205 -0
  218. package/src/env/EnvCodeGenerator.js +157 -0
  219. package/src/env/EnvDumper.js +356 -0
  220. package/src/env/EnvExtractor.js +220 -0
  221. package/src/env/HookBase.js +618 -0
  222. package/src/env/NetworkHook.js +159 -0
  223. package/src/env/modules/bom/history.js +29 -0
  224. package/src/env/modules/bom/location.js +26 -0
  225. package/src/env/modules/bom/navigator.js +70 -0
  226. package/src/env/modules/bom/screen.js +26 -0
  227. package/src/env/modules/bom/storage.js +23 -0
  228. package/src/env/modules/dom/document.js +110 -0
  229. package/src/env/modules/dom/event.js +51 -0
  230. package/src/env/modules/index.js +34 -0
  231. package/src/env/modules/webapi/fetch.js +46 -0
  232. package/src/env/modules/webapi/url.js +47 -0
  233. package/src/env/modules/webapi/xhr.js +48 -0
  234. package/src/index.js +27 -0
  235. package/src/mcp/server.js +89 -0
  236. package/src/store/DataStore.js +708 -0
  237. package/src/store/Store.js +158 -0
  238. package/src/store/Validator.js +24 -0
  239. package/test/analyze.test.js +90 -0
  240. package/test/envdump.test.js +74 -0
  241. package/test/flow.test.js +90 -0
  242. package/test/hooks.test.js +138 -0
  243. package/test/plugin.test.js +35 -0
  244. package/test/refactor-full.test.js +30 -0
  245. package/test/refactor.test.js +21 -0
  246. package/test/samples/obfuscated.js +61 -0
  247. package/test/samples/original.js +66 -0
  248. package/test/samples/v10_eval_chain.js +52 -0
  249. package/test/samples/v11_bytecode_vm.js +81 -0
  250. package/test/samples/v12_polymorphic.js +69 -0
  251. package/test/samples/v1_ob_basic.js +98 -0
  252. package/test/samples/v2_ob_advanced.js +99 -0
  253. package/test/samples/v3_jjencode.js +77 -0
  254. package/test/samples/v4_aaencode.js +73 -0
  255. package/test/samples/v5_control_flow.js +86 -0
  256. package/test/samples/v6_string_encryption.js +71 -0
  257. package/test/samples/v7_jsvmp.js +83 -0
  258. package/test/samples/v8_anti_debug.js +79 -0
  259. package/test/samples/v9_proxy_trap.js +49 -0
  260. package/test/samples.test.js +96 -0
  261. 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
+ ];