

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

# 适用于 AWS CloudHSM 客户端 SDK 的 JCE 提供商 3
<a name="java-library_3"></a>

 AWS CloudHSM JCE 提供程序是基于 Java 加密扩展 (JCE) 提供程序框架构建的提供程序实现。您可通过 JCE，使用 Java 开发工具包 (JDK) 执行加密操作。在本指南中， AWS CloudHSM JCE 提供者有时被称为 JCE 提供者。使用 JCE 提供程序和 JDK 将加密操作分流至 HSM。

**Topics**
+ [为 AWS CloudHSM 客户端 SDK 安装 JCE 提供程序 3](java-library-install.md)
+ [AWS CloudHSM 客户端 SDK 3 的 JCE 提供程序中的密钥管理基础知识](java-library-key-basics.md)
+ [适用于客户端 SDK 3 的客户 AWS CloudHSM 端 SDK 3 支持的机制](java-lib-supported.md)
+ [AWS CloudHSM 客户端 SDK 3 支持的 Java 密钥属性](java-lib-attributes.md)
+ [适用于客户端 SDK 的 Java AWS CloudHSM 软件库的代码示例 3](java-samples_3.md)
+ [AWS CloudHSM KeyStore 适用于客户端 SDK 的 Java 类 3](alternative-keystore.md)

# 为 AWS CloudHSM 客户端 SDK 安装 JCE 提供程序 3
<a name="java-library-install"></a>

在使用 JCE 提供程序之前，需要 AWS CloudHSM 客户端。

客户端是一个守护程序，用于与集群 HSMs 中的建立 end-to-end加密通信。JCE 提供程序在本地与客户端通信。如果您尚未安装和配置 AWS CloudHSM 客户端软件包，请立即按照中的步骤进行操作[安装客户端 (Linux)](cmu-install-and-configure-client-linux.md)。在您安装和配置客户端之后，可以使用以下命令来启动客户端。

请注意 JCE 提供程序仅在 Linux 和兼容的操作系统中受支持。

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

```
$ sudo start cloudhsm-client
```

------
#### [ Amazon Linux 2 ]

```
$ sudo systemctl start cloudhsm-client
```

------
#### [ CentOS 7 ]

```
$ sudo systemctl start cloudhsm-client
```

------
#### [ CentOS 8 ]

```
$ sudo systemctl start cloudhsm-client
```

------
#### [ RHEL 7 ]

```
$ sudo systemctl start cloudhsm-client
```

------
#### [ RHEL 8 ]

```
$ sudo systemctl start cloudhsm-client
```

------
#### [ Ubuntu 16.04 LTS ]

```
$ sudo systemctl start cloudhsm-client
```

------
#### [ Ubuntu 18.04 LTS ]

```
$ sudo systemctl start cloudhsm-client
```

------
#### [ Ubuntu 20.04 LTS ]

```
$ sudo systemctl start cloudhsm-client
```

------

使用以下部分来安装、验证提供程序并向提供程序提供凭证。

**Topics**
+ [步骤 1：安装 JCE 提供程序](#install-java-library)
+ [步骤 2：验证安装](#validate-install)
+ [步骤 3：向 JCE 提供程序提供凭证](#java-library-credentials)

## 步骤 1：安装 JCE 提供程序
<a name="install-java-library"></a>

使用以下命令下载和安装 JCE 提供程序。此提供程序仅在 Linux 和兼容的操作系统上受支持。

**注意**  
有关升级，请参阅[升级 Client SDK 3](client-upgrade.md)。

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

```
$ wget https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/EL6/cloudhsm-client-jce-latest.el6.x86_64.rpm
```

```
$ sudo yum install ./cloudhsm-client-jce-latest.el6.x86_64.rpm
```

------
#### [ Amazon Linux 2 ]

```
$ wget https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/EL7/cloudhsm-client-jce-latest.el7.x86_64.rpm
```

```
$ sudo yum install ./cloudhsm-client-jce-latest.el7.x86_64.rpm
```

------
#### [ CentOS 7 ]

```
$ wget https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/EL7/cloudhsm-client-jce-latest.el7.x86_64.rpm
```

```
$ sudo yum install ./cloudhsm-client-jce-latest.el7.x86_64.rpm
```

------
#### [ CentOS 8 ]

```
$ wget https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/EL8/cloudhsm-client-jce-latest.el8.x86_64.rpm
```

```
$ sudo yum install ./cloudhsm-client-jce-latest.el8.x86_64.rpm
```

------
#### [ RHEL 7 ]

```
$ wget https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/EL7/cloudhsm-client-jce-latest.el7.x86_64.rpm
```

```
$ sudo yum install ./cloudhsm-client-jce-latest.el7.x86_64.rpm
```

------
#### [ RHEL 8 ]

```
$ wget https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/EL8/cloudhsm-client-jce-latest.el8.x86_64.rpm
```

```
$ sudo yum install ./cloudhsm-client-jce-latest.el8.x86_64.rpm
```

------
#### [ Ubuntu 16.04 LTS ]

```
$ wget https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/Xenial/cloudhsm-client-jce_latest_amd64.deb
```

```
$ sudo apt install ./cloudhsm-client-jce_latest_amd64.deb
```

------
#### [ Ubuntu 18.04 LTS ]

```
$ wget https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/Bionic/cloudhsm-client-jce_latest_u18.04_amd64.deb
```

```
$ sudo apt install ./cloudhsm-client-jce_latest_u18.04_amd64.deb
```

------

运行上述命令后，可以找到以下 JCE 提供程序文件：
+ `/opt/cloudhsm/java/cloudhsm-<version>.jar`
+ `/opt/cloudhsm/java/cloudhsm-test-<version>.jar`
+ `/opt/cloudhsm/java/hamcrest-all-1.3.jar`
+ `/opt/cloudhsm/java/junit.jar`
+ `/opt/cloudhsm/java/log4j-api-2.17.1.jar`
+ `/opt/cloudhsm/java/log4j-core-2.17.1.jar`
+ `/opt/cloudhsm/lib/libcaviumjca.so`

## 步骤 2：验证安装
<a name="validate-install"></a>

在 HSM 上执行基本操作来验证安装。

**验证 JCE 提供程序的安装**

1. （可选）如果您尚未在您的环境中安装 Java，可使用以下命令安装它。

------
#### [ Linux (and compatible libraries) ]

   ```
   $ sudo yum install java-1.8.0-openjdk
   ```

------
#### [ Ubuntu ]

   ```
   $ sudo apt-get install openjdk-8-jre
   ```

------

1. 使用以下命令可设置必要的环境变量。*<password>*用加密用户 (CU) 的凭据替换*<HSM user name>*和。

   ```
   $ export LD_LIBRARY_PATH=/opt/cloudhsm/lib
   ```

   ```
   $ export HSM_PARTITION=PARTITION_1
   ```

   ```
   $ export HSM_USER=<HSM user name>
   ```

   ```
   $ export HSM_PASSWORD=<password>
   ```

1. 使用以下命令可运行基本功能测试。如果成功，命令的输出应该与下面的输出类似。

   ```
   $ java8 -classpath "/opt/cloudhsm/java/*" org.junit.runner.JUnitCore TestBasicFunctionality
   
   JUnit version 4.11
   .2018-08-20 17:53:48,514 DEBUG [main] TestBasicFunctionality (TestBasicFunctionality.java:33) - Adding provider.
   2018-08-20 17:53:48,612 DEBUG [main] TestBasicFunctionality (TestBasicFunctionality.java:42) - Logging in.
   2018-08-20 17:53:48,612 INFO [main] cfm2.LoginManager (LoginManager.java:104) - Looking for credentials in HsmCredentials.properties
   2018-08-20 17:53:48,612 INFO [main] cfm2.LoginManager (LoginManager.java:122) - Looking for credentials in System.properties
   2018-08-20 17:53:48,613 INFO [main] cfm2.LoginManager (LoginManager.java:130) - Looking for credentials in System.env
    SDK Version: 2.03
   2018-08-20 17:53:48,655 DEBUG [main] TestBasicFunctionality (TestBasicFunctionality.java:54) - Generating AES Key with key size 256.
   2018-08-20 17:53:48,698 DEBUG [main] TestBasicFunctionality (TestBasicFunctionality.java:63) - Encrypting with AES Key.
   2018-08-20 17:53:48,705 DEBUG [main] TestBasicFunctionality (TestBasicFunctionality.java:84) - Deleting AES Key.
   2018-08-20 17:53:48,707 DEBUG [main] TestBasicFunctionality (TestBasicFunctionality.java:92) - Logging out.
   
   Time: 0.205
   
   OK (1 test)
   ```

## 步骤 3：向 JCE 提供程序提供凭证
<a name="java-library-credentials"></a>

HSMs 需要先对您的 Java 应用程序进行身份验证，然后应用程序才能使用它们。每个应用程序都可以使用一个会话。 HSMs 使用显式登录或隐式登录方法对会话进行身份验证。

**显式登录**：此方法可让您直接在应用程序中提供 CloudHSM 凭证。它使用 `LoginManager.login()` 方法，在其中传递 CU 用户名、密码和 HSM 分区 ID。有关使用显式登录方法的更多信息，请参阅[登录到 HSM](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/LoginRunner.java) 代码示例。

**隐式登录**：此方法可让您在新属性文件或系统属性中设置 CloudHSM 凭证，或将此类凭证设置为环境变量。
+ **新属性文件**：创建一个名为 `HsmCredentials.properties` 的新文件，然后将该文件添加到应用程序的 `CLASSPATH`。该文件应包含以下内容：

  ```
  HSM_PARTITION = PARTITION_1
  HSM_USER = <HSM user name>
  HSM_PASSWORD = <password>
  ```
+ **系统属性**：在运行应用程序时通过系统属性设置凭证。以下示例演示了可执行此操作的两种不同方式：

  ```
  $ java -DHSM_PARTITION=PARTITION_1 -DHSM_USER=<HSM user name> -DHSM_PASSWORD=<password>
  ```

  ```
  System.setProperty("HSM_PARTITION","PARTITION_1");
  System.setProperty("HSM_USER","<HSM user name>");
  System.setProperty("HSM_PASSWORD","<password>");
  ```
+ **环境变量**：将凭证设置为环境变量。

  ```
  $ export HSM_PARTITION=PARTITION_1
  $ export HSM_USER=<HSM user name>
  $ export HSM_PASSWORD=<password>
  ```

如果应用程序未提供凭证，或者在 HSM 验证会话前尝试执行操作，则凭证可能不可用。在这些情况下，适用于 Java 的 CloudHSM 软件库按以下顺序搜索凭证：

1. `HsmCredentials.properties`

1. 系统属性

1. 环境变量

**错误处理**  
通过显式登录方法处理错误比通过隐式登录方法处理错误更轻松。在使用 `LoginManager` 类时，您可以更好地控制应用程序处理失败情况的方式。当凭据无效或身份验证会话时出现问题时，隐式登录方法会使错误处理变得难以理解。 HSMs 

# AWS CloudHSM 客户端 SDK 3 的 JCE 提供程序中的密钥管理基础知识
<a name="java-library-key-basics"></a>

JCE 提供程序中密钥管理的基础知识涉及导入密钥、导出密钥、通过句柄加载密钥或删除密钥。有关管理密钥的更多信息，请参阅[管理密钥](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/KeyUtilitiesRunner.java)代码示例。

另外，您可以在 [代码示例](java-samples_3.md) 中找到更多 JCE 提供程序代码示例。

# 适用于客户端 SDK 3 的客户 AWS CloudHSM 端 SDK 3 支持的机制
<a name="java-lib-supported"></a>

本主题提供有关 AWS CloudHSM 客户端 SDK 3 支持的 JCE 提供程序的机制的信息。有关支持的 Java 密码学架构 (JCA) 接口和引擎类的信息 AWS CloudHSM，请参阅以下主题。

**Topics**
+ [支持的密钥](#java-keys)
+ [支持的密码](#java-ciphers)
+ [支持的摘要](#java-digests)
+ [支持 HMAC 散列消息认证码算法](#java-mac)
+ [支持的 sign/verify 机制](#java-sign-verify)
+ [机制注释](#w2aac25c23c25c11c17)

## 支持的密钥
<a name="java-keys"></a>

Java AWS CloudHSM 软件库允许您生成以下密钥类型。
+ AES – 128、192 和 256 位 AES 密钥。
+ DESede — 92 位 3DES 密钥。有关即将发生的更改，请参阅下面的注释 [1](#java-keys-note-1)。
+ NIST 曲线 secp256r1 (P-256)、secp384r1 (P-384) 和 secp256k1（区块链）的 ECC 密钥对。
+ RSA 2048 位到 4096 位 RSA 密钥，增量为 256 位。

除了标准参数以外，我们对于生成的每个密钥还支持以下参数。
+ **Label**：可用于搜索密钥的密钥标签。
+ **isExtractable**：指示密钥是否可从 HSM 中导出。
+ **isPersistent**：指示在当前会话结束时密钥是否保留在 HSM 上。

**注意**  
 利用 Java 库版本 3.1，可以更详细地指定参数。有关更多信息，请参阅[支持的 Java 属性](java-lib-attributes.md)。

## 支持的密码
<a name="java-ciphers"></a>

Java AWS CloudHSM 软件库支持以下算法、模式和填充组合。


| 算法 | Mode | Padding | 注意 | 
| --- | --- | --- | --- | 
| AES | CBC |  `AES/CBC/NoPadding` `AES/CBC/PKCS5Padding`  | 实施 `Cipher.ENCRYPT_MODE` 和 `Cipher.DECRYPT_MODE`。  | 
| AES | ECB |  `AES/ECB/NoPadding` `AES/ECB/PKCS5Padding`  | 实施 Cipher.ENCRYPT\$1MODE 和 Cipher.DECRYPT\$1MODE。使用转换 AES。 | 
| AES | CTR |  `AES/CTR/NoPadding`  |  实施 `Cipher.ENCRYPT_MODE` 和 `Cipher.DECRYPT_MODE`。  | 
| AES | GCM | AES/GCM/NoPadding | 实施 `Cipher.ENCRYPT_MODE` 和 `Cipher.DECRYPT_MODE`，以及 `Cipher.WRAP_MODE` 和 `Cipher.UNWRAP_MODE`。执行 AES-GCM 加密时，HSM 会忽略请求中的初始化向量 (IV) 并使用其生成的 IV。当该操作完成时，您必须调用 `Cipher.getIV()` 以获取 IV。 | 
| AESWrap | ECB |  `AESWrap/ECB/ZeroPadding` `AESWrap/ECB/NoPadding` `AESWrap/ECB/PKCS5Padding`  |  实施 `Cipher.WRAP_MODE` 和 `Cipher.UNWRAP_MODE`。使用转换 AES。  | 
| DESede （三重 DES） | CBC |  `DESede/CBC/NoPadding` `DESede/CBC/PKCS5Padding`  |  实施 `Cipher.ENCRYPT_MODE` 和 `Cipher.DECRYPT_MODE`。 密钥生成程序接受 168 或 192 位的大小。但是，在内部，所有 DESede 密钥都是 192 位。 有关即将发生的更改，请参阅下面的注释 [1](#java-keys-note-1)。  | 
| DESede （三重 DES） | ECB | `DESede/ECB/NoPadding``DESede/ECB/PKCS5Padding` | 实施 `Cipher.ENCRYPT_MODE` 和 `Cipher.DECRYPT_MODE`。 密钥生成程序接受 168 或 192 位的大小。但是，在内部，所有 DESede 密钥都是 192 位。 有关即将发生的更改，请参阅下面的注释 [1](#java-keys-note-1)。  | 
| RSA | ECB | `RSA/ECB/NoPadding``RSA/ECB/PKCS1Padding` | 实施 `Cipher.ENCRYPT_MODE` 和 `Cipher.DECRYPT_MODE`。 有关即将发生的更改，请参阅下面的注释 [1](#java-keys-note-1)。 | 
| RSA | ECB | `RSA/ECB/OAEPPadding` `RSA/ECB/OAEPWithSHA-1ANDMGF1Padding` `RSA/ECB/OAEPWithSHA-224ANDMGF1Padding` `RSA/ECB/OAEPWithSHA-256ANDMGF1Padding` `RSA/ECB/OAEPWithSHA-384ANDMGF1Padding` `RSA/ECB/OAEPWithSHA-512ANDMGF1Padding`  |  实施 `Cipher.ENCRYPT_MODE`、`Cipher.DECRYPT_MODE`、`Cipher.WRAP_MODE` 和 `Cipher.UNWRAP_MODE`。 `OAEPPadding` 是采用 `SHA-1` 填充类型的 `OAEP`。  | 
| RSAAESWrap | ECB | OAEPPADDING | 实施 Cipher.WRAP\$1Mode 和 Cipher.UNWRAP\$1MODE。 | 

## 支持的摘要
<a name="java-digests"></a>

Java AWS CloudHSM 软件库支持以下消息摘要。
+ `SHA-1`
+ `SHA-224`
+ `SHA-256`
+ `SHA-384`
+ `SHA-512`

**注意**  
长度小于 16 KB 的数据将在 HSM 上进行哈希处理，而较大的数据将在软件中本地进行哈希处理。

## 支持 HMAC 散列消息认证码算法
<a name="java-mac"></a>

Java AWS CloudHSM 软件库支持以下 HMAC 算法。
+ `HmacSHA1`
+ `HmacSHA224`
+ `HmacSHA256`
+ `HmacSHA384`
+ `HmacSHA512`

## 支持的 sign/verify 机制
<a name="java-sign-verify"></a>

Java AWS CloudHSM 软件库支持以下类型的签名和验证。

**RSA 签名类型**
+ `NONEwithRSA`
+ `SHA1withRSA`
+ `SHA224withRSA`
+ `SHA256withRSA`
+ `SHA384withRSA`
+ `SHA512withRSA`
+ `SHA1withRSA/PSS`
+ `SHA224withRSA/PSS`
+ `SHA256withRSA/PSS`
+ `SHA384withRSA/PSS`
+ `SHA512withRSA/PSS`

**ECDSA 签名类型**
+ `NONEwithECDSA`
+ `SHA1withECDSA`
+ `SHA224withECDSA`
+ `SHA256withECDSA`
+ `SHA384withECDSA`
+ `SHA512withECDSA`

## 机制注释
<a name="w2aac25c23c25c11c17"></a>

[1] 根据 NIST 指导，2023 年以后处于 FIPS 模式的集群不允许这样做。对于处于非 FIPS 模式的集群，2023 年之后仍然允许。有关详细信息，请参阅[FIPS 140 合规：2024 年机制弃用](compliance-dep-notif.md#compliance-dep-notif-1)。

# AWS CloudHSM 客户端 SDK 3 支持的 Java 密钥属性
<a name="java-lib-attributes"></a>

本主题介绍如何使用 Java 库版本 3.1 的专有扩展来设置 AWS CloudHSM 客户端 SDK 3 的关键属性。使用此扩展可在以下操作期间设置受支持的密钥属性及其值：
+ 密钥生成
+ 密钥导入
+ 密钥解开包装

**注意**  
用于设置自定义密钥属性的扩展是一项可选功能。如果您已有适用于 Java 库版本 3.0 的代码，则无需修改该代码。您创建的密钥仍将包含与以前相同的属性。

**Topics**
+ [了解属性](#java-understanding-attributes)
+ [支持的 属性](#java-attributes)
+ [设置密钥的属性](#java-setting-attributes)
+ [组合起来](#java-attributes-summary)

## 了解属性
<a name="java-understanding-attributes"></a>

可以使用密钥属性指定允许对密钥对象（包括公有密钥或私有密钥）执行哪些操作。可以在创建密钥对象的过程中定义密钥属性和值。

但是，Java Cryptography Extension (JCE) 不指定如何设置密钥属性值，因此，默认情况下允许执行大多数操作。相比之下，PKCS \$111 标准定义了一组具有更受限的默认值的综合属性。从 Java 库版本 3.1 开始，CloudHSM 提供了专有扩展，使您能够为常用属性设置更受限的值。

## 支持的 属性
<a name="java-attributes"></a>

可以为下表中列出的属性设置值。作为最佳实践，仅为应受限的属性设置值。如果您未指定值，CloudHSM 将使用下表中指定的默认值。默认值列中的空单元格表示未向该属性分配特定的默认值。


****  

| 属性 | 默认值 | 注意 | 
| --- | --- | --- | 
|  | 对称密钥 | 密钥对中的公有密钥 | 密钥对中的私有密钥 |  | 
| CKA\$1TOKEN | FALSE | FALSE | FALSE | 永久密钥，可在集群 HSMs 中的所有密钥中复制并包含在备份中。CKA\$1TOKEN = FALSE 表示一个会话密钥，该密钥仅加载到一个 HSM 上，并且系统会在与 HSM 的连接断开时自动将其擦除。 | 
| CKA\$1LABEL |   |  |  | 用户定义的字符串。您可以通过它轻松识别 HSM 上的密钥。 | 
| CKA\$1EXTRACTABLE | TRUE |  | TRUE | True 表示可从 HSM 中导出此密钥。 | 
| CKA\$1ENCRYPT | TRUE | TRUE |  | True 表示可使用密钥对任何缓冲区进行加密。 | 
| CKA\$1DECRYPT | TRUE |  | TRUE | True 表示可使用密钥对任何缓冲区进行解密。对于其 CKA\$1WRAP 设置为 true 的密钥，通常将此项设置为 FALSE。 | 
| CKA\$1WRAP | TRUE | TRUE |  | True 表示可使用密钥包装另一个密钥。对于私有密钥，通常将此项设置为 FALSE。 | 
| CKA\$1UNWRAP | TRUE |  | TRUE | True 表示可使用密钥解开包装（导入）另一个密钥。 | 
| CKA\$1SIGN | TRUE |  | TRUE | True 表示可使用密钥对消息摘要进行签名。对于已存档的公有密钥和私有密钥，此项通常设置为 FALSE。 | 
| CKA\$1VERIFY | TRUE | TRUE |  | True 表示可使用密钥验证签名。对于私有密钥，此项通常设置为 FALSE。 | 
| CKA\$1PRIVATE | TRUE | TRUE | TRUE | True 表示用户在通过身份验证之前将无法访问密钥。为了清楚起见，用户在通过身份验证之前将无法访问 CloudHSM 上的任何密钥，即使此属性设置为 FALSE 也是如此。 | 

**注意**  
您将获得对 PKCS \$111 库中属性的更广泛支持。有关更多信息，请参阅[支持的 PKCS \$111 属性](pkcs11-attributes.md)。

## 设置密钥的属性
<a name="java-setting-attributes"></a>

`CloudHsmKeyAttributesMap` 是一个类似于 [Java Map](https://devdocs.io/openjdk~8/java/util/map) 的对象，可以使用它设置密钥对象的属性值。`CloudHsmKeyAttributesMap` 函数的方法与用于 Java 映射操作的方法类似。

可以通过下面两种方式为属性设置自定义值：
+ 使用下表中列出的方法
+ 使用本文档后面演示的生成器模式

属性映射对象支持通过以下方法来设置属性：


****  

| 操作 | 返回值 | `CloudHSMKeyAttributesMap` 方法 | 
| --- | --- | --- | 
| 获取现有密钥的密钥属性值 | 对象（包含值）或 null |  **get**(keyAttribute)  | 
| 填充一个密钥属性的值  | 与密钥属性关联的上一个值，或 null（如果没有密钥属性的映射） |  **put**(keyAttribute, value)  | 
| 填充多个密钥属性的值 | 不适用 |  **putall** () keyAttributesMap  | 
| 从属性映射中删除密钥/值对 |  与密钥属性关联的上一个值，或 *null*（如果没有密钥属性的映射）  |  **remove**(keyAttribute)  | 

**注意**  
未明确指定的任何属性都将设置为 [支持的 属性](#java-attributes) 中前面的表中列出的默认值。

### 生成器模式示例
<a name="java-setting-attributes-builder-example"></a>

开发人员通常会发现，可以通过生成器模式更轻松地使用类。例如：

```
import com.amazonaws.cloudhsm.CloudHsmKeyAttributes;
import com.amazonaws.cloudhsm.CloudHsmKeyAttributesMap;
import com.amazonaws.cloudhsm.CloudHsmKeyPairAttributesMap;

CloudHsmKeyAttributesMap keyAttributesSessionDecryptionKey = 
   new CloudHsmKeyAttributesMap.Builder()
      .put(CloudHsmKeyAttributes.CKA_LABEL, "ExtractableSessionKeyEncryptDecrypt")
      .put(CloudHsmKeyAttributes.CKA_WRAP, false)
      .put(CloudHsmKeyAttributes.CKA_UNWRAP, false)
      .put(CloudHsmKeyAttributes.CKA_SIGN, false)
      .put(CloudHsmKeyAttributes.CKA_VERIFY, false)
      .build();

CloudHsmKeyAttributesMap keyAttributesTokenWrappingKey = 
   new CloudHsmKeyAttributesMap.Builder()
      .put(CloudHsmKeyAttributes.CKA_LABEL, "TokenWrappingKey")
      .put(CloudHsmKeyAttributes.CKA_TOKEN, true)
      .put(CloudHsmKeyAttributes.CKA_ENCRYPT, false)
      .put(CloudHsmKeyAttributes.CKA_DECRYPT, false)
      .put(CloudHsmKeyAttributes.CKA_SIGN, false)
      .put(CloudHsmKeyAttributes.CKA_VERIFY, false)
      .build();
```

开发人员还可以利用预定义的属性集来轻松地实施密钥模板中的最佳实践。例如：

```
//best practice template for wrapping keys

CloudHsmKeyAttributesMap commonKeyAttrs = new CloudHsmKeyAttributesMap.Builder()
    .put(CloudHsmKeyAttributes.CKA_EXTRACTABLE, false)
    .put(CloudHsmKeyAttributes.CKA_DECRYPT, false)
    .build();

// initialize a new instance of CloudHsmKeyAttributesMap by copying commonKeyAttrs
// but with an appropriate label

CloudHsmKeyAttributesMap firstKeyAttrs = new CloudHsmKeyAttributesMap(commonKeyAttrs);
firstKeyAttrs.put(CloudHsmKeyAttributes.CKA_LABEL, "key label");

// alternatively, putAll() will overwrite existing values to enforce conformance

CloudHsmKeyAttributesMap secondKeyAttrs = new CloudHsmKeyAttributesMap();
secondKeyAttrs.put(CloudHsmKeyAttributes.CKA_DECRYPT, true);
secondKeyAttrs.put(CloudHsmKeyAttributes.CKA_ENCRYPT, true);
secondKeyAttrs.put(CloudHsmKeyAttributes.CKA_LABEL, “safe wrapping key”);
secondKeyAttrs.putAll(commonKeyAttrs); // will overwrite CKA_DECRYPT to be FALSE
```

### 设置密钥对的属性
<a name="java-setting-attributes-key-pair"></a>

使用 Java 类 `CloudHsmKeyPairAttributesMap` 处理密钥对的密钥属性。`CloudHsmKeyPairAttributesMap` 封装了两个 `CloudHsmKeyAttributesMap` 对象；一个用于公有密钥，另一个用于私有密钥。

要分别为公有密钥和私有密钥设置单个属性，您可以对该密钥的相应 `CloudHsmKeyAttributes` 映射对象使用 `put()` 方法。使用 `getPublic()` 方法可检索公有密钥的属性映射，使用 `getPrivate()` 可检索私有密钥的属性映射。使用 `putAll()` 填充公有密钥和私有密钥对的多个密钥属性的值，并将密钥对属性映射作为其参数。

### 生成器模式示例
<a name="java-setting-attributes-key-pair-builder-example"></a>

开发人员通常会发现，可以通过生成器模式更轻松地设置密钥属性。例如：

```
import com.amazonaws.cloudhsm.CloudHsmKeyAttributes;
import com.amazonaws.cloudhsm.CloudHsmKeyAttributesMap;
import com.amazonaws.cloudhsm.CloudHsmKeyPairAttributesMap;

//specify attributes up-front 
CloudHsmKeyAttributesMap keyAttributes = 
    new CloudHsmKeyAttributesMap.Builder()
        .put(CloudHsmKeyAttributes.CKA_SIGN, false)
        .put(CloudHsmKeyAttributes.CKA_LABEL, "PublicCertSerial12345")
        .build();

CloudHsmKeyPairAttributesMap keyPairAttributes =
    new CloudHsmKeyPairAttributesMap.Builder()
        .withPublic(keyAttributes)
        .withPrivate(
            new CloudHsmKeyAttributesMap.Builder() //or specify them inline 
                .put(CloudHsmKeyAttributes.CKA_LABEL, "PrivateCertSerial12345")
                .put (CloudHSMKeyAttributes.CKA_WRAP, FALSE)
                .build()
        )
        .build();
```

**注意**  
有关此专有扩展的更多信息，请参阅 [Javadoc](https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/Docs/CloudHsm_CustomKeyAttributes_Javadoc.zip) 存档和上的[示例](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/CustomKeyAttributesRunner.java)。 GitHub要浏览 Javadoc，请下载并展开档案。

## 组合起来
<a name="java-attributes-summary"></a>

要使用密钥操作指定密钥属性，请执行以下步骤：

1. 实例化对称密钥的 `CloudHsmKeyAttributesMap` 或密钥对的 `CloudHsmKeyPairAttributesMap`。

1. 使用所需的密钥属性和值来定义步骤 1 中的属性对象。

1. 实例化与特定密钥类型对应的 `Cavium*ParameterSpec` 类，并将此配置的属性对象传入其构造函数。

1. 将此 `Cavium*ParameterSpec` 对象传递给相应的加密类或方法。

下表包含支持自定义密钥属性的 `Cavium*ParameterSpec` 类和方法以供您参考。


****  

| 密钥类型 | 参数规范类 | 示例构造函数 | 
| --- | --- | --- | 
| 基本类 | CaviumKeyGenAlgorithmParameterSpec | CaviumKeyGenAlgorithmParameterSpec(CloudHsmKeyAttributesMap keyAttributesMap) | 
| DES | CaviumDESKeyGenParameterSpec | CaviumDESKeyGenParameterSpec(int keySize, byte[] iv, CloudHsmKeyAttributesMap keyAttributesMap) | 
| RSA | CaviumRSAKeyGenParameterSpec | CaviumRSAKeyGenParameterSpec(int keysize, BigInteger publicExponent, CloudHsmKeyPairAttributesMap keyPairAttributesMap) | 
| Secret | CaviumGenericSecretKeyGenParameterSpec | CaviumGenericSecretKeyGenParameterSpec(int size, CloudHsmKeyAttributesMap keyAttributesMap) | 
| AES | CaviumAESKeyGenParameterSpec | CaviumAESKeyGenParameterSpec(int keySize, byte[] iv, CloudHsmKeyAttributesMap keyAttributesMap) | 
| EC | CaviumECGenParameterSpec | CaviumECGenParameterSpec(String stdName, CloudHsmKeyPairAttributesMap keyPairAttributesMap) | 

### 示例代码：生成和包装密钥
<a name="example-generate-wrap-key"></a>

这些简短的代码示例演示了两项不同的操作的步骤：密钥生成和密钥包装：

```
// Set up the desired key attributes

KeyGenerator keyGen = KeyGenerator.getInstance("AES", "Cavium");
CaviumAESKeyGenParameterSpec keyAttributes = new CaviumAESKeyGenParameterSpec(
    256,
    new CloudHsmKeyAttributesMap.Builder()
        .put(CloudHsmKeyAttributes.CKA_LABEL, "MyPersistentAESKey")
        .put(CloudHsmKeyAttributes.CKA_EXTRACTABLE, true)
        .put(CloudHsmKeyAttributes.CKA_TOKEN, true)
        .build()
);

// Assume we already have a handle to the myWrappingKey
// Assume we already have the wrappedBytes to unwrap

// Unwrap a key using Custom Key Attributes

CaviumUnwrapParameterSpec unwrapSpec = new CaviumUnwrapParameterSpec(myInitializationVector, keyAttributes);

Cipher unwrapCipher = Cipher.getInstance("AESWrap", "Cavium");
unwrapCipher.init(Cipher.UNWRAP_MODE, myWrappingKey, unwrapSpec);
Key unwrappedKey = unwrapCipher.unwrap(wrappedBytes, "AES", Cipher.SECRET_KEY);
```

# 适用于客户端 SDK 的 Java AWS CloudHSM 软件库的代码示例 3
<a name="java-samples_3"></a>

本主题提供有关 AWS CloudHSM Client SDK 3 的 Java 代码示例的资源和信息。

## 先决条件
<a name="java-samples-prereqs"></a>

 运行示例前，必须设置环境：
+ 安装和配置 [Java 加密扩展（JCE）提供程序](java-library-install.md#install-java-library)和[AWS CloudHSM 客户端包](cmu-install-and-configure-client-linux.md)。
+ 设置有效的 [HSM 用户名和密码](manage-hsm-users.md)。加密用户 (CU) 权限足以执行这些任务。在每个示例中，您的应用程序都将使用这些凭证登录 HSM。
+ 决定如何向 [JCE 提供程序](java-library-install.md#java-library-credentials) 提供凭证。

## 代码示例
<a name="java-samples-code"></a>

以下代码示例向您展示了如何使用 [AWS CloudHSM JCE 提供程序](java-library.md) 执行基本任务。有关更多代码示例，请访问[GitHub](https://github.com/aws-samples/aws-cloudhsm-jce-examples/)。
+ [登录 HSM](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/LoginRunner.java)
+ [管理密钥](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/KeyUtilitiesRunner.java)
+ [生成 AES 密钥](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/SymmetricKeys.java)
+ [使用 AES-GCM 加密和解密](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/AESGCMEncryptDecryptRunner.java)
+ [使用 AES-CTR 加密和解密]( https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/AESCTREncryptDecryptRunner.java)
+ [使用 D3DES-ECB 加密和解密]( https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/DESedeECBEncryptDecryptRunner.java)**请参阅备注 [1](#java-samples-code-note-1)**
+ [使用 AES-GCM 对密钥进行包装和解开包装](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/AESGCMWrappingRunner.java)
+ [使用 AES 对密钥进行包装和解开包装](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/AESWrappingRunner.java)
+ [使用 RSA 对密钥进行包装和解开包装](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/RSAWrappingRunner.java)
+ [使用支持的关键属性](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/CustomKeyAttributesRunner.java)
+ [枚举密钥存储中的密钥](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/KeyStoreExampleRunner.java)
+ [使用 CloudHSM 密钥存储](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/CloudHSMKeyStoreExampleRunner.java)
+ [在多线程示例中签名消息](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/SignThreadedRunner.java)
+ [使用 EC 密钥签名和验证](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/ECOperationsRunner.java)

[1] 根据 NIST 指导，2023 年以后处于 FIPS 模式的集群不允许这样做。对于处于非 FIPS 模式的集群，2023 年之后仍然允许。有关详细信息，请参阅[FIPS 140 合规：2024 年机制弃用](compliance-dep-notif.md#compliance-dep-notif-1)。

# AWS CloudHSM KeyStore 适用于客户端 SDK 的 Java 类 3
<a name="alternative-keystore"></a>

**该 AWS CloudHSM `KeyStore`类提供了一个特殊用途的 PKCS12 密钥存储库，允许通过 k **eytool** 和 jarsigner 等应用程序访问 AWS CloudHSM 密钥。**该密钥库可以将证书与您的密钥数据一起存储，并将它们与存储在 AWS CloudHSM上的密钥数据相关联。

**注意**  
由于证书是公共信息，并且为了最大限度地提高加密密钥的存储容量，因此 AWS CloudHSM 不支持在上 HSMs存储证书。

该 AWS CloudHSM `KeyStore`类实现了 Java 密码学扩展 (JCE) 的`KeyStore`服务提供者接口 (SPI)。有关使用的更多信息`KeyStore`，请参阅 C [lass KeyStore](https://docs.oracle.com/javase/8/docs/api/java/security/KeyStore.html)。

## 为 AWS CloudHSM 客户端 SDK 3 选择合适的密钥库
<a name="choosing_keystore"></a>

 AWS CloudHSM Java 加密扩展 (JCE) 提供程序带有默认的直通式只读密钥存储，可将所有交易传递到 HSM。此默认密钥库不同于特殊用途 AWS CloudHSM KeyStore密钥库。在大多数情况下，您将通过使用默认值获得更好的运行时性能和吞吐量。除了将 AWS CloudHSM KeyStore 密钥操作卸载到 HSM 之外，您只应将它用于需要支持证书和基于证书的操作的应用程序。

尽管两个密钥库都使用 JCE 提供程序执行操作，但是它们是独立的实体，并且彼此之间不交换信息。

为您的 Java 应用程序加载默认密钥库，如下所示：

```
KeyStore ks = KeyStore.getInstance("Cavium");
```

按如下方式加载特殊用途 KeyStore CloudHSM：

```
KeyStore ks = KeyStore.getInstance("CloudHSM")
```

## AWS CloudHSM KeyStore 为客户端 SDK 初始化 3
<a name="initialize_cloudhsm_keystore"></a>

使用与登录 JCE 提供程序相同的方式登录。 AWS CloudHSM KeyStore 您可以使用环境变量或系统属性文件，并且应该在开始使用 CloudHSM KeyStore 之前登录。有关使用 JCE 提供程序登录 HSM 的示例，请参阅[登录到 HSM](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/LoginRunner.java)。

如果需要，您可以指定密码来加密包含密钥存储数据的本地 PKCS12 文件。创建 AWS CloudHSM 密钥库时，需要设置密码，并在使用加载、设置和获取方法时提供密码。

按如下方式实例化一个新的 CloudHSM 对象 KeyStore ：

```
ks.load(null, null);
```

使用 `store` 方法将密钥库数据写入文件。从那时起，您可以使用带有源文件和密码的 `load` 方法加载现有密钥库，如下所示：

```
ks.load(inputStream, password);
```

## 使用 AWS CloudHSM KeyStore 适用于 AWS CloudHSM 客户端 SDK 3
<a name="using_cloudhsm_keystore"></a>

[https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html](https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html)您也可以直接使用代码访问该对象。

AWS CloudHSM KeyStore 符合 JCE [类KeyStore](https://docs.oracle.com/javase/8/docs/api/java/security/KeyStore.html)规范，并提供以下功能。
+ `load`

  从给定输入流加载密钥库。如果在保存密钥库时设置了密码，则必须提供相同的密码才能成功加载。将两个参数都设置为 null 可以初始化一个新的空密钥库。

  ```
  KeyStore ks = KeyStore.getInstance("CloudHSM");
  ks.load(inputStream, password);
  ```
+ `aliases`

  返回给定密钥库实例中所有条目的别名的枚举。结果包括本地存储在 PKCS12 文件中的对象和驻留在 HSM 上的对象。

  **示例代码：**

  ```
  KeyStore ks = KeyStore.getInstance("CloudHSM");
  for(Enumeration<String> entry = ks.aliases(); entry.hasMoreElements();) 
  	{    
  		String label = entry.nextElement();    
  		System.out.println(label);
  	}
  ```
+ `ContainsAlias`

  如果密钥库可以访问至少一个具有指定别名的对象，则返回 true。密钥库检查存储在 PKCS12 文件中的本地对象和驻留在 HSM 上的对象。
+ `DeleteEntry`

  从本地 PKCS12 文件中删除证书条目。不支持使用删除存储在 HSM 中的密钥数据。 AWS CloudHSM KeyStore您可以使用 CloudHSM 的 [key\$1mgmt\$1util](https://docs.aws.amazon.com/cloudhsm/latest/userguide/key_mgmt_util.html) 工具删除密钥。
+ `GetCertificate`

  返回与别名关联的证书（如果可用）。如果别名不存在或引用的对象不是证书，则该函数返回 NULL。

  ```
  KeyStore ks = KeyStore.getInstance("CloudHSM");
  Certificate cert = ks.getCertificate(alias)
  ```
+ `GetCertificateAlias`

  返回其数据与给定证书匹配的第一个密钥库条目的名称（别名）。

  ```
  KeyStore ks = KeyStore.getInstance("CloudHSM");
  String alias = ks.getCertificateAlias(cert)
  ```
+ `GetCertificateChain`

  返回与给定别名关联的证书链。如果别名不存在或引用的对象不是证书，则该函数返回 NULL。
+ `GetCreationDate`

  返回由给定别名标识的条目的创建日期。如果创建日期不可用，则函数返回证书生效的日期。
+ `GetKey`

  GetKey 传递给 HSM 并返回与给定标签对应的密钥对象。当`getKey`直接查询 HSM 时，它可以用于 HSM 上的任何密钥，无论该密钥是否由生成。 KeyStore

  ```
  Key key = ks.getKey(keyLabel, null);
  ```
+ `IsCertificateEntry`

  检查具有给定别名的条目是否表示证书条目。
+ `IsKeyEntry`

  检查具有给定别名的条目是否表示密钥条目。该操作在 PKCS12 文件和 HSM 中搜索别名。
+ `SetCertificateEntry`

  将给定证书分配给给定别名。如果给定的别名已被用于标识密钥或证书，则会引发 `KeyStoreException`。您可以使用 JCE 代码获取密钥对象，然后使用 KeyStore `SetKeyEntry`方法将证书与密钥相关联。
+ 使用 `byte[]` 密钥执行 `SetKeyEntry`

  **客户端软件开发工具包 3 目前不支持此 API。**
+ 使用 `Key` 对象执行 `SetKeyEntry`

  将给定密钥分配到给定别名并将其存储在 HSM 中。如果 `Key` 对象不属于类型 `CaviumKey`，则该密钥将作为可提取会话密钥导入到 HSM 中。

  如果 `Key` 对象属于类型 `PrivateKey`，则它必须伴随相应的证书链。

  如果别名已存在，则 `SetKeyEntry` 调用会引发 `KeyStoreException`，并阻止该密钥被覆盖。如果密钥必须被覆盖，请为此目的使用 KMU 或 JCE。
+ `EngineSize`

  返回密钥库中的条目数。
+ `Store`

  将密钥存储库作为 PKCS12 文件存储到给定输出流，并使用给定的密码对其进行保护。此外，它会保留所有加载的密钥（使用 `setKey` 调用进行设置）。