Creating and importing encryption keys
Learn how to create, encrypt, and bring your encryption keys to the cloud by using Hyper Protect Crypto Services.
Objectives
This tutorial walks you through creating and securely importing encryption keys into the Hyper Protect Crypto Services service. It's intended for users who are new to the key management function of Hyper Protect Crypto Services, but who might have some familiarity with key management systems. The following steps need to take about 20 minutes to complete.
- Setting up the key management service API
- Preparing your Hyper Protect Crypto Services service instance to begin importing keys
- Creating and encrypting keys using the OpenSSL cryptography toolkit
- Importing an encrypted key to your Hyper Protect Crypto Services service instance
This tutorial won't incur any charges to your IBM Cloud account.
Task flow
The following flow chart gives you an overview on how to create and import encryption keys. You can click each step on the chart to view details of the step.
Before you begin
To get started, you need the IBM Cloud CLI so that you can interact with services that you provision on IBM Cloud. You also need the openssl
and jq
packages installed locally on your workstation.
-
Create an IBM Cloud account.
-
Download and install the IBM Cloud CLI for your operating system.
-
Download and install the IBM Key Protect CLI plug-in v0.6.3 or later, and configure it to use in Hyper Protect Crypto Services. Make sure to update the
KP_PRIVATE_ADDR
variable to the current instance key management endpoint URL.To check your IBM Key Protect CLI plug-in version:
ibmcloud plugin show key-protect
To update your IBM Key Protect CLI plug-in to the latest version:
ibmcloud plugin update key-protect -r 'IBM Cloud'
-
Download and install the OpenSSL cryptography library.
You can use
openssl
commands to create encryption keys on your local workstation if you're trying out Hyper Protect Crypto Services for the first time. This tutorial requires OpenSSL version1.0.2r
or above.If you're using a Mac, you can quickly get up and running with OpenSSL by using Homebrew. Run
brew install openssl
if you're installing the package for the first time, or runbrew upgrade openssl
to upgrade your existing package to the latest version. -
Download and install jq.
jq
helps you slice up JSON data. You'll usejq
in this tutorial to grab and use specific data that's returned when you call the Hyper Protect Crypto Services key management service API. -
Initialize the Hyper Protect Crypto Services service instance.
-
Set up the Hyper Protect Crypto Services key management service API.
Create an import token
With your service credentials, you can start interacting with the key management service API to create and bring your encryption keys to the service.
In the following step, you'll create an import token for your Hyper Protect Crypto Services service instance. By creating an import token based on a policy that you specify, you enable extra security for your encryption key while it's in flight to the service.
-
From the command line, change into a new
hs-crypto-test
directory.mkdir hs-crypto-test && cd hs-crypto-test
You'll use this directory to store the files that you'll create in later steps.
-
You can create an import token for your Hyper Protect Crypto Services service instance by either using the key management service API or using the CLI, and then save the response to a JSON file.
-
Use the API
curl -X POST $HPCS_API_URL/api/v2/import_token \ -H "Accept: application/vnd.ibm.collection+json" \ -H "Authorization: $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -H "Bluemix-Instance: $INSTANCE_ID" \ -d '{ "expiration": 1200, "maxAllowedRetrievals": 1 }' > createImportTokenResponse.json
In the request body, you can specify a policy on the import token that limits the use based on time and usage count. In this example, you set the expiration time for the import token to 1200 seconds (20 minutes), and you also allow only one retrieval of that token within the expiration time.
-
Use the IBM Key Protect CLI
ibmcloud kp import-token create --instance-id $INSTANCE_ID --max-retrievals=1 --expiration=1200 -o json > createImportTokenResponse.json
-
-
View details for the import token.
jq '.' createImportTokenResponse.json
The output displays the metadata that is associated with your import token, such as the creation date and policy details. The following snippet shows example output.
{ "creationDate": "2020-06-08T16:58:29Z", "expirationDate": "2020-06-08T17:18:29Z", "maxAllowedRetrievals": 1, "remainingRetrievals": 1 }
Retrieve the import token
In the previous step, you created an import token and you viewed the metadata that is associated with the token.
In this step, you'll retrieve the public key and nonce value that are associated with the import token. You'll need the public key to encrypt data in a later step, and the nonce to verify your secure import request to the Hyper Protect Crypto Services service.
To retrieve the import token contents:
-
Retrieve the import token that you generated the previous step, and then save the response to a JSON file.
-
Use the API
curl -X GET $HPCS_API_URL/api/v2/import_token \ -H "Accept: application/vnd.ibm.collection+json" \ -H "Authorization: $ACCESS_TOKEN" \ -H "Bluemix-Instance: $INSTANCE_ID" > getImportTokenResponse.json
-
Use the IBM Key Protect CLI
ibmcloud kp import-token show -o json > getImportTokenResponse.json
-
-
Optional: Inspect the contents of the import token.
jq '.' getImportTokenResponse.json
The output displays detailed information about the import token. The following snippet shows example output with truncated values.
{ "creationDate": "2020-06-08T16:58:29Z", "expirationDate": "2020-06-08T17:18:29Z", "maxAllowedRetrievals": 1, "remainingRetrievals": 0, "payload": "MIICIjANBgkqhkiG...", "nonce": "8zJE9pKVdXVe/nLb" }
The
payload
value represents the public key that is associated with the import token. This value is base64 encoded. For extra security, Hyper Protect Crypto Services provides anonce
value that is used to verify the originality of a request to the service. You'll need to encrypt and provide this value when you import your encryption key. -
Decode and save the public key to a file called
PublicKey.pem
, and extract values into variables to be used later.jq -r '.payload' getImportTokenResponse.json | openssl enc -base64 -A -d -out PublicKey.pem
HPCS_PUBKEY="$(jq -r '.payload' getImportTokenResponse.json)" NONCE="$(jq -r '.nonce' getImportTokenResponse.json)"
The public key is now downloaded to your workstation in PEM format. Continue to the next step.
Create an encryption key
With Hyper Protect Crypto Services, you can enable the security benefits of Keep Your Own Key (KYOK) by creating and uploading your own encryption keys for use on IBM Cloud.
In the following step, you'll create a 256-bit AES symmetric key on your local workstation.
This tutorial uses the OpenSSL cryptography toolkit to generate a pseudo-random key, but you might want to explore different options for generating stronger keys based on your security needs. For example, you might want to use your organization's internal key management system, backed by an on-premises hardware security module (HSM), to create and export keys.
If you want to create a 256-bit AES symmetric key, from the command line, run the following openssl
command:
openssl rand 32 > PlainTextKey.bin
You can skip this step if you use your own key in this tutorial.
Success! Your encryption key is now saved in a file called PlainTextKey.bin
. Continue to the next step.
Set the encryption key as an environment variable
If you create the key by following step 3, to encode the key and set the encoded value as an environment variable, perform the following command. You can skip this step if you use your own key in this tutorial:
KEY_MATERIAL=$(openssl enc -base64 -A -in PlainTextKey.bin)
Encrypt the nonce with the encryption key
For extra security, Hyper Protect Crypto Services requires nonce verification when you import a encryption key to the service.
In cryptography, a nonce serves as a session token that checks the originality of a request to protect against malicious attacks and unauthorized calls. By using the same nonce that was distributed by Hyper Protect Crypto Services, you help to ensure that your request to upload a key is valid. The nonce value must be encrypted by using the same key that you want to import into the service.
To encrypt the nonce value:
-
If you are going to use the API to perform the subsequent steps, do the following:
You don't need to perform this step if you are going to use the IBM Key Protect CLI.
-
Download the sample
kms-encrypt-nonce
binary that is compatible with your operating system. Extract the file, and then move the binary to thehs-crypto-test
directory.The binary contains a script that you can use to run AES-CBC encryption on the nonce value by using the key that you generated in step 2. To learn more about the script, check out the source file on GitHub.
-
If you are using Linux, mark the file as executable by running the following
chmod
command. You can skip this step if you are using Windows.chmod +x ./kms-encrypt-nonce
-
Run the script to encrypt the nonce value with the key that you generated in step 2.
-
-
Save the encrypted nonce to a file called
EncryptedValues.json
.-
Use the API
./kms-encrypt-nonce -key $KEY_MATERIAL -nonce $NONCE -alg "CBC" > EncryptedValues.json
-
Use the IBM Key Protect CLI
ibmcloud kp import-token nonce-encrypt --key "$KEY_MATERIAL" --nonce "$NONCE" --cbc -o json > EncryptedValues.json
-
-
Optional: Inspect the contents of the JSON file.
jq '.' EncryptedValues.json
The output displays the values that you'll need to provide for the next step. The following snippet shows example output with truncated values.
{ "encryptedNonce": "DVy/Dbk37X8gSVwRA5U6vrHdWQy8T2ej+riIVw==", "iv": "puQrzDX7gU1TcTTx" }
The
encryptedNonce
value represents the original nonce that is wrapped (or encrypted) by th key that you generated using OpenSSL. Theiv
value is the initialization vector (IV) that is created by the AES-CBC algorithm, and it's required later so that Hyper Protect Crypto Servicescan successfully decrypt the nonce.
Encrypt the created encryption key
Next, use the public key that was distributed by Hyper Protect Crypto Services in step 2 to encrypt the encryption key that you created using OpenSSL.
-
Encrypt the created encryption key with the API, and assign the key to the environment variable:
openssl pkeyutl \ -encrypt \ -pubin \ -keyform PEM \ -inkey PublicKey.pem \ -pkeyopt rsa_padding_mode:oaep \ -pkeyopt rsa_oaep_md:sha1 \ -in PlainTextKey.bin \ -out EncryptedKey.bin
ENCRYPTED_KEY=$(openssl enc -base64 -A -in EncryptedKey.bin)
If you run into a parameter settings error when you run the
openssl
command on Mac OSX, you might need to ensure that OpenSSL is properly configured for your environment. If you installed OpenSSL by using Homebrew, runbrew update
and thenbrew install openssl
to get the latest version. Then, runexport PATH="/usr/local/opt/openssl/bin:$PATH"' >> ~/.bash_profile
to symlink the package. From the command line, runwhich openssl && openssl version
to verify that the latest version of OpenSSL is available under the/usr/local/
location. If you continue to encounter errors, be sure to use only the parameters that are listed in this example. -
Encrypt the created encryption key with the IBM Key Protect CLI:
ibmcloud kp import-token key-encrypt -k "$KEY_MATERIAL" -p "$HPCS_PUBKEY" --hash SHA1 -o json > EncryptedKey.json ENCRYPTED_KEY=$(jq -r '.encryptedKey' EncryptedKey.json)
Success! You're all set to upload your encrypted key into Hyper Protect Crypto Services. Continue to the next step.
Import the encrypted key
You can now import the encrypted key using the key management service API.
To import the encrypted key:
-
Gather the encrypted nonce and the initialization vector (IV) values.
ENCRYPTED_NONCE=$(jq -r '.encryptedNonce' EncryptedValues.json)
IV=$(jq -r '.iv' EncryptedValues.json)
-
Store the encrypted key in your Hyper Protect Crypto Services service instance.
-
Use the API
curl -X POST $HPCS_API_URL/api/v2/keys \ -H "Accept: application/vnd.ibm.collection+json" \ -H "Authorization: $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -H "Bluemix-Instance: $INSTANCE_ID" \ -d '{ "metadata": { "collectionType": "application/vnd.ibm.kms.key+json", "collectionTotal": 1 }, "resources": [ { "name": "encrypted-root-key", "type": "application/vnd.ibm.kms.key+json", "payload": "'"$ENCRYPTED_KEY"'", "extractable": false, "encryptionAlgorithm": "RSAES_OAEP_SHA_1", "encryptedNonce": "'"$ENCRYPTED_NONCE"'", "iv": "'"$IV"'" } ] }' > createRootKeyResponse.json
In the request body, you provide the encryption key that you prepared in the previous step. You also supply the encrypted nonce and the IV values that are required to verify the request. Finally, the
extractable
value set tofalse
designates your new key as a root key in the service that you can use for envelope encryption.If the API request fails with an import token expired error, return to step 1 to create a new import token. Remember that import tokens and their associated public keys expire based on the policy that you specify at creation time.
-
Use the IBM Key Protect CLI
ibmcloud kp key create new-imported-key --key-material "$ENCRYPTED_KEY" --encrypted-nonce "$ENCRYPTED_NONCE" --iv "$IV" --sha1 -o json > createRootKeyResponse.json
Behind the scenes, Hyper Protect Crypto Services receives your encrypted packet over a TLS 1.2 connection. Within a hardware security module, the system uses the private key to decrypt the symmetric key. Finally, the system uses the symmetric key and the IV to decrypt the nonce and verify the request. Your key is now stored in a tamper-resistant, FIPS 140-2 Level 4 validated hardware security module.
-
-
View details for the key.
jq '.' createRootKeyResponse.json
The following snippet shows an example output.
{ "metadata": { "collectionType": "application/vnd.ibm.kms.key+json", "collectionTotal": 1 }, "resources": [ { "id": "644cba65-e240-471f-8b84-14115447d2ae", "type": "application/vnd.ibm.kms.key+json", "name": "encrypted-root-key", "state": 1, "crn": "crn:v1:bluemix:public:hs-crypto:us-south:a/f047b55a3362ac06afad8a3f2f5586ea:346d9f67-4bb2-481e-a3e1-3c2c646aa886:key:644cba65-e240-471f-8b84-14115447d2ae", "extractable": false, "imported": true } ] }
-
The
id
value is a unique identifier that is assigned to your key and is used for subsequent calls to the key management service API. -
The
state
value set to 1 indicates that your key is now in the Active key state. -
The
crn
value provides the full scoped path to the key that specifies where the resource resides within IBM Cloud. -
Finally, the
extractable
andimported
values describe this resource as a root key that you imported to the service. When you set theextractable
attribute totrue
, the service designates the key as a standard key that you can store in your apps or services. Otherwise, when you set theextractable
attribute tofalse
, the service designates the key as a root key.
-
-
Optional: Navigate to the Hyper Protect Crypto Services dashboard to view and manage your key.
You can browse the general characteristics of your keys from the application details page. Choose from a list of options for managing your key, such as rotating the key or deleting the key.
Clean up
-
Gather the identifier for the encryption key that you imported in the previous step.
ROOT_KEY_ID=$(jq -r '.resources[].id' createRootKeyResponse.json)
-
Remove the encryption key from your Hyper Protect Crypto Services service instance.
-
Use the API
curl -X DELETE $HPCS_API_URL/api/v2/keys/$ROOT_KEY_ID \ -H "Accept: application/vnd.ibm.collection+json" \ -H "Authorization: $ACCESS_TOKEN" \ -H "Bluemix-Instance: $INSTANCE_ID" | jq .
-
Use the IBM Key Protect CLI
ibmcloud kp key delete {ROOT_KEY_ID}
-
-
Remove all the local files associated with this tutorial.
rm kms-encrypt-nonce *.json *.bin *.pem
-
Delete the test directory that you created for this tutorial.
cd .. && rm -r hs-crypto-test
-
Optional: Remove your Hyper Protect Crypto Services service instance.
ibmcloud resource service-instance-delete import-keys-demo
If you created more test keys in your service instance, be sure to remove all encryption keys from your service instance before you deprovision the instance.
Next steps
In this tutorial, you learned how to set up the Hyper Protect Crypto Services key management service API, create an encryption key, and securely import an encrypted key into your Hyper Protect Crypto Services service instance.
- Learn more about using your root key to protect data at rest.
- Deploy your root key across supported cloud services.
- Learn more about the key management service API.