

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# （可选）创建架构（高级用户）
<a name="create-schema"></a>

手动创建架构适用于高级用户。

以下是对带或不带列标题的输入文件的 JSON 架构文件格式的描述。如果需要，高级用户可以直接编写或修改架构。

**注意**  
C3R 加密客户端可通过 [示例：生成带有 sealed、fingerprint 和 cleartext 列的加密架构](gen-encryption-schema-csv.md#gen-encryption-schema) 中描述的交互式流程或通过创建存根模板协助您创建架构。

## 映射和定位表架构
<a name="mapped-and-positional-schemas"></a>

以下部分描述了两种表架构：
+ **映射表架构** — 此架构用于加密带有标题行的 .csv 文件和 Apache Parquet 文件。
+ **位置表架构** — 此架构用于加密没有标题行的 .csv 文件。

C3R 加密客户端可以加密表格文件以进行协作。为此，它必须具有相应的架构文件，该文件指定应如何从输入中导出加密输出。

C3R 加密客户端可以通过在命令行运行 C3R 加密客户端架构命令来帮助为 `INPUT` 文件生成架构。命令的一个示例是 `java -jar c3r-cli.jar schema --interactive INPUT`。

架构指定以下信息：

1. 哪些源列通过标题名称（映射架构）或位置（位置架构）映射到输出文件中哪些已转换的列

1. 哪些目标列要保留 cleartext

1. 要对哪些目标列进行加密以进行 SELECT 查询

1. 要对哪些目标列进行加密以进行 JOIN 查询

这些信息在特定于表的 JSON 架构文件中编码，该文件由一个对象组成，其 `headerRow` 字段是一个布尔值。对于有标题行的 Parquet 文件和 .csv 文件，该值必须为 `true`，否则为 `false`。

### 映射表架构
<a name="mapped-schemas"></a>

映射架构具有以下形状。

```
{
  "headerRow": true,
  "columns": [
    {
      "sourceHeader": STRING,
      "targetHeader": STRING,
      "type": TYPE,
      "pad": PAD
    },
    ...
  ]
}
```

如果 `headerRow` 为 `true`，对象中的下一个字段就是 `columns`，其中包含一个将源标题映射到目标标题的列架构（即描述输出列应包含内容的 JSON 对象）数组。
+ `sourceHeader` — 数据来源于的源列的 `STRING` 标题名称。
**注意**  
同一个源列可以用于多个目标列。  
输入文件中未列为架构中任意位置的 `sourceHeader` 列不会出现在输出文件中。
+ `targetHeader` — 输出文件中相应列的 `STRING` 标题名称。
**注意**  
对于映射架构，此字段为可选项。如果省略此字段，输出中的标题名称将重复使用 `sourceHeader`。如果输出列分别为 fingerprint 列或 sealed 列，则附加 `_fingerprint` 或 `_sealed`。
+ `type` — 输出文件中目标列的 `TYPE`。即 `cleartext`、`sealed` 或 `fingerprint` 其中之一，具体取决于该列在协作中的使用方式。
+ `pad` — 列架构对象的字段，仅当 `TYPE` 为 `sealed` 才存在。其对应的 `PAD` 值是一个对象，用于描述数据在加密前应如何填充。

  ```
  {
    "type": PAD_TYPE,
    "length": INT
  }
  ```

  要指定加密前的填充，请按如下方式使用 `type` 和 `length`：
  + `PAD_TYPE` 为 `none` — 不对列的数据进行填充，`length` 字段不适用（即省略）。
  + `PAD_TYPE` 为 `fixed` — 将列的数据填充到指定的字节 `length`。
  + `PAD_TYPE` 为 `max` — 列的数据填充到最长值的字节长度加上额外的 `length` 字节。

以下是映射架构的示例，每个类型都有一列。

```
{
  "headerRow": true,
  "columns": [
    {
      "sourceHeader": "FullName",
      "targetHeader": "name",
      "type": "cleartext"
    },
    {
      "sourceHeader": "City",
      "targetHeader": "city_sealed",
      "type": "sealed",
      "pad": {
        "type": "max",
        "length": 16
      }
    },
    {
      "sourceHeader": "PhoneNumber",
      "targetHeader": "phone_number_fingerprint",
      "type": "fingerprint"
    },
    {
      "sourceHeader": "PhoneNumber",
      "targetHeader": "phone_number_sealed",
      "type": "sealed",
      "pad": {
        "type": "fixed",
        "length": 20
      }
    }
  ]
}
```

作为一个更复杂的示例，以下是带有标题的 .csv 文件示例。

```
FirstName,LastName,Address,City,State,PhoneNumber,Title,Level,Notes
Jorge,Souza,12345 Mills Rd,Anytown,SC,703-555-1234,CEO,10,
Paulo,Santos,0 Street,Anytown,MD,404-555-111,CIO,9,This is a really long note that could really be a paragraph
Mateo,Jackson,1 Two St,Anytown,NY,304-555-1324,COO,9,""
Terry,Whitlock4 N St,Anytown,VA,407-555-8888,EA,7,Secret notes
Diego,Ramirez,9 Hollows Rd,Anytown,VA,407-555-1222,SDE I,4,null
John,Doe,8 Hollows Rd,Anytown,VA,407-555-4321,SDE I,4,Jane's younger brother
Jane,Doe,8 Hollows Rd,Anytown,VA,407-555-4322,SDE II,5,John's older sister
```

在以下映射架构示例中，列 `FirstName` 和 `LastName` 是 `cleartext` 列。`State` 列作为 `fingerprint` 列和 `sealed` 列进行加密，填充为 `none`。其余列均省略。

```
{
  "headerRow": true,
  "columns": [
    {
      "sourceHeader": "FirstName",
      "targetHeader": "GivenName",
      "type": "cleartext"
    },
    {
      "sourceHeader": "LastName",
      "targetHeader": "Surname",
      "type": "cleartext"
    },
    {
      "sourceHeader": "State",
      "targetHeader": "State_Join",
      "type": "fingerprint"
    },
    {
      "sourceHeader": "State",
      "targetHeader": "State",
      "type": "sealed",
      "pad": {
        "type": "none"
      }
    }
  ]
}
```

以下是映射架构生成的 .csv 文件。

```
givenname,surname,state_fingerprint,state
John,Doe,01:hmac:UK8s8Cn/WR2JO/To2dTxWD73aDEe2ZUXeSHy3Tv+1Mk=,01:enc:FQ3n3Ahv9BQQNWQGcugeHzHYzEZE1vapHa2Uu4SRgSAtZ3qObjPA4TcsHt+BOkMKBcnHWI13BeGG/SBqmj7vKpI=
Paulo,Santos,01:hmac:CHF4eIrtTNgAooU9v4h9Qjc+txBnMidQTjdjWuaDTTA=,01:enc:KZ5n5GtaXACco65AXk48BQO2durDNR2ULc4YxmMC8NaZZKKJiksU1IwFadAvV4iBQ1Bus5TU5c4biez3bilfTY8=
Mateo,Jackson,01:hmac:iIRnjfNBzryusIJ1w35lgNzeY1RQ1bSfq6PDHW8Xrbk=,01:enc:mLKpS5HIOSgphdEsrzhEdIp/eN9nBO2gAbIygt4OFn4LalYn9Xyj/XUWXlmn8zFe2T4kyDTD8kGOvpQEUGxAUFk=
Diego,Ramirez,01:hmac:UK8s8Cn/WR2JO/To2dTxWD73aDEe2ZUXeSHy3Tv+1Mk=,01:enc:rmZhT98Zm+IIGw1UTjMIJP4IrW/AAltBLMXcHvnYfRgmWP623VFQ6aUnhsb2MDqEw4G5Uwg5rKKZepUxx5uKbfk=
Jorge,Souza,01:hmac:3BxJdXiFFyZ8HBbYNqqEhBVqhNOd7s2ZiKUe7QiTyo8=,01:enc:vVaqWC1VRbhvkf8gnuR7q0zxVPcvEjuaglYz34+KyyLcGZLpAmsDUc6wZ07f2KvHoOySqRsEU7dG1QfdHYcTSWE=
Terry,Whitlock01:hmac:UK8s8Cn/WR2JO/To2dTxWD73aDEe2ZUXeSHy3Tv+1Mk=,01:enc:3c9VEWbODO/xbQjdGuccLvI7oZTBdPU+SyrJIyr2kudfAxbuMQ2uRdU/q7rbgyJjxZS8M2U35ILJf/lDgTyg7cM=
Jane,Doe,01:hmac:UK8s8Cn/WR2JO/To2dTxWD73aDEe2ZUXeSHy3Tv+1Mk=,01:enc:9RWv46YLveykeNZ/G0NdlYFg+AVdOnu05hHyAYTQkPLHnyX+0/jbzD/g9ZT8GCgVE9aB5bV4ooJIXHGBVMXcjrQ=
```

### 位置表架构
<a name="positional-schemas"></a>

映射架构具有以下形状。

```
{
  "headerRow": false,
  "columns": [
    [
      {
        "targetHeader": STRING,
        "type": TYPE,
        "pad": PAD
      },
      {
        "targetHeader": STRING,
        "type": TYPE,
        "pad": PAD
      }
    ],
    [],
    ...
  ]
}
```

如果 `headerRow` 是 `false`，则对象中的下一个字段是 `columns`，其中包含一个条目数组。每个条目本身就是一个由零个或多个位置列架构（无 `sourceHeader` 字段）组成的数组，这些架构是描述输出应包含内容的 JSON 对象。
+ `sourceHeader` — 数据来源于的源列的 `STRING` 标题名称。
**注意**  
在位置架构中必须省略此字段。在位置架构中，源列由架构文件中该列的相应索引推断出来。
+ `targetHeader` — 输出文件中相应列的 `STRING` 标题名称。
**注意**  
对于位置架构，此字段为必填字段。
+ `type` — 输出文件中目标列的 `TYPE`。即 `cleartext`、`sealed` 或 `fingerprint` 其中之一，具体取决于该列在协作中的使用方式。
+ `pad` — 列架构对象的字段，仅当 `TYPE` 为 `sealed` 才存在。其对应的 `PAD` 值是一个对象，用于描述数据在加密前应如何填充。

  ```
  {
    "type": PAD_TYPE,
    "length": INT
  }
  ```

  要指定加密前的填充，请按如下方式使用 `type` 和 `length`：
  + `PAD_TYPE` 为 `none` — 不对列的数据进行填充，`length` 字段不适用（即省略）。
  + `PAD_TYPE` 为 `fixed` — 将列的数据填充到指定的字节 `length`。
  + `PAD_TYPE` 为 `max` — 列的数据填充到最长值的字节长度加上额外的 `length` 字节。
**注意**  
如果您提前知道列数据的字节大小的上限，则 `fixed` 很有用。如果该列中的任何数据长于指定的 `length`，则会引发错误。  
当输入数据的确切大小未知时，`max` 很方便，因为无论数据的大小如何，它都能正常工作。但是，由于它会对数据进行两次加密，因此 `max` 需要额外的处理时间。`max` 在读入临时文件时对数据进行一次加密，在已知列中最长的数据条目之后加密一次。  
此外，最长值的长度不会在两次调用客户端之间保存。如果您计划分批加密数据或定期加密新数据，请注意生成的加密文字长度可能因批次而异。

以下是位置架构的示例。

```
{
  "headerRow": false,
  "columns": [
    [
      {
        "targetHeader": "name",
        "type": "cleartext"
      }
    ],
    [
      {
        "targetHeader": "city_sealed",
        "type": "sealed",
        "pad": {
          "type": "max",
          "length": 16
        }
      }
    ],
    [
      {
        "targetHeader": "phone_number_fingerprint",
        "type": "fingerprint"
      },
      {
        "targetHeader": "phone_number_sealed",
        "type": "sealed",
        "pad": {
          "type": "fixed",
          "length": 20
        }
      }
    ]
  ]
}
```

举一个复杂的示例，以下是一个 .csv 文件示例，前提是它的第一行没有标题。

```
Jorge,Souza,12345 Mills Rd,Anytown,SC, 703 -555 -1234,CEO, 10,
Paulo,Santos, 0 Street,Anytown,MD, 404-555-111,CIO, 9,This is a really long note that could really be a paragraph
Mateo,Jackson, 1 Two St,Anytown,NY, 304-555-1324,COO, 9, ""
Terry,Whitlock, 4 N St,Anytown,VA, 407-555-8888,EA, 7,Secret notes
Diego,Ramirez, 9 Hollows Rd,Anytown,VA, 407-555-1222,SDE I, 4,null
John,Doe, 8 Hollows Rd,Anytown,VA, 407-555-4321,SDE I, 4,Jane's younger brother
Jane,Doe, 8 Hollows Rd,Anytown,VA, 407-555-4322,SDE II, 5,John's older sister
```

映射架构具有以下形式。

```
{
  "headerRow": false,
  "columns": [
    [
      {
        "targetHeader": "GivenName",
        "type": "cleartext"
      }
    ],
    [
      {
        "targetHeader": "Surname",
        "type": "cleartext"
      }
    ],
    [],
    [],
    [
      {
        "targetHeader": "State_Join",
        "type": "fingerprint"
      },
      {
        "targetHeader": "State",
        "type": "sealed",
        "pad": {
          "type": "none"
        }
      }
    ],
    [],
    [],
    [],
    []
  ]
}
```

上述架构生成以下输出文件，该文件具有包含指定目标标题的标题行。

```
givenname,surname,state_fingerprint,state
Mateo,Jackson,01:hmac:iIRnjfNBzryusIJ1w35lgNzeY1RQ1bSfq6PDHW8Xrbk=,01:enc:ENS6QD3cMVl9vQEGfe9MNWfR0UOupchswZFr94zOMG5jY/Q8m/Y5SA89dJwKpT5rGPp8e36h6klwDoslpFzGvU0=
Jorge,Souza,01:hmac:3BxJdXiFFyZ8HBbYNqqEhBVqhNOd7s2ZiKUe7QiTyo8=,01:enc:LKo0zirq2++XEIIIMNRjAsGMdyWUDwYaum0B+IFP+rUf1BNeZDJjtFe1Z+zbZfXQWwJy52Rt7HqvAb2WIK1oMmk=
Paulo,Santos,01:hmac:CHF4eIrtTNgAooU9v4h9Qjc+txBnMidQTjdjWuaDTTA=,01:enc:MyQKyWxJ9kvK1xDQQtXlUNwv3F+yrBRr0xrUY/1BGg5KFgOn9pK+MZ7g+ZNqZEPcPz4lht1u0t/wbTaqzOCLXFQ=
Jane,Doe,01:hmac:UK8s8Cn/WR2JO/To2dTxWD73aDEe2ZUXeSHy3Tv+1Mk=,01:enc:Pd8sbITBfb0/ttUB4svVsgoYkDfnDvgkvxzeci0Yxq54rLSwccy1o3/B50C3cpkkn56dovCwzgmmPNwrmCmYtb4=
Terry,Whitlock01:hmac:UK8s8Cn/WR2JO/To2dTxWD73aDEe2ZUXeSHy3Tv+1Mk=,01:enc:Qmtzu3B3GAXKh2KkRYTiEAaMopYedsSdF2e/ADUiBQ9kv2CxKPzWyYTD3ztmKPMka19dHre5VhUHNpO3O+j1AQ8=
Diego,Ramirez,01:hmac:UK8s8Cn/WR2JO/To2dTxWD73aDEe2ZUXeSHy3Tv+1Mk=,01:enc:ysdg+GHKdeZrS/geBIooOEPLHG68MsWpx1dh3xjb+fG5rmFmqUcJLNuuYBHhHAlxchM2WVeV1fmHkBX3mvZNvkc=
John,Doe,01:hmac:UK8s8Cn/WR2JO/To2dTxWD73aDEe2ZUXeSHy3Tv+1Mk=,01:enc:9uX0wZuO7kAPAx+Hf6uvQownkWqFSKtWS7gQIJSe5aXFquKWCK6yZN0X5Ea2N3bn03Uj1kh0agDWoiP9FRZGJA4=
```