9 个版本 (4 个破坏性更新)
0.5.0 | 2021 年 6 月 9 日 |
---|---|
0.4.1 | 2021 年 6 月 9 日 |
0.3.1 | 2021 年 5 月 28 日 |
0.2.0 | 2021 年 5 月 18 日 |
0.1.2 | 2021 年 4 月 22 日 |
在 #authenticating 中排名第 4
6MB
85K SLoC
sig-proxy - 基于签名的认证代理
这是什么?
sig-proxy
是一个 HTTP 服务的代理,它验证签名,为这些服务提供身份验证层。它还具有针对客户端的功能,可以自动将签名注入请求中。
我能用它做什么?
截至 0.2
,支持智能合约。这些允许使用代币作为可转移许可,用于受控服务。
一些示例
- 一个允许授权用户下载资产的 OCI 仓库。
- 一个允许项目支持者获得优先支持的缺陷跟踪器。
- 一个允许客户按比例投票权决定功能开发的项目的路线图。
- 一个需要 N-of-M 授权用户才能部署到生产环境的部署管道。
- 一个具有去中心化许可的应用商店,其中作者保留许可控制权,而不是平台。
- 一个数字图书馆,借阅由代币管理,归还由智能合约强制执行。
为什么存在这个?
这实际上是两个问题,让我们来分析一下...
为什么这个概念有用?
基于签名的身份验证避免了基于密码身份验证的许多陷阱。服务器只需要知道公钥,如果这些公钥泄露了...谁在乎?它们是 公开 键。
假设两种情况都有合理的用户界面,用户可以像更改密码一样轻松地旋转密钥。他们可以将部分权限委派给其他密钥(就像我们在其他地方使用访问令牌一样)。
密钥是用户 生成 的,而不是用户 记忆 的。这完全消除了密码重用等问题。
为什么这种方法实用?
以代理的形式实现这一功能,允许它在不修改的情况下应用于大多数现有的 HTTP(S) 应用程序。
将签名与验证分离,可以更细致地控制哪些可以访问私钥。这也意味着代理只需在需要的地方使用。如果客户端应用程序可以本地处理签名,那么它应该这样做。
将此作为一系列可组合的中间件实现,使其简单易扩展,并(负责任地)尝试新功能。
如果需要,它可以部署为边车容器。
我如何获得这个卓越的工具?
cargo install sig-proxy
或者,如果你更喜欢 Docker
docker pull colstrom/sig-proxy:0.3.1
我如何使用它?
首先,你需要某种类型的服务,你希望将代理放在其前面。
为了演示和开发目的,sig-proxy
包含了一个嵌入的示例服务,该服务将在响应体中打印请求头。
$ sig-proxy demo
tide::log Logger started
level DEBUG
tide::server Server listening on http://127.0.0.1:8080
接下来,您需要有一个可用于与 sig-proxy
交互的以太坊 JSON-RPC (Web3) 服务。对于本地使用,Ganache 是一个非常好的选择,因此本文档的其余部分假定您已使用 Ganache。
首先,选择您想要用于签名请求的地址:
然后,找到此地址的私钥:
将此私钥添加到环境变量中
使用 fish
set -x SECRET_KEY_DATA PUT_THE_DATA_HERE
使用复古壳如 bash
export SECRET_KEY_DATA=PUT_THE_DATA_HERE
现在您可以运行它了!让我们看看帮助信息
$ sig-proxy web3 --help
sig-proxy-web3 0.1.0
Runs the proxy service
USAGE:
sig-proxy web3 [FLAGS] [OPTIONS]
FLAGS:
-h, --help Prints help information
-V, --provides-account-verification verify signatures and provide account addresses
-B, --provides-balances provide account balances
-S, --provides-signatures provide signatures
--version Prints version information
OPTIONS:
--address-header <name> [env: ADDRESS_HEADER=] [default: X-Web3-Account-Address]
-b, --backend <url> [env: BACKEND=] [default: http://127.0.0.1:8080]
--balance-header <name> [env: BALANCE_HEADER=] [default: X-Web3-Account-Balance]
--balance-maximum <amount> [env: BALANCE_MAXIMUM=]
--balance-minimum <amount> [env: BALANCE_MINIMUM=]
-u, --balance-scale <unit> [env: BALANCE_SCALE=] [default: Wei]
-c, --challenge <phrase> [env: CHALLENGE=] [default: totes-legit]
-l, --listen <address> [env: LISTEN=] [default: 0.0.0.0:8000]
-K, --secret-key-data <hex> [env: SECRET_KEY_DATA=]
-k, --secret-key-file <path> [env: SECRET_KEY_FILE=]
--signature-header <name> [env: SIGNATURE_HEADER=] [default: X-Web3-Signature]
-w, --web3-rpc-url <url> [env: WEB3_RPC_URL=] [default: ws://127.0.0.1:7545]
所有这些选项都是可选的,尽管如果没有启用至少一个选项,它将不会执行任何操作。让我们关注两种情况。
情况 1 - 提供签名
在这种模式下,sig-proxy
将为它处理的每个请求添加一个签名。
$ sig-proxy web3 --provides-signatures
tide::log Logger started
level DEBUG
tracing::span new
tracing::span build
isahc::agent agent waker listening on 127.0.0.1:61558
isahc::agent agent_thread; port=61558
isahc::agent agent took 409.705µs to start up
tide::server Server listening on http://0.0.0.0:8000
尽管如此,需要秘密(私钥)来签名这些请求。这可以通过文件(--secret-key-file
)或十六进制字符串(--secret-key-data
)提供。如果两者都提供了,则忽略 --secret-key-file
。这些也可以通过环境变量提供,这正是我们上面所做的那样。
此密钥用于对挑战短语(目前由 --challenge
提供)进行签名,该短语应被客户端和服务器所知晓。它不需要是私有的。
此签名将使用由 --signature-header
提供的头部添加到请求中。
情况 2 - 提供账户验证
在这种模式下,sig-proxy
预期请求包含一个签名头,并将拒绝不包含该头的请求。这些头将被验证,并将在每个请求中添加用于签名的地址。
请注意,客户端没有明确提供地址。他们签署了一个双方都知晓的挑战短语,签名的地址可以从有效的签名中恢复。
$ sig-proxy web3 --provides-account-verification
tide::log Logger started
level DEBUG
tracing::span new
tracing::span build
isahc::agent agent waker listening on 127.0.0.1:56181
isahc::agent agent_thread; port=56181
isahc::agent agent took 312.747µs to start up
tide::server Server listening on http://0.0.0.0:8000
如果签名有效,则使用由 --address-header
提供的头部将地址添加到请求中。假设后端知道如何处理此头。例如,您可以使用 X-Remote-User
头部将 sig-proxy
与 Dex 集成。
情况 3 - 提供账户余额
在这种模式下,sig-proxy
预期请求包含一个账户头,并拒绝不包含该头的请求。它将处理每个请求中该头提供的地址的余额。
$ sig-proxy web3 --provides-balances
tide::log Logger started
level DEBUG
tracing::span new
tracing::span build
isahc::agent agent waker listening on 127.0.0.1:54608
isahc::agent agent_thread; port=54608
isahc::agent agent took 313.524µs to start up
tide::server Server listening on http://0.0.0.0:8000
默认情况下,这并不关心余额是多少,它只是将余额添加到由 --balance-header
提供的头部。但是,有一些选项可以基于余额限制访问。
可以使用 --balance-minimum
选项来要求最小余额。这可以用作“参与游戏”的一种方式,通过要求非零余额(可能有助于防止机器人或协助速率限制),或者如果您出于某种原因只想让大玩家访问。
可以使用 --balance-maximum
选项来拒绝余额超过特定金额的账户。这可以用来限制风险,或者如果您愿意,只让普通人访问。
可以使用 --balance-unit
选项来方便地缩放上述限制。一个 Gwei 有多少个零?不需要记住,只需设置 --balance-unit=Gwei
,sig-proxy
就会内部进行缩放。不过,余额头信息仍然以 Wei 表示。
注意
上面的例子展示了如何独立使用这些功能,但它们都被实现为可组合的中间件。您可以在单个进程中启用所有这些功能。同时在同一个进程中使用签名和验证看起来有点荒谬,但您完全可以这样做。
试试看吧!
假设您已启用所有功能,并且代理位于演示应用程序之前,如果您使用 curl
查询每个应用程序,您将看到如下内容
直接查询演示应用程序
$ curl -s http://127.0.0.1:8080 | sort
accept: ["*/*"]
host: ["127.0.0.1:8080"]
user-agent: ["curl/7.64.1"]
通过代理查询
$ curl -s http://127.0.0.1:8000 | sort
accept-encoding: ["deflate, gzip"]
accept: ["*/*"]
content-length: ["0"]
content-type: ["application/octet-stream"]
forwarded: ["by=127.0.0.1:8000;for=\"127.0.0.1:52698\";host=127.0.0.1:8000;proto=http"]
host: ["127.0.0.1:8000"]
user-agent: ["curl/7.64.1"]
x-web3-address: ["24f9f97c9e540fed57ef81f6c9aeabdb6fc73acd"]
x-web3-balance: ["100000000000000000000"]
x-web3-signature: ["krpQZO9WpgAEso2uk6eAKDy29QjeVtr+gdDZ7iG4bFkYiTfNvTvU5l4bb2iod5F4Ab8a8tJqzXHSXLkyz9U/gRs="]
智能合约
嵌入式预设
为了帮助您开始使用,sig-proxy
集成了一些来自 OpenZeppelin 项目的预设。这些预设解决了一些更常见的用例,并且根据 OpenZeppelin 文档,它们是生产就绪的。
目前包括五个预设,以及部署和与每个预设交互的实用工具。这些可以在 contract
子命令下找到。
为了帮助您确定哪个合约是合适的,请检查 guide
子命令。在那里,您将找到一个交互程序,它会问您几个简单的问题,并提供推荐。
路线图
- 0.1 - 初始发布,包含 Web3 账户验证
- 0.2 - 支持代币标准
- 0.3 - 智能合约可观察性
愿望清单(无特定顺序)
TLS 支持
- 用随机挑战替换固定消息,添加非ces和过期时间等。
可选端点用于在浏览器中支持嵌入式脚本。
- 使用 Web Crypto API 进行密钥生成和签名。
- 使用 Web Storage API 进行密钥存储。
- 使用 Fetch API 进行头信息操作和身份验证流程。
X509 支持
- 这会提供一种替代方案,当选择信任链模型时。
PGP 支持
- 这会提供一种替代方案,当选择信任网模型时。
许可
sig-proxy
在 MIT 许可下可用。有关完整内容,请参阅 LICENSE.txt
。
sig-proxy
集成了来自 OpenZeppelin Contracts 的合约 ABI 规范和文档摘录。这些内容也根据 MIT 许可证条款分发 此处。
依赖
~47-65MB
~1M SLoC