

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

# 适用于客户端 SDK 5 的 AWS CloudHSM JCE 高级配置
<a name="java-lib-configs"></a>

 AWS CloudHSM JCE 提供商包括以下高级配置，这些配置不是大多数客户使用的常规配置的一部分。
+ [连接到多个集群](java-lib-configs-multi.md)
+ [使用 JCE 提取密钥](java-lib-configs-getencoded.md)
+ [JCE 重试配置](java-lib-configs-retry.md)

# 使用 JCE 提供程序连接到多个 AWS CloudHSM 集群
<a name="java-lib-configs-multi"></a>

此配置允许单个客户端实例与多个 AWS CloudHSM 集群通信。对于某些用例来说，与让单个实例仅与单个集群通信相比，这可能是项节省成本的功能。该`CloudHsmProvider`类是 [Java AWS CloudHSM Security 的 Provider 类的](https://docs.oracle.com/javase/8/docs/api/java/security/Provider.html)实现。此类的每个实例都代表与整个 AWS CloudHSM 集群的连接。您可以实例化该类并将其添加到 Java Security 提供程序的列表中，以便您可以使用标准 JCE 类与之交互。

以下示例实例化该类并将其添加到 Java Security 提供程序的列表中：

```
if (Security.getProvider(CloudHsmProvider.PROVIDER_NAME) == null) {
    Security.addProvider(new CloudHsmProvider());
}
```

`CloudHsmProvider` 可以通过下列两种方式进行配置：

1. 使用文件进行配置（默认配置）

1. 使用代码进行配置

以下主题介绍了这些配置以及如何连接到多个集群。

**Topics**
+ [使用文件配置 AWS CloudHSM `CloudHsmProvider` 类（默认配置）](java-lib-configs-default.md)
+ [使用代码配置 AWS CloudHSM `CloudHsmProvider` 类](java-lib-configs-using-code.md)
+ [Connect 连接到多个 AWS CloudHSM 集群](java-lib-connecting-to-multiclusters.md)

# 使用文件配置 AWS CloudHSM `CloudHsmProvider` 类（默认配置）
<a name="java-lib-configs-default"></a>

配置 AWS CloudHSM `CloudHsmProvider`类的默认方法是使用文件。

当您使用默认构造函数实例化 `CloudHsmProvider` 时，默认情况下，它会在 Linux 的 `/opt/cloudhsm/etc/cloudhsm-jce.cfg` 路径中查找配置文件。该配置文件可使用 `configure-jce` 进行配置。

使用默认构造函数创建的对象将使用默认 CloudHSM 提供程序名称 `CloudHSM`。提供程序的名称对于与 JCE 交互非常有用，可以让 JCE 知道要使用哪个提供程序进行各类操作。使用 CloudHSM 提供程序名称进行密码操作的示例如下所示：

```
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "CloudHSM");
```

# 使用代码配置 AWS CloudHSM `CloudHsmProvider` 类
<a name="java-lib-configs-using-code"></a>

从客户端 SDK 版本 5.8.0 开始，您还可以使用 Java 代码配置该 AWS CloudHSM `CloudHsmProvider`类。做到这一点的方法是使用 `CloudHsmProviderConfig` 类的对象。您可以使用 `CloudHsmProviderConfigBuilder` 构建此对象。

`CloudHsmProvider` 还有另一个接受 `CloudHsmProviderConfig` 对象的构造函数，如以下示例所示。

**Example**  

```
CloudHsmProviderConfig config = CloudHsmProviderConfig.builder()  
                                    .withCluster(  
                                        CloudHsmCluster.builder()  
                                            .withHsmCAFilePath(hsmCAFilePath)
                                            .withClusterUniqueIdentifier("CloudHsmCluster1")
        .withServer(CloudHsmServer.builder().withHostIP(hostName).build())  
                        .build())  
        .build();
CloudHsmProvider provider = new CloudHsmProvider(config);
```

在此示例中，JCE 提供程序的名称为 `CloudHsmCluster1`。这是应用程序随后可用于与 JCE 交互的名称：

**Example**  

```
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "CloudHsmCluster1");
```

或者应用程序也可以使用上面创建的提供程序对象让 JCE 知道要使用该提供程序进行操作：

```
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", provider);
```

如果未在 `withClusterUniqueIdentifier` 方法中指定唯一标识符，则会为您创建一个随机生成的提供程序名称。要获取这个随机生成的标识符，应用程序可以调用 `provider.getName()` 获取该标识符。

# Connect 连接到多个 AWS CloudHSM 集群
<a name="java-lib-connecting-to-multiclusters"></a>

每个都`CloudHsmProvider`代表与您的集 AWS CloudHSM 群的连接。如果您想与来自同一应用程序的另一个集群通信，则可以使用另一个集群的配置创建另一个 `CloudHsmProvider` 对象，也可以使用提供程序对象或提供程序名称与另一个集群进行交互，如以下示例所示。

**Example**  

```
CloudHsmProviderConfig config = CloudHsmProviderConfig.builder()  
                                    .withCluster(  
                                        CloudHsmCluster.builder()  
                                            .withHsmCAFilePath(hsmCAFilePath)
                                            .withClusterUniqueIdentifier("CloudHsmCluster1")
        .withServer(CloudHsmServer.builder().withHostIP(hostName).build())  
                        .build())  
        .build();
CloudHsmProvider provider1 = new CloudHsmProvider(config);

if (Security.getProvider(provider1.getName()) == null) {
    Security.addProvider(provider1);
}

CloudHsmProviderConfig config2 = CloudHsmProviderConfig.builder()  
                                    .withCluster(  
                                        CloudHsmCluster.builder()  
                                            .withHsmCAFilePath(hsmCAFilePath2)
                                            .withClusterUniqueIdentifier("CloudHsmCluster2")
        .withServer(CloudHsmServer.builder().withHostIP(hostName2).build())  
                        .build())  
        .build();
CloudHsmProvider provider2 = new CloudHsmProvider(config2);

if (Security.getProvider(provider2.getName()) == null) {
    Security.addProvider(provider2);
}
```

配置了上面的两个提供程序（均为集群）后，就可以使用提供程序对象或提供程序名称与它们进行交互。

在此演示如何与之交谈的示例的基础上`cluster1`，您可以使用以下示例进行AES/GCM/NoPadding操作：

```
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", provider1);
```

在同一个应用程序中，要使用提供程序名称在第二个集群上生成“AES”密钥，也可以使用以下示例：

```
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", provider2.getName());
```

# 使用 JCE 提取密钥 AWS CloudHSM
<a name="java-lib-configs-getencoded"></a>

Java 密码学扩展 (JCE) 使用的架构允许插入不同的加密实现。 AWS CloudHSM 发布了一个这样的 JCE 提供商，它可以将加密操作卸载到 HSM。对于大多数其他 JCE 提供商来说，要使用存储在 AWS CloudHSM 中的密钥，他们必须将您的密钥字节以明文形式提取 HSMs 到您的计算机内存中供他们使用。 HSMs 通常只允许将密钥提取为封装对象，而不允许以明文形式提取。但是，为了支持提供商间集成用例， AWS CloudHSM 允许使用选择加入配置选项来启用密钥字节的提取。

**重要**  
 AWS CloudHSM 无论何时指定 AWS CloudHSM 提供程序或 AWS CloudHSM 使用密钥对象，JCE 都会将操作卸载到任何时候。如果您希望在 HSM 内部进行操作，则无需以明文方式提取密钥。只有当您的应用程序由于第三方库或 JCE 提供程序的限制而无法使用安全机制（例如包装和解包密钥）时，才需要以明文提取密钥。

默认情况下， AWS CloudHSM JCE 提供程序允许提取**公钥**，以便与外部 JCE 提供程序配合使用。始终允许使用以下方法：


| 类 | 方法 | 格式 (getEncoded) | 
| --- | --- | --- | 
| EcPublicKey | getEncoded() | X.509 | 
|  | getW() | 不适用 | 
| RSAPublic钥匙 | getEncoded() | X.509 | 
|  | getPublicExponent() | 不适用 | 
| CloudHsmRsaPrivateCrtKey | getPublicExponent() | 不适用 | 

默认情况下， AWS CloudHSM JCE 提供程序不允许提取私钥或**私**钥的**密**钥字节。如果您的用例需要，则可以在以下条件下启用**私有**密钥或**机密**密钥的明文密钥字节提取功能：

1. 私有密钥和机密密钥的 `EXTRACTABLE` 属性设置为 **true**。
   + 默认情况下，私有密钥和机密密钥的 `EXTRACTABLE` 属性设置为 **true**。`EXTRACTABLE` 密钥是允许从 HSM 中导出的密钥。有关更多信息，请参阅《[客户端软件开发工具包 5](java-lib-attributes_5.md) 支持的 Java 属性》。

1. 私有密钥和机密密钥的 `WRAP_WITH_TRUSTED` 属性设置为 **false**。
   + `getEncoded`、`getPrivateExponent` 和 `getS` 不能与无法以明文导出的私有密钥一起使用。`WRAP_WITH_TRUSTED` 不允许您的私有密钥以明文从 HSM 中导出。有关更多信息，请参阅[使用可信密钥控制密钥解包](manage-keys-using-trusted-keys.md)。

# 允许 JCE 提供者从中提取私钥机密 AWS CloudHSM
<a name="get-encoded-take-out-private-keys"></a>

使用以下步骤允许 AWS CloudHSM JCE 提供者提取您的私钥机密。

**重要**  
此配置更改允许从 HSM 集群中以明文提取所有 `EXTRACTABLE` 密钥字节。为了提高安全性，您应该考虑使用[密钥包装方法](java-lib-supported_5.md)将密钥安全地从 HSM 中提取出来。这样可以防止无意中从 HSM 中提取密钥字节。

1. 使用以下命令从 JCE 中提取您的**私有**密钥或**机密**密钥：

------
#### [ Linux ]

   ```
   $ /opt/cloudhsm/bin/configure-jce --enable-clear-key-extraction-in-software
   ```

------
#### [ Windows ]

   ```
   PS C:\> & "C:\Program Files\Amazon\CloudHSM\bin\configure-jce.exe" --enable-clear-key-extraction-in-software
   ```

------

1. 一旦启用了明文密钥提取功能，就会启用以下方法将私有密钥提取到内存中。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/cloudhsm/latest/userguide/get-encoded-take-out-private-keys.html)

如果要恢复默认行为并且不允许 JCE 以明文导出密钥，请运行以下命令：

------
#### [ Linux ]

```
$ /opt/cloudhsm/bin/configure-jce --disable-clear-key-extraction-in-software
```

------
#### [ Windows ]

```
PS C:\> & "C:\Program Files\Amazon\CloudHSM\bin\configure-jce.exe" --disable-clear-key-extraction-in-software
```

------

# 用于 JCE 的重试命令 AWS CloudHSM
<a name="java-lib-configs-retry"></a>

AWS CloudHSM 客户端 SDK 5.8.0 及更高版本具有内置的自动重试策略，该策略将从客户端重试 HSM 限制的操作。当 HSM 因忙于执行之前的操作而无法接受更多请求而限制操作时，客户端 SDKs 将尝试重试受限制的操作最多 3 次，同时呈指数级退缩。这种自动重试策略可设置为以下两种模式之一：**关闭**和**标准**。
+ **关闭**：客户端软件开发工具包 不会对 HSM 的任何节流操作执行任何重试策略。
+ **标准**：这是客户端软件开发工具包版本 5.8.0 及更高版本的默认模式。在此模式下，客户端 SDKs 将通过指数级退出自动重试受限制的操作。

有关更多信息，请参阅 [HSM 节流](troubleshoot-hsm-throttling.md)。

## 将重试命令设置为关闭模式
<a name="w2aac25c21c25c25c15b9"></a>

------
#### [ Linux ]

**在 Linux 上将客户端软件开发工具包 5 的重试命令设置为 **off****
+ 您可以使用以下命令将重试配置设置为 **off** 模式：

  ```
  $ sudo /opt/cloudhsm/bin/configure-jce --default-retry-mode off
  ```

------
#### [ Windows ]

**在 Windows 上将客户端软件开发工具包 5 的重试命令设置为 **off****
+ 您可以使用以下命令将重试配置设置为 **off** 模式：

  ```
  PS C:\> & "C:\Program Files\Amazon\CloudHSM\bin\configure-jce.exe" --default-retry-mode off
  ```

------