8 个版本
0.3.0 | 2021 年 4 月 15 日 |
---|---|
0.2.7 | 2021 年 3 月 9 日 |
#22 在 #trusted
在 2 个包中使用(通过 fluence-fork-libp2p-kad)
48KB
869 行
信任图
概述
在 Web 2.0 中,使用集中式 CA(证书授权中心)解决了访问控制和权限的问题。然而,考虑到 Web 3.0 的去中心化特性,这种问题变得尤为紧迫和具有挑战性。信任图是我们对这个挑战解决方案的看法。
信任图是开放 p2p 网络的信任底层:每个对等节点都可以获得类似 SSL 的证书,并在网络上推广。服务提供商和对等节点可以根据其证书集对待证书持有者。
信任图是一个基本组件,允许存储和管理证书,而无需关于如何决定信任谁以及将谁视为不可信的额外逻辑。
为什么它很重要?
在 p2p 网络中,对等选择和优先级的问题非常紧迫。如果没有对任何网络参与者的信任,我们无法可靠且可预测地使用网络。我们还应该标记并避免恶意节点。此外,我们还需要在运行时控制我们应用程序的访问和权限,以确保其连续运行而不会中断和重新部署。
它是什么?
信任图基本上是一个至少有一个根的定向图,顶点是节点 ID,边是两种类型的加密关系之一:信任和撤销。
根 是一个我们对它无条件信任直到它被移除的节点 ID,由节点所有者定义。每个根都有代表信任链最大长度的特征。
作为 到根的路径,我们考虑只有信任边的路径,给定以下规则:链 R > A > ... > C
如果 A 撤销了 C,则不是路径。
信任是一种加密关系,表示节点A信任节点B,直到这种信任到期或被撤销。信任关系是传递的。如果节点A信任节点B,而节点B信任节点C,则导致节点A间接信任节点C。信任关系意味着您基于自己的业务逻辑和选择的指标进行连接、计算或存储。
信任数据结构包含以下字段:
- 节点ID,信任颁发给
- 创建时间戳
- 过期时间戳
- 发行者签名,包含所有之前字段并已签名的签名
因此,信任是设计上已签名和防篡改的。
证书是从自签名根信任开始的信任链。考虑到信任和证书数据结构,可以追踪信任关系的链:证书中第一条信任的issued_for
字段表示根节点ID,第二项是根信任的对象,依此类推。因此,如果我们有一个证书中的链R->A->B->C
,它看起来像以下信任链:R->R
,R->A
,A->B
,B->C
。由于证书是签名的信任的组合,因此它是防篡改的。
因此,如果节点A在信任图实例中与节点B之间存在路径,则节点A被节点B信任。证书的选择是主观的,由节点所有者通过选择根和最大链长度来定义。目前,对于通用情况没有默认的指标。
撤销是一种加密关系,表示节点A认为节点C是恶意的或不可靠的。例如,包含从A到C的路径的所有链将不会被处理为有效。因此,如果A信任节点B,而B信任节点C,节点A对C的间接信任将不存在,否则会有。
每个节点都有一个权重。权重表示2的幂或零。如果没有从任何根到节点的路径,给定撤销,其权重为零。越接近根,权重越大。权重也是主观的,并在本地信任图范围内相关。
信任图是内建的,意味着每个节点都包含一个信任图实例和预定义的证书。
在加密关系方面,信任是传递的。另一方面,由于根的选择,每个网络参与者的信任和证书的子集是主观的。
如何在 Aqua 中使用它
如何导入
import "@fluencelabs/trust-graph/trust-graph-api.aqua"
import "@fluencelabs/trust-graph/trust-graph.aqua"
func my_function(peer_id: string) -> u32:
on HOST_PEER_ID:
result <- get_weight(peer_id)
<- result
如何添加根
set_root(peer_id:PeerId,max_chain_len: u32) ->SetRootResult
add_root_trust(node:PeerId,peer_id:PeerId,max_chain_len: u32) -> ?Error
让我们将我们的节点ID设置为中继上的根并添加自签名信任
func set_me_as_root(max_chain_len):
result <- add_root_trust(HOST_PEER_ID, INIT_PEER_ID, max_chain_len)
-- if you use peer_id different from INIT_PEER_ID
-- you should add keypair in your Sig service
if result.success:
-- do smth
Op.noop()
else:
-- handle failure
Op.noop()
- 您还可以使用
set_root
+add_trust
来实现相同的目标 - 如何将密钥对添加到Sig服务
- 只有服务所有者才能添加根
max_chain_len
指定根链中的信任数量。对于只包含根信任的链,为零。
如何颁发和添加信任
issue_trust(issuer:PeerId,issued_for:PeerId,expires_at_sec: u64) -> ?Trust, ?Error
import_trust(trust:Trust,issuer:PeerId) -> ?Error
add_trust(node:PeerId,issuer:PeerId,issued_for:PeerId,expires_at_sec: u64) -> ?Error
让我们颁发信任并将其导入我们的中继
func issue_trust_by_me(issued_for: PeerId, expires_at_sec: u64):
trust, error <- issue_trust(INIT_PEER_ID, issued_for, expires_at_sec)
if trust == nil:
-- handle failure
Op.noop()
else:
on HOST_PEER_ID:
error <- import_trust(trust!, INIT_PEER_ID)
-- handle error
add_trust
是issue_trust
和import_trust
的组合- 如果您想通过不是
INIT_PEER_ID
的方式颁发信任,请查看 Sig 服务的 文档
如何撤销信任
issue_revocation(revoked_by:PeerId,revoked:PeerId) -> ?撤销, ?Error
import_revocation(撤销:撤销) -> ?Error
revoke(node:PeerId,revoked_by:PeerId,revoked:PeerId) -> ?Error
让我们通过我们的对等节点 ID 撤销一些对等节点
func revoke_peer(revoked: PeerId):
revocation, error <- issue_revocation(INIT_PEER_ID, revoked)
if revocation == nil:
-- handle failure
Op.noop()
else:
on HOST_PEER_ID:
error <- import_revocation(revocation!)
-- handle error
revoke
是issue_revocation
和import_revocation
的组合- 如果您想通过不是
INIT_PEER_ID
的方式颁发撤销,请查看 Sig 服务的 文档
如何获取证书
get_all_certs(issued_for:PeerId) ->AllCertsResult
get_all_certs_from(issued_for:PeerId,issuer:PeerId) ->AllCertsResult
get_host_certs() ->AllCertsResult
get_host_certs_from(issuer:PeerId) ->AllCertsResult
让我们获取我们向我们的中继对等节点 ID (HOST_PEER_ID) 颁发的所有证书
func get_certs_issued_by_me() -> AllCertsResult:
on HOST_PEER_ID:
result <- get_host_certs_from(INIT_PEER_ID)
<- result
get_host_certs
只是get_all_certs
(HOST_PEER_ID) 的别名_from
调用结果只包含由issuer
颁发的证书
如何获取权重
get_weight(peer_id:PeerId) ->WeightResult
get_weight_from(peer_id:PeerId,issuer:PeerId) ->WeightResult
让我们获取我们的中继为我们包含信任的证书的权重
func get_our_weight() -> ?u32, ?string:
weight: ?u32
error: ?string
on HOST_PEER_ID:
result <- get_weight_from(INIT_PEER_ID, HOST_PEER_ID)
if result.success:
weight <<- result.weight
else:
error <<- result.error
<- weight, error
get_weight
返回所有证书中的结果,而get_weight_from
只返回包含发行者信任的证书
如何在 TS/JS 中使用它
-
在 Aqua 的 文档 中添加
export.aqua
-
将以下内容添加到您的依赖项中
@fluencelabs/trust-graph
@fluencelabs/aqua
@fluencelabs/aqua-lib
@fluencelabs/fluence
@fluencelabs/fluence-network-environment
-
导入依赖项
import * as tg from "./generated/export";
import { Fluence, KeyPair } from "@fluencelabs/fluence";
import { krasnodar, Node } from "@fluencelabs/fluence-network-environment";
- 创建一个客户端(如果您是节点所有者,请指定密钥对 链接)
await Fluence.start({ connectTo: relay /*, KeyPair: builtins_keypair*/});
- 添加一个根并颁发根信任。
let peer_id = Fluence.getStatus().peerId;
let relay = Fluence.getStatus().relayPeerId;
assert(peer_id !== null);
assert(relay !== null);
let max_chain_len = 2;
let far_future = 99999999999999;
let error = await tg.add_root_trust(relay, peer_id, max_chain_len, far_future);
if (error !== null) {
console.log(error);
}
- 默认情况下,使用客户端的私钥签名信任/撤销。要使用不同的密钥签名,请参阅 Sig 服务的 文档。
// issue signed trust
let error = await tg.issue_trust(relay, peer_id, issued_for_peer_id, expires_at_sec);
if (error !== null) {
console.log(error);
}
用例
创建一个可信子网络
您可以使用您选择的对等节点或选择指标组织子网络。因此,您可以将对等节点(或密钥)给出的信任视为证据。
让我们考虑我们拥有对等节点 A、B 和 C
- 选择对等节点 A 作为权威,将其设置为所有对等节点的本地 TrustGraph 的根
- 由对等节点 A 自签名的信任作为根信任颁发并放置
- 由对等节点 A 向对等节点 B 和 C 颁发信任,并将它们放置在所有对等节点上
- 因此,对于调用
get_weight_from(targetPeer, peerA)
将反映目标对等节点是否在子网络 ABC 中
服务权限管理
您可以在运行时指定谁可以根据本地 TrustGraph(证书、权重)访问服务功能。根据 四联体,可以检查证明的来源。例如,只有权重非零的对等节点可以执行服务函数 trusted_call(weight: WeightResult) -> u8
。
因此,如果您想拥有服务权限管理,您应该遵循以下步骤
- 将
WeightResult
从 TrustGraph 传递到您需要控制的函数
...
weight_result <- get_weight(INIT_PEER_ID)
result <- MyService.trusted_call(weight_result)
...
- 在您的服务内部,您需要检查类似 这里 的四元组,以确保它们是由本地 TrustGraph 生成的
- 将
INIT_PEER_ID
或另一个选择的关键字作为根节点添加 - 向可以调用此函数的节点发放信任
func grant_access(issued_for: PeerId, expires_at_sec: u64):
error <- add_trust(INIT_PEER_ID, issued_for, expires_at_sec)
if error != nil
-- handle error
标记可信对等节点,并仅在节点上执行计算
查看 示例
- 如何在 TS/JS 中调用
trust-graph
函数 - 逐步描述
README
常见问题解答
-
权重可以在时间过程中改变吗?
- 如果到根节点的最短路径发生变化,在信任过期、导入或吊销的情况下,权重也会发生变化。
-
零权重意味着什么?
- 零权重表示没有信任,也没有从任何根节点到目标节点的路径。
-
我们如何解释证书和/或节点权重?
- 证书包含从根节点到我们正在寻找的目标节点的路径。权重代表这些证书的存在以及节点与根节点之间的接近程度。
-
权重是如何计算的,基于什么反馈?
- 权重是基于从根节点存在的信任链计算的。例如,如果我们有一个最大链长度等于 4 的根节点,并且有一个链
R -> A -> B -> C
,那么相应节点的权重分别是8
、4
、2
、1
。如果没有路径变化,权重相同。只要没有度量标准,所有信任/吊销逻辑都是 TrustGraph 用户的责任。
- 权重是基于从根节点存在的信任链计算的。例如,如果我们有一个最大链长度等于 4 的根节点,并且有一个链
-
我该如何将所有权重设置为不可信,然后随着时间的推移逐渐增加对节点的信任?
- 默认情况下,所有节点都是不可信的。信任未度量,权重代表节点与根节点的距离,权重越大,越接近根节点,因此如果您想增加目标节点的权重,您应该从根节点或比该节点更接近根节点的节点那里获得信任。
-
我如何知道其他节点是否使用相同的流程来更新权重?
- 基于包含不可变签名的信任证书进行本地计算。权重是主观的,并且只在本地对精确的节点有意义。
-
我可以启动自己的信任图实例,还是有可用的全局版本?
- 每个 Fluence 节点都捆绑了一个内置的 TrustGraph 实例,但如果您是节点所有者,您可以将任何服务更改或删除。
API
高级 API 在 trust-graph-api.aqua 模块中定义。API 参考很快将在文档中提供。
目录结构
-
src
是包含所有信任图逻辑的主要项目 -
keypair
目录是抽象的密码学层(密钥对、公钥、签名等) -
service
是一个提供marine
API 的包,可以编译为 Wasm 文件。它使用SQLite
作为存储 -
example
是一个js
脚本,展示了如何使用信任图来标记节点 -
builtin-package
包含了本地或通过 CI 生成内置包的蓝图、配置和脚本 -
admin
是一个js
脚本,用于生成builtin-package/on_start.json
文件,其中包含 Fluence Labs 节点的证书
学习 Aqua
依赖项
~21MB
~498K SLoC