How do I use OpenSSL and the CloudHSM Command Line Tool to securely transfer my keys to CloudHSM?

7 minute read
3

I want to use the "key unwrap" subcommand with the CloudHSM Command Line Tool (CloudHSM CLI) to import local keys to AWS CloudHSM.

Resolution

First, encrypt your payload key with an ephemeral Advanced Encryption Standard (AES) key. Then, encrypt the ephemeral AES with your public key from a key pair. Finally, join the encrypted payload key and encrypted ephemeral key into a single file. The file is sent to your CloudHSM in an encrypted format, and the private key decrypts the file from the key pair. The AES_KEY_WRAP mechanism decrypts the ephemeral AES key and uses the key to decrypt your payload key.

Create the following keys:

  • Payload AES, RSA, or EC key. This is the key that you import and use with your CloudHSM.
  • Temporary AES key required by AES_KEY_WRAP to encrypt the payload. It's a best practice to use AES because there are no size limits on what you can encrypt.
  • RSA key pair that's used to securely wrap and unwrap the keys into your CloudHSM.

Before you begin, make sure that you have OpenSSL v 3.x to use envelop wrap:

openssl version
OpenSSL 3.0.8 7 Feb 2023 (Library: OpenSSL 3.0.8 7 Feb 2023)

In the following commands, replace these values:

  • YOUR_CRYPTO_USER_NAME with your crypto-user name
  • YOUR_CRYPTO_USER_PASSWORD with your password
  • YOUR_WRAPPING_KEY_LABEL with the key label assigned to your RSA public key for wrapping
  • YOUR_UNWRAPPING_KEY_LABEL with the key label assigned to your RSA private key for unwrapping
  • YOUR_IMPORTED_KEY_LABEL with the key label assigned to the imported payload key

Note: The key generate-file command and key unwrap command require that wrapping keys are uniquely identifiable because key labels are a filter condition. Make sure that YOUR_WRAPPING_KEY_LABEL and YOUR_UNWRAPPING_KEY_LABEL are unique key labels. Or, use a different filter condition to uniquely identify keys. For more information about key filters, see Filter keys using CloudHSM CLI.

Set crypto-user credentials for CloudHSM CLI

Run the following command:

export CLOUDHSM_ROLE="crypto-user"
export CLOUDHSM_PIN="YOUR_CRYPTO_USER_NAME:YOUR_CRYPTO_USER_PASSWORD"

Import the AES payload

To create, encrypt, and import the local keys, complete the following steps:

  1. To create the payload AES, ephemeral AES, and RSA keys, run the following commands:

    openssl rand -out payload_aes 32
    openssl rand -out ephemeral_aes 32
    /opt/cloudhsm/bin/cloudhsm-cli key generate-asymmetric-pair rsa --public-label YOUR_WRAPPING_KEY_LABEL --private-label YOUR_UNWRAPPING_KEY_LABEL --modulus-size-bits 4096 --public-exponent 65537 --private-attributes unwrap=true
    /opt/cloudhsm/bin/cloudhsm-cli key generate-file --encoding pem --path public.pem --filter attr.label=YOUR_WRAPPING_KEY_LABEL

    Note: To track your files, create these keys in their own directory.

  2. To output the raw hex values of the ephemeral AES key into a variable, run the following command:

    EPHEMERAL_AES_HEX=$(hexdump -v -e '/1 "%02X"' < ephemeral_aes)

    Note: Make sure that you have the hexdump utility installed. If you don't install hexdump, then the preceding command returns an error. Refer to your operating system (OS) documentation for instructions on how to install the hexdump utility.

  3. To wrap the payload with the ephemeral AES key, run the OpenSSL enc command:

    openssl enc -id-aes256-wrap-pad -K $EPHEMERAL_AES_HEX -iv A65959A6 -in payload_aes -out payload_wrapped

    Note: The -id-aes256-wrap-pad cipher is the RFC 3394-compliant wrap mechanism that coincides with CKM_RSA_AES_KEY_WRAP. The RFC 3394 extension, RFC 5649, sets the -iv values. For more information, see AES key wrap with padding algorithm and AES key wrap algorithm on the IETF website.

  4. Encrypt the AES key with the public key from the RSA key pair:

    openssl pkeyutl -encrypt -in ephemeral_aes -out ephemeral_wrapped -pubin -inkey public.pem -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha1 -pkeyopt rsa_mgf1_md:sha1
  5. From your local machine, join the encrypted payload key and ephemeral AES key into a single file that's named rsa_aes_wrapped:

    cat ephemeral_wrapped payload_wrapped > rsa_aes_wrapped
  6. To use the RSA private key with the key unwrap rsa-aes to unwrap the joined payload key into the CloudHSM, run the following command:

    /opt/cloudhsm/bin/cloudhsm-cli key unwrap rsa-aes --data-path rsa_aes_wrapped --key-type-class aes --label YOUR_IMPORTED_KEY_LABEL --hash-function sha1 --mgf mgf1-sha1 --filter attr.label=YOUR_UNWRAPPING_KEY_LABEL --attributes decrypt=true encrypt=true

    Note: You must use --key-type-class aes to unwrap AES keys. Based on key usage, use --attributes to assign key attributes. For more information about options and key attributes, see the key unwrap rsa-aes example and Key attributes for CloudHSM CLI, respectively.

    You receive a successful import of the payload AES key that's similar to the following output:

    {
      "error_code": 0,
      "data": {
        "key": {
          "key-reference": "0x000000000068031a",
          "key-info": {
            "key-owners": [
              {
                "username": "YOUR_CRYPTO_USER_NAME",
                "key-coverage": "full"
              }
            ],
            "shared-users": [],
            "cluster-coverage": "full"
          },
          "attributes": {
            "key-type": "aes",
            "label": "YOUR_IMPORTED_KEY_LABEL",
            "id": "0x",
            "check-value": "0xb31c2a",
            "class": "secret-key",
            "encrypt": true,
            "decrypt": true,
            "token": true,
            "always-sensitive": false,
            "derive": false,
            "destroyable": true,
            "extractable": true,
            "local": false,
            "modifiable": true,
            "never-extractable": false,
            "private": true,
            "sensitive": true,
            "sign": true,
            "trusted": false,
            "unwrap": false,
            "verify": true,
            "wrap": false,
            "wrap-with-trusted": false,
            "key-length-bytes": 32
          }
        }
      }
    }

Import the RSA payload

To import the payload, complete the following steps:

  1. To unwrap an RSA private key into the CloudHSM, run the following commands to change the payload key to an RSA private key:

    openssl genrsa -out payload_rsa.pem 2048
    openssl rand -out ephemeral_aes 32
  2. Use a plaintext editor to check the format of the RSA keys:

    PKCS1 format: -----BEGIN RSA PRIVATE KEY----- - PKCS8 format: -----BEGIN PRIVATE KEY-----

    Note: The RSA keys are in PKCS #1 format. However, the CloudHSM CLI assumes that the private key is in PKCS #8 DER format.

  3. To convert the payload_rsa.pem key into PKCS #8 format and DER encoded, run the following command:

    openssl pkcs8 -topk8 -inform PEM -outform DER -in payload_rsa.pem -out payload_rsa_pkcs8.der -nocrypt
  4. Complete steps 2-5 from the Import the AES payload section. Replace payload_aes with payload_rsa_pkcs8.der.

  5. To unwrap the payload RSA private key into the CloudHSM, run the following command:

    /opt/cloudhsm/bin/cloudhsm-cli key unwrap rsa-aes --data-path rsa_aes_wrapped --key-type-class rsa-private --label YOUR_IMPORTED_KEY_LABEL --hash-function sha1 --mgf mgf1-sha1 --filter attr.label=YOUR_UNWRAPPING_KEY_LABEL --attributes decrypt=true sign=true

    Note: You must use --key-type-class rsa-private to unwrap RSA keys. Based on key usage, use --attributes to assign key attributes.

Import the EC payload

To import the payload, complete the following steps:

  1. To unwrap an EC private key into the CloudHSM, run the following commands to change the payload key to an EC private key:

    openssl ecparam -name secp256k1 -genkey -noout -out payload_ec.pemopenssl rand -out ephemeral_aes 32
  2. Use a plaintext editor to check the format of the EC keys:

    PKCS1 format: -----BEGIN EC PRIVATE KEY----- - PKCS8 format: -----BEGIN PRIVATE KEY-----

    Note: The EC keys are in PKCS #1 format. However, the CloudHSM CLI assumes that the private key is in PKCS #8 DER format.

  3. To convert the payload_ec.pem key into PKCS #8 format and DER encoded, run the following command:

    openssl pkcs8 -topk8 -inform PEM -outform DER -in payload_ec.pem -out payload_ec_pkcs8.der -nocrypt
  4. Complete steps 2-5 from the Import the AES payload section. Replace payload_aes with payload_ec_pkcs8.der.

  5. To unwrap the payload EC private key into the CloudHSM, run the following command:

    /opt/cloudhsm/bin/cloudhsm-cli key unwrap rsa-aes --data-path rsa_aes_wrapped --key-type-class ec-private --label YOUR_IMPORTED_KEY_LABEL --hash-function sha1 --mgf mgf1-sha1 --filter attr.label=YOUR_UNWRAPPING_KEY_LABEL --attributes decrypt=true sign=true

    Note: You must use --key-type-class ec-private to unwrap EC keys. Based on key usage, use --attributes to assign key attributes.

Related information

Supported mechanisms for the PKCS #11 library for AWS CloudHSM Client SDK 5

AWS OFFICIAL
AWS OFFICIALUpdated 3 months ago
1 Comment

We are having trouble getting all these steps to work, we run into a problem on the last command that the input data to the cryptographic operation was invalid. Any pointers? We are using SDK5 cli.

replied 3 days ago