使用客戶端 SDK 3 與 Java Keytool 和 Jarsigner 整合 - AWS CloudHSM

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用客戶端 SDK 3 與 Java Keytool 和 Jarsigner 整合

AWS CloudHSM 金鑰存放區是一種用途特殊的 JCE 金鑰存放區,會透過第三方工具 (例如 keytooljarsigner) 使用與 HSM 金鑰相關聯的憑證。AWS CloudHSM 不會在 HSM 儲存憑證,因為憑證是公開的非機密資料。AWS CloudHSM 金鑰存放區會將憑證儲存在本機檔案中,並將憑證對應至 HSM 的對應金鑰。

當您使用 AWS CloudHSM 金鑰存放區產生新金鑰時,本機金鑰存放區檔案中不會產生任何項目;金鑰會在 HSM 上建立。同樣的,當您使用 AWS CloudHSM 金鑰存放區搜尋金鑰時,搜尋會傳遞至 HSM。當您在 AWS CloudHSM 金鑰存放區中儲存憑證時,提供商會確認 HSM 上是否存在具有對應別名的金鑰對,然後將提供的憑證與對應的金鑰對產生關聯。

必要條件

若要使用 AWS CloudHSM 金鑰存放區,您必須先初始化和設定 AWS CloudHSM JCE SDK。

步驟 1:安裝 JCE

若要安裝 JCE (包括 AWS CloudHSM 用戶端必要條件),請遵循安裝 Java 程式庫的步驟。

步驟 2:將 HSM 登入憑證新增至環境變數

設定環境變數以包含您的 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 金鑰存放區的文章。

步驟 3:註冊 JCE 提供商

要註冊 JCE 提供程序,請在 Java CloudProvider 配置中。

  1. 在 Java 安裝中開啟 java.security 組態檔案以進行編輯。

  2. 在 java.security 組態檔案中,新增 com.cavium.provider.CaviumProvider 為最後一個提供商。例如,如果 java.security 檔案中有九個提供商,請將下列提供商新增為區段中的最後一個提供商。如果將 Cavium 提供商新增為優先順序較高的提供商,可能會對您的系統效能帶來負面影響。

    security.provider.10=com.cavium.provider.CaviumProvider

    注意

    進階使用者可能習慣在使用 keytool 時指定 -providerName-providerclass-providerpath 命令列選項,而不是更新安全性組態檔案。如果您嘗試在使用 AWS CloudHSM 金鑰存放區產生金鑰時指定命令列選項,則會導致系統發生錯誤。

搭配 Keytool 使用 AWS CloudHSM 金鑰存放區

Keytool 是 Linux 系統中常見的金鑰和憑證任務的常用命令列執行程序。完整的 Keytool 教學並不在AWS CloudHSM 文件範圍之內。本文說明在透過 AWS CloudHSM 金鑰存放區,以信任的根目錄方式使用 AWS CloudHSM 時,您應該搭配多種 Keytool 函數使用的特定參數。

搭配 AWS CloudHSM 金鑰存放區使用 Keytool 時,請將下列引數指定給任意 Keytool 命令:

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

如果您要使用 AWS CloudHSM 金鑰存放區建立新金鑰存放區檔案,請參閱 使用 AWS CloudHSM KeyStore。若要要使用現有的金鑰存放區,請使用金鑰存放區引數指定其名稱 (包含路徑) 至 Keytool。如果您在 Keytool 命路中指定不存在的金鑰存放區檔案,AWS CloudHSM 金鑰存放區會建立新金鑰存放區檔案。

使用 Keytool 建立新金鑰

您可以使用 Keytool 產生由 AWS CloudHSM 的 JCE SDK 支援的任何類型金鑰。請參閱 Java 程式庫的支援金鑰文章中金鑰和長度的完整清單。

重要

透過 Keytool 產生的金鑰會在軟體中產生,然後將其以可擷取的持久性金鑰方式匯入至 AWS CloudHSM。

在 HSM 直接建立不可解壓縮金鑰,然後搭配 Keytool 或 Jarsigner 使用的說明,會在使用 AWS CloudHSM 金鑰存放區註冊既有金鑰的程式碼範例中提供。我們強烈建議您不要在 Keytool 中產生不可匯出的金鑰,然後又匯入相對應的憑證至金鑰存放區。如果您透過 Keytool 和 Jarsigner 使用可擷取的 RSA 或 EC 金鑰,則提供商會從 AWS CloudHSM 匯出金鑰,然後在本機使用金鑰進行簽署作業。

如果您有多個用戶端執行個體連接到 CloudHSM 叢集,請注意,在一個用戶端執行個體的金鑰存放區上匯入憑證不會自動讓憑證可於其他用戶端執行個體使用。若要在每個用戶端執行個體上註冊金鑰和相關憑證,您必須執行 Java 應用程式,如使用 Keytool 產生 CSR中所述。或者,您可以在一個用戶端上進行必要的變更,並將產生的金鑰存放區檔案複製到其他每個用戶端執行個體。

範例 1: 產生帶對稱 AES-256 金鑰,並將其儲存在工作目錄中名為「my_keystore.store」的金鑰存放區檔案中。將 <secret label> 取代為唯一的標籤。

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

範例 2:產生 RSA 2048 金鑰對,並將其儲存在工作目錄中名為「my_keystore.store」的金鑰存放區檔案中。將 <RSA key pair label> 取代為唯一的標籤。

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

範例 3:產生 p256 ED 金鑰,並將其儲存在工作目錄中名為「my_keystore.store」的金鑰存放區檔案中。將 <ec key pair label> 取代為唯一的標籤。

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

您可以在 Java 程式庫中找到支援的簽章演算法清單。

使用 Keytool 刪除金鑰

AWS CloudHSM 金鑰存放區不支援刪除金鑰。若要刪除金鑰,您必須使用 AWS CloudHSM 命令列工具 deleteKeydeleteKey 函數。

使用 Keytool 產生 CSR

如果您使用 OpenSSL 動態引擎,您可以在產生憑證簽署要求 (CSR) 時獲得最大的彈性。以下命令使用 Keytool 來產生具有別名 my-key-pair 的金鑰對適用 CSR。

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

若要使用 Keytool 的金鑰對,該金鑰對必須再指定的金鑰存放區檔案中有項目。如果您要使用非 Keytool 產生的金鑰對,則必須將金鑰和憑證中繼資料匯入至金鑰存放區。如需匯入金鑰存放區資料的說明,請參閱使用 Keytool 將中繼和根憑證匯入 AWS CloudHSM 金鑰存放區

使用 Keytool 將中繼和根憑證匯入至 AWS CloudHSM 金鑰存放區

若要匯入 CA 憑證,您必須在新匯入的憑證上啟用完整憑證鏈的驗證。以下為命令的範例。

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

如果您連接多個用戶端執行個體至您的 AWS CloudHSM 叢集,請注意,在一個用戶端執行個體的金鑰存放區上匯入憑證不會自動讓憑證可於其他用戶端執行個體使用。您必須在每個用戶端執行個體上匯入憑證。

使用 Keytool 從 AWS CloudHSM 金鑰存放區刪除憑證

下列範例顯示命令如何從 Java Keytool 金鑰存放區庫刪除憑證。

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

如果您連接多個用戶端執行個體至您的 AWS CloudHSM 叢集,請注意,在一個用戶端執行個體的金鑰存放區上刪除憑證不會自動從其他用戶端執行個體刪除憑證。您必須在每個用戶端執行個體上刪除憑證。

使用 Keytool 將工作憑證匯入 AWS CloudHSM 金鑰存放區

憑證簽署要求 (CSR) 簽署後,您就可以將其匯入 AWS CloudHSM 金鑰存放區,並與適當的金鑰對建立關聯。以下是命令範例。

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

別名應為金鑰存放區中具有關聯憑證的金鑰對。如果金鑰是非 Keytool 產生,或是在不同的用戶端執行個體上產生,您就必須先將金鑰和憑證中繼資料匯入金鑰存放區。如需匯入憑證中繼資料的說明,請參閱使用 AWS CloudHSM 金鑰存放區註冊既有金鑰中的程式碼範例。

憑證鏈必須是可驗證的。如果您無法驗證憑證,則可能需要將簽署 (憑證授權單位) 憑證匯入金鑰存放區,以便驗證該鏈結。

使用 Keytool 匯出憑證

下列範例會產生二進位 X.509 格式的憑證。若要匯出人類可讀的憑證,請新增 -rfc-exportcert 命令。

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

搭配 Jarsigner 使用 AWS CloudHSM 金鑰存放區

Jarsigner 是一種流行的命令行實用程序,用於使用安全地存儲在 HSM 上的密鑰簽名 JAR 文件。完整的 Jarsigner 教學並不在 AWS CloudHSM 文件範圍之內。本節說明您在簽署和驗證簽名時應使用的 Jarsigner 參數,且透過 AWS CloudHSM 金鑰存放區以 AWS CloudHSM 為信任的根目錄。

設定金鑰和憑證

在您可以使用 Jarsigner 簽署 JAR 文件之前,請確保您已經設定或完成以下步驟:

  1. 遵循 AWS CloudHSM金鑰存放區必要條件中的指引。

  2. 設定簽署金鑰,以及應儲存在目前伺服器或用戶端執行個體 AWS CloudHSM 金鑰存放區中的相關憑證和憑證鏈。在 AWS CloudHSM 上建立金鑰,然後將關聯的中繼資料匯入 AWS CloudHSM 金鑰存放區。使用在使用 AWS CloudHSM 金鑰存放區註冊既有金鑰中的程式碼範例,將中繼資料匯入至金鑰存放區。如果您要使用 Keytool 設定金鑰和憑證,請參閱 使用 Keytool 建立新金鑰。如果您使用多個用戶端執行個體來簽署 JAR,請建立金鑰並匯入憑證鏈。然後將生成的金鑰存放區文件複製到每個用戶端執行個體。如果您經常產生新的金鑰,您可能會發現將憑證個別匯入至每個用戶端執行個體更容易。

  3. 整個憑證鏈必須是可驗證的。為了要讓憑證鏈可以驗證,您可能需要將 CA 憑證和中繼憑證新增至 AWS CloudHSM 金鑰存放區。請參閱使用 AWS CloudHSM 簽署 JAR 檔案中的程式碼片段,以取得使用 Java 程式碼驗證憑證鏈的說明。如果需要,您也可以使用 Keytool 匯入憑證。如需有關使用 Keytool 的說明,請參閱使用 Keytool 將中繼憑證和根憑證匯入 AWS CloudHSM 金鑰存放區

使用 AWS CloudHSM 和 Jarsigner 簽署 JAR 檔案

使用以下命令來簽署 JAR 檔案:

jarsigner -keystore my_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 my_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>

已知問題

以下清單提供已知問題的最新清單。

  • 使用 keytool 生成密鑰時,提供程序配置中的第一個提供程序不能是 CaviumProvider。

  • 使用 Keytool 產生金鑰時,系統會使用安全性組態檔案中的第一個 (受支援的) 提供商來產生金鑰。這通常是軟體提供商。然後在金鑰新增程序期間,產生的金鑰會獲得一個別名,並將其作為持續性 (字符) 金鑰匯入 AWS CloudHSM HSM。

  • 搭配 AWS CloudHSM 金鑰存放區使用 Keytool 時,請勿在命令列中指定 -providerName-providerclass-providerpath 選項。按照金鑰存放區先決條件中的說明,在安全提供商檔案中指定這些選項。

  • 當透過 Keytool 和 Narsigner 使用不可擷取的 EC 金鑰時,SunEC 提供商必須從 java.security 檔案的提供商清單中移除/停用。如果您透過 Keytool 和 Jarsigner 使用可擷取 EC 金鑰,則提供商會從 AWS CloudHSM HSM 匯出金鑰位元,並使用本機金鑰進行簽署作業。我們不建議您搭配 Keytool 或 Jarsigner 使用可匯出的金鑰。

使用 AWS CloudHSM 金鑰存放區註冊既有的金鑰

為了獲得屬性和標籤的最大安全性和彈性,建議您使用 key_mgmt_util 產生簽署金鑰。您也可以使用 Java 應用程式來產生 AWS CloudHSM 中的金鑰。

下一節提供程式碼範例,示範如何在 HSM 上產生新的金鑰對,並使用匯入至 AWS CloudHSM 金鑰存放區的既有金鑰來註冊。匯入的金鑰可以與第三方工具 (如 Keytool 和 Jarsigner) 搭配使用。

若要使用既有的金鑰,請修改程式碼範例以依標籤查詢金鑰,而不是產生新金鑰。在上 GitHub的 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 alises 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()); } } }