#security #hash #web #utility #server-side #server-client

bin+lib spow

服务器和客户端的工作量证明 + WASM

4 个版本 (2 个破坏性更新)

0.3.0 2024年7月17日
0.2.0 2023年12月25日
0.1.1 2023年12月19日
0.1.0 2023年12月19日

WebAssembly 中排名 #189

Download history 132/week @ 2024-04-24 166/week @ 2024-05-01 116/week @ 2024-05-08 131/week @ 2024-05-15 160/week @ 2024-05-22 75/week @ 2024-05-29 98/week @ 2024-06-05 120/week @ 2024-06-12 127/week @ 2024-06-19 108/week @ 2024-06-26 73/week @ 2024-07-03 106/week @ 2024-07-10 226/week @ 2024-07-17 157/week @ 2024-07-24 126/week @ 2024-07-31 75/week @ 2024-08-07

每月下载量 595
leptos-captcha 中使用

Apache-2.0 许可

90KB
618 行 代码

spow - 服务器和客户端工作量证明 + WASM

为什么?

每个人都喜欢验证码,对吧?嗯,并不是那么喜欢。它们绝对是令人讨厌的,有时甚至人类也无法解决,因为某些东西只是处于边缘,或者服务器另一边只是认为你很愚蠢,给你另一个。
它们提供了一个绝对糟糕的用户体验,它们存在的唯一原因就是防止垃圾邮件。

工作量证明(PoW)解决的是类似的问题,但它对用户体验没有实际影响,但方式不同。它不是让用户解决一个谜题,而是让您的计算机为您解决。用户除了等待一小段时间直到谜题自动解决之外,没有其他事情可做。

背后的想法是,对于任何机器人或垃圾邮件发送者来说,为单个动作做这件事的成本实在太高了。如果您只是使用应用程序或网页的普通人,您不在乎,甚至不会注意到您的计算机时不时必须做的这项小工作量,但如果您是垃圾邮件发送者,同时在数百万个应用程序上同时这样做,这将是完全不可能的。

这里确实有一些非常复杂的解决方案,比如我非常喜欢的 Cloudflare Turnstile。然而,这个小小的 crate 使得在保持相同用户体验的同时,可以轻松自托管并集成到您的 API 中,而不需要任何外部依赖。

如何?

在后端,这不能更简单了

  1. 在应用程序启动时,您只需调用一次 Pow::init()Pow::init_random()。这将初始化用于签名挑战的秘密,这样您就知道挑战是否确实来自您的后端,或者其他人只是自己生成的一个。
  2. 如果您想在某个时候为客户创建一个新的挑战,那么您只需要使用以下任一方法创建一个新的PoW:使用Pow::new()Pow::with_difficulty()。这将创建一个随机且唯一的PoW,可以将其转换为客户的挑战,使用以下任一方法:.build_challenge().to_string()
  3. 将挑战字符串发送给客户端
  4. 客户端需要做一些工作来解决这个谜题。为此,您可以使用wasm或仅JS版本。这些位于frontend/文件夹中,可以直接在任何前端中使用。如果没有真正充分的理由不使用它,您应该始终使用wasm版本,因为它比仅JS快约20倍。这意味着您可以使用更高的难度而不会影响用户体验。
  5. 当您从客户端收到已解决的谜题时,只需使用Pow::validate()进行验证。这将...
    • 验证版本标签
    • 验证难度(必须是10 - 99)
    • 验证PoW的过期时间(在Pow::new()期间设置)
    • 验证挑战实际上来自同一后端且未被更改
    • 使用给定的难度验证谜题结果本身

...就是这样。

在幕后,spow使用修改后的扩展版Hashcat PoW算法,该算法也被用于例如比特币区块链。

难度

难度是一个介于10和99之间的整数。默认值为20
每一步,解决谜题的时间将以指数级增加,而后端验证它的时间将始终保持不变,且与难度无关。

您想设置多高很大程度上取决于您的用例,您的应用程序将在哪里运行(强大的桌面机器、笔记本电脑或智能手机上的应用程序)以及您想让用户等待多久。

这些谜题的工作方式是,您可能会非常幸运并快速解决它,或者运气不佳,需要比平均值长得多。所有这些都取决于创建PoW时的随机值。为了找到合适的值,您应该在目标系统上测试很多不同的PoW,以找到合适的平均值。
此项目有一个bin目标,它实际上在后台执行此操作。您可以使用例如cargo run --release 20 100运行它,它将解决100个难度为20的随机生成的谜题,并在最后打印出平均值。但请注意,后端代码的性能比浏览器中的代码要高得多。在首次测试中,浏览器中的wasm版本需要大约2.5 - 3倍的时间,这是在优化后的纯Rust代码中后端所需的时间。JS版本比wasm慢约20倍。

examples”文件夹包含了一个使用Svelte的小型前端演示。尽管它使用的是硬编码的挑战,但截至目前它只展示了如何解决谜题。它并不能很好地指示解决这些难度谜题所需的平均时间。

依赖项

约1.2-2.1MB
约41K SLoC