Registrar chaves pré-existentes com o repositório de chaves do AWS CloudHSM - AWS CloudHSM

Registrar chaves pré-existentes com o repositório de chaves do AWS CloudHSM

Para maior segurança e flexibilidade em atributos e rotulagem, recomendamos gerar suas chaves de assinatura do AWS CloudHSM usando key_mgmt_util. Você também pode usar um aplicativo Java para gerar a chave no AWS CloudHSM.

A seção a seguir fornece um exemplo de código que demonstra como gerar um novo par de chaves no HSM e registrá-lo usando chaves existentes importadas para o repositório de chaves do AWS CloudHSM. As chaves importadas estão disponíveis para uso com ferramentas de terceiros, como keytool e Jarsigner.

Para usar uma chave pré-existente, modifique o exemplo de código para procurar uma chave por rótulo em vez de gerar uma nova chave. O código de exemplo para procurar uma chave por rótulo está disponível no exemplo KeyUtilitiesRunner.java no GitHub.

Importante

Registrar uma chave armazenada em AWS CloudHSM com um repositório de chaves local não exporta a chave. Quando a chave é registrada, o repositório de chaves registra o alias (ou rótulo) da chave e correlaciona localmente objetos de certificado de armazenamento com um par de chaves no AWS CloudHSM. Desde que o par de chaves seja criado como não exportável, os bits de chave não sairão do 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()); } } }