跳到主要内容

API身份验证与TLS

节点通过HTTP Basic对磁盘上的机密文件保护其面向所有者的接口。钱包以相同方式保护其Owner API,使用自己的机密文件,且Owner API v3还需要一个通过钱包密码获取的令牌。外部接口不需要凭据,因为交互式转账需要接收方可被陌生人访问。TLS终止由运营者自行处理。

接口概览​

接口默认端口凭据调用方
节点/v1/*3413Basic,api_secret_path,每条路由均需,除GET /v1/version外本机调用
节点/v2/owner3413Basic,api_secret_path。单次get_status调用无需身份验证即可响应本机调用
节点/v2/foreign3413可选 Basic,foreign_api_secret_path任何读取链数据的客户端
钱包 Owner /v3/owner3420Basic、钱包的api_secret_path,以及加密信封内来自open_wallet的令牌本机调用
钱包 Owner /v2/owner3420Basic、钱包的api_secret_path。已由/v3/owner取代无。将监听器绑定到回环地址
钱包 Foreign /v2/foreign3415无向你付款的对手方

钱包的Foreign API接收一个slate,返回一个部分签名的slate,为配置为向该钱包支付的矿工构建coinbase,并报告其版本。在代理处限制对其的访问。

节点的/v1凭据覆盖整个前缀,包括在/v2/foreign上开放的链读取操作。唯一的例外是精确匹配GET /v1/version,该路径对任何人开放;对同一路径发起POST仍需凭据。参见v1 REST接口。

api_secret_path在每个二进制文件的配置中指向不同的文件。两个节点接口均读取节点的配置文件,即.api_secret。钱包的配置文件名为.owner_api_secret,用于保护钱包自身的Owner监听器。

钱包的Owner访问权限​

/v3/owner有两道验证关卡,调用必须同时通过两道。

第一道是监听器上的HTTP Basic身份验证。用户名为epic,密码为钱包.owner_api_secret的内容,realm为EpicOwnerAPI。它覆盖Owner监听器上除/v2/foreign之外的所有内容,包括/v3/owner和/v2/owner,并在任何方法执行前进行检查(controller/src/controller.rs:143)。注释掉钱包的api_secret_path后,此层将不会安装。

第二道是令牌。v3 trait中的每个方法都需要令牌(api/src/owner_rpc_s.rs:78),获取令牌需要完成ECDH握手,然后使用钱包密码调用open_wallet。参见加密握手。

第一次调用建立共享密钥。它仅携带Basic凭据,不携带其他内容:

curl -s -u epic:$(cat ~/.epic/main/.owner_api_secret) \
-d '{"jsonrpc":"2.0","method":"init_secure_api","params":{"ecdh_pubkey":"<your compressed public key, hex>"},"id":1}' \
http://127.0.0.1:3420/v3/owner

没有-u,监听器在握手开始前即返回401。如果钱包位于其他目录,将~/.epic/main替换为该钱包目录。

在该凭据之上,/v3/owner上的每个方法都需要token,令牌来自open_wallet,该调用需要钱包密码。owner_api_interface默认为127.0.0.1;如需远程访问,请通过隧道连接到回环地址。监听器为controller/src/controller.rs:123。

完整的方法列表、加密信封以及哪些调用会转移资产,详见钱包Owner API页面。

节点凭据​

节点的/v1前缀和/v2/owner使用HTTP Basic身份验证,用户名固定为epic,密码为机密文件的内容:

Authorization: Basic base64("epic:" + <secret file contents>)

节点在首次运行时创建~/.epic/<network>/.api_secret,并将api_secret_path指向该文件,因此无需配置即可使用:

curl -u epic:$(cat ~/.epic/main/.api_secret) \
-d '{"jsonrpc":"2.0","method":"get_status","params":[],"id":1}' \
http://127.0.0.1:3413/v2/owner

机密文件存储一个20字符的随机字母数字字符串,末尾无换行符(config/src/config.rs:84),比较操作为常数时间(basic_auth_matches())。realm在owner接口上为EpicAPI,在foreign接口上为EpicForeignAPI。任一二进制文件上被拒绝的调用均返回401,并附带WWW-Authenticate头部和JSON-RPC错误响应体:

{"jsonrpc": "2.0", "error": {"code": -32600, "message": "Unauthorized"}, "id": null}

以下两个调用无需凭据即可响应:

  • GET /v1/version,精确匹配该方法和路径(api/src/handlers.rs:118)。
  • 在/v2/owner上发起一个get_status,单独发送而非批量发送,params为[]或null,请求体不超过4 KiB。其返回状态与已通过身份验证的调用相同。其他任何方法、批量请求或无法解析的请求体均返回401(is_legacy_status_request())。

其余行为源于节点的默认关闭策略:

  • 注释掉api_secret_path,或指向不存在的文件时,没有可匹配的机密,因此所有受保护的调用无论是否携带-u均对所有人返回401。只有上述两个调用仍会响应。注释掉该键会锁定/v1和/v2/owner,而不会开放它们。
  • 空的.api_secret会以新值重新生成,而不是被读取为"无机密",因此清空文件并不会关闭身份验证(config/src/config.rs:96)。
  • OPTIONS在凭据检查之前直接透传,这正是CORS预检请求能够正常工作的原因。

节点Foreign接口的可选凭据​

foreign_api_secret_path使节点的/v2/foreign也需要凭据。自行创建机密文件并提供绝对路径:

head -c 40 /dev/urandom | base64 | tr -dc 'A-Za-z0-9' | head -c 20 > ~/.epic/main/.foreign_api_secret
[server]
foreign_api_secret_path = "/home/you/.epic/main/.foreign_api_secret"

realm为EpicForeignAPI,用户名仍为epic。验证方式:

curl -s -o /dev/null -w '%{http_code}\n' -X POST http://127.0.0.1:3413/v2/foreign
# 放置机密后返回401
epic-wallet 4.1.0 cannot use a node with a foreign secret

无论钱包自身的.api_secret中配置了什么,钱包向节点的/v2/foreign发送请求时从不携带凭据,因此它发起的所有链读取操作均返回401,并以Unauthorized (HTTP 401)停止运行。该错误提示检查node_api_secret_path,但这无济于事。对于钱包所连接的任何节点,不要创建foreign_api_secret_path所指向的文件(该键默认已设置,文件不存在时无害),或注释掉该键,并在代理层限制foreign接口的访问。

钱包向节点提交的凭据​

node_api_secret_path指向另一方:它是钱包持有的节点机密,默认值为<wallet dir>/.api_secret。钱包仅在除get_status之外的/v2/owner调用中发送该机密,且从不发送至/v2/foreign或/v2/tor(impls/src/node_clients/http.rs:115)。

实际上只有一个调用,get_onion_addresses,钱包在最终确认epicbox转账时调用它,以便通过Tor广播。机密缺失或不匹配会导致该查询返回空结果,钱包则改用普通方式广播。钱包向节点发出的其他所有请求——余额、输出(output)、内核(kernel)、广播交易以及同步检查——均指向无需凭据的端点。同步检查使用Foreign API的ready_for_txs,只有不支持该方法的节点才会改用未经身份验证的get_status。

因此,钱包的.api_secret与节点不同时,钱包仍可正常工作。节点返回401指向其他原因:节点上的foreign_api_secret_path配置问题(见上文),或节点版本早于4.1.0。第二种情况来自代码分析,未经实测:带有机密的4.0.x节点会将整个/v2/owner置于Basic auth之后,因此会拒绝钱包未经身份验证的get_status。

TLS​

两个二进制文件使用相同的一对参数,默认均已注释掉:

tls_certificate_file = "/path/to/fullchain.pem"
tls_certificate_key = "/path/to/privkey.pem"

设置证书后,监听器从HTTP切换为HTTPS。仅设置证书而不设置密钥会导致启动错误。证书以PEM链格式读取;密钥可以是PKCS#1、PKCS#8或SEC1 PEM格式。无法打开、无法解析或与证书不匹配的文件会导致进程停止,而不是回退到HTTP,因此错误的密钥对会在启动时明确报错。

内置的epic client子命令通过http://(src/bin/cmd/client.rs:160)与节点通信。如需连接TLS监听器,请使用curl。

下一步​