IBM Cloud Docs
Creating and importing encryption keys

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.

Click each step to get more details on the flow
Task flow of creating and importing an encryption key
1. Create an import token 2. Retrieve the import token 3. Create an encryption key 4. Set the encryption key as an environment variable 5. Encrypt the nonce with the encryption key 6. Encrypt the created encryption key 7. Import the encrypted key 8. Clean up

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.

  1. Create an IBM Cloud account.

  2. Download and install the IBM Cloud CLI for your operating system.

  3. 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'
    
  4. 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 version 1.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 run brew upgrade openssl to upgrade your existing package to the latest version.

  5. Download and install jq.

    jq helps you slice up JSON data. You'll use jq in this tutorial to grab and use specific data that's returned when you call the Hyper Protect Crypto Services key management service API.

  6. Create a Hyper Protect Crypto Services service instance.

  7. Initialize the Hyper Protect Crypto Services service instance.

  8. 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.

  1. 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.

  2. 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
      
  3. 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:

  1. 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
      
  2. 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 a nonce 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.

  3. 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:

  1. 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.

    1. Download the sample kms-encrypt-nonce binary that is compatible with your operating system. Extract the file, and then move the binary to the hs-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.

    2. 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
      
    3. Run the script to encrypt the nonce value with the key that you generated in step 2.

  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
      
  3. 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. The iv 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, run brew update and then brew install openssl to get the latest version. Then, run export PATH="/usr/local/opt/openssl/bin:$PATH"' >> ~/.bash_profile to symlink the package. From the command line, run which 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:

  1. Gather the encrypted nonce and the initialization vector (IV) values.

    ENCRYPTED_NONCE=$(jq -r '.encryptedNonce' EncryptedValues.json)
    
    IV=$(jq -r '.iv' EncryptedValues.json)
    
  2. 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 to false 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.

  3. 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 and imported values describe this resource as a root key that you imported to the service. When you set the extractable attribute to true, the service designates the key as a standard key that you can store in your apps or services. Otherwise, when you set the extractable attribute to false, the service designates the key as a root key.

  4. 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

  1. Gather the identifier for the encryption key that you imported in the previous step.

    ROOT_KEY_ID=$(jq -r '.resources[].id' createRootKeyResponse.json)
    
  2. 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}
      
  3. Remove all the local files associated with this tutorial.

    rm kms-encrypt-nonce *.json *.bin *.pem
    
  4. Delete the test directory that you created for this tutorial.

    cd .. && rm -r hs-crypto-test
    
  5. 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.