首页/新闻资讯/正文详情

Cap 内部工作原理:自托管 CAPTCHA 的 SHA-256 工作量证明与埋点挑战全流程解析

发布时间:2026/9/27 23:35:11 来源:云帆数科 栏目:资讯中心
Cap 内部工作原理:自托管 CAPTCHA 的 SHA-256 工作量证明与埋点挑战全流程解析
网络安全应用安全后端【免费下载链接】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 替代方案在浏览器与服务端之间的完整工作链路从 widget 的注册与 shadow DOM 构建到挑战请求、基于 Rust WASM 与 Web Worker 的并行求解、沙箱 iframe 中的埋点instrumentation挑战再到服务端基于同一种子重放挑战、验证并兑换一次性令牌。读完本文你将能准确理解 Cap 的种子化挑战 双重验证 一次性令牌设计并能在部署、集成与排查时定位到每一环节对应的源码实现。说明本文仅覆盖 SHA-256 PoW 与 instrumentation 挑战链路不包含 HashWX相关内容见 HashWX 说明。希望获得更宏观的对抗效果概述可阅读 效果评估。1. 总体流程一次人类验证的九步生命周期原文档将 Cap 的完整流程归纳为三个阶段九个步骤我们可以把一次验证的生命周期整理如下阶段步骤发生位置核心动作初始化1–2浏览器注册自定义元素cap-widget构建 shadow DOM 与全部 UI 元素请求挑战3–4浏览器 ↔ 服务端请求challenge接口获得 token、挑战配置与可选的压缩埋点数据由固定种子派生多个挑战计算解5–6浏览器WASM Web Workers 并行求解 SHA-256 PoW在沙箱 iframe 中解压并执行埋点挑战兑换令牌7–9浏览器 ↔ 服务端提交解至redeem接口服务端独立重放挑战并校验消费解并签发一次性令牌核心设计思想挑战与验证都是**确定性deterministic**的——双方使用同一个 token 作为种子依据同样的参数推导出相同的 salt 与 target因此服务端可以脱离任何会话状态仅凭提交的 token 与解就能完成校验而消耗即作废的一次性令牌设计nonce 消费则保证同一份解不能被重复兑换。2. 初始化自定义元素与 shadow DOM2.1 自定义元素的注册Cap 的 widget 是一个继承自HTMLElement的CapWidget类。脚本加载后会在页面全局注册名为cap-widget的自定义元素if (!customElements.get(cap-widget) !window?.CAP_DONT_SKIP_REDEFINE) { customElements.define(cap-widget, CapWidget); }若页面中已存在同名自定义元素Cap 会跳过注册并打印警告同时提供了window.CAP_DONT_SKIP_REDEFINE true用于强制覆盖见 widget/src/src/cap.js。widget 同时以window.Cap暴露构造器并兼容 CommonJS / AMD / ESM 导出。2.2 shadow DOM 的构建在connectedCallback()元素被插入文档时触发中Cap 完成以下初始化this.#shadow this.attachShadow({ mode: open }); // 创建 open 模式的 shadow DOM this.createUI(); // 构建 widget 全部 UI 元素 this.addEventListeners(); // 绑定事件 this.initialize(); // 预创建 Worker、AbortController 等 this.#host.innerHTML input typehidden name${this.#fieldName}; // 隐藏表单字段其中隐藏表单字段cap-token默认data-cap-hidden-field-name用于在表单提交时携带验证令牌见 widget/src/src/cap.js 与 widget/src/src/cap.js。Worker 数量默认取navigator.hardwareConcurrency也可通过data-cap-worker-count属性指定。3. 请求挑战challenge 接口与种子化派生3.1 请求的发起用户点击验证或页面预加载触发后widget 向data-cap-api-endpoint指定的服务端地址发起POST {endpoint}/challenge请求。Cap 支持通过window.CAP_CUSTOM_FETCH注入自定义 fetch 实现以适配非标准网络环境见 widget/src/src/cap.js。在自托管 standalone 部署中对应的路由为/:siteKey/challenge见 standalone/src/cap.js。服务端在签发挑战前会执行一系列前置检查校验 site key 是否存在及其jwtSecret配置按 IP 进行封禁规则匹配支持精确 IP、cidr:前缀、asn:、country:等规则可选地拦截非浏览器 UAblockNonBrowserUA与缺失必需请求头requiredHeaders的请求执行基于 Valkey/Redis 的限流默认 30 次 / 5 秒可被 site key 级配置覆盖。3.2 服务端如何生成挑战服务端核心调用capjs-core的generateChallenge(secret, opts)。以 SHA-256 PoWformat 1默认协议为例挑战的默认参数与约束如下参数默认值合法范围含义challengeCountc501–1000需要求解的挑战个数challengeSizes321–256salt 的十六进制长度即字节数×2challengeDifficultyd41–16目标哈希前缀长度十六进制位expiresMs10 分钟—挑战令牌的过期时间tokenTtlMs20 分钟—兑换出的令牌的有效期以上默认值与范围定义可见 core/src/index.js 与 core/src/index.js。若同时启用了 instrumentation服务端还会生成埋点脚本并将期望值以 AES-256-GCM 加密encryptGcm后写入令牌载荷payload.ei字段见 core/src/index.js。随后挑战配置、随机 noncen: randomHex(25)、过期时间等被封装为 HS256 签名的 JWT 令牌见 core/src/crypto.js。这个令牌同时充当派生挑战的种子——它的签名与载荷共同保证了挑战只能由签发它的服务端验证。3.3 浏览器端从种子派生 salt 与 target响应格式为{ challenge: { c: 50, s: 32, d: 4 }, token: JWT, expires: 1730000000000, instrumentation: 压缩后的 base64 数据可选 }浏览器端利用 PRNG 从 token 种子逐个派生 salt 与 targetchallenges Array.from({ length: challenge.c }, () { i; return [ prng(${token}${i}, challenge.s), // salt以 token序号 为种子的确定性随机串 prng(${token}${i}d, challenge.d), // target以 token序号d 为种子派生前缀 ]; });对应实现见 widget/src/src/cap.js。prng采用 FNV-1a 哈希播种 xorshift 生成器见 core/src/prng.js并保证两次相同输入得到完全一致的输出——这正是服务端可以独立重放的前提。若提供了 instrumentation 数据widget 会先将其解压再放入沙箱 iframe 执行见 widget/src/src/cap.js。3.4 服务端验证侧的派生公式在验证时服务端并不依赖记忆任何状态而是从令牌出发复算 salt 与 targetconst tokenFnv fnv1a(token); // 令牌 FNV-1a 哈希作为种子 for (let i 0; i c; i) { const saltSeed fnv1aResume(tokenFnv, String(i 1)); const targetSeed fnv1aResume(saltSeed, d); const salt prngFromHash(saltSeed, size); const target prngFromHash(targetSeed, difficulty); // 校验 sha256(salt nonce) 是否以 target 为前缀 }对应实现见 core/src/index.js。parseHexPrefix支持奇数长度的十六进制前缀并保留半字节掩码powMatchesPrefix逐字节比较哈希前缀见 core/src/crypto.js。4. 计算解Rust WASM Web Worker 并行求解4.1 Worker 池与并行策略widget 内部维护了一个WorkerPool任务进入队列后被派发给空闲 Workerdata-cap-worker-count控制池大小默认navigator.hardwareConcurrency || 8。Worker 通过 Blob URL 从内联脚本创建支持失败后自动替换最多重试 3 次与stop消息优雅终止见 widget/src/src/cap.js。每个 Worker 的求解逻辑伪代码循环: 将 salt 与递增的 nonce 组合 计算 SHA-256(salt nonce) 若哈希以 target 前缀开头 → 返回该 nonce 否则 nonce4.2 WASM 求解器与 JS 回退WASM 模块通过window.CAP_CUSTOM_WASM_URL可自定义地址默认从cap.js/wasm包加载见 widget/src/src/cap.js。Rust 侧的求解器针对 WebAssembly SIMD 做了 4 路并行4-way multiway ARXSHA-256 优化每条消息4 个不同 nonce 的 salt 组合同时处理并一次性提取每个哈希的前 64 位进行目标匹配见 wasm/src/rust/src/lib.rs 与 wasm/src/rust/src/lib.rs。从源码结构看Rust 侧parse_target断言目标不超过 64 位bits 64因为超过 64 位的前缀在实际求解中已不现实——这也解释了challengeDifficulty上限被约束在 16即 64 位十六进制的原因见 wasm/src/rust/src/lib.rs。当 WebAssembly 不可用时如极旧浏览器Worker 会回退到纯 JS 求解器使用crypto.subtle.digest(SHA-256)按 50000 次一批计算并逐字节/半字节比对目标前缀见 widget/src/src/worker.js。回退模式会显著变慢属于降级兼容路径。4.3 投机式求解speculative solving为进一步优化用户体验Cap 实现了隐形预求解widget 在用户首次交互mousemove/touchstart/keydown后若可见则延迟 2500ms 提前拉取挑战并仅用 1 个 Worker 后台求解用户真正点击验证时若预求解尚未完成则立即将 Worker 池扩容至全量并接力继续见 widget/src/src/cap.js 与 widget/src/src/cap.js。已获得的令牌会被缓存使用直到过期后自动reset()。5. 计算解沙箱 iframe 中的埋点挑战5.1 解压与执行当服务端启用了 instrumentation 时挑战响应会附带一段压缩数据。widget 优先使用浏览器原生的DecompressionStream(deflate-raw)解压若不可用则动态加载 pako 作为回退也可通过window.CAP_PAKO_URL指定 CDN 地址见 widget/src/src/cap.js。解压出的脚本被注入一个sandbox 隔离的 iframe中执行iframe.setAttribute(sandbox, allow-scripts); // 仅允许脚本无同源能力 iframe.style.cssText position:absolute;width:1px;height:1px;top:-9999px;...; // 完全不可见脚本通过window.postMessage与主页面通信超时上限为 20 秒若检测到自动化浏览器iframe 会回传blocked标记见 widget/src/src/cap.js。这一设计使得埋点挑战与主页面环境相互隔离既防止脚本被页面脚本干扰也避免其影响页面自身。5.2 埋点检测什么服务端生成 instrumentation 脚本的核心是generateInstrumentation见 core/src/instrumentation.js脚本会在 iframe 内探测一系列环境特征并在生成阶段就为每个探针字段注入随机变量名与期望值服务端已知答案客户端无法预判。检测维度包括自动化框架标记window/document/navigator上残留的 Selenium、WebDriver、PhantomJS、Playwright 等特征属性与前缀见 core/src/instrumentation.js引擎一致性Gecko 引擎却带有 Chromium 特征如deviceMemory、userAgentData的矛盾判断无头浏览器User-Agent 与 brand 列表中的HeadlessChrome等 token字体指纹几何特征通过一组字体栈探测量化后的字体宽度分布是否过于整数化geometry_quantized视图窗口异常单显示器下 outerHeight 超过屏幕高度、viewport 被强制覆盖为全屏等自动化痕迹原生方法篡改被 JS 覆写的navigator属性tamper 检测。上述检测规则完整实现于 core/src/detect.jsdetectAutomation返回pass、checks、blockedBy与riskFlags。其中 gating门禁类检查不通过即拦截非门禁类如 tamper仅作为风险标记可由上层策略决定。5.3 服务端如何验证埋点结果widget 将埋点执行结果随兑换请求提交instr字段。服务端在验证时先解密令牌中的ei载荷取出服务端期望值expectedVals、vars等再调用verifyInstrumentationResult对提交结果逐项比对若启用了blockAutomatedBrowsers且检测到自动化标记则直接拒绝返回instr_automated_browser。失败原因包括instr_corrupted数据损坏、instr_expired过期、instr_timeout超时、instr_missing未提交等见 core/src/index.js。standalone 服务端将上述失败映射为对应的 HTTP 状态码与错误信息见 standalone/src/cap.js便于前端据此展示不同的错误 UI。6. 兑换令牌服务端独立验证与一次性消费6.1 redeem 请求求解完成后widget 向POST {endpoint}/redeem提交{ token: 挑战令牌, solutions: [12345, 67890, ...], instr: { 字段1: 值1, 字段2: 值2 } // 启用 instrumentation 时 }6.2 服务端验证流程standalone 的/:siteKey/redeem路由调用validateChallenge(secret, body, opts)见 standalone/src/cap.js核心校验步骤依次为令牌校验JWT 签名与载荷验证jwtVerify比对scopesite key检查exp是否过期参数合法性c/s/d必须在约束范围内solutions必须是长度为c的数字数组逐条重放校验对每个挑战重新执行 FNV-1a PRNG 派生 salt 与 target计算sha256Bytes(salt solutions[i])并比对powMatchesPrefix任一失败即返回invalid_solution埋点校验若启用解密ei载荷、比对 instrumentation 结果一次性消费nonce 防重放调用consumeNonce(sigHex, ttlMs)在 standalone 中即对令牌签名哈希执行 RedisSET key 1 NX EX ttl原子操作成功才表示未被兑换过失败返回already_redeemed见 standalone/src/cap.js。针对上述校验路径core/test/core.test.js 覆盖了错误 secret、篡改 JWT、解数量不匹配、非数字解、过期挑战、scope 不匹配、解重放already_redeemed等全部失败分支是理解验证语义的绝佳参考。6.3 签发最终令牌验证通过后服务端消费本次挑战解并签发可证明人类的一次性令牌若提供了signToken回调standalone 即采用此方式则生成{siteKey}:{redeemId}:{redeemSecret}格式令牌并写入 RedisTTL 2 小时见 standalone/src/cap.js 与 standalone/src/cap.js否则由capjs-core生成{id}:{verToken}形式令牌并返回tokenKeySHA-256 后的密钥供服务端存储比对。响应形如{ success: true, token: 一次性令牌, expires: 1730007600000 }widget 收到后将其写入隐藏表单字段cap-token触发solve事件并派发 100% 进度同时根据expires设置自动reset()定时器令牌过期后自动进入下一轮验证见 widget/src/src/cap.js。表单提交时应用服务端即可依据该令牌放行请求。7. 安全特性总结与排查指引7.1 关键安全设计特性机制源码位置挑战不可伪造挑战令牌为 HS256 JWTsalt/target 由令牌确定性派生core/src/index.js、core/src/index.js解不可复用consumeNonce一次性消费RedisNX EX原子占位standalone/src/cap.js埋点不可造假期望值加密进令牌随机变量名服务端比对core/src/index.js、core/src/index.js挑战不可转移scope绑定 site keycore/src/index.js过期兜底挑战 10 分钟、令牌 20 分钟standalone 为 15 分钟 / 2 小时core/src/index.js、standalone/src/cap.js自动化识别沙箱 iframe 探针 服务端规则引擎core/src/detect.js7.2 常见问题定位提示 Invalid solution多为解被篡改或服务端 secret 与签发时不一致可对照 core/test/core.test.js 的重放逻辑检查提示 Challenge already redeemed同一 token 被重复兑换说明一次性消费机制生效属预期行为见 core/test/core.test.js提示 Challenge expiredtoken 超过expiresMs前端应在过期后重新请求挑战埋点相关 403对应instr_automated_browser、instr_timeout、instr_missing等分支可结合 standalone/src/cap.js 的错误映射确认具体原因性能调优通过data-cap-worker-count控制并行 Worker 数对高配置服务器可适当提升challengeDifficulty低端设备则相应调低以缩短求解时间。8. 延伸阅读capjs-core 核心库说明generateChallenge/validateChallenge的完整 API 与集成方式服务端部署指南自托管 standalone 服务的安装与配置Widget 使用指南自定义元素属性、事件与表单集成埋点配置与疑难排查instrumentation 启停与误报处理HashWX 协议本文未覆盖的替代 PoW 协议相关实现位于 core/src/hashwx.js赞分享网络安全应用安全后端【免费下载链接】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点击查看免费下载相关推荐res-downloader 网络资源嗅探完整教程从克隆仓库到保存第一条无水印视频res downloader 网络资源嗅探完整教程从克隆仓库到保存第一条无水印视频 res downloader 是一款基于 Go 与 Wails 的跨平台网网络安全应用安全后端Myrtille终极指南原生HTML远程桌面协议与SSH客户端的完整解析Myrtille终极指南原生HTML远程桌面协议与SSH客户端的完整解析 Myrtille是一款强大的原生HTML4/HTML5远程桌面协议RDP和SSHCap 的 HashWX 工作量证明GPU 抗性挑战协议的原理、成本与配置实战Cap 的 HashWX 工作量证明GPU 抗性挑战协议的原理、成本与配置实战 HashWX 是开源项目 Cap 的默认挑战协议也是其对抗 GPU 算力碾压网络安全应用安全后端上一篇如何快速掌握cel-go深入理解表达式语言的核心实现原理下一篇5分钟打造专业音乐播放器foobox-cn美化配置终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

别被建站公司坑了3000块,这3个免费工具搞定wordpress订单提醒功能
别被建站公司坑了3000块,这3个免费工具搞定wordpress订单提醒功能

别被建站公司坑了3000块,这3个免费工具搞定wordpress订单提醒功能 找建站公司,最怕的就是“功能定制费”。明明只是加个订单提醒,对方张口就是三千块起步,还得等一周。很多设计师转做前端或独立开发者,其实完全没必要为这种基础功能买单。… · 2026/9/27 23:35:11

PyTorch全连接网络实现垃圾邮件分类:从文本清洗到模型训练
PyTorch全连接网络实现垃圾邮件分类:从文本清洗到模型训练

简介:面向毕业设计及机器学习初学者,提供一套基于Pytorch的MLP全连接神经网络垃圾邮件分类完整工程,内含可直接运行的Python源码、spambase邮件数据集及配套图表。工程完成有监督学习下的二分类任务,利用PytorchViz将神经网络结构… · 2026/9/27 23:35:11

PyTorch全连接神经网络垃圾邮件分类实战:从文本清洗到模型训练
PyTorch全连接神经网络垃圾邮件分类实战:从文本清洗到模型训练

简介:这份PyTorch全连接神经网络垃圾邮件分类资源,面向需要完成毕业设计或课程综合实践的计算机相关专业学生,解决利用深度学习进行有监督文本分类的完整落地问题。项目基于Pycharm与Anaconda环境,使用Pytorch搭建MLP全连接神经网… · 2026/9/27 23:35:11

网站猜你喜欢怎么做:揭秘3种方案多少钱及避坑指南
网站猜你喜欢怎么做:揭秘3种方案多少钱及避坑指南

网站猜你喜欢怎么做:揭秘3种方案多少钱及避坑指南 找建站公司做“猜你喜欢”推荐模块,最怕的就是被忽悠报高价。很多老板问:“加个智能推荐功能到底多少钱?”是几千块的模板插件,还是几万块的定制开发?… · 2026/9/28 0:11:58

2026最新大型网站开发实例图解:从被黑挂马到稳健架构的实战复盘
2026最新大型网站开发实例图解:从被黑挂马到稳健架构的实战复盘

2026最新大型网站开发实例图解:从被黑挂马到稳健架构的实战复盘 凌晨三点,运维监控报警灯疯狂闪烁,你盯着后台日志,发现官网首页源码被替换成了赌博广告代码,甚至跳转链接都指向了境外非法站点。更让你冷汗直流的是,这种“网站被黑挂马不知道怎么办… · 2026/9/28 0:11:45

3个月搞定官网+排名,揭秘网站推广排名公司背后的源码下载陷阱
3个月搞定官网+排名,揭秘网站推广排名公司背后的源码下载陷阱

3个月搞定官网+排名,揭秘网站推广排名公司背后的源码下载陷阱 改个需求建站公司拖一周,源码下载还要加钱?这种憋屈事,我见得太多了。很多老板花几万块找所谓的 网站推广排名公司… · 2026/9/28 0:11:33

WordPress新版无法保存?5个排查步骤+最佳实践
WordPress新版无法保存?5个排查步骤+最佳实践

WordPress新版无法保存?5个排查步骤+最佳实践 刚接手一个重庆做建材外贸的站点,后台一进去就发现不对劲。客户急得直跺脚,说刚改完产品描述,点保存没反应,刷新页面全没了。更吓人的是,之前有次更新完插件,首页突然弹出一堆博彩广告,点进去… · 2026/9/28 0:10:57

军博做网站公司从零搭建官网避坑指南
军博做网站公司从零搭建官网避坑指南

军博做网站公司从零搭建官网避坑指南 网站做好了没人访问,这大概是很多站长最头疼的事。你花大价钱找 军博做网站公司 ,甚至自己 从零搭建 ,结果上线半个月,后台流量还是个位数。别急着怪算法,大概率是底子没打对。… · 2026/9/28 0:10:50

做游戏用什么电脑系统下载网站看3个实战案例
做游戏用什么电脑系统下载网站看3个实战案例

做游戏用什么电脑系统下载网站看3个实战案例 别再被那些花里胡哨的模板网站忽悠了,看着高大上,实际跑起来卡顿、加载慢,用户留不住。很多刚入行的运营或者小团队老板,总想着找个“做游戏用什么电脑系统下载网站”这种关键词直接套模板,结果上线后发现搜… · 2026/9/28 0:10:32

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

制作网页比较方便的软件怎么选?一文搞懂避坑指南
制作网页比较方便的软件怎么选?一文搞懂避坑指南

制作网页比较方便的软件怎么选?一文搞懂避坑指南 很多老板一上来就问:做个网站多少钱?但我反问他:你的域名买了吗?服务器租了吗?他一脸懵。这就是典型的“域名服务器搞不懂”。别急,今天咱们不聊虚的,直接 一文搞懂 那些让你头秃的技术名词。… · 2026/9/28 0:00:06

婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量
婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量

婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量 找婚恋网站建站公司,最怕的就是被坑高价。很多同行跟我吐槽,报价单上写得模棱两可,功能栏里全是“高级定制”、“专属UI”,结果落地全是套壳。今天不聊虚的,直接甩几个我经手的 实战案例… · 2026/9/28 0:00:19

济南做网站多少钱:3个案例拆解,防黑源码下载全攻略
济南做网站多少钱:3个案例拆解,防黑源码下载全攻略

济南做网站多少钱:3个案例拆解,防黑源码下载全攻略 上周济南一个做建材的老板找我,脸都绿了。他的官网首页弹出了赌博广告,后台被植入了挖矿脚本。他慌得问我:“网站被黑挂马不知道怎么办?能不能直接找之前的外包公司要源码下载,看看哪里被动了手脚?… · 2026/9/28 0:00:25

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码