news 2026/9/29 2:48:13

Cap 服务端工作量证明求解器:在 Bun 上使用 `@cap.js/solver` 完成 M2M 质询

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Cap 服务端工作量证明求解器:在 Bun 上使用 `@cap.js/solver` 完成 M2M 质询
  • 网络安全
  • 应用安全
  • 后端

【免费下载链接】cap

Free, open-source and self-hosted CAPTCHA alternative to reCAPTCHA. Privacy-first and powered by proof-of-work and instrumentation challenges.

项目地址:https://gitcode.com/gh_mirrors/cap13/cap
点击查看免费下载

@cap.js/solver是 Cap 开源 CAPTCHA 项目提供的一个独立服务端库,用于在机器对机器(M2M)场景下直接求解 Cap 的工作量证明质询,而无需经过浏览器验证组件。它零依赖、单文件、体积小巧,求解速度与验证组件相当,但只能在 Bun 运行时下使用。读完本文,你将掌握该库的安装方式、两种质询输入形式(基于种子与基于质询列表)、全部可选参数(workerCount、onProgress、c/s/d)的语义,并从源码层面理解其求解与验证背后的 SHA-256 工作量证明原理。

什么是@cap.js/solver:M2M 场景的定位

在 Cap 的常规流程中,工作量证明质询由浏览器里的验证组件负责求解:服务端签发质询,客户端用 WASM 和 Web Worker 并行计算解,再把解回传兑换令牌(详见 Cap 是如何工作的?)。

@cap.js/solver把"求解"这一步搬到服务端执行,服务于**机器对机器(M2M)**场景——例如你的后端服务需要自己先通过一次 Cap 质询,才能继续调用受 CAPTCHA 保护的下游接口。与浏览器求解不同,它没有 WASM 编译、Web Worker 调度、shadow DOM 等浏览器上下文依赖,因此实现极度精简:零依赖、单文件,但求解吞吐与验证组件一样高效。

需要明确的是:这个包不会绕过任何实际的工作量证明。它按照与浏览器验证组件相同的算法老老实实计算 nonce,所以服务端同样要付出对应的计算成本;同时它不支持 instrumentation 质询(instrumentation 是浏览器环境检测类质询,需要真实浏览器环境才能通过,服务端无法模拟),详见下文"边界与限制"。

安装

该库只在 Bun 生态中分发,使用 Bun 的包管理器安装即可:

bun add @cap.js/solver

安装后通过默认导出引入:

import solver from "@cap.js/solver";

@cap.js/solver与服务端签发/验证库是解耦的。如果你需要在自己后端签发质询,可配合 Cap 的无状态服务端库capjs-core(文档)或开箱即用的 Cap Standalone 使用。

用法一:基于种子的质询(seeded challenges)

最常用的形式是传入种子令牌(challenge token)与配置对象,让求解器按种子生成并求解一组质询:

import solver from "@cap.js/solver"; console.log( await solver("challenge token", { c: 50, // 质询数量 s: 32, // 盐的长度(十六进制字符数) d: 4, // 难度(目标前缀长度) }), );

配置对象中的三个参数与验证组件/服务端库的生成参数一一对应:

  • c(challenge count):要生成的质询数量。服务端默认签发50个质询,因此通常传50。
  • s(salt size):每个质询的盐长度,单位是十六进制字符数,默认32。盐是工作量证明输入的一部分,由种子确定性派生。
  • d(difficulty):难度,即哈希结果需要匹配的目标前缀长度(十六进制字符数),默认4。d越大,找到有效 nonce 的期望哈希次数越多。

这三个参数与capjs-core中generateChallenge的challengeCount、challengeSize、challengeDifficulty默认值(50、32、4)完全对齐(见 core/src/index.js 的参数校验逻辑)。

用法二:基于质询列表(challenge list)

第二种形式是直接传入质询列表,列表中每个元素是[盐, 目标前缀]二元组。这种形式通常用于:你已经从服务端拿到了具体的质询对,只想针对它们逐一求解:

import solver from "@cap.js/solver"; const challenges = [ ["a5b6fda4aaed97cf61d7dd9259f733b5", "d455"], ["286bcc39249f9ee698314b600c32e40f", "f0ff"], ["501350aa7c46573cb604284554045703", "4971"], ["a55c02f3b9b4cd088a5a7ee3d4941c14", "eab7"], ["5f3362c12e2779f56f4ef75b4494f5e6", "999f"], /* ... */ ]; console.log(await solver(challenges));

列表形式下求解器不再自行生成质询,而是对每个[salt, target]对直接暴力搜索有效 nonce,因此不需要(也不接受)c/s/d这三个种子派生参数。

输出示例:

[67302, 64511, 40440, 27959, 71259 /* ... */]

输出的每个数字对应一个质询的有效 nonce,顺序与输入质询列表(或种子派生出的质询)一一对应。拿到这些 nonce 后,即可按验证组件同样的格式把它们作为solutions提交给服务端兑换令牌。

第二个参数:通用选项与种子专属选项

第二个参数可选,但任何时候都可以传入,且始终是一个对象。它包含两类选项:

所有质询类型通用

  • workerCount:指定使用的 worker 数量,默认值为 CPU 核心数。这与浏览器验证组件的并行策略一致——验证组件把质询分发给多个 Web Worker 并行计算(见 widget/src/src/worker.js 中 worker 按workerIndex/workerCount分块递增 nonce 的逻辑)。在服务端,workerCount决定了求解器并行搜索的通道数;调大可降低单次求解延迟,但会占用更多 CPU 资源。
  • onProgress:进度更新回调。当求解器在处理大量质询时,可通过该回调获取当前进度,用于日志记录、进度条展示或任务管理。

仅基于种子的质询专属

  • c:要生成的解(质询)数量;
  • s:质询大小(盐长度);
  • d:难度。

也就是说,{ c, s, d }只对字符串种子形式的调用有效;传入质询列表时这些键会被忽略。

底层原理:求解器在算什么

要正确使用求解器,有必要理解它计算的对象。Cap 的 SHA-256 工作量证明遵循如下流程(详见 Cap 是如何工作的?):

  1. 服务端基于种子令牌与质询索引确定性派生每个质询的盐(salt)与目标前缀(target);
  2. 客户端将盐与递增的nonce拼接,计算 SHA-256 哈希;
  3. 检查哈希是否以目标前缀开头;若不是,nonce 递增后重试。

在浏览器端,这一循环由 Rust 编写的 WASM 与 Web Worker 并行执行(见 widget/src/src/worker.js 中的solveFallback与 WASMsolve_pow分支);@cap.js/solver在服务端执行的是同样的算法——所以它绝不绕过工作量证明,只是把计算位置从浏览器挪到了 Bun 进程里。

服务端验证侧的对应逻辑可在capjs-core源码中印证(core/src/index.js):

const salt = prngFromHash(saltSeed, size); const target = prngFromHash(targetSeed, difficulty); const hash = sha256Bytes(salt + solutions[i]); if (!powMatchesPrefix(hash, parseHexPrefix(target))) { return fail("invalid_solution"); }

验证方会用同样的种子派生方式重建每个质询的盐和目标,再对提交的 nonce 重算一次 SHA-256 并与前缀比对。这也解释了为什么基于列表形式要求[盐, 目标]与种子派生结果完全一致:服务端校验的是"提交的 nonce 是否满足该盐/目标对应的哈希前缀条件",而非 nonce 的来源。

边界与限制

  • 仅支持 Bun:库依赖 Bun 运行时特性,不能直接在 Node.js 或浏览器中运行。
  • 不支持 instrumentation 质询:instrumentation 质询是需要在真实浏览器沙箱中执行并回报指纹的检测型质询(配置方式见 capjs-core 的 instrumentation 选项 与 Standalone 选项)。服务端求解器无法伪造浏览器环境,因此@cap.js/solver对此类质询无能为力——如果你面对的密钥/路由开启了 instrumentation,请走正常的浏览器验证组件流程。
  • 不绕过 PoW:求解依然要消耗真实算力,难度d越高,期望哈希次数越多。若要降低服务端求解成本,应与服务端协商更低的难度或更少的质询数量。
  • 注意协议:Cap 的默认质询协议是抗 GPU 的 HashWX(Standalone 新建密钥的默认协议)。HashWX 与经典 SHA-256 PoW 的求解接口不同,使用求解器前请确认目标服务签发的质询属于 SHA-256 PoW 格式;对 HashWX 格式质询的求解,验证组件使用独立的 WASM 运行时(hashwx.wasm),@cap.js/solver的经典[salt, target]接口并不适用。

完整实战示例

综合以上内容,一个典型的 M2M 集成流程如下:

import solver from "@cap.js/solver"; // 从受保护服务获取质询令牌(此处为示意,实际由你的后端路由返回) const token = await fetchChallengeToken(); // 1) 基于种子求解 50 个难度 4 的质询,开满全部 CPU 核心 const solutions = await solver(token, { c: 50, s: 32, d: 4, workerCount: 8, onProgress: (p) => console.log(`progress: ${p}`), }); // 2) 把 nonce 数组作为 solutions 回传兑换 const { success, token: redeemToken } = await fetch("/cap/redeem", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ token, solutions }), }).then((r) => r.json()); if (success) { // 3) 用兑换令牌继续访问受保护的业务接口 }

在调度大量求解任务、需要在主流程之外异步处理时,请把求解逻辑放入 worker 池或独立进程,避免阻塞 Bun 的事件循环——这一点与浏览器端把求解卸载到 Web Worker 的思路(widget/src/src/worker.js)是相通的。

  • 网络安全
  • 应用安全
  • 后端

【免费下载链接】cap

Free, open-source and self-hosted CAPTCHA alternative to reCAPTCHA. Privacy-first and powered by proof-of-work and instrumentation challenges.

项目地址:https://gitcode.com/gh_mirrors/cap13/cap
点击查看免费下载
上一篇:BilibiliDown 多平台B站视频下载器使用指南
下一篇:嘿!数学爱好者:用Markdown-it-KaTeX让你的数学公式飞起来

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 2:47:01

FileZilla Server 0.9.39 汉化绿色版部署与配置实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 2:46:55

大麦网抢票脚本保姆级教程:3步配置自动抢票

大麦网抢票脚本保姆级教程:3步配置自动抢票 【免费下载链接】Automatic_ticket_purchase 大麦网抢票脚本 项目地址: https://gitcode.com/GitHub_Trending/au/Automatic_ticket_purchase 手点"立即购买"总慢人一步?这个 大麦网抢票脚本 帮你把登录、查票、提…

作者头像 李华
网站建设 2026/9/29 2:46:47

MIPI LP RX调试全攻略:从协议到实战,解决没信号与花屏问题

1. 从一个“没信号”的调试现场说起如果你正在调试一块MIPI屏幕,上电后背光亮了、屏也热了,但画面就是黑的,示波器探头搭在LP信号线上却什么都抓不到,那你大概率已经踩进了MIPI LP RX这个坑里。LP,Low Power&#xff0…

作者头像 李华
网站建设 2026/9/29 2:46:28

工业级无人机调度平台开源架构实战:MAVLink+Celery+GeoHash

简介:这是一款面向工业级低空空域管理场景的开源无人机智能调度与管理平台,适用于无人机系统开发者、低空经济领域科研人员及电网、交通、城市安防等行业的技术实施团队,解决多机型协同调度、任务自动化执行与三维可视化管控等核心问题。资源…

作者头像 李华