AWS CloudHSM 키 스토어에 기존 키 등록 - AWS CloudHSM

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

AWS CloudHSM 키 스토어에 기존 키 등록

속성 및 레이블 지정의 보안과 유연성을 극대화하려면 key_mgmt_util을 사용하여 AWS CloudHSM 서명 키를 생성하는 것이 좋습니다. 또한 Java 애플리케이션을 사용하여 AWS CloudHSM에서 키를 생성할 수도 있습니다.

다음 섹션에서는에서 새 키 페어를 생성하고 키 AWS CloudHSM 스토어로 가져온 기존 키를 사용하여 HSM 등록하는 방법을 보여주는 코드 샘플을 제공합니다. 가져온 키는 keytool 및 Jarsigner와 같은 타사 도구와 함께 사용할 수 있습니다.

기존 키를 사용하려면, 새 키를 생성하는 대신 레이블별로 키를 조회하도록 코드 샘플을 수정합니다. 레이블별로 키를 조회하기 위한 샘플 코드는 KeyUtilitiesRunner.java 샘플에서 사용할 수 있습니다 GitHub.

중요

에 저장된 키를 로컬 키 스토어 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()); } } }