# 06. Manifest（MFT）

## 6.1 对象定位

Manifest 是 CA 发布点内对象的“清单”（文件名 + hash），用于 RP 侧检测删除/替换/回放等不一致情况。RFC 9286 §1；RFC 9286 §6。

Manifest 是一种 RPKI Signed Object：CMS 外壳遵循 RFC 6488/9589，eContent 遵循 RFC 9286。RFC 9286 §4；RFC 6488 §4；RFC 9589 §4。

## 6.2 原始载体与编码

- 外壳：CMS SignedData DER（见 `05_signed_object_cms.md`）。RFC 9286 §4；RFC 6488 §2。
- eContentType：`id-ct-rpkiManifest`，OID `1.2.840.113549.1.9.16.1.26`。RFC 9286 §4.1。
- eContent：DER 编码 ASN.1 `Manifest`。RFC 9286 §4.2。

### 6.2.1 eContentType 与 eContent 的 ASN.1 定义（RFC 9286 §4.1；RFC 9286 §4.2）

Manifest 是一种 RPKI signed object（CMS 外壳见 `05_signed_object_cms.md`）。其 `eContentType` 与 `eContent` 的 ASN.1 由 RFC 9286 明确定义。RFC 9286 §4。

**eContentType（OID）**：RFC 9286 §4.1。

```asn1
id-smime OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
                          rsadsi(113549) pkcs(1) pkcs9(9) 16 }

id-ct OBJECT IDENTIFIER ::= { id-smime 1 }

id-ct-rpkiManifest OBJECT IDENTIFIER ::= { id-ct 26 }
```

**eContent（Manifest 结构）**：RFC 9286 §4.2。

```asn1
Manifest ::= SEQUENCE {
 version     [0] INTEGER DEFAULT 0,
 manifestNumber  INTEGER (0..MAX),
 thisUpdate      GeneralizedTime,
 nextUpdate      GeneralizedTime,
 fileHashAlg     OBJECT IDENTIFIER,
 fileList        SEQUENCE SIZE (0..MAX) OF FileAndHash
 }

FileAndHash ::=     SEQUENCE {
 file            IA5String,
 hash            BIT STRING
}
```

解码要点：

- `fileHashAlg` 决定 `FileAndHash.hash` 的算法与输出长度（RPKI profile 要求 SHA-256）。RFC 9286 §4.2.1；RFC 7935 §2。
- `hash` 在 ASN.1 中是 BIT STRING，但 hash 输出是按字节的比特串，DER 编码时应为 “unused bits = 0” 的 octet-aligned BIT STRING（实现可据此做一致性检查）。RFC 9286 §4.2。

## 6.3 解析规则（eContent 语义层）

输入：`RpkiSignedObject`。

1) 先按通用 Signed Object 外壳解析得到 `encap_content_info.econtent_type` 与 `econtent_der`。RFC 6488 §3；RFC 9589 §4。  
2) 要求 `econtent_type == 1.2.840.113549.1.9.16.1.26`。RFC 9286 §4.1；RFC 9286 §4.4(1)。  
3) 将 `econtent_der` 以 DER 解析为 `Manifest` ASN.1。RFC 9286 §4.2。  
4) 将 `fileList` 映射为语义字段 `files: list[FileAndHash]`，其中 `hash` 为 `fileHashAlg` 对应算法的输出字节序列。RFC 9286 §4.2.1（fileHashAlg/fileList 定义）。

## 6.4 抽象数据模型（接口）

### 6.4.1 `ManifestObject`

| 字段 | 类型 | 语义 | 约束/解析规则 | RFC 引用 |
|---|---|---|---|---|
| `signed_object` | `RpkiSignedObject` | CMS 外壳 | 外壳约束见 RFC 6488/9589 | RFC 9286 §4；RFC 6488 §3；RFC 9589 §4 |
| `econtent_type` | `Oid` | eContentType | 必须为 `1.2.840.113549.1.9.16.1.26` | RFC 9286 §4.1 |
| `manifest` | `ManifestEContent` | eContent 语义对象 | 见下 | RFC 9286 §4.2 |

### 6.4.2 `ManifestEContent`

| 字段 | 类型 | 语义 | 约束/解析规则 | RFC 引用 |
|---|---|---|---|---|
| `version` | `int` | Manifest.version | MUST 为 0 | RFC 9286 §4.2.1（version） |
| `manifest_number` | `int` | manifestNumber | 0..MAX；可达 20 octets；issuer 必须单调递增；RP 必须可处理至 20 octets | RFC 9286 §4.2；RFC 9286 §4.2.1（manifestNumber） |
| `this_update` | `UtcTime` | thisUpdate | 由 ASN.1 `GeneralizedTime` 解析为 UTC 时间点；且必须比先前生成的 manifest 更新 | RFC 9286 §4.2；RFC 9286 §4.2.1（thisUpdate） |
| `next_update` | `UtcTime` | nextUpdate | 由 ASN.1 `GeneralizedTime` 解析为 UTC 时间点；且必须晚于 thisUpdate | RFC 9286 §4.2；RFC 9286 §4.2.1（nextUpdate） |
| `file_hash_alg` | `Oid` | fileHashAlg | 必须为 `id-sha256`（`2.16.840.1.101.3.4.2.1`） | RFC 9286 §4.2.1（fileHashAlg）；RFC 7935 §2（引用 RFC 5754） |
| `files` | `list[FileAndHash]` | fileList | `SEQUENCE SIZE (0..MAX)`；每项含文件名与 hash | RFC 9286 §4.2；RFC 9286 §4.2.1（fileList） |

### 6.4.3 `FileAndHash`

| 字段 | 类型 | 语义 | 约束/解析规则 | RFC 引用 |
|---|---|---|---|---|
| `file_name` | `string` | 文件名（不含路径） | 字符集限制：`[a-zA-Z0-9-_]+` + `.` + 三字母扩展；扩展必须在 IANA “RPKI Repository Name Schemes” 注册表中 | RFC 9286 §4.2.2 |
| `hash_bytes` | `bytes` | 文件内容 hash | 由 `file_hash_alg` 指定算法计算 | RFC 9286 §4.2.1（fileHashAlg/fileList） |

## 6.5 字段级约束清单（实现对照）

- eContentType 必须为 `id-ct-rpkiManifest`（OID `1.2.840.113549.1.9.16.1.26`）。RFC 9286 §4.1。
- eContent 必须 DER 编码且符合 `Manifest` ASN.1。RFC 9286 §4.2。
- `version` 必须为 0。RFC 9286 §4.2.1。
- `manifestNumber` 由 issuer 单调递增；RP 必须能处理至 20 octets；issuer 不得超过 20 octets。RFC 9286 §4.2.1。
- `nextUpdate` 必须晚于 `thisUpdate`。RFC 9286 §4.2.1。
- `fileHashAlg` 必须符合算法 profile（SHA-256）。RFC 9286 §4.2.1；RFC 7935 §2。
- `fileList` 中 `file` 名称字符集与扩展名受限；实现需按 RFC 限制解析并保留大小写语义。RFC 9286 §4.2.2。

## 6.6 与 EE 证书的语义约束（为后续验证准备）

Manifest 使用“one-time-use EE certificate”进行签名验证，规范对该 EE 证书的使用方式给出约束：

- Manifest 相关 EE 证书应为 one-time-use（每次新 manifest 生成新密钥对/新 EE）。RFC 9286 §4（Section 4 前导段落）。
- 用于签名/验证 manifest 的 EE 证书在 RFC 3779 的资源扩展中描述 INRs 时，**MUST** 使用 `inherit`（而不是显式列出资源集合）。RFC 9286 §5.1（生成步骤 2）。
  - 若证书包含 **IP Address Delegation Extension**（IP prefix delegation）：内容必须为 `inherit`（不得显式列 prefix/range）。RFC 9286 §5.1；RFC 3779。
  - 若证书包含 **AS Identifier Delegation Extension**（ASN delegation）：内容必须为 `inherit`（不得显式列 ASID/range）。RFC 9286 §5.1；RFC 3779。
  - 另外按资源证书 profile：资源证书 **MUST** 至少包含上述两类扩展之一（也可两者都有），且这些扩展 **MUST** 标记为 critical。RFC 6487 §2。
- 用于验证 manifest 的 EE 证书 **MUST** 具有与 `thisUpdate..nextUpdate` 区间一致的有效期，以避免 CRL 无谓增长。RFC 9286 §4.2.1（manifestNumber 段落前的说明）。
- 替换 manifest 时，CA 必须撤销旧 manifest 对应 EE 证书；且若新 manifest 早于旧 manifest 的 nextUpdate 发行，则 CA **MUST** 同时发行新 CRL 撤销旧 manifest EE。RFC 9286 §4.2.1（nextUpdate 段落末）；RFC 9286 §5.1（生成步骤）。
