尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Cap 工作原理深度解析:从 Proof-of-Work 挑战到签名 Token 的完整链路
网络安全应用安全后端【免费下载链接】capFree, 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 是一个免费、开源、可自托管的 CAPTCHA 替代方案其核心思想是不依赖图像拼图或行为追踪而是用**工作量证明Proof-of-Work与浏览器环境检测Instrumentation**双重挑战来区分人与机器人。本文基于仓库文档 docs/guide/workings.md逐层拆解 Cap 从组件初始化、请求挑战、客户端求解、服务端验收到最终签发 Token 的完整技术链路并结合cap.js组件、worker.js求解器与capjs-core服务端库的源码实现帮助你理解这套无感验证机制的底层原理。说明本文聚焦于 Cap 的 SHA-256 工作量证明与 instrumentation 挑战即workings.md的主体内容。GPU 抗性的 HashWX 挑战协议 不在本文展开但在关键环节会指出其与本文主线的差异与衔接整体效果评估可参考 effectiveness 文档。整体流程九步带你走完一次验证workings.md将一次完整的验证概括为三个阶段的九个步骤这是理解 Cap 全貌的最佳骨架Cap 初始化时在浏览器中自动注册一个自定义元素cap-widget作为验证组件组件创建 Shadow DOM并向其中挂载所有必要元素当需要求解时组件向服务器请求挑战服务器返回 Token、待解的挑战配置以及可选的压缩后的 instrumentation 数据组件以挑战 Token 为种子、结合服务器配置在本地生成多个挑战若存在 instrumentation 数据则在沙箱 iframe 中解压并执行组件使用 Rust 风格 WASM 与 Web Worker 并行求解每个 Worker 反复尝试把 salt 与不同 nonce 组合、计算 SHA-256 哈希、检查哈希是否以目标前缀开头WASM 递增 nonce 直到找到匹配若存在 instrumentation 挑战解压并执行之找到合法解后组件把结果回传服务器进行校验服务器使用同一 Token 与配置自行生成相同的挑战逐一验证组件提交的解验证通过后服务器兑换该解并签发可用于后续请求认证的 Token。下面逐阶段深入讲解。阶段一组件初始化步骤 1–2注册自定义元素当cap.min.js被加载并执行时脚本先做环境探测typeof window undefined时直接返回随后把整个 widget 定义为 Web Components 自定义元素。在 widget/src/src/cap.js#L2002 可以看到注册语句customElements.define(cap-widget, CapWidget);这意味着页面中只需书写cap-widget/cap-widget浏览器即会自动实例化CapWidget类。CapWidget还通过static formAssociated truecap.js#L493声明为可关联表单的元素配合attachInternals()实现表单校验required属性未满足时触发valueMissing错误因此它能无缝嵌入现有form提交流程。创建 Shadow DOM在connectedCallback()元素挂载到文档时触发中组件创建并挂载 Shadow DOMcap.js#L953-L954if (!this.shadowRoot) { this.#shadow this.attachShadow({ mode: open }); }随后把样式与 UI 全部注入 Shadow DOM 内部cap.js#L1643-L1645this.#shadow.innerHTML style${window.CAP_CSS_NONCE ? nonce${window.CAP_CSS_NONCE} : }%%capCSS%%/style; this.#shadow.appendChild(this.#div);Shadow DOM 带来的隔离性是 Cap 无需依赖 CSS 框架的关键外部页面的样式无法污染组件内部组件样式也不会泄漏到页面配合window.CAP_CSS_NONCE属性可适配严格 CSP 环境。同时组件还会在宿主元素内插入一个隐藏表单域cap.js#L969this.#host.innerHTML input typehidden name${this.#fieldName};默认字段名为cap-tokendata-cap-hidden-field-name可改验证成功后 Token 会被写入该字段随表单一并提交到你的后端。阶段二请求挑战步骤 3–4向服务器要一份挑战说明书当组件需要求解用户点击验证按钮或开启后台预解时页面首次交互后经SPECULATIVE_DELAY_MS 2500毫秒的延迟触发它会向{api-endpoint}/challenge发送POST请求cap.js#L616-L619。服务器返回三类数据token挑战令牌后续赎回redeem时回传用于服务端复原挑战挑战配置包括挑战数量、盐长度、难度等参数{ c, s, d }或 format-2 的challenges数组instrumentation可选一份经 deflate 压缩再 base64 编码的 JavaScript 程序。这份配置在服务端由capjs-core的generateChallenge()生成——它返回{ challenge, token, expires, instrumentation? }其中token是一个携带挑战配置的签名 JWT详见 capjs-core 文档。SHA-256 模式下的默认参数为参数默认值含义challengeCount50生成的 PoW 谜题数量challengeSize32盐长度十六进制字符数challengeDifficulty4目标前缀长度十六进制字符数expiresMs600_000挑战有效期10 分钟在浏览器端重建挑战服务器并不会把 50 个具体的谜题都下发给浏览器——那样负载过大。它只给一个种子即token由组件在本地确定性再生出全部挑战。从源码看cap.js#L645-L651if (!Array.isArray(challenges)) { let i 0; challenges Array.from({ length: challenge.c }, () { i; return [ prng(${token}${i}, challenge.s), // 第 i 个谜题的 salt prng(${token}${i}d, challenge.d), // 第 i 个谜题的 target 前缀 ]; }); }prng()cap.js#L86-L113是一个以 FNV-1a 做种子、xorshift 风格的确定性伪随机数生成器同样的token i输入必然产生同样的 salt同样的token i d必然产生同样的 target。这保证了客户端生成什么、服务端就能生成什么——步骤 8 中服务器自行重算挑战成为可能。Instrumentation 数据怎么复活若响应中携带instrumentation字段组件调用runInstrumentationChallenge()cap.js#L168-L238先用atob解码 base64再经DecompressionStream(deflate-raw)解压不支持时降级加载 pako可通过window.CAP_PAKO_URL指定 CDN解压出的是一段自包含的 JavaScript 程序它被注入到一个sandboxallow-scripts的 1×1 像素隐藏 iframe 中执行srcdoc注入iframe 内程序执行浏览器 API 探测与 DOM 运算链最终通过postMessage以{ type: cap:instr }消息把结果回传父窗口若 20 秒内未收到结果__timeout或程序自报blocked__blocked自动化浏览器被拦截组件按失败处理。沙箱化的意义在于即使服务器下发的 JS 被恶意注入或被篡改它也只能在一个与主页面完全隔离、无权限的 1×1 不可见 iframe 里运行无法接触页面数据。关于 instrumentation 挑战为何要混入 DOM 运算、以及七项自动化检测的细节参见 instrumentation 文档。阶段三计算解步骤 5–6SHA-256 工作量证明找前缀匹配的 nonce核心求解逻辑是标准的哈希碰撞式 PoW给定 salt 与 target 前缀暴力递增 nonce寻找满足sha256(salt nonce) 的前缀 target的 nonce。workings.md第 5 步描述的正是这一过程。仓库中 widget/src/src/worker.js#L18-L77 的solveFallback给出了最直白的参考实现这是无 WASM 时的纯 JS 兜底同样逻辑的 WASM 版本性能高得多while (true) { for (let i 0; i batchSize; i) { // 每批 50000 次 const inputString salt nonce; const hashBytes new Uint8Array(await crypto.subtle.digest(SHA-256, encoder.encode(inputString))); // 逐字节比较 hash 前缀与 targetBytes匹配则上报 nonce if (matches) { self.postMessage({ nonce, found: true }); return; } nonce; } }该实现对 target 的处理很讲究targetBits target.length * 4前缀位数完整字节部分逐字节比对不足一字节的剩余位数用掩码(0xff (8 - remainingBits)) 0xff只比较高位——这正是哈希以目标前缀开头的精确语义。WASM Web Worker并行暴力破解纯 JS 逐次await crypto.subtle.digest太慢。生产路径下组件会通过getWasmModule()cap.js#L242-L268从cap.js/wasm包默认 jsDelivr CDN可用window.CAP_CUSTOM_WASM_URL覆盖拉取并WebAssembly.compile编译cap_wasm_bg.wasm它由 Rust 编译而来——这就是workings.md所说的 Rust-flavoured WASM用WorkerPoolcap.js#L344-L490创建数量等于navigator.hardwareConcurrency || 8可用data-cap-worker-count覆盖的 Web Worker把 salt、target 与编译好的wasmModule通过postMessage分发给各 Worker每个 Worker 初始化 WASM 实例后调用wasm.solve_pow(saltPtr, saltLen, targetPtr, targetLen)worker.js#L358-L364Rust 侧循环递增 nonce 直至找到前缀匹配的哈希随后把 nonce 上报主线程。WorkerPool还包含健壮性设计Worker 崩溃时自动terminate并替换最多尝试 3 次任务以队列 空闲 Worker 分发的形式调度stopAll()会向所有 Worker 发送{ kind: stop }优雅停机250ms 宽限期后强制终止用于组件重置时立刻停止无谓的算力消耗。HashWX默认协议的方向性差异值得说明的是workings.md明确声明本文不覆盖 HashWX。但在当前仓库中HashWX 已是 Standalone 新站点密钥的默认挑战协议见 standalone/options.md#hashwx-proof-of-work其思路与 SHA-256 PoW 有本质区别不再用固定哈希函数而是由服务器下发的 32 字节挑战c通过sha256(c || u64le(block))生成种子再据种子现场构造一个全新的、含大量分支与 16KB 非对齐 scratchpad 访问的哈希函数见 core/src/hashwx.js#L58-L67 的hashwxSeed。由于每个挑战的函数都不同GPU 无法像对待固定 SHA-256 那样锁步并行优势从约 150 倍被压到约 2 倍。从 core/src/hashwx.js#L98-L143 的mintHashwxChallenges可见其默认参数difficulty 1_000_000期望哈希数即难度、noncesPerHash 65_536、challengeCount 4默认拆成 4 个子挑战以缩短长尾延迟。而求解端Worker 通过hashwx_make(ctx, seedPtr)现场生成函数、以WebAssembly.ModuleJIT 编译该函数再对整块 nonce 区执行worker.js#L182-L265。若浏览器不支持 WebAssemblyHashWX 会直接报错——这是它与 SHA-256 路径有纯 JS 兜底最大的可用性差异。Instrumentation 挑战的执行步骤 6 中若存在 instrumentation 数据组件在求解 PoW 的同时或之后执行沙箱 iframe 程序取回计算结果向量{ vp: [window.innerWidth, window.innerHeight], ...result }cap.js#L212将其随解一并提交。该向量中既包含程序主运算链的期望终值也包含navigator.webdriver、文本度量、窗口几何等浏览器事实——服务端据此判定是否运行在真实渲染引擎中。阶段四兑换 Token步骤 7–9提交解redeem 端点找到全部合法 nonce数量必须等于challenge.c且 instrumentation 程序返回结果后组件向{api-endpoint}/redeem发送POSTcap.js#L770-L779const redeemRaw await capFetch(${apiEndpoint}redeem, { method: POST, body: JSON.stringify({ token: challengeResp.token, // 原挑战令牌 solutions, // 每个谜题找到的 nonce 数组 ...(instrOut { instr: instrOut }), // instrumentation 结果向量 }), headers: { Content-Type: application/json }, });服务端重算一遍再验证服务端收到请求后调用validateChallenge()其验证次序是令牌核验JWT 签名、参数边界、scope匹配、有效期默认 10 分钟过期即拒解格式核验solutions必须是数组且长度等于挑战数重算挑战用同样的 token 与配置即步骤 4 中客户端所用同一套确定性再生逻辑生成每个谜题的 salt 与 target逐一验证 PoW 解对 SHA-256 路径重算sha256(salt nonce)比对前缀对 HashWX 路径则调用verifyHashwxSolution()——先解析 nonce、由nonce / n推算所在 block、hashwxSeed(challenge, block)还原该 block 的种子并生成对应哈希函数、执行一次并判断H (2^64 - 1) / dcore/src/hashwx.js#L145-L175。整个验证只执行一次哈希而非客户端那样暴力搜索因此服务端成本极低校验 instrumentation若启用在服务端用detectAutomation对提交的向量跑检测器失败则返回reason: instr_automated_browser及blockedBy数组该过程同时产出riskFlags如native_tamper供业务方决定是否提高下一轮难度防重放可选若配置了consumeNonce回调以 JWT 签名的十六进制为键执行SET NX EX语义的原子写入重复提交返回false对应失败原因already_redeemed。注意此检查排在 PoW 与 instrumentation 验证之后垃圾解不会烧掉合法用户的 nonce。签发可用 Token全部通过后服务器兑换解并签发新 Token默认格式为id:secret的二元组id可公开secret的 SHA-256 哈希作为查询键。业务后端按 capjs-core 文档 中给出的方式持久化该键的过期时间默认 20 分钟并在后续请求中据用户回传的 Token 重新派生键来鉴权。组件拿到resp.token后将其写入隐藏表单域、触发solve事件并设置到期自动重置定时器cap.js#L808-L846一次验证闭环至此完成。两个值得注意的设计细节确定性再生是整套机制的地基从步骤 4 到步骤 8客户端与服务端没有任何共享的谜题库全靠同一个 token 种子 确定性 PRNG / 确定性哈希函数生成。这意味着挑战配置必须由签名 JWT 承载且不可被篡改篡改即 JWT 验签失败这是 capjs-core 把挑战参数放进签名 payload 的原因也意味着服务端验证是 O(1) 级别的单次重算而非重放整个搜索过程。后台预解把验证藏进用户交互间隙组件实现了投机性预解speculative solving监听mousemove/touchstart/keydown等首次交互事件交互后延迟 2.5 秒且组件可见时就开始静默请求挑战并求解cap.js#L565-L668期间只启用 1 个 Worker 以控制资源占用。用户真正提交表单时若预解已完成直接零等待取用缓存 Token日志里甚至记录了省下的毫秒数served from speculative cache (saved ...)。这就是 Cap 能在多数场景下做到无用户交互、无感知通过的工程支撑。相关文档导航本文是workings.md的深度展开以下文档可继续深入Cap 对抗效果评估effectiveness为何选择 PoW、成本如何影响攻击者经济模型HashWX 挑战协议默认协议的完整协议描述、GPU 抗性来源与实测数据Instrumentation 挑战七项自动化检测细则与安全边界capjs-core 服务端库generateChallenge/validateChallenge的完整 API 与无状态部署模式Standalone 部署选项站点密钥级协议切换与难度配置默认1_000_000合法范围50_000–5_000_000。如需查看实现源码可分别阅读 widget 组件、Worker 求解器 与 服务端 HashWX 验证。赞分享网络安全应用安全后端【免费下载链接】capFree, 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 工作原理全解析从种子 Proof-of-Work 挑战到服务端签名令牌的完整链路Cap 工作原理全解析从种子 Proof of Work 挑战到服务端签名令牌的完整链路 Cap 是一款免费、开源、可自托管的 CAPTCHA 替代方案其核网络安全应用安全后端Cap Benchmark 解析Cap 开源 CAPTCHA 的 Proof-of-Work 挑战在低端到高端设备上的真实求解耗时Cap Benchmark 解析Cap 开源 CAPTCHA 的 Proof of Work 挑战在低端到高端设备上的真实求解耗时 本文基于仓库中的 德文版基网络安全应用安全后端Cap 项目 HashWX 实战指南GPU 抗性 Proof-of-Work 的原理、成本与配置Cap 项目 HashWX 实战指南GPU 抗性 Proof of Work 的原理、成本与配置 HashWX 是 Cap免费开源、可自托管的 reCAPT网络安全应用安全后端上一篇DLRS安装与配置完全攻略从零基础到熟练应用下一篇OpenTracing-Python异步编程支持asyncio、gevent和Tornado集成指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

projectcalico/api 深入解读:Calico v3 API 定义、ClientSet 使用与新增 API 完整实践

projectcalico/api 深入解读:Calico v3 API 定义、ClientSet 使用与新增 API 完整实践

网络云原生网络安全 【免费下载链接】calico Cloud native networking and network security 项目地址: https://gitcode.com/gh_mirrors/cal/calico 点击查看 免费下载 导读 api/ 目录是 Projectcalico(Calico 项目)API 定义的权威来源&am…

📅 2026/9/28 2:45:48
开关机芯片选型指南:驱动电流、静态功耗、封装尺寸与保护功能四维解析

开关机芯片选型指南:驱动电流、静态功耗、封装尺寸与保护功能四维解析

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

📅 2026/9/28 2:40:48
Boa 虚拟机(VM)架构深度解析:从字节码编译到执行引擎

Boa 虚拟机(VM)架构深度解析:从字节码编译到执行引擎

编程语言编译器开发工具 【免费下载链接】boa Boa is an embeddable Javascript engine written in Rust. 项目地址: https://gitcode.com/gh_mirrors/bo/boa 点击查看 免费下载 Boa 是一个用 Rust 编写的可嵌入式 JavaScript 引擎,其执行核心是一套自研…

📅 2026/9/28 2:40:48
MORE NEWS

更多资讯

📰

Transformer Encoder在多输入单输出回归预测中的实践指南

做回归预测还想着用Transformer的人,不少一开始是被"杀鸡用牛刀"这类说法劝退的。常规的多输入单输出回归,大家习惯了直接上多层感知机,顶多加个LSTM或者GRU,似乎线性层堆叠就能解决一切。但当我遇到一组高维、强非线性…

📰

HTTP请求方法详解:从GET/POST语义到工程实践与性能优化

1. GET 与 POST 的本质差异:别再只会说“查和改”很多人聊到 GET 和 POST,第一反应就是“GET 拿数据,POST 提交数据”。这话没错,但太粗了。我在面试前端候选人的时候,经常问一个问题:“你现在要给后端传一…

📰

基于Web的在线考试系统设计与毕业设计LW完整实战指南

如果要在计算机毕设里评一个“最眼熟题目”,基于Web的网络在线考试系统绝对排前三。它的常见交付形式就是一整套:代码工程、数据库脚本,加上一份毕业设计论文文档——也就是题目里那个尾缀“LW”。网上能搜到大量成品下载,但真正自…

📰

FFmpeg与MediaMTX实战:把Windows摄像头变RTSP监控源

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

📰

荆州排名前五的阀芯装配机定制工厂:综合实力推荐

台州超尚自动化设备有限公司,是扎根于中国阀门之都浙江玉环的专精自动化设备研发制造企业,专注于暖通阀芯自动化装配领域十余年,是暖通阀芯装配机专业制造商,核心主营CS-14暖通阀芯装配机及各类非标自动化设备研发生产&#xff0c…

📰

MATLAB ISODATE聚类算法实战:从解压到调参避坑

简介:这份资源是面向MATLAB初学者与数据挖掘学习者的ISODATA聚类算法实现包,用于解决类别数量不确定、数据分布复杂场景下的自动聚类问题。压缩包内共1个文件,为m脚本类型,整体约3KB,核心是ISODATA算法的完整逻辑代码&…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬