

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

# 可搜索的加密
<a name="searchable-encryption"></a>


****  

|  | 
| --- |
| 我们的客户端加密库已重命名为 AWS 数据库加密 SDK。本开发人员指南仍提供有关 [DynamoDB 加密客户端](legacy-dynamodb-encryption-client.md)的信息。 | 

可搜索加密使您无需解密整个数据库即可搜索加密的记录。该操作使用*信标*完成，信标在写入字段的明文值和实际存储在数据库中的加密值之间创建映射。 AWS 数据库加密 SDK 将信标存储在添加到记录中的新字段中。根据您使用的信标类型，您可以对加密的数据执行完全匹配搜索或更为自定义的复杂查询。

**注意**  
 AWS 数据库加密 SDK 中的可搜索加密不同于学术研究中定义的可搜索对称加密，例如可[搜索](https://dl.acm.org/doi/10.1145/1180405.1180417)的对称加密。



信标是一种截断的 HMAC 散列消息认证码（HMAC）标签，用于在字段的明文值和加密值之间创建映射。当您向配置为可搜索加密的加密字段写入新值时， AWS 数据库加密 SDK 会根据纯文本值计算 HMAC。此 HMAC 输出与该字段的明文值进行一对一（1:1）匹配。HMAC 输出会被截断，以便多个不同的明文值映射到同一个被截断的 HMAC 标签中。这些误报限制了未经授权的用户识别有关明文值的区别信息的能力。当您查询信标时， AWS 数据库加密 SDK 会自动筛选掉这些误报，并返回查询的明文结果。

为每个信标生成的平均误报数通过截断后剩余的信标长度决定。如需帮助确定适合您的实现的信标长度，请参阅[确定信标长度](choosing-beacon-length.md)。

**注意**  
可搜索加密旨在在未填充的新数据库中实现。在现有数据库中配置的任何信标都只能映射上传到数据库的新记录，信标无法映射现有的数据。

**主题**
+ [信标是否适合我的数据集？](#are-beacons-right-for-me)
+ [可搜索的加密场景](#beacon-overview-example)

## 信标是否适合我的数据集？
<a name="are-beacons-right-for-me"></a>

使用信标对加密的数据执行查询会降低与客户端加密数据库相关的性能成本。当您使用信标时，查询的效率和泄露的有关数据分布的信息量之间存在内在权衡。信标不会更改字段的加密状态。使用 AWS 数据库加密 SDK 对字段进行加密和签名时，该字段的纯文本值永远不会暴露给数据库。数据库将存储字段的随机加密值。

信标与计算信标所依据的加密字段一同存储。这意味着，即使未经授权的用户无法查看加密字段的明文值，他们也可以对信标进行统计分析，以了解有关数据集分布的更多信息，并在极端情况下识别信标映射到的明文值。配置信标的方式可以缓解这些风险。特别是，[选择适当的信标长度](choosing-beacon-length.md)可以帮助您保护数据集的机密性。

**安全与性能**
+ 信标长度越短，越能保证安全性。
+ 信标长度越长，越能保证性能。

可搜索的加密可能无法为所有数据集同时提供所需的性能和安全级别。配置任何信标之前，请查看您的威胁模型、安全要求和性能需求。

确定可搜索加密是否适合您的数据集时，请考虑以下数据集唯一性要求。

**分布**  
信标所保证的安全程度取决于数据集的分布。将加密字段配置为可搜索加密时， AWS 数据库加密 SDK 会根据写入该字段的纯文本值计算 HMAC。为给定字段计算的所有信标均使用相同的密钥计算，但多租户数据库除外，它们对每个租户使用不同的密钥。这意味着，如果多次向该字段写入相同的明文值，则会为该明文值的每个实例创建相同的 HMAC 标签。  
您应避免使用包含非常常见值的字段构造信标。例如，考虑一个存储伊利诺伊州每位居民地址的数据库。如果您从加密的 `City` 字段构建信标，则由于居住在芝加哥的伊利诺伊州人口比例很大，因此按“芝加哥”计算的信标将被过度代表。即使未经授权的用户只能读取加密的值和信标值，如果信标保留了此分布，它们也可能能够识别哪些记录包含芝加哥居民的数据。为了最大限度地减少所泄露的有关您的分布的区分信息量，您必须充分截断信标。隐藏这种不均匀分布所需的信标长度会带来巨大的性能成本，可能无法满足您的应用程序需求。  
您必须仔细分析数据集的分布，以确定需要将信标截断多少。截断后剩余的信标长度与可以识别的关于分布的统计信息量直接相关。您可能需要选择较短的信标长度，以充分地最大限度减少泄露的有关数据集的区分信息量。  
在极端情况下，您无法为分布不均匀的数据集计算信标长度，以有效地平衡性能和安全性。例如，您不应使用存储罕见疾病医学检查结果的字段构造信标。由于 `NEGATIVE` 结果预计在数据集中会更加普遍，因此可以很容易地通过 `POSITIVE` 结果的罕见程度来识别结果。当字段只包含两个可能的值时，隐藏分布非常困难。如果您使用的信标长度足够短，可以隐藏分布，则所有明文值都会映射到相同的 HMAC 标签。如果您使用更长的信标长度，则可以很明显看到哪些信标会映射到明文 `POSITIVE` 值。

**相关性**  
强烈建议您避免使用具有相关值的字段构造不同的信标。使用相关字段构造的信标需要更短的信标长度，以充分地最大限度减少向未经授权的用户泄露的有关每个数据集分布的信息量。您必须仔细分析数据集，包括它的熵和相关值的联合分布，以确定需要将信标截断多少。如果产生的信标长度不能满足您的性能需求，则信标可能不适合您的数据集。  
例如，您不应使用 `City` 和 `ZIPCode` 字段构造两个单独的信标，因为邮政编码可能只与一个城市相关联。通常，信标生产生误报会限制未经授权的用户识别有关您的数据集的区分信息的能力。但是 `City` 和 `ZIPCode` 字段之间的关联意味着未经授权的用户可以轻松识别哪些结果是误报，并区分不同的邮政编码。  
您还应避免使用包含相同明文值的字段构造信标。例如，您不应使用 `mobilePhone` 和 `preferredPhone` 字段构造信标，因为它们可能具有相同的值。如果您从两个字段构造不同的信标，则 AWS 数据库加密 SDK 会使用不同的密钥为每个字段创建信标。这会为相同的明文值生成两个不同的 HMAC 标签。这两个不同的信标不太可能产生相同的误报，且未经授权的用户可能能够区分不同的电话号码。

即使您的数据集包含相关字段或具有不均匀的分布，您也可以使用较短的信标长度来构造能够保护数据集机密性的信标。但是，信标长度并不能保证数据集中的每个唯一值都会产生大量误报，从而有效地最大限度减少泄露的有关数据集的区分信息量。信标长度仅能估计产生的误报平均数。数据集分布越不均匀，信标长度在确定产生的误报平均数量方面的有效性就越低。

请仔细考虑您构造信标所依据的字段的分布，并考虑需要将信标长度截断多少才能满足您的安全要求。本章节中的以下主题假设您的信标分布均匀，并且不包含相关数据。

## 可搜索的加密场景
<a name="beacon-overview-example"></a>

下面的示例演示了一种简单的可搜索加密解决方案。在应用中，本示例中使用的示例字段可能不符合信标的分布和关联唯一性建议。在阅读本章节中的可搜索加密概念时，您可以将此示例作为参考。

以一个名为 `Employees` 的跟踪公司员工数据的数据库为例。*数据库中的每条记录都包含名为 *employeeID *LastName**、*FirstName*、和 “地址” 的字段。*`Employees` 数据库中的每个字段都由主键 `EmployeeID` 标识。

以下是数据库中的明文记录示例。

```
{
    "EmployeeID": 101,
    "LastName": "Jones",
    "FirstName": "Mary",
    "Address": {
                "Street": "123 Main",
                "City": "Anytown",
                "State": "OH",
                "ZIPCode": 12345
    }
}
```

如果您在[加密操作](concepts.md#crypt-actions)中将 `LastName` 和 `FirstName` 字段标记为 `ENCRYPT_AND_SIGN`，则这些字段中的值在上传到数据库之前会在本地进行加密。上传的已加密数据是完全随机的，数据库无法将这些数据识别为受保护。它只检测典型的数据条目。这意味着，实际存储在数据库中的记录可能如下所示。

```
{
    "PersonID": 101,
    "LastName": "1d76e94a2063578637d51371b363c9682bad926cbd",
    "FirstName": "21d6d54b0aaabc411e9f9b34b6d53aa4ef3b0a35",
    "Address": {
                "Street": "123 Main",
                "City": "Anytown",
                "State": "OH",
                "ZIPCode": 12345
    }
}
```

如果您需要在数据库中查询`LastName`字段中的精确匹配项，请[配置一个名为的标准信标](configure-beacons.md#config-standard-beacons)，*LastName*以将写入该`LastName`字段的纯文本值映射到存储在数据库中的加密值。

该信标根据字段 HMACs 中的纯文本值进行`LastName`计算。每个 HMAC 输出都被截断，因此不再与明文值完全匹配。例如，`Jones` 的完整哈希值和截断后的哈希值可能如下所示。

**完整哈希值**

`2aa4e9b404c68182562b6ec761fcca5306de527826a69468885e59dc36d0c3f824bdd44cab45526f70a2a18322000264f5451acf75f9f817e2b35099d408c833`

**截断后的哈希值**

`b35099d408c833`

配置标准信标后，您可以在 `LastName` 字段上执行相等搜索。例如，如果要搜索`Jones`，请使用*LastName*信标执行以下查询。

```
LastName = Jones
```

 AWS 数据库加密 SDK 会自动过滤掉误报并返回查询的纯文本结果。