> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/contributor/contributor-zh/ren-zheng/authchain.md).

# 认证链

Decentraland 协议中的许多操作都需要或受益于由用户的以太坊账户签名进行授权。例如：

1. 上传任意 [实体](https://github.com/decentraland/docs/blob/main/content/entities.md) 他们拥有的（例如他们的个人资料）。
2. 向第三方服务进行身份验证。
3. 授权代理代表他们行事。

要执行这些操作，用户和代理必须对描述其意图的载荷进行签名，并生成一个 *认证链*.

## 简介

认证链封装了一系列验证步骤，每一步都依赖于前一步成功验证。对于任何受限操作，要生效，验证者必须将所有步骤视为有效。

每条链都从识别用户开始，并以一个表示所请求操作的已签名载荷结束。因此，最小的链包含两个元素，分别表示：

```md
1. 权限主体是以太坊账户 <user-address>
2. 载荷是 <payload>，由 <user-signature> 授权
```

通过验证签名的公钥与该地址对应，可以评估这条基础链。在这种情况下，它等同于普通签名。

当用户授权代理代表他们行事时，链中会出现中间步骤。例如，只有一次委托的链会表示：

```md
1. 权限主体是以太坊账户 <user-address>
2. 代理是 <delegate-address>，由 <user-signature> 授权，直至 <date>
3. 载荷是 <payload>，由 <delegate-signature> 授权
```

当代理再授权自己的代理时，链会更长。换句话说，授权是可传递的。

{% hint style="info" %}
你可以把认证链类比为 HTTPS 中使用的 TLS 证书链，其中用户相当于根权威。
{% endhint %}

这种单一代理链是 Decentraland 中最常见的授权形式，因为用户会为其 World Explorer 授权一个密钥，从而避免必须用其以太坊账户为每个单独操作签名。

### 构建链 <a href="#constructing" id="constructing"></a>

认证链中的每一步都包含三项信息：一个 `类型`、一个 `负载` 以及相应的 `签名`.

| 字段   | 值                             |
| ---- | ----------------------------- |
| `类型` | 某个类型的名称（[见下文](#types)).       |
| `负载` | 一个依赖于类型的字符串。                  |
| `签名` | 以下内容的十六进制编码以太坊签名 `负载`，以 `0x`. |

{% hint style="info" %}
由于认证链最常见的序列化形式是 JSON 数组，下面的示例以该形式展示。参见 [传输链](#transmitting) 了解更多详情。
{% endhint %}

### 第一步：识别

第一步用于识别原始权威（即用户），必须满足以下条件：

1. 该 `类型` 为 [`SIGNER`](#SIGNER)
2. 该 `负载` 是编码后的以太坊账户。
3. 该 `签名` 为空。

例如：

```json
// 任何认证链中的第一步：
{
  "type": "SIGNER",
  "payload": "0xdB055877e6c13b6A6B25aBcAA29B393777dD0a73",
  "signature": ""
}
```

第二步必须携带一个 `签名` 来自该账户、用于其 `负载`.

### 中间步骤：委托

当代理代表用户行事时，会为每个代理在链中间添加一项。这些步骤的条件是：

1. 类型是 [`ECDSA_EPHEMERAL`](#ECDSA_EPHEMERAL)
2. 该 `负载` 是一个特制文本（见下文）。

该 `负载` 其设计目标是易于阅读和解析，因为人类（在使用其钱包界面时）和程序（在构造和验证时）都必须处理它。它恰好包含 3 行区分大小写的纯文本：

```md
<purpose>
临时地址：<delegate-address>
过期时间：<date>
```

例如，这是一段 World Explorer 在登录时使用的典型载荷，它会生成临时代理密钥供用户批准：

```
Decentraland 登录
临时地址：0xBB9aDF0183b1742196A4Aa55622D5838f4f483a7
过期时间：2023-02-25T13:00:19.730Z
```

请注意：

1. 该 `临时地址` 不需要是区块链中一个真正持有资金的以太坊账户。该字段可以仅表示一个临时公钥。
2. 该 `过期时间` 是一个序列化的日期时间，采用 [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) 格式。它不必是 UTC。
3. 由于该过期时间，委托密钥必须定期由用户重新签名续期。

{% hint style="info" %}
每次续期都生成一个新密钥是标准做法（而且强烈推荐这样做）（因此名称 `ECDSA_EPHEMERAL`).
{% endhint %}

一个委托步骤示例（为清晰起见，值已缩写）：

```json
{
  "type": "ECDSA_EPHEMERAL",
  "payload": "Decentraland 登录\n临时地址：0xBBa7...\n过期时间：2021-01-25T...",
  "signature": "0x1370a4120a7cb0d2f6e4a5..."
}
```

下一步，无论是另一次委托还是最终授权，都会携带来自该委托密钥的签名。

### 最后一步：授权

在 `SIGNER` 已指定且所有 `ECDSA_EPHEMERAL` 委托密钥都通过验证中间签名链而得到验证之后，最后一步就是需要被授权的实际操作。

该 `负载` 依赖于 `类型` 该步骤的。例如，如果用户正在向内容服务器上传新的个人资料（或他们拥有的任何实体），最后一个元素将采用以下形式：

```json
{
  // 类型表示 `payload` 是一个实体 ID（详情见内容部分）：
  "type": "ECDSA_SIGNED_ENTITY",

  // 载荷是原始 ID 字符串：
  "payload": "bafkreicfbg7ybpuoslkcf6x2vfnvzl5vwgqtb2pnheqiut2i4sgpblicqi",

  // 签名由上一步中的账户（用户或委托人）生成：
  "signature": "0x7e71dbbab..."
}
```

如果这个最后的签名也有效，操作就可以继续。

### 传输链 <a href="#transmitting" id="transmitting"></a>

如上所述，认证链最常见的序列化形式是 JSON 数组。这是推荐的方法。

不过，协议并不强制如此。开发者可以在特定用例中采用更方便的替代序列化方式，例如 YAML、CSV 文件、优化后的二进制格式，或带分隔字段的简单字符串。

在协议本身中可以找到一种替代序列化的示例，位于 [`SignedFetch`](https://github.com/decentraland/docs/blob/main/runtime/modules/signed_fetch.md) 模块中，它使用一系列 HTTP 头而不是 JSON 数组。

### 选择过期时间

在为委托密钥选择有效时长时，需要权衡：更短的过期时间会提高安全性，但更长的过期时间会改善用户体验（因为委托所需的人工交互频率更低）。

没有一种通用策略可以决定有效时间窗口应是多少。作为参考，基金会的 World Explorer 会请求其委托密钥有效一个月的授权。

{% hint style="info" %}
临时密钥绝不应持有资金或具备转移数字资产的能力。如果临时密钥泄露不会导致财务损失，对终端用户来说会安全得多。
{% endhint %}

## 形式化

下面给出所涉及流程更正式、更精确的定义。请遵循这些说明以成功处理认证链。

### 创建

为用户构建认证链的客户端遵循以下步骤：

1. 添加识别步骤：
   1. 将 `类型` 设置为 `SIGNER`.
   2. 将 `负载` 设置为用户的以太坊地址。
   3. 将 `签名` 设置为空字符串。
2. 添加委托步骤：
   1. 生成或使用现有的委托私钥（可能需要交互）。
   2. 计算由相应公钥派生出的委托以太坊地址。
   3. 将 `类型` 设置为 `ECDSA_EPHEMERAL`.
   4. 将 `过期时间` 设为未来的某个日期。
   5. 选择一个 `用途` 用于此密钥。
   6. 将 `负载` 设为以下精确格式：

      ```md
      <purpose>
      临时地址：<delegate-address>
      过期时间：<date>
      ```
   7. 将 `签名` 字段设置为 `负载` 来自前一个密钥（用户或委托人）的签名。
   8. 对每个后续委托重复。
3. 添加操作授权步骤：
   1. 将 `类型` 设为一个有效值（[见下文](#types))
   2. 将 `负载` 设为特定于类型的值（例如实体 ID）。
   3. 将 `签名` 字段设置为 `负载` 来自前一个密钥（用户或委托人）的签名。
4. 将认证链发送给验证者。

### 验证

实现验证的内容服务器和第三方服务遵循以下步骤：

1. 验证识别：
   1. 验证 `类型` 为 `SIGNER`.
   2. 验证 `负载` 是用户的以太坊地址。
   3. 验证 `签名` 是空字符串。
2. 验证委托：
   1. 验证 `类型` 为 `ECDSA_EPHEMERAL`.
   2. 验证 `负载` 采用以下形式并提取字段：

      ```md
      <purpose>
      临时地址：<delegate-address>
      过期时间：<date>
      ```
   3. 验证 `日期` 仍然在未来。
   4. 验证 `用途` 受你的服务支持。
   5. 验证 `签名` 对于给定的 `负载` 以及前一个公钥有效。
   6. 对每个后续委托重复。
3. 验证操作授权：
   1. 验证 `类型` 是一个有效值（[见下文](#types)).
   2. 验证 `负载` 对这个 `类型`.
   3. 验证 `签名` 对于给定的 `负载` 以及前一个公钥有效。
4. 接受认证链。

### 标准操作类型和用途 <a href="#types" id="types"></a>

该 `类型` 和 `负载` 用于识别和委托的值是标准化的，必须如上所述进行验证，但客户端和服务可以就任何操作 `类型`，以及其 `负载` 结构，并为其设置一个 `用途` 他们认为有效的委托密钥的。

协议定义了三种标准类型，以及一种标准用途：

**类型 `SIGNER`**

**必须** 是最初的 `类型` 位于链中，其中 `负载` 是用户的以太坊地址，并且 `签名` 是空字符串。

**类型 `ECDSA_EPHEMERAL`**

**必须** 必须是 `类型` 用于链中间步骤的 `负载` 采用上文所述的形式。

**类型 `ECDSA_SIGNED_ENTITY`**

链中的最终 `类型` 用于授权实体部署，其中 `负载` 是用户拥有的实体 ID。

**目的 `Decentraland 登录`**

通常的 `用途` 适用于 World Explorers，在登录世界和续期其委托密钥时都会签署。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.decentraland.org/contributor/contributor-zh/ren-zheng/authchain.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
