> 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/shen-fen-yan-zheng/authchain.md).

# 认证链

在 Decentraland 协议中，许多操作要么需要，要么会受益于使用用户的以太坊账户签名进行授权。例如：

1. 上传任何……的新版本 [实体](https://github.com/decentraland/docs/tree/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 Explorers 在登录期间使用的典型有效载荷，当他们为用户生成临时代理密钥以供批准时：

```
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/tree/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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.decentraland.org/contributor/contributor-zh/shen-fen-yan-zheng/authchain.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
