AWS Database Blog

Import Ethereum private keys to AWS KMS

In the world of digital assets, private keys have always been of utmost importance. Unlike traditional assets, digital assets are controlled by private keys (a string of letters and numbers), just like passwords, which unlock the right to manage and use assets. Private keys can be used to irreversibly transfer funds from the wallet, thus, it is essential to keep these keys stored securely and ensure they cannot be compromised. With the widespread use of Ethereum blockchain globally, individuals and relevant practitioners, are encrypting and storing the keys they own. By default, AWS Key Management Service (AWS KMS) generates the key material for that KMS key. But you can create a KMS key without key material and then import your own key material into that KMS key, a feature often known as “bring your own key” (BYOK). With this feature, we can store our private key securely in AWS.

In typical blockchain usage scenarios, when users intend to transfer their assets to others or verify past asset transfers, the process involves signing and verification that necessitate the use of private keys. However, this also amplifies the potential risk of private key exposure.

On June 5, 2023, AWS announced that you can now import asymmetric and HMAC keys into AWS KMS and use them within supported AWS KMS-integrated AWS services and your own applications.

Solution overview

This solution builds on the post “How to sign Ethereum EIP-1559 transactions using AWS KMS”. We can configure and install that solution first so that we can easily test and verify our post. The following diagram shows the deployment architecture of the wallet application, which uses the AWS Management Console, AWS Lambda, AWS KMS, Amazon Managed Blockchain, and more.

After signing or validating a transaction or message, you may choose to establish an AMB node within a secured private subnet or install a self-built Ethereum mainnet blockchain. Subsequently, you can utilize the AMB provided endpoint for your Ethereum node along with a compatible web3 sdk, such as Web3.js, Ethers.js, etc., to seamlessly propagate the transactional message onto the Ethereum mainnet. This approach enhances the security and integrity of business operations.

AWS also offers AWS CloudHSM to maintain and manage private keys. You export Ethereum private keys generated based on CloudHSM, and import them, offering you more flexible operational capabilities. However, this is not discussed in this post.

There are two methods to create a customer-managed key (AWS KMS key material): create a new key through

the AWS KMS console, or import an existing private key. When using AWS KMS, the private key cannot be exported, and the entire life cycle is managed by AWS KMS. We can set permissions for this key based on AWS Identity and Access Management (IAM) to ensure its security during use.

Create Lambda functions

We use “Deploy the solution with AWS CDK” to create two Lambda functions: one is based on the EIP-1559 protocol for signing and verification, and the other is a traditional method for directly signing a transaction.

Configure the EIP-1559 function’s environmental variables as follows:

  • ETH_NETWORK specifies the type of Ethereum blockchain. (mainnet, rinkeby, goerli)
  • KMS_KEY_ID the ID of asymmetric AWS KMS key material. (you can follow the post to generate the key ID)
  • LOG_LEVEL sets the level of log output. (DEBUG, INFO, WARN, ERROR)

The following image shows an example of the concrete value.

Create an AWS KMS key material

In this blog, we focus on importing AWS KMS key material. If you want to create an AWS KMS key material without import an existing private key, please check the Appendix.

Import an existing private key into a AWS KMS key material

The AWS KMS key material created in this way cannot be downloaded by the user, but the user already has the private key, and as long as it is well preserved, it can be imported again at any time. We can use the AWS CLI for this process, but for this post, we demonstrate on the console. For more information about using the AWS CLI, refer to create-key.

  1. On the AWS KMS console, choose Customer managed keys in the navigation pane.
  2. Choose Create key.
  1. For Key type, select Asymmetric.
  2. For Key usage, select Sign and verify.
  3. For Key spec, choose the key encryption algorithm ECC_SECG_P256K1.
  4. Expand Advanced options.
  5. For Key material origin, select External (Import Key material).
  6. Select the acknowledgement check box.
  7. For Regionality, select Single-Region key.
  8. Choose Next.
  9. Enter an alias, optional description, and optional tags, then choose Next.
  10. Select the administrator of this key and choose Next.
  11. Select the users of this key and choose Next.
  12. Review the creation process and choose Finish.

At this point, we need to upload the key material.

  1. Navigate to the key details page and on the Key material tab, choose Import key material.
  2. In the Configuration section, specify your wrapping key spec and wrapping algorithm.
  3. Choose Next.

Copy this Key ID as we will use it later: 9bd5ca27-xxxx-xxxx-xxxx-xxxxxxxxxxx.

  1. Return to the Customer managed keys page and copy the key ID to use later (for this post, the key is 9bd5ca27-xxxx-xxxx-xxxx-xxxxxxxxxxx)

For the key Generation and upload steps, you can create an Amazon Elastic Compute Cloud (Amazon EC2) instance for this, or you can directly operate through AWS Cloud Shell.

  1. If you don’t have OpenSSL installed, use the following command to install it, then run the subsequent commands to import the key:
sudo yum install openssl -y
  • Generate Ethereum Supported Private key
openssl ecparam -name secp256k1 -genkey -noout -out ec-secp256k1-priv-key.pem
  • Set variables to download the PublicKey and ImportToken of the wrap key created above, making it easier for us to generate the key material that satisfies the requirements
export KEY=`aws kms get-parameters-for-import --region ap-southeast-1 \
--key-id 9bd5ca27-9b87-4c95-a60d-6f9f0885d464 \
--wrapping-algorithm RSAES_OAEP_SHA_256 \
--wrapping-key-spec RSA_2048 \
--query '{Key:PublicKey,Token:ImportToken}' \
--output text`
echo $KEY | awk '{print $1}' > PublicKey.b64
echo $KEY | awk '{print $2}' > ImportToken.b64
openssl enc -d -base64 -A -in PublicKey.b64 -out PublicKey.bin
openssl enc -d -base64 -A -in ImportToken.b64 -out ImportToken.bin

  • Convert the private key to Base64 and generate a binary file, We can accomplish this in one step with the appropriate command
cat ec-secp256k1-priv-key.pem | openssl pkcs8 -topk8 -outform der \
-nocrypt > ec-secp256k1-priv-key.der
  • Next, we use pkeyutl to encrypt the generated binary file and generate the required key material
openssl pkeyutl \
-encrypt \
-in ec-secp256k1-priv-key.der \
-out EncryptedKeyMaterial.bin \
-inkey PublicKey.bin \
-keyform DER \
-pubin -encrypt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256

  • Next, we perform the upload operation
aws kms import-key-material --region ap-southeast-1 \
--key-id 9bd5ca27-9b87-4c95-a60d-6f9f0885d464 \
--encrypted-key-material fileb://EncryptedKeyMaterial.bin \
--import-token fileb://ImportToken.bin \
--expiration-model KEY_MATERIAL_DOES_NOT_EXPIRE

At this point, we can see that the key has been successfully imported

Test the private key

 Next, we test our generated private key against third-party wallet tools:

We continue to use the AWS CloudShell to execute the following commands:

  1. Based on the generated PEM file, save it in text format:
cat ec-secp256k1-priv-key.pem | openssl ec -text -noout > key
  1. Extract the public key address
cat key | grep pub -A 5 | tail -n +2 | tr -d '\n[:space:]:' | sed 's/^04//' > pub
  1. Extract the private key address, removing the initial 00. The parameter priv will store the private key, which fits the Ethereum format:
cat key | grep priv -A 3 | tail -n +2 | tr -d '\n[:space:]:' | sed 's/^00//' > priv


Now we import the private key address into the third-party wallet.

  1. In some third-party wallet tools, on the options menu, choose Import account.

  1. Enter your private key and choose Import.

  1. Copy the corresponding key.

  1. On the Lambda console, navigate to the function you created as part of the AWS CDK deploy and filter with the value “EIP”.

  1. Enter the key you copied as the value for KMS_KEY_ID and choose Save.

  1. Go back to this function details page, On the Test tab, verify the address is correct.

We found that the generated address is the same as we expected.

  1. Next, we sign it and find that the signing function is also working normally.

Clean up

After you complete the deployment and functional verification, to avoid continuous charges, use the following steps below to stop the application or delete all deployed components:

  1. Delete AWS CDK generated resources(which created in the post “How to sign Ethereum EIP-1559 transactions using AWS KMS” )
  2. If AWS CDK does not delete the AWS Lambda function, Open the Lambda Console and delete the corresponding Lambda function

  1. Delete the created AWS KMS key material, refer to schedule-key-deletion

Conclusion

In this post, we showed you how to manage important key information using both managed and imported methods for your KMS Keys on AWS. We provided step-by-step instructions for setup, allowing clients to maintain their important private key in a safer and more convenient way.

If you have any questions or suggestions, leave them in the comments section.

Appendix

Create an AWS KMS key material

The AWS KMS key material created in this way is completely managed by AWS, and we cannot export it. For this post, we demonstrate how to create the AWS KMS key material using the AWS KMS console, but you can also use the AWS Command Line Interface (AWS CLI). For more information about using the AWS CLI, refer to create-key.

  1. On the AWS KMS console, choose Customer managed keys in the navigation pane.
  2. Choose Create key.

  1. For Key type, select Asymmetric.
  2. For Key usage, select Sign and verify.
  3. For Key spec, select the key encryption algorithm ECC_SECG_P256K1.
  4. Choose Next.

  1. For Alias, enter an alias for the key.
  2. Enter an optional description and tags, then choose Next

  1. Select the administrator of this key, then choose Next.

  1. Select the users of this key, then choose Next.

This helps us separate the personnel who manage the key and those who use the key, thereby

providing additional security.

  1. Review the creation process and choose Finish.

At this point, the AWS KMS generated key is successfully created.


About the Author

Chaoqun Sun is a Solutions Architect responsible for architecture consulting, design, and implementation based on AWS Cloud computing solutions, and empowers enterprises to grow with technology. He is also passionate about designing and building end-to-end blockchain solutions for customers.