Cap,一个基于PoW的自托管验证码系统
前言
最近发现一款开源的自托管验证码系统,研究了下觉得设计思想很有趣,打算写一篇博文分享一下。
什么是Cap
Cap 是一款自托管的验证码系统,用隐形的工作量证明替代了传统的图像拼图。用户只需点击一个复选框,工作量便会在其浏览器中静默运行,而用户的任何数据都不会离开你的服务器。无需谷歌、无遥测、无按次收费。
项目地址:https://trycap.dev
下面是我自己部署的一个demo:
SHA-256版:
RSW版:
验证流程
首先,客户端会向验证码服务器发起请求,拿到挑战。
然后客户端会在本地完成完成PoW,以及运行挑战里附带的JavaScript程序来验证浏览器环境。
完成指定轮数的PoW和浏览器环境验证后,向验证码服务器发送结果。
验证码服务器完成校验后,下发token。
此时用户浏览器再携带token向资源服务器发起实际请求。
资源服务器收到请求后使用向验证码服务器验证token正确性。
验证码服务器回应验证情况,资源服务器确认验证成功后允许请求。
什么是PoW
以下是维基百科 工作量证明的解释
工作量证明(Proof-of-Work,PoW)是一种对应服务与资源滥用、或是阻断服务攻击的经济对策。一般要求使用者进行一些耗时适当的复杂运算,并且答案能被服务方快速验算,以此耗用的时间、设备与能源做为担保成本,以确保服务与资源是被真正的需求所使用。此概念最早由Cynthia Dwork和Moni Naor于1993年的学术论文提出,而工作量证明一词则是在1999年由Markus Jakobsson与Ari Juels.所发表。现时此技术成为了加密货币的主流共识机制之一,如比特币所采用的技术。
工作量证明系统的核心特性在于其非对称性:证明者需完成适度困难(但可行)的计算工作,而验证者能极高效地验证结果。Hal Finney于2004年透过“可重用工作量证明”(RPOW)概念将此机制应用于数位代币,采用160位元SHA-1演算法。
为什么是PoW
下面是Cap官网的原话:
Every CAPTCHA can eventually be solved, whether by AIs, algorithms, reverse-engineering and spoofing fingerprints, or humans paid via CAPTCHA farms, and this results in an endless cat-and-mouse game between attackers and defenders. The crucial difference lies in the cost imposed on attackers.
Cap’s goal is to make automated abuse expensive and hard while keeping the experience fast and virtually invisible for real users. Proof-of-work is a perfect balance for this issue, stopping abuse by requiring computational effort rather than relying solely on human verification methods that bots continuously learn to mimic.
Imagine sending 10,000 spam messages costs $1, potentially earning $10 – a profitable venture. If Cap increases the computational cost so that sending those messages now costs $100, the spammer loses $90. This eliminates the financial incentive.
Cap’s proof-of-work is heavily inspired by Hashcash. Our instrumentation challenges are inspired by Twitter and YouTube’s own custom challenges.
简而言之,就是通过PoW,增加攻击者的成本,拉低其收益。让原来一次攻击只要花费1块钱,变成10块钱甚至100块钱。从而消除掉攻击者的动机。
最直观的就是,通过PoW,让原来一秒可以向一个端口请求一万次的脚本,强行限制到一秒请求两次,甚至两秒请求一次,让其效率约等于人工手动点击。
而且相较于传统验证码,我觉得它的另一个亮点是——Open
它的整个工作流程都是透明且公开的,没有混淆,没有对抗。
它就这样明晃晃的摆在那,但是你却无可奈何,必须要消耗掉一定的资源才能完成。
就像柯克霍夫原则(Kerckhoffs’s principle)。
好的加密方法绝不依赖闭源,一个真正强大、优秀的加密算法,不仅不怕开源,反而必须开源。
只有经过全球顶尖密码学家和黑客长年累月的公开攻击和审查却依然屹立不倒,才能证明它是安全的。
也因为Open,所以完全不惧开源。
还有一个亮点,也是Cap主要亮点之一——隐私友好
因为PoW主打的是资源消耗,完全不需要任何个人信息参与和用户行为判定
可以在https://trycap.dev/guide/compliance.html看到
用户数据始终不会离开你的基础设施。终端用户无需使用Cookie或追踪机制,验证流程中无第三方调用,工作量证明完全在访客浏览器中运行。
PoW工作原理
Cap有好几种工作模式,这里举例最简单的一种
1 | const tokenFnv = fnv1a(token); // ① FNV-1a(token全文) |
然后暴力枚举 SHA-256 前缀匹配
假设 target = “0000”(d=4),salt = “a1b2c3…”:
n=0: SHA-256(“a1b2c3…0”) → c4f8… 前缀不匹配
n=1: SHA-256(“a1b2c3…1”) → 9e2d… 前缀不匹配
n=2: SHA-256(“a1b2c3…2”) → 00007f… 前缀匹配
那么答案就是2
客户端要做的,就是根据题目要求,找到一个n,使得符合题目对于哈希前缀的要求。
众所周知,密码学哈希函数有一个著名的特性叫雪崩效应(Avalanche Effect),哪怕仅仅将输入数据改变了1个比特,输出的256位哈希值也会发生翻天覆地的、毫无规律的改变。
因此无法通过前一个值预测后一个值是什么,只能老老实实花时间算。
而出题者只需要根据你的答案重新算一次,就知道是不是符合题目的要求了,这也体现了PoW中非对称特性。
另外我们也可以进行一个期望计算:
SHA-256的输出结果在整个可能的值域[0,(2^256)-1]里是均匀分布的,而且每次计算只有成功与失败两种结果,每次计算因为雪崩效应也是独立的,因此它是契合几何分布的。
例如d为4,要求前四个字符为某个特定值(假设为0000)
哈希值的每一位出现 0 的概率是 。
要哈希值的前四个字符连续都是0,那么概率就是相乘:
根据几何分布的期望公式 ,期望值就是:
也就是平均要计算65536次哈希,才能找到一个前缀为四个0的合法哈希。
优化
众所周知,SHA-256这种算法,GPU算起来最快了。因此Cap还支持RSW时间锁谜题算法,专门用来抗GPU。
具体算法原理这里就不展开了。
不过目前RSW还处于实验阶段,并且不是默认开启的。
缺点
与其说是缺点,我觉得应该是有些人对于Cap的设计理念理解错了。
Cap的核心理念是通过PoW来提高攻击成本,但它并没有阻止脚本程序的功能。
我让AI写了个python解题脚本,测试参数如下:
- Challenge protocol:SHA-256
- Difficulty:4
- Challenge count:80
- Enable instrumentation challenges
- Attempt to block headless browsers
- Block non-browser user agents
- Require browser headers
不考虑出题和验证,以及传输的时间,在使用纯CPU计算下:
PoW工作量证明花费4s19',调起浏览器完成浏览器环境检测1s22'


可见用脚本完全可以实现自动化,只是原来一次一秒可以打几千发,现在只能老老实实五秒一发了。
另外如果用cuda写结合GPU算,时间应该会更短。
后记
Cap还是蛮好玩的。
Use this card to join MyBlog and participate in a pleasant discussion together .
Welcome to GoodBoyboy 's Blog,wish you a nice day .
