# 00. 公共类型、编码约定与 OID 表

本文件定义各数据对象文档共用的类型与记号。

## 0.1 规范关键字

文中 “MUST/SHOULD/MAY/MUST NOT/SHOULD NOT” 语义遵循 RFC 2119 / RFC 8174。

## 0.2 编码/序列化约定

### 0.2.1 DER

- `DER`：ASN.1 Distinguished Encoding Rules（DER）。RPKI Signed Object 与其 eContent 均要求 DER 编码。RFC 6488 §2；RFC 9286 §4.2；RFC 9582 §4。

### 0.2.2 X.509 v3 扩展（Extension）编码模板

> 用途：解释证书/CRL里“按 OID 挂扩展”的通用编码方式。该模板来自 RFC 5280，对 RPKI 来说是“所有 extnID 扩展”的外层载体。

证书与 CRL 的扩展都使用同一个外层结构（DER 编码）。其 ASN.1 定义如下：RFC 5280 §4.1。

```asn1
Extension  ::=  SEQUENCE  {
     extnID      OBJECT IDENTIFIER,
     critical    BOOLEAN DEFAULT FALSE,
     extnValue   OCTET STRING
                 -- contains the DER encoding of an ASN.1 value
                 -- corresponding to the extension type identified
                 -- by extnID
     }
```

解码要点：

- 先按 `extnID` 选择“要用哪一种内层 ASN.1 结构”。
- 再把 `extnValue` 的 octets 作为 DER 进行**二次解码**，得到该扩展的内层值（例如 SIA/AIA/CRLDP/3779 资源扩展等）。

编码要点：

- 先把内层值按其 ASN.1 结构 DER 编码，得到 `inner_der`；
- 再写入 `extnValue = OCTET STRING(inner_der)`。

RFC 引用：RFC 5280 §4.1（证书扩展位置）；RFC 5280 §4.2（扩展定义与语义）。

### 0.2.3 AIA/SIA 的内层容器结构（AccessDescription + GeneralName URI）

Authority Information Access（AIA）与 Subject Information Access（SIA）的内层值都是一个 “AccessDescription 列表”。其 ASN.1 定义如下：RFC 5280 §4.2.2.1；RFC 5280 §4.2.2.2。

```asn1
AuthorityInfoAccessSyntax  ::=
        SEQUENCE SIZE (1..MAX) OF AccessDescription

SubjectInfoAccessSyntax  ::=
        SEQUENCE SIZE (1..MAX) OF AccessDescription

AccessDescription  ::=  SEQUENCE {
        accessMethod          OBJECT IDENTIFIER,
        accessLocation        GeneralName  }
```

其中 `accessLocation` 的 `GeneralName`（URI 用 `uniformResourceIdentifier` 分支）定义如下：RFC 5280 §4.2.1.6。

```asn1
GeneralName ::= CHOICE {
     otherName                       [0]     OtherName,
     rfc822Name                      [1]     IA5String,
     dNSName                         [2]     IA5String,
     x400Address                     [3]     ORAddress,
     directoryName                   [4]     Name,
     ediPartyName                    [5]     EDIPartyName,
     uniformResourceIdentifier       [6]     IA5String,
     iPAddress                       [7]     OCTET STRING,
     registeredID                    [8]     OBJECT IDENTIFIER }
```

解码要点：

- 先按 `extnID` 识别是 AIA(`1.3.6.1.5.5.7.1.1`) 或 SIA(`1.3.6.1.5.5.7.1.11`)；
- 再把 `extnValue` 解码成 “SEQUENCE OF AccessDescription”；
- 每条 `AccessDescription` 用 `accessMethod` 的 OID 区分语义；
- URI 通常出现在 `GeneralName.uniformResourceIdentifier`（IA5String）中。

RFC 引用：RFC 5280 §4.2.2.1；RFC 5280 §4.2.2.2；RFC 5280 §4.2.1.6。

### 0.2.2 Base64（仅 TAL）

- `Base64`：TAL 中的 `subjectPublicKeyInfo` 以 DER 字节序列经 Base64 编码表示；允许插入换行。RFC 8630 §2.2。

### 0.2.4 换行

- `LF` 或 `CRLF`：TAL 文件允许使用 `\n` 或 `\r\n`。RFC 8630 §2.2。

## 0.3 基本类型（抽象模型层）

> 说明：这些类型用于描述“语义对象”，不等同于 ASN.1 具体类型，但会给出从 ASN.1/文本到该类型的解析规则。

- `DerBytes`: `bytes`，承载一个 DER 编码对象的原始字节（入口）。
- `Oid`: `string`（点分十进制），例如 `1.2.840.113549.1.9.16.1.26`。
- `Uri`: `string`，URI 文本；其语法来自 RFC 3986，但在 RPKI profile 下会被进一步限制（见各对象文档）。
- `Utf8Text`: `string`，UTF-8 文本（例如 TAL 注释行）。RFC 8630 §2.2（引用 RFC 5198 §2 的限制）。
- `UtcTime`: `string`，承载“UTC 时间点”的语义值；来源可能是 X.509 `Time`（UTCTime/GeneralizedTime）或 ASN.1 `GeneralizedTime`（如 Manifest）。RFC 5280 §4.1.2.5；RFC 9286 §4.2。
- `HexBytes`: `bytes` 的十六进制展示形态（仅文档说明用，不建议作为接口字段）。

## 0.4 RPKI 资源集合语义（高层表示）

### 0.4.1 IP 资源集合（语义模型）

用于表达 RFC 3779 的 `IPAddrBlocks`（以及 ROA 的“仅前缀”子集）。

#### 类型：`IpResourceSet`

- `families: list[IpFamilyResources]`

#### 类型：`IpFamilyResources`

- `afi: enum { ipv4, ipv6 }`
- `safi: optional[int]`
  - 在公用互联网资源证书语义中，SAFI **MUST NOT** 使用。RFC 6487 §4.8.10。
- `choice: enum { inherit, explicit }`
- `explicit_resources: optional[list[IpRangeOrPrefix]]`

#### 类型：`IpRangeOrPrefix`

- `kind: enum { prefix, range }`
- `prefix: optional[IpPrefix]`
- `range: optional[IpRange]`

#### 类型：`IpPrefix`

- `address: bytes`（IPv4 4 字节或 IPv6 16 字节的网络序）
- `prefix_len: int`

#### 类型：`IpRange`

- `min: bytes`
- `max: bytes`

解析与约束要点（实现应在解析阶段保留必要信息供后续验证使用）：

- RFC 3779 `IPAddress`/`IPAddressRange` 以 `BIT STRING` 编码前缀/范围，并对排序/去重/规范编码给出要求。RFC 3779 §2.2.3.6-§2.2.3.9。
- RFC 3779 `inherit` 语义表示资源集合继承自签发者。RFC 3779 §2.2.3.5。

### 0.4.2 AS 资源集合（语义模型）

用于表达 RFC 3779 的 `ASIdentifiers`。

#### 类型：`AsResourceSet`

- `asnum: optional[AsIdentifierChoice]`
  - 在 RPKI profile 中，`asnum` 与 `rdi` 不能都缺省到导致“无 AS 资源扩展”的语义；但 RC 层面允许 “仅 IP” 或 “仅 AS” 或两者都存在。RFC 6487 §4.8.10；RFC 6487 §4.8.11。
- `rdi: optional[AsIdentifierChoice]`
  - RPKI profile **不支持** RDI，MUST NOT 使用。RFC 6487 §4.8.11。

#### 类型：`AsIdentifierChoice`

- `choice: enum { inherit, explicit }`
- `explicit_ranges: optional[list[AsRangeOrId]]`

#### 类型：`AsRangeOrId`

- `kind: enum { id, range }`
- `id: optional[int]`（0..4294967295）
- `range: optional[AsRange]`

#### 类型：`AsRange`

- `min: int`
- `max: int`

解析与约束要点：

- `inherit` 语义与排序/范围编码规则来自 RFC 3779。RFC 3779 §3.2.3.3；RFC 3779 §3.2.3.8。

## 0.5 常用 OID 表（最小集合）

> 说明：表中 “来源 RFC” 给出该 OID 在本模型中的直接规范引用点；在实现时也可以直接用点分十进制比对。

| OID | 符号名/含义 | 来源 RFC |
|---|---|---|
| `1.2.840.113549.1.7.2` | CMS SignedData（ContentInfo.contentType） | RFC 6488 §3(1a) |
| `1.2.840.113549.1.9.3` | CMS signedAttrs: content-type | RFC 6488 §3(1f) |
| `1.2.840.113549.1.9.4` | CMS signedAttrs: message-digest | RFC 6488 §3(1f) |
| `1.2.840.113549.1.9.5` | CMS signedAttrs: signing-time | RFC 9589 §4（更新 RFC 6488 §3(1f)/(1g)） |
| `1.2.840.113549.1.9.16.1.24` | ROA eContentType: id-ct-routeOriginAuthz | RFC 9582 §3 |
| `1.2.840.113549.1.9.16.1.26` | Manifest eContentType: id-ct-rpkiManifest | RFC 9286 §4.1 |
| `1.2.840.113549.1.9.16.1.35` | Ghostbusters eContentType: id-ct-rpkiGhostbusters | RFC 6493 §6；RFC 6493 §9.1 |
| `1.2.840.113549.1.9.16.1.49` | ASPA eContentType: id-ct-ASPA | `draft-ietf-sidrops-aspa-profile-21` §2 |
| `1.3.6.1.5.5.7.1.1` | X.509 v3 扩展：authorityInfoAccess | RFC 5280 §4.2.2.1 |
| `1.3.6.1.5.5.7.1.11` | X.509 v3 扩展：subjectInfoAccess | RFC 5280 §4.2.2.2；RPKI 约束见 RFC 6487 §4.8.8 |
| `1.3.6.1.5.5.7.48.2` | AIA accessMethod: id-ad-caIssuers | RFC 5280 §4.2.2.1 |
| `1.3.6.1.5.5.7.48.5` | SIA accessMethod: id-ad-caRepository | RFC 5280 §4.2.2.2；RPKI 语义见 RFC 6481 §2.2；约束见 RFC 6487 §4.8.8.1 |
| `1.3.6.1.5.5.7.48.10` | SIA accessMethod: id-ad-rpkiManifest | RFC 6487 §4.8.8.1 |
| `1.3.6.1.5.5.7.48.11` | SIA accessMethod: id-ad-signedObject | RFC 6487 §4.8.8.2 |
| `1.3.6.1.5.5.7.48.13` | SIA accessMethod: id-ad-rpkiNotify（RRDP Notification） | RFC 8182 §3.2 |
| `1.3.6.1.5.5.7.1.7` | RFC 3779 IP 资源扩展：id-pe-ipAddrBlocks | RFC 3779 §2.2.1 |
| `1.3.6.1.5.5.7.1.8` | RFC 3779 AS 资源扩展：id-pe-autonomousSysIds | RFC 3779 §3.2.1 |
| `2.5.29.31` | X.509 v3 扩展：cRLDistributionPoints | RFC 5280 §4.2.1.13；RPKI 约束见 RFC 6487 §4.8.6 |
| `2.5.29.32` | X.509 v3 扩展：certificatePolicies | RFC 5280 §4.2.1.4；RPKI 约束见 RFC 6487 §4.8.9；更新见 RFC 7318 §2 |
| `2.5.29.14` | X.509 v3 扩展：subjectKeyIdentifier | RFC 5280 §4.2.1.2；RPKI 约束见 RFC 6487 §4.8.2 |
| `2.5.29.35` | X.509 v3 扩展：authorityKeyIdentifier（证书/CRL） | RFC 5280 §4.2.1.1（证书）；RFC 5280 §5.2.1（CRL）；RPKI 约束见 RFC 6487 §4.8.3 / RFC 9829 §3.1 |
| `2.5.29.15` | X.509 v3 扩展：keyUsage | RFC 5280 §4.2.1.3；RPKI 约束见 RFC 6487 §4.8.4 |
| `2.5.29.19` | X.509 v3 扩展：basicConstraints | RFC 5280 §4.2.1.9；RPKI 约束见 RFC 6487 §4.8.1 |
| `2.5.29.20` | CRL 扩展：cRLNumber | RFC 5280 §5.2.3；RPKI 约束更新见 RFC 9829 §3.1 |
| `1.3.6.1.5.5.7.14.2` | RPKI Certificate Policy：id-cp-ipAddr-asNumber | RFC 6484 §1.2；证书中使用要求见 RFC 6487 §4.8.9 |
| `1.3.6.1.5.5.7.2.1` | Policy Qualifier：id-qt-cps | RFC 5280 §4.2.1.4；RPKI 限制见 RFC 7318 §2 |
| `2.16.840.1.101.3.4.2.1` | `id-sha256`（SHA-256 摘要算法 OID） | RFC 7935 §2（引用 RFC 5754） |
| `1.2.840.113549.1.1.1` | `rsaEncryption`（CMS SignerInfo.signatureAlgorithm 生成时使用） | RFC 7935 §2（引用 RFC 3370） |
| `1.2.840.113549.1.1.11` | `sha256WithRSAEncryption`（证书/CRL 签名算法；CMS 验证兼容） | RFC 7935 §2（引用 RFC 4055） |

## 0.6 `None` 类型字段的含义（文档约定）

在本目录的“抽象数据模型（接口）”字段表里，如果某字段的类型标为 `None`，表示：

- 该字段/子字段在通用 ASN.1 结构里**可能存在**（或是可选字段/可扩展集合），但在 RPKI profile 下被明确规定 **MUST NOT be present / MUST be omitted**；
- 因此它**不应作为正常语义数据对象的可用字段**出现；
- 实现可以选择两种方式之一：
  1) **不在对象结构中建模该字段**，仅在“约束清单”里写明禁止出现；解析时若遇到该字段则直接报“profile 违规”；或
  2) 为了便于输出结构化诊断，把它保留成“永远为 None 的占位字段”，并规定：若从 DER 中解析到该字段，则对象不符合 profile。

注意：像 CMS `signedAttrs` 中的 “other attributes MUST NOT be included” 这类规则，本质是“集合不得含额外成员”。文档里用 `other_attrs: None` 只是为了把“禁止项”放进同一张字段表，便于实现逐条对照；它不代表 ASN.1 里真的有一个名为 `other_attrs` 的字段。
