☰
Solving Cap Proof-of-Work Challenges Server-Side with @cap.js/solver on Bun
2026/9/28 3:03:26 网站建设 项目流程
  • 网络安全
  • 应用安全
  • 后端

【免费下载链接】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 开源验证码项目中@cap.js/solver的完整用法:这是一个零依赖、单文件的服务端求解库,专为机器对机器(M2M)流程设计,只能运行在 Bun 上。读完本文,你将掌握如何在服务端从种子(seed)或质询列表直接求解 Cap 的工作量证明(proof-of-work)质询、理解其底层求解算法,以及如何把求解结果提交给 Cap 服务端完成验证与换取通行令牌。

什么是 @cap.js/solver

@cap.js/solver是 Cap 提供的一个独立(standalone)库,用于在服务端求解 Cap 质询(challenge)。与面向浏览器的 widget 相比,它同样快速高效,但实现上"极度简单"——零依赖、单文件,且有一个硬性前提:只能在 Bun 运行时下使用。

需要特别强调两点边界:

  • 它不会绕过任何实际的工作量证明。solver 老老实实地完成质询所要求的计算,只是把原本在浏览器 widget 里完成的求解过程搬到了服务端,因此它产出的是真实、可被服务端验证的合法解。
  • 它不支持 instrumentation 质询。Cap 有两种质询类型:proof-of-work(工作量证明)和 instrumentation(浏览器行为探针)。instrumentation 质询依赖浏览器环境的运行特征(详见 instrumentation 指南),服务端没有浏览器环境,因此@cap.js/solver只覆盖 proof-of-work 类质询。

从仓库源码看,Cap 的 proof-of-work 质询共包含三种协议,均可在服务端被求解:

协议原理相关实现
sha256-pow寻找 noncen,使SHA-256(salt + n)的十六进制结果以target前缀开头core/src/crypto.js、core/test/helpers.js
hashwx基于 WASM 的专用哈希函数,寻找满足hash <= U64_MAX / difficulty的 noncecore/src/hashwx.js、widget/src/src/worker.js
rsw基于 RSA 的重复平方(repeated squaring),计算y = x^(2^t) mod Ncore/src/rsw.js

安装

solver以 npm 包形式发布,通过 Bun 的包管理器安装:

bun add @cap.js/solver

由于库只在 Bun 上运行,请确保你的服务端环境已经安装 Bun。安装完成后即可在 Bun 脚本中直接import使用。

用法一:从种子(seeded)质询求解

服务端最典型的场景是:你已经通过 Cap 的generateChallenge拿到了一个 JWT 形式的质询令牌(token),其中携带了质询数量c、盐长度s与难度d等参数。此时可以把 token 直接交给 solver,并显式传入这些参数:

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

solver会基于该 token 派生出c组 salt/target,并逐一求出满足条件的 nonce,最终返回一个数组:

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

种子派生逻辑的源码依据:token 的种子派生在仓库中有明确实现。capjs-core通过 FNV-1a 哈希与自实现 PRNG 从 token 派生 salt 与 target——prng(token + i, s)生成第 i 个质询的盐,prng(token + i + "d", d)生成其目标前缀,然后循环递增 nonce,直到SHA-256(salt + nonce)以 target 开头(见 core/src/prng.js 与 core/test/helpers.js)。服务端求解器执行的正是这套算法,因此其结果与服务端验证逻辑完全一致。

参数的默认值与取值范围

solver 的种子参数与服务端generateChallenge的默认值一一对应。仓库中 core/src/index.js 定义:

  • c(质询数量):默认50,合法范围1 ~ 1000;
  • s(盐长度):默认32,合法范围1 ~ 256;
  • d(难度,即 target 前缀的十六进制位数):默认4,合法范围1 ~ 16。

难度d每增加 1,平均需要多计算约 16 倍哈希,因此在实际 M2M 场景中,应结合自身服务端 CPU 能力与对延迟的容忍度选择合适的难度。

用法二:从质询列表求解

如果服务端不希望维护"种子派生"这层间接关系,也可以直接传入显式的质询列表。列表中每一项是一个二元组:第一项为盐(salt),第二项为难度前缀(target):

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

输出同样是一个与输入顺序对应的 nonce 数组:

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

这种形式对应 Cap format-2 质询中的sha256-pow协议:服务端生成的每个质询载荷都包含{ salt, target },客户端只需寻找 nonce 使SHA-256(salt + nonce)以target开头(生成与验证逻辑见 core/src/index.js 与 core/src/index.js)。

提示:hashwx与rsw协议同样属于 proof-of-work。从 core/src/index.js 的实现看,rsw质询的载荷为{ N, x, t }(模数、基值与迭代次数),hashwx质询的载荷为{ c, d, n }(挑战、难度、每哈希 nonce 数)。这些质询同样可以在服务端被求解,只是求解方式与参数形态不同。

第二个参数:选项详解

await solver(challenges, options)的第二个参数是可选的,且始终是一个对象。无论传不传、传多少,workerCount与onProgress对所有质询类型都生效;c/s/d仅对基于种子的质询有意义。

workerCount

  • 作用范围:所有质询类型。
  • 含义:求解时使用的 worker 数量。
  • 默认值:CPU 核心数(即navigator.hardwareConcurrency)。

worker 划分逻辑在仓库的 widget worker 中可以看到同样模式:每个 worker 从自己的起始区块开始,按步长workerCount推进搜索空间(见 widget/src/src/worker.js)。在服务端,更高的workerCount可以更充分地利用多核 CPU,但也会占用更多内存与 CPU 时间,需要根据机器的核心数与同时处理的请求量做权衡。

onProgress

  • 作用范围:所有质询类型。
  • 含义:进度更新回调。

进度回调的典型形态可以参考 widget 端的实现:worker 每完成一定量哈希就上报一次进度(widget 中为每约 150ms 上报一次,见 widget/src/src/worker.js)。在 M2M 场景中,onProgress常用于日志记录、超时判断或给调用方返回阶段性状态:

await solver(challenges, { workerCount: 4, onProgress: (progress) => { console.log(`solving... ${progress}`); }, });

c/s/d(仅限种子质询)

  • 作用范围:仅基于种子的质询。
  • 含义:指定要生成的解的数量(c)、质询(盐)的大小(s)与难度(d)。

当第一个参数是字符串 token 时,solver 需要这三个参数才能确定要生成多少组 salt/target、以多大强度求解;当第一个参数是显式质询列表时,这些信息已经包含在列表中,无需(也不应)再传。

完整的 M2M 集成流程

把上面的知识串起来,一个典型的服务端 M2M 流程如下:

  1. 获取质询:调用 Cap 实例的POST /<site-key>/challenge接口(或通过capjs-core的generateChallenge在本地生成),拿到携带质询参数、带有过期时间的 JWT token(生成逻辑见 standalone/src/cap.js)。
  2. 服务端求解:把 token 或显式质询列表交给@cap.js/solver,得到 nonce 数组。
  3. 提交验证:将{ token, solutions: [nonce, ...] }POST 到 Cap 实例的POST /<site-key>/redeem接口。服务端会校验每个 nonce 对应的哈希是否满足 target 前缀条件、token 是否过期、是否已被兑换(nonce 一次性消费),验证通过后返回一个带 TTL 的兑换令牌(见 standalone/src/cap.js 与 core/src/index.js)。

这套流程让没有浏览器环境的服务端程序(如批量数据抓取、自动化测试、CI 流水线、服务间调用)也能正常通过 Cap 的验证,同时保持与浏览器 widget 相同的求解效率。

边界与注意事项

  • 仅限 Bun:@cap.js/solver依赖 Bun 的运行时能力,不能在 Node.js 或 Deno 下使用。
  • 只覆盖 proof-of-work:如果目标站点配置了 instrumentation 质询,solver 无法求解,需配合真实浏览器环境(如 Cap 的前端 widget 或 programmatic 模式,见 programmatic 模式指南)。
  • 不绕过工作量证明:求解计算是真实的、可验证的,不要指望通过它"跳过"验证——服务端会逐一校验解的正确性。
  • 注意默认参数:种子模式下c=50, s=32, d=4是常见默认组合,难度越高单次求解耗 CPU 越多,请为服务端预留足够的计算资源(仓库中的 core/test/benchmark.js 展示了不同参数组合下generateChallenge/validateChallenge的基准测试方式,可用于评估容量)。

延伸阅读

  • Cap 核心库说明:capjs-core的质询生成与验证 API。
  • hashwx 协议指南:hashwx 质询的难度、nonce 与验证细节。
  • instrumentation 指南:solver 不支持的另一种质询类型。
  • Standalone 部署指南:如何自托管 Cap 实例并提供/challenge与/redeem接口。
  • 编程式集成指南:在客户端 JS 中通过new Cap()编程式求解(适用于浏览器环境)。
  • 网络安全
  • 应用安全
  • 后端

【免费下载链接】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
点击查看免费下载
上一篇:多平台直播分发神器:OBS同步推流插件完全指南
下一篇:终极指南:WhateverGreen与其他kexts的协同工作,构建稳定显卡驱动环境

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询