Exporting a Software-protected key by Applying RSA-OAEP with Temporary AES Key

Export a software-protected master encryption key by applying RSA-OAEP with a temporary AES key using the Command Line Interface (CLI).

Using the CLI

The following example script invokes the RSA AES key wrap mechanism to generate a temporary AES key that wraps and unwraps the exportable key material. The process by which you transform the temporary AES key is called Optimal Asymmetric Encryption Padding (OAEP). OAEP is commonly used with the RSA encryption algorithm (RSA-OAEP). The Vault service supports RSA-OAEP with a SHA-256 hash.

Applying OAEP with the RSA encryption algorithm (RSA-OAEP) with a SHA-256 hash to wrap the temporary AES key with the provided public RSA wrapping key generates a wrapped temporary AES key. The wrapped temporary AES key and the wrapped exportable key material are concatenated to produce blob output that jointly represents them and which only the possessor of the private RSA wrapping key can decrypt.

To export a software-protected master encryption key, open a command prompt, and then run the following script, replacing example file names and values as appropriate:

#!/usr/bin/env bash

#
# This script is for demonstration purposes only. It provides
# a functioning set of calls to show how to export software-protected AES key material 
# from the Vault service by using the RSA_OAEP_AES_SHA256 algorithm.
#


set -x

OPENSSL="<path_to_OpenSSL>" # Use OpenSSL 1.1.1.
KEY_OCID="<key_OCID>" # The Oracle Cloud Identifier (OCID) of the software-protected master encryption key to export.
ENCRYPTION_ALGORITHM="RSA_OAEP_AES_SHA256"
RSA_KEY_SIZE_IN_BYTES="<key_size_in_bytes>" # Specify 256 (for 2048 bits) or 512 (for 4096 bits).
VAULT_CRYPTO_ENDPOINT="<vault_data_plane_URL>" # The cryptographic endpoint of the vault that contains the software-protected master encryption key.
PUBLIC_KEY_STRING="<public_RSA_wrapping_key_in_PEM_format>" # The content of the public key.
PRIVATE_KEY_PATH="<path_to_private_RSA_wrapping_key>" # The location of the private key.
SOFTWARE_KEY_PATH="<path_to_output_exported_master_encryption_key>" # The location for outputting the software-protected master encryption key.
TEMP_AES_KEY_PATH="<path_to_output_temporary_AES_key>" # The location for outputting the temporary AES key.
TEMP_WRAPPED_AES_PATH="<path_to_output_wrapped_temporary_AES_key>" # The location for outputting the wrapped temporary AES key.
WRAPPED_SOFTWARE_KEY_PATH="<path_to_output_wrapped_master_encryption_key>" # The location for outputting the wrapped software-protected master encryption key, otherwise known as the wrapped target key.

declare -a hex_array wrapped_temp_aes_key_array wrapped_targetKey_array wrapped_targetKey_array_length

# Invoke the CLI to export a software-protected master encryption key. (The response contains the wrapped data in two parts.
# The first part is a wrapped temporary AES key. The second part is the wrapped software-protected master encryption key, 
# also known as the wrapped target key.)
wrapped_data=$(oci kms crypto key export --key-id ${KEY_OCID} --algorithm ${ENCRYPTION_ALGORITHM} --public-key "${PUBLIC_KEY_STRING}" --endpoint 
${VAULT_CRYPTO_ENDPOINT} | grep encrypted-key | cut -d: -f2  | sed 's# "\(.*\)",#\1#g')"

# Decode the encoded wrapped data and convert it to hexadecimal format.
wrapped_data_hex_array=(`echo ${wrapped_data} | base64 -d | xxd -p -c1`)
wrapped_data_hex_array_length=${#wrapped_data_hex_array[*]}

# Extract the wrapped temporary AES key. (The length of this first portion of the wrapped data is equal to the length of the private RSA wrapping key.)
wrapped_temp_aes_key_array=("${wrapped_data_hex_array[@]:0:${RSA_KEY_SIZE_IN_BYTES}}")
start_index_target_key=${#wrapped_temp_aes_key_array[*]}

# Extract the wrapped target key. (This second portion of the wrapped data is the software-protected master encryption key.)
wrapped_targetKey_array=("${wrapped_data_hex_array[@]:${start_index_target_key}:$(( ${wrapped_data_hex_array_length} - ${start_index_target_key} ))}")
wrapped_targetKey_array_length=${#wrapped_targetKey_array[*]}

# Trim spaces so that only hexadecimals remain. Convert hexadecimals to data and write to file.
wrapped_temp_aes_key_data="${wrapped_temp_aes_key_array[@]} | tr -d ' ' | xxd -p -r"
eval "echo -n $wrapped_temp_aes_key_data > $TEMP_WRAPPED_AES_PATH"

# Trim spaces so that only hexadecimals remain. Convert hexadecimals to data and write to file.
wrapped_target_key_data="${wrapped_targetKey_array[@]} | tr -d ' ' | xxd -p -r"
eval "echo $wrapped_target_key_data > $WRAPPED_SOFTWARE_KEY_PATH"

# Unwrap the wrapped_temp_aes_key by using the private RSA wrapping key.
${OPENSSL} pkeyutl -decrypt -inkey ${PRIVATE_KEY_PATH} -in ${TEMP_WRAPPED_AES_PATH} -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256 -out
${TEMP_AES_KEY_PATH}

TEMP_AES_KEY_HEX=$(hexdump -v -e '/1 "%02X"' < ${TEMP_AES_KEY_PATH})

# Unwrap the wrapped software-protected key material by using the unwrapped temporary AES key. The -id-aes256-wrap-pad OpenSSL cipher value specifies the RFC-3394-compliant CKM_RSA_AES_KEY_WRAP mechanism to use for unwrapping. As required by RFC 5649, -iv specifies an "alternative initial value" that is a 32-bit message length indicator expressed in hexadecimal.
${OPENSSL} enc -iv A65959A6 -in $WRAPPED_SOFTWARE_KEY_PATH -d -id-aes256-wrap-pad -k ${TEMP_AES_KEY_PATH} -out ${SOFTWARE_KEY_PATH}

For a complete list of parameters and values for CLI commands, see the CLI Command Reference.