

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Client SDK 3 を使用して Java Keytool および Jarsigner AWS CloudHSM と統合する
<a name="keystore-third-party-tools"></a>

AWS CloudHSM key store は、ハードウェアセキュリティモジュール (HSM) のキーに関連付けられた証明書を、 `keytool`や などのサードパーティーツールを使用して使用する専用 JCE キーストアです`jarsigner`。証明書はパブリックで非機密データであるため、HSM に証明書を保存 AWS CloudHSM しません。 AWS CloudHSM キーストアは証明書をローカルファイルに格納し、証明書を HSM の対応するキーにマッピングします。

 AWS CloudHSM キーストアを使用して新しいキーを生成すると、ローカルキーストアファイルにエントリは生成されず、キーは HSM に作成されます。同様に、 AWS CloudHSM キーストアを使用してキーを検索すると、検索が HSM に渡されます。証明書を AWS CloudHSM キーストアに保存すると、プロバイダーは対応するエイリアスを持つキーペアが HSM に存在することを確認し、提供された証明書を対応するキーペアに関連付けます。

**Topics**
+ [前提条件](keystore-prerequisites.md)
+ [keytool でキーストアの使用](using_keystore_with_keytool.md)
+ [Jarsigner でキーストアを使用する](using_keystore_jarsigner.md)
+ [既知の問題](known-issues-keytool-jarsigner.md)
+ [既存のキーをキーストアに登録する](register-pre-existing-keys-with-keystore.md)

# クライアント SDK 3 を使用して Java Keytool および Jarsigner AWS CloudHSM と統合するための前提条件
<a name="keystore-prerequisites"></a>

 AWS CloudHSM キーストアを使用するには、まず AWS CloudHSM JCE SDK を初期化して設定する必要があります。これを行うには、次の手順を実行します。

## 手順 1: JCE をインストールする
<a name="prereq-step-one"></a>

 AWS CloudHSM クライアントの前提条件を含む JCE をインストールするには、[Java ライブラリをインストールする](java-library-install.md)ステップに従います。

## 手順 2: 環境変数に HSM ログイン認証情報を追加する
<a name="prereq-step-two"></a>

HSM ログイン認証情報を格納する環境変数を設定します。

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

**注記**  
CloudHSM JCE には、さまざまなログインオプションがあります。サードパーティーアプリケーションで AWS CloudHSM キーストアを使用するには、環境変数で暗黙的なログインを使用する必要があります。アプリケーションコードによる明示的なログインを使用する場合は、 AWS CloudHSM キーストアを使用して独自のアプリケーションを構築する必要があります。詳細については、[AWS CloudHSM 「 キーストアの使用](alternative-keystore.md)」の記事を参照してください。

## 手順 3: JCE プロバイダーを登録する
<a name="prereq-step-three"></a>

JCE プロバイダーを登録するには、Java クラウドプロバイダーの設定を使用します。

1. Java インストールで java.security 設定ファイルを開き、編集します。

1. java.security 設定ファイルで、`com.cavium.provider.CaviumProvider` を最後のプロバイダーとして追加します。たとえば、java.security ファイルに 9 つのプロバイダーがある場合は、セクションの最後のプロバイダーとして次のプロバイダーを追加します。Cavium プロバイダーの優先順位を高く設定すると、システムのパフォーマンスに悪影響を与える可能性があります。

   `security.provider.10=com.cavium.provider.CaviumProvider`
**注記**  
パワーユーザーは、keytool を使用する際、セキュリティ構成ファイルを更新する代わりに `-providerName`、`-providerclass` および `-providerpath` のコマンドラインオプションを指定することに慣れているかもしれませんが、 AWS CloudHSM キーストアでキーを生成するときにコマンドラインオプションを指定しようとすると、エラーが発生します。

# クライアント SDK 3 を使用して AWS CloudHSM keytool でキーストアを使用する
<a name="using_keystore_with_keytool"></a>

[keytool](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html) は、Linux システム上の一般的なキーおよび証明書タスク向けの一般的なコマンドラインユーティリティです。keytool に関する完全なチュートリアルは、 AWS CloudHSM ドキュメントの範囲外です。この記事では、 をキーストアを通じて信頼のルート AWS CloudHSM として使用する場合に、さまざまな AWS CloudHSM keytool 関数で使用する特定のパラメータについて説明します。

keytool をキー AWS CloudHSM ストアで使用する場合は、任意の keytool コマンドに次の引数を指定します。

```
-storetype CLOUDHSM \
		-J-classpath '-J/opt/cloudhsm/java/*' \
		-J-Djava.library.path=/opt/cloudhsm/lib
```

キーストアを使用して新しい AWS CloudHSM キーストアファイルを作成する場合は、「」を参照してください[AWS CloudHSM クライアント SDK 3 に AWS CloudHSM KeyStoreを使用する](alternative-keystore.md#using_cloudhsm_keystore)。既存のキーストアを使用するには、keytool の –keystore 引数を使用して、その名前 (パスを含む) を指定します。keytool コマンドで存在しないキーストアファイルを指定すると、 AWS CloudHSM キーストアは新しいキーストアファイルを作成します。

# keytool を使用して新しい AWS CloudHSM キーを作成する
<a name="create_key_keytool"></a>

keytool を使用して、 AWS CloudHSM JCE SDK でサポートされている任意のタイプのキーを生成できます。キーと長さの完全なリストについては、Java ライブラリの「[サポートされるキー](java-lib-supported.md#java-keys)」の記事を参照してください。

**重要**  
keytool で生成されたキーはソフトウェアで生成され、抽出可能な永続キー AWS CloudHSM として にインポートされます。

抽出不可能なキーをハードウェアセキュリティモジュール (HSM) で直接作成し、keytool または Jarsigner で使用する手順は、「既存の[キーを AWS CloudHSM キーストアに登録する](register-pre-existing-keys-with-keystore.md)」のコードサンプルに示されています。エクスポートできないキーを keytool の外部で生成したうえで、対応する証明書をキーストアにインポートすることを強くお勧めします。keytool と jarsigner を使用して抽出可能な RSA キーまたは EC キーを使用する場合、プロバイダーは からキーをエクスポート AWS CloudHSM し、ローカルでキーを使用して署名操作を行います。

CloudHSM クラスターに複数のクライアントインスタンスが接続されている場合、1 つのクライアントインスタンスのキーストアに証明書をインポートしても、他のクライアントインスタンスで自動的に使用できるようにはなりません。各クライアントインスタンスでキーおよび関連する証明書を登録するには、「[keytool を使用して CSR を生成する](generate_csr_using_keytool.md)」の説明に従って Java アプリケーションを実行する必要があります。または、1 つのクライアントで必要な変更を行い、結果のキーストアファイルを他のすべてのクライアントインスタンスにコピーすることもできます。

**例 1: **対称型 AES-256 キーを生成し、作業ディレクトリの「example\$1keystore.store」という名前のキーストアファイルに保存します。*<secret label>* を独自のラベルに置き換えます。

```
keytool -genseckey -alias <secret label> -keyalg aes \
		-keysize 256 -keystore example_keystore.store \
		-storetype CloudHSM -J-classpath '-J/opt/cloudhsm/java/*' \
		-J-Djava.library.path=/opt/cloudhsm/lib/
```

**例 2: **RSA 2,048 キーペアを生成し、作業ディレクトリの「example\$1keystore.store」という名前のキーストアファイルに保存します。*<RSA key pair label>* を独自のラベルに置き換えます。

```
keytool -genkeypair -alias <RSA key pair label> \
        -keyalg rsa -keysize 2048 \
        -sigalg sha512withrsa \
        -keystore example_keystore.store \
        -storetype CLOUDHSM \
        -J-classpath '-J/opt/cloudhsm/java/*' \
        -J-Djava.library.path=/opt/cloudhsm/lib/
```

**例 3: **p256 ED キーを生成し、作業ディレクトリの「example\$1keystore.store」という名前のキーストアファイルに保存します。*<ec key pair label>* を独自のラベルに置き換えます。

```
keytool -genkeypair -alias <ec key pair label> \
        -keyalg ec -keysize 256 \
        -sigalg SHA512withECDSA \
        -keystore example_keystore.store \
        -storetype CLOUDHSM \
        -J-classpath '-J/opt/cloudhsm/java/*' \
        -J-Djava.library.path=/opt/cloudhsm/lib/
```

[サポートされている署名アルゴリズム](java-lib-supported.md#java-sign-verify)のリストは、Java ライブラリにあります。

# keytool を使用して AWS CloudHSM キーを削除する
<a name="delete_key_using_keytool"></a>

 AWS CloudHSM キーストアはキーの削除をサポートしていません。キーを削除するには、 AWS CloudHSMのコマンドラインツール の `deleteKey`関数を使用する必要があります[KMU を使用して AWS CloudHSM キーを削除する](key_mgmt_util-deleteKey.md)。

# keytool AWS CloudHSM を使用して CSR を生成する
<a name="generate_csr_using_keytool"></a>

[AWS CloudHSM クライアント SDK 5 用の OpenSSL Dynamic Engine](openssl-library.md) を使用すると、証明書署名要求 (CSR) を柔軟に生成できます。次のコマンドは、keytool を使用して、エイリアス `example-key-pair` を持つキーペアの CSR を生成します。

```
keytool -certreq -alias <key pair label> \
        -file example_csr.csr \
        -keystore example_keystore.store \
        -storetype CLOUDHSM \
        -J-classpath '-J/opt/cloudhsm/java/*' \
        -J-Djava.library.path=/opt/cloudhsm/lib/
```

**注記**  
keytool のキーペアを使用するには、指定されたキーストアファイルにそのキーペアのエントリが必要です。keytool の外部で生成されたキーペアを使用する場合は、キーおよび証明書のメタデータをキーストアにインポートする必要があります。キーストアデータのインポート手順については、[「Keytool を使用した AWS CloudHSM キーストアへの中間証明書とルート証明書のインポート](import_cert_using_keytool.md)」を参照してください。

# keytool を使用して中間証明書とルート証明書を AWS CloudHSM キーストアにインポートする
<a name="import_cert_using_keytool"></a>

CA 証明書を にインポートするには AWS CloudHSM、新しくインポートされた証明書で完全な証明書チェーンの検証を有効にする必要があります。次のコマンドでは、例を示しています。

```
keytool -import -trustcacerts -alias rootCAcert \
        -file rootCAcert.cert -keystore example_keystore.store \
        -storetype CLOUDHSM \
        -J-classpath '-J/opt/cloudhsm/java/*' \
        -J-Djava.library.path=/opt/cloudhsm/lib/
```

複数のクライアントインスタンスを AWS CloudHSM クラスターに接続する場合、1 つのクライアントインスタンスのキーストアに証明書をインポートしても、他のクライアントインスタンスで証明書が自動的に使用可能になることはありません。各クライアントインスタンスで証明書をインポートする必要があります。

# keytool を使用して AWS CloudHSM キーストアから証明書を削除する
<a name="delete_cert_using_keytool"></a>

次のコマンドは、Java keytool キーストアから AWS CloudHSM 証明書を削除する方法の例を示しています。

```
keytool -delete -alias mydomain -keystore \
        -keystore example_keystore.store \
        -storetype CLOUDHSM \
        -J-classpath '-J/opt/cloudhsm/java/*' \
        -J-Djava.library.path=/opt/cloudhsm/lib/
```

複数のクライアントインスタンスを AWS CloudHSM クラスターに接続しても、1 つのクライアントインスタンスのキーストアで証明書を削除しても、他のクライアントインスタンスから証明書は自動的に削除されません。各クライアントインスタンスで証明書を削除する必要があります。

# keytool を使用して作業証明書を AWS CloudHSM キーストアにインポートする
<a name="import_working_cert_using_keytool"></a>

証明書署名要求 (CSR) が署名されると、それを AWS CloudHSM キーストアにインポートし、適切なキーペアに関連付けることができます。次のコマンドでは、例を示しています。

```
keytool -importcert -noprompt -alias <key pair label> \
        -file example_certificate.crt \
        -keystore example_keystore.store
        -storetype CLOUDHSM \
        -J-classpath '-J/opt/cloudhsm/java/*' \
        -J-Djava.library.path=/opt/cloudhsm/lib/
```

エイリアスは、キーストア内の関連付けられた証明書を持つキーペアである必要があります。キーが keytool の外部で生成される場合や、別のクライアントインスタンスで生成される場合は、まずキーおよび証明書のメタデータをキーストアにインポートする必要があります。証明書メタデータをインポートする手順については、[AWS CloudHSM 「 キーストアで既存のキーを登録する](register-pre-existing-keys-with-keystore.md)」のコードサンプルを参照してください。

証明書チェーンは検証可能である必要があります。証明書を検証できない場合は、チェーンを検証できるように、署名 (証明機関) 証明書をキーストアにインポートする必要があります。

# keytool AWS CloudHSM を使用して から証明書をエクスポートする
<a name="export_cert_using_keytool"></a>

次の例では、バイナリ X.509 形式の証明書を生成します。人間が読み取り可能な証明書をエクスポートするには AWS CloudHSM、 `-exportcert` コマンド`-rfc`に を追加します。

```
keytool -exportcert -alias <key pair label> \
        -file example_exported_certificate.crt \
        -keystore example_keystore.store \
        -storetype CLOUDHSM \
        -J-classpath '-J/opt/cloudhsm/java/*' \
        -J-Djava.library.path=/opt/cloudhsm/lib/
```

# クライアント SDK 3 を使用して Jarsigner で AWS CloudHSM キーストアを使用する
<a name="using_keystore_jarsigner"></a>

Jarsigner は、ハードウェア セキュリティ モジュール (HSM) に安全に保存されたキーを使用して JAR ファイルに署名するための一般的なコマンドラインユーティリティです。Jarsigner に関する完全なチュートリアルは、 AWS CloudHSM ドキュメントの対象外です。このセクションでは、 AWS CloudHSM キーストアを通じて信頼のルート AWS CloudHSM として を使用して署名および検証するために使用する Jarsigner パラメータについて説明します。

# Jarsigner で AWS CloudHSM キーと証明書をセットアップする
<a name="jarsigner_set_up_certificates"></a>

Jarsigner で AWS CloudHSM JAR ファイルに署名する前に、次の手順を設定または完了していることを確認してください。

1. 「[AWS CloudHSM キーストアの前提条件](keystore-prerequisites.md)」のガイダンスに従います。

1. 現在のサーバーまたはクライアントインスタンスの AWS CloudHSM キーストアに保存する必要がある署名キー、関連する証明書、証明書チェーンを設定します。でキーを作成し AWS CloudHSM 、関連するメタデータを AWS CloudHSM キーストアにインポートします。[「既存のキーを AWS CloudHSM キーストアに登録する](register-pre-existing-keys-with-keystore.md)」のコードサンプルを使用して、メタデータをキーストアにインポートします。keytool を使用してキーおよび証明書を設定する場合は、「[keytool を使用して新しい AWS CloudHSM キーを作成する](create_key_keytool.md)」を参照してください。複数のクライアントインスタンスを使用して JAR に署名する場合は、キーを作成し、証明書チェーンをインポートします。次に、結果のキーストアファイルを各クライアントインスタンスにコピーします。新しいキーを頻繁に生成する場合は、各クライアントインスタンスに証明書を個別にインポートする方が簡単です。

1. 証明書チェーン全体が検証可能である必要があります。証明書チェーンを検証できるようにするには、CA 証明書と中間証明書を AWS CloudHSM キーストアに追加する必要がある場合があります。Java コードを使用して証明書チェーンを検証する手順については、[「JAR ファイルの署名」の「コードスニペット AWS CloudHSM 」と「Jarsigner](jarsigner_sign_jar_using_hsm_jarsigner.md)」を参照してください。必要に応じて、keytool を使用して証明書をインポートできます。keytool を使用する手順については、[「Keytool を使用して中間証明書とルート証明書を AWS CloudHSM Key Store にインポート](import_cert_using_keytool.md)する」を参照してください。

# AWS CloudHSM と Jarsigner を使用して JAR ファイルに署名する
<a name="jarsigner_sign_jar_using_hsm_jarsigner"></a>

次のコマンドを使用して、 AWS CloudHSM と jarsigner を使用して JAR ファイルに署名します。

```
jarsigner -keystore example_keystore.store \
        -signedjar signthisclass_signed.jar \
        -sigalg sha512withrsa \
        -storetype CloudHSM \
        -J-classpath '-J/opt/cloudhsm/java/*:/usr/lib/jvm/java-1.8.0/lib/tools.jar' \
        -J-Djava.library.path=/opt/cloudhsm/lib \
        signthisclass.jar <key pair label>
```

署名付き JAR を確認するには、次のコマンドを使用します。

```
jarsigner -verify \
        -keystore example_keystore.store \
        -sigalg sha512withrsa \
        -storetype CloudHSM \
        -J-classpath '-J/opt/cloudhsm/java/*:/usr/lib/jvm/java-1.8.0/lib/tools.jar' \
        -J-Djava.library.path=/opt/cloudhsm/lib \
        signthisclass_signed.jar <key pair label>
```

# クライアント SDK 3 を使用した Java Keytool と Jarsigner AWS CloudHSM の統合に関する既知の問題
<a name="known-issues-keytool-jarsigner"></a>

次のリストは、クライアント SDK 3 を使用した AWS CloudHSM および Java Keytool および Jarsigner との統合に関する既知の問題の現在のリストを示しています。
+ keytool を使用してキーを生成する場合、プロバイダー設定の最初のプロバイダを CaviumProvider にすることはできません。
+ keytool を使用してキーを生成する場合、セキュリティ構成ファイル内の最初の (サポートされている) プロバイダーを使用してキーを生成します。これは通常、ソフトウェアプロバイダーです。生成されたキーにはエイリアスが割り当てられ、キーの追加プロセス中に永続的 (トークン) キーとして AWS CloudHSM HSM にインポートされます。
+  keytool を AWS CloudHSM キーストアで使用するときは、コマンドラインで `-providerName`、`-providerclass`、または `-providerpath`オプションを指定しないでください。これらのオプションは、「[キーストアの前提条件](keystore-prerequisites.md)」の説明に従って、セキュリティプロバイダーファイルで指定します。
+ keytool と Jarsigner を介して抽出不可能な EC キーを使用する場合、SunEC プロバイダーを java.security ファイル内のプロバイダーのリストから削除する、または無効にする必要があります。keytool と Jarsigner を介して抽出可能な EC キーを使用する場合、プロバイダーは AWS CloudHSM HSM からキービットをエクスポートし、キーをローカルで署名オペレーションに使用します。keytool または Jarsigner でエクスポート可能なキーを使用することはお勧めしません。

# 既存のキーを AWS CloudHSM キーストアに登録する
<a name="register-pre-existing-keys-with-keystore"></a>

属性とラベル付けのセキュリティと柔軟性を最大限に高めるために、[key\$1mgmt\$1util](generate-keys.md) を使用して AWS CloudHSM 署名キーを生成することをお勧めします。Java アプリケーションを使用して、 AWS CloudHSMでキーを生成することもできます。

次のセクションでは、HSM で新しいキーペアを生成し、 AWS CloudHSM キーストアにインポートされた既存のキーを使用して登録する方法を示すコードサンプルを提供します。インポートされたキーは、keytool や Jarsigner などのサードパーティー製ツールで使用できます。

既存のキーを使用するには、新しいキーを生成するのではなく、ラベルでキーを検索するようにコードサンプルを変更します。ラベルでキーを検索するためのサンプルコードは、GitHubの [KeyUtilitiesRunner.java サンプル](https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/master/src/main/java/com/amazonaws/cloudhsm/examples/KeyUtilitiesRunner.java)で入手できます。

**重要**  
に保存されたキーを AWS CloudHSM ローカルキーストアに登録しても、キーはエクスポートされません。キーが登録されると、キーストアはキーのエイリアス (またはラベル) を登録し、 AWS CloudHSMでローカルに保存された証明書オブジェクトとのキーペアを関連付けます。キーペアがエクスポート不可として作成されている限り、キービットが HSM から離れることはありません。

```
                      	
                      	
                      	//
 // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy of this
 // software and associated documentation files (the "Software"), to deal in the Software
 // without restriction, including without limitation the rights to use, copy, modify,
 // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 // permit persons to whom the Software is furnished to do so.
 //
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
package com.amazonaws.cloudhsm.examples;

import com.cavium.key.CaviumKey;
import com.cavium.key.parameter.CaviumAESKeyGenParameterSpec;
import com.cavium.key.parameter.CaviumRSAKeyGenParameterSpec;
import com.cavium.asn1.Encoder;
import com.cavium.cfm2.Util;

import javax.crypto.KeyGenerator;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;

import java.math.BigInteger;

import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.KeyStore.PasswordProtection;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.KeyStore.Entry;

import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;

//
// KeyStoreExampleRunner demonstrates how to load a keystore, and associate a certificate with a
// key in that keystore.
//
// This example relies on implicit credentials, so you must setup your environment correctly.
//
// https://docs.aws.amazon.com/cloudhsm/latest/userguide/java-library-install.html#java-library-credentials
//

public class KeyStoreExampleRunner {

     private static byte[] COMMON_NAME_OID = new byte[] { (byte) 0x55, (byte) 0x04, (byte) 0x03 };
     private static byte[] COUNTRY_NAME_OID = new byte[] { (byte) 0x55, (byte) 0x04, (byte) 0x06 };
     private static byte[] LOCALITY_NAME_OID = new byte[] { (byte) 0x55, (byte) 0x04, (byte) 0x07 };
     private static byte[] STATE_OR_PROVINCE_NAME_OID = new byte[] { (byte) 0x55, (byte) 0x04, (byte) 0x08 };
     private static byte[] ORGANIZATION_NAME_OID = new byte[] { (byte) 0x55, (byte) 0x04, (byte) 0x0A };
     private static byte[] ORGANIZATION_UNIT_OID = new byte[] { (byte) 0x55, (byte) 0x04, (byte) 0x0B };

     private static String helpString = "KeyStoreExampleRunner%n" +
            "This sample demonstrates how to load and store keys using a keystore.%n%n" +
            "Options%n" +
            "\t--help\t\t\tDisplay this message.%n" +
            "\t--store <filename>\t\tPath of the keystore.%n" +
            "\t--password <password>\t\tPassword for the keystore (not your CU password).%n" +
            "\t--label <label>\t\t\tLabel to store the key and certificate under.%n" +
            "\t--list\t\t\tList all the keys in the keystore.%n%n";

    public static void main(String[] args) throws Exception {
        Security.addProvider(new com.cavium.provider.CaviumProvider());
        KeyStore keyStore = KeyStore.getInstance("CloudHSM");

        String keystoreFile = null;
        String password = null;
        String label = null;
        boolean list = false;
        for (int i = 0; i < args.length; i++) {
            String arg = args[i];
            switch (args[i]) {
                case "--store":
                    keystoreFile = args[++i];
                    break;
                case "--password":
                    password = args[++i];
                    break;
                case "--label":
                    label = args[++i];
                    break;
                case "--list":
                    list = true;
                    break;
                case "--help":
                    help();
                    return;
            }
        }

        if (null == keystoreFile || null == password) {
            help();
            return;
        }

        if (list) {
            listKeys(keystoreFile, password);
            return;
        }

        if (null == label) {
            label = "Keystore Example Keypair";
        }

        //
        // This call to keyStore.load() will open the pkcs12 keystore with the supplied
        // password and connect to the HSM. The CU credentials must be specified using
        // standard CloudHSM login methods.
        //
        try {
            FileInputStream instream = new FileInputStream(keystoreFile);
            keyStore.load(instream, password.toCharArray());
        } catch (FileNotFoundException ex) {
            System.err.println("Keystore not found, loading an empty store");
            keyStore.load(null, null);
        }

        PasswordProtection passwd = new PasswordProtection(password.toCharArray());
        System.out.println("Searching for example key and certificate...");

        PrivateKeyEntry keyEntry = (PrivateKeyEntry) keyStore.getEntry(label, passwd);
        if (null == keyEntry) {
            //
            // No entry was found, so we need to create a key pair and associate a certificate.
            // The private key will get the label passed on the command line. The keystore alias
            // needs to be the same as the private key label. The public key will have ":public"
            // appended to it. The alias used in the keystore will We associate the certificate
            // with the private key.
            //
            System.out.println("No entry found, creating...");
            KeyPair kp = generateRSAKeyPair(2048, label + ":public", label);
            System.out.printf("Created a key pair with the handles %d/%d%n", ((CaviumKey) kp.getPrivate()).getHandle(), ((CaviumKey) kp.getPublic()).getHandle());

            //
            // Generate a certificate and associate the chain with the private key.
            //
            Certificate self_signed_cert = generateCert(kp);
            Certificate[] chain = new Certificate[1];
            chain[0] = self_signed_cert;
            PrivateKeyEntry entry = new PrivateKeyEntry(kp.getPrivate(), chain);

            //
            // Set the entry using the label as the alias and save the store.
            // The alias must match the private key label.
            //
            keyStore.setEntry(label, entry, passwd);

            FileOutputStream outstream = new FileOutputStream(keystoreFile);
            keyStore.store(outstream, password.toCharArray());
            outstream.close();

            keyEntry = (PrivateKeyEntry) keyStore.getEntry(label, passwd);
        }

        long handle = ((CaviumKey) keyEntry.getPrivateKey()).getHandle();
        String name = keyEntry.getCertificate().toString();
        System.out.printf("Found private key %d with certificate %s%n", handle, name);
    }

    private static void help() {
        System.out.println(helpString);
    }

    //
    // Generate a non-extractable / non-persistent RSA keypair.
    // This method allows us to specify the public and private labels, which
    // will make KeyStore aliases easier to understand.
    //
    public static KeyPair generateRSAKeyPair(int keySizeInBits, String publicLabel, String privateLabel)
            throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException {

        boolean isExtractable = false;
        boolean isPersistent = false;
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("rsa", "Cavium");
        CaviumRSAKeyGenParameterSpec spec = new CaviumRSAKeyGenParameterSpec(keySizeInBits, new BigInteger("65537"), publicLabel, privateLabel, isExtractable, isPersistent);

        keyPairGen.initialize(spec);

        return keyPairGen.generateKeyPair();
    }

    //
    // Generate a certificate signed by a given keypair.
    //
    private static Certificate generateCert(KeyPair kp) throws CertificateException {
        CertificateFactory cf = CertificateFactory.getInstance("X509");
        PublicKey publicKey = kp.getPublic();
        PrivateKey privateKey = kp.getPrivate();
        byte[] version = Encoder.encodeConstructed((byte) 0, Encoder.encodePositiveBigInteger(new BigInteger("2"))); // version 1
        byte[] serialNo = Encoder.encodePositiveBigInteger(new BigInteger(1, Util.computeKCV(publicKey.getEncoded())));

        // Use the SHA512 OID and algorithm.
        byte[] signatureOid = new byte[] {
            (byte) 0x2A, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xF7, (byte) 0x0D, (byte) 0x01, (byte) 0x01, (byte) 0x0D };
        String sigAlgoName = "SHA512WithRSA";

         byte[] signatureId = Encoder.encodeSequence(
                                         Encoder.encodeOid(signatureOid),
                                         Encoder.encodeNull());

         byte[] issuer = Encoder.encodeSequence(
                                     encodeName(COUNTRY_NAME_OID, "<Country>"),
                                     encodeName(STATE_OR_PROVINCE_NAME_OID, "<State>"),
                                     encodeName(LOCALITY_NAME_OID, "<City>"),
                                     encodeName(ORGANIZATION_NAME_OID, "<Organization>"),
                                     encodeName(ORGANIZATION_UNIT_OID, "<Unit>"),
                                     encodeName(COMMON_NAME_OID, "<CN>")
                                 );

         Calendar c = Calendar.getInstance();
         c.add(Calendar.DAY_OF_YEAR, -1);
         Date notBefore = c.getTime();
         c.add(Calendar.YEAR, 1);
         Date notAfter = c.getTime();
         byte[] validity = Encoder.encodeSequence(
                                         Encoder.encodeUTCTime(notBefore),
                                         Encoder.encodeUTCTime(notAfter)
                                     );
         byte[] key = publicKey.getEncoded();

         byte[] certificate = Encoder.encodeSequence(
                                         version,
                                         serialNo,
                                         signatureId,
                                         issuer,
                                         validity,
                                         issuer,
                                         key);
         Signature sig;
         byte[] signature = null;
         try {
             sig = Signature.getInstance(sigAlgoName, "Cavium");
             sig.initSign(privateKey);
             sig.update(certificate);
             signature = Encoder.encodeBitstring(sig.sign());

         } catch (Exception e) {
             System.err.println(e.getMessage());
             return null;
         }

         byte [] x509 = Encoder.encodeSequence(
                         certificate,
                         signatureId,
                         signature
                         );
         return cf.generateCertificate(new ByteArrayInputStream(x509));
    }

     //
     // Simple OID encoder.
     // Encode a value with OID in ASN.1 format
     //
     private static byte[] encodeName(byte[] nameOid, String value) {
         byte[] name = null;
         name = Encoder.encodeSet(
                     Encoder.encodeSequence(
                             Encoder.encodeOid(nameOid),
                             Encoder.encodePrintableString(value)
                     )
                 );
         return name;
     }

    //
    // List all the keys in the keystore.
    //
    private static void listKeys(String keystoreFile, String password) throws Exception {
        KeyStore keyStore = KeyStore.getInstance("CloudHSM");

        try {
            FileInputStream instream = new FileInputStream(keystoreFile);
            keyStore.load(instream, password.toCharArray());
        } catch (FileNotFoundException ex) {
            System.err.println("Keystore not found, loading an empty store");
            keyStore.load(null, null);
        }

        for(Enumeration<String> entry = keyStore.aliases(); entry.hasMoreElements();) {
            System.out.println(entry.nextElement());
        }
    }

}
```