AWS Database Blog

Make EOA private keys compatible with AWS KMS

Those who choose to take ownership of digital assets, such as cryptocurrency or non-fungible tokens (NFTs), are faced with a crucial decision when creating a wallet: do they opt to manage their own wallet or delegate that responsibility to a trusted third party? Non-custodial wallet solutions, whereby a user manages their own wallet, are popular because they allow the user to have full control and ownership over their digital asset wallets. Alternatively, those who do not wish to take on the responsibility of managing their own wallet can turn to a custodial wallet provider, a third party who takes on the role of managing the wallet on behalf of the user. Custodial wallets, however, have unique risks associated with them, including but not limited to the custodian’s security shortfalls, bankruptcy, and insider threats that can render loss of funds in custodial wallet scenarios.

Although non-custodial wallets have their own set of risks, such as the increased responsibility to maintain the security of one’s own wallet, retaining full control of your wallet is a mechanism to insulate yourself from this third-party risk.

In this post, we discuss the following topics:

  • A high-level introduction to account types in Ethereum
  • Why it might be beneficial to use fully managed services such as AWS Key Management Service (AWS KMS) for the management of private keys associated with non-custodial blockchain wallets
  • How elliptic curve private keys are being stored, and the Public-Key Cryptography Standard 8 (PKCS #8) and Abstract Syntax Notation One (ASN1.) standard
  • How to convert private keys to PKCS #8, thereby making them compatible with AWS KMS

Ethereum account types

Ethereum has two account types: Externally Owned Accounts (EOAs), which can be controlled by a private key, and contract accounts, which are associated with a smart contract and are controlled by code.

Whereas EOAs can sign and initiate a transaction on their own, smart contract accounts cannot and always require an external account to trigger the code.

In general, EOA wallets such as MetaMask have a single associated private key. The private key’s corresponding public key determines the public address of the wallet.

As a result, EOAs are often set up in a way that whoever has access to the private key has full control over all the assets (no authorization system) in that wallet. Malicious parties often target EOA wallets for this reason, because access to the private key for that wallet gives the attacker unlimited ability to drain the wallet of all its assets. Furthermore, EOAs lack effective key recovery mechanisms and authorization management. The primary way of key recovery these days is using the Secret Recovery Phrase, which consist of 12 words. If the list is lost, the wallet cannot be recreated. If an attacker gets access to the list, the entire wallet can be drained.

Smart contract wallets, such as Gnosis Safe, are more complex and often associated with use cases like a treasury for large decentralized autonomous organizations (DAOs). Smart contract wallets usually use a multi-signature scheme where multiple EOA signatures are required to authorize and initiate a blockchain transaction. This provides additional security layers that an attacker must circumvent to drain a wallet, preventing the compromise of one single private key from rendering a total loss of funds.

Mitigating operational risks by using purpose-built services

To address some of the operational challenges associated with private key or EOA wallet management, it can be beneficial to use a purpose-built solution such as an online HSM or a fully managed service like AWS KMS.

Using AWS KMS as a fully managed solution, which is also FIPS-140 Level 3 validated, helps with mitigating operational key management risks.

After it’s imported, the key only exists within AWS KMS and the original EOA source, with no ability for the KMS key instance to be exported. AWS KMS stores multiple copies of encrypted versions of your keys in systems that are designed for 99.999999999% durability. For more information, refer to Scalability, durability, and high availability. See AWS Key Management Service FAQs for more information on permitted key operations.

A service such as AWS KMS is well suited for use cases where frequent programmatic access to the key is required. This is due to the full integration with AWS Identity and Access Management (IAM) for authentication and authorization management. Also, the KMS API supports all required cryptographic operations on the imported private key, such as the creation of a digital signature.

Costs need to be considered for such a solution as well. Imported keys managed by AWS KMS are charged $1 per month, independent from their usage. For use cases where a large volume of keys must be managed, key management solutions based on AWS Nitro Enclaves can be more cost-efficient. For additional information about Nitro Enclaves for key management, refer to AWS Nitro Enclaves for secure blockchain key management.

Importing keys to fully managed, purpose-built services like HSMs or AWS KMS is not entirely risk free. For AWS KMS, it’s up to the customer to maintain appropriate IAM permissions granting access to the imported keys while AWS enforces physical security in their data centers. This separation of responsibilities is also referred to as the shared responsibility model.

Elliptic curve private key representation

Elliptic curve private keys are random integers within the curves field size, typically 256 bit or 32 bytes in size. For example, the curve field parameters for the secp256k1 curve are listed in section 2.4, page 9 of SEC 2: Recommended Elliptic Curve Domain Parameters.

Elliptic curve public keys, on the other hand, are pairs of integer coordinates (x, y) laying on the curve 256 bit in size each. Due to the special symmetric property of elliptic curves, the public key can be compressed to a 256 bit coordinate + 1 bit, indicating if the point lays on the upper or the lower section of the curve, as visualized in the following plot of an elliptic curve.

The corresponding parameter in the blockchain world, or more particularly in Ethereum, is the parity of the y value, which can be 0 or 1. Refer to EIP-155 for additional information.

Ethereum Virtual Machine (EVM) compatible EOA wallets use the raw private key (32 bytes) without any metadata associated; therefore, the elliptic curve parameters such as the name are fixed to secp256k1. For the export and transport of private keys, the 32 bytes are usually converted to 64-character hex strings because there are no additional escape requirements. As a consequence, the hex string can, for example, be directly stored and distributed using the JSON syntax.

PKCS #8 and ASN.1 standard for private key representation

Fully managed key management services such as AWS KMS use Public-Key Cryptography Standards (PKCS) for their key management operations.

For key import and export, AWS KMS relies on the PKCS #8 standard, which defines a syntax for private key information such as the private key itself (plaintext and encrypted) and a set of attributes.

PKCS #8 uses the Abstract Syntax Notation One (ASN.1) standard. ASN.1 is a globally accepted standard interface description language for defining data structures that can be serialized and deserialized in a cross-platform way.

As pointed out in the Internet Engineering Task Force (IETF) Request for Comments (RFC) on Elliptic Curve Private Key Structure, “The structure defined in this document allows the entity that generates the private and public keys to distribute the key pair and the associated domain parameters.” Version 1 of the structure is as follows:

ECPrivateKey ::= SEQUENCE {
     version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
     privateKey     OCTET STRING,
     parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
     publicKey  [1] BIT STRING OPTIONAL
   }

It consists of the following fields:

  • version references the syntax version used for the elliptic curve private key structure. The associated IETF standard is version 1 as of this writing.
  • privateKey is a byte sequence representation of the private key unsigned integer.
  • parameters is an optional field and specifies the elliptic curve domain parameters such as the name of the curve, for example secp256k1 for Ethereum- or Bitcoin-compatible private keys.
  • publicKey is an optional field that you can use to store the associated public key for the private key. Because the public key can always be recomputed from the private key, it exists as a convenience to the consumer.

ASN.1 structures can be parsed and created with many high-level programming languages, such as Python using the asn1tools package or via OpenSSL using the asn1parse or ASN1_generate_v3 instructions.

Disclaimer

Be aware that private key management comes with great risk. All commands and examples shown in this post are used for technical demonstration and are not considered production ready. Furthermore, you are responsible for key management, security, availability, and durability outside of AWS.

Convert a raw private key into a valid PKCS #8 structure

Private keys used in certain Web3 frameworks and SDKs such as Python web3py or EOA wallet solutions such as MetaMask are stored as 32-byte integers without any associated domain parameters.

To convert these integers into a valid PKCS #8/ASN.1 format, you need to specify the domain parameters such as the elliptic curve that these private keys are associated with. By default, Ethereum- or EVM-compatible chains rely on the secp256k1 elliptic curve.

Complete the following steps to create a temporary private key, similar to how non-custodial crypto wallets manage their keys, and convert it to PKCS #8 format, thereby making it compatible to import into AWS KMS:

  1. Generate a temporary secp256k1 private key, print its public key (for comparison later), and extract the raw private key:
openssl ecparam -name secp256k1 -genkey -out private-key.pem
openssl ec -in private-key.pem -pubout -out public-key.pem
cat private-key.pem | openssl ec -text -noout | grep priv -A 3 | tail -n +2 | tr -d '\n[:space:]:' | sed 's/^00//'

The result will be a raw private key encoded as a hex string, similar to how non-custodial EOA wallets store their keys.

  1. Use the openssl command to reassemble the ASN.1 structure and store the new key in PKCS #8 format as required by AWS KMS:
openssl pkcs8 -topk8 -outform DER -nocrypt -inform DER -in <(echo "302e0201010420 <private_key> a00706052b8104000a" | xxd -r -p) -out private-key_reassembled.pkcs8

In this example, we convert the hex string representation of the key along with the serialized ASN.1 parameters:

  • 302e0201010420 defines the start of the ASN.1 sequence and specifies the total length without the public key.
  • a00706052b8104000a defines the named_curve parameter encoded as OID 1.2.132.0.10, which is secp256k1. OIDs can be seen as a global registrar for accepted standards such as cryptographic algorithms.

For more details on ASN.1 and the values used to reassemble the key structure, refer to Stackoverflow 1 or Stackoverflow 2.

As pointed out in the previous section, the ASN.1 structure can also be assembled and serialized in a higher-level language like Python, as shown in the following code snippet. For this example, we use predefined values to avoid additional external dependencies.

The -inform DER and -outform DER flag indicates that we are importing and exporting the plain text key in binary format described by ASN.1.

Optionally, to calculate the public key from the converted private key and compare it to the initially saved public key, complete the following additional steps:

  1. Parse the recreated private key and print out the public key:
openssl ec -in private-key_reassembled.pkcs8 -pubout -outform PEM -out public-key_reassembled.pem
  1. Compare the initial and the recreated public key, for example by using diff and ensure that they are equal:
diff public-key.pem public-key_reassembled.pem

Make keys PKCS #8 compatible

You can download a shell script from the following GitHub repo to automatically convert a secp256k1 private key represented as a 64-character hex string to a valid PKCS #8 structure encoded as DER. Downloading the script directly without cloning the entire repository requires you to add the run permissions via chmod +x script_name first:

./reassemble_pkcs8.sh <private_key>

If successful, the reassemble_pkcs8.sh script will write the DER-encoded private key to the local folder.

You can now use the files to import the keys to AWS KMS. Refer to Importing key material for AWS KMS keys for instructions about how to import the reassembled private key into AWS KMS. The high-level steps are as follows:

  1. Create a KMS key.
  2. Download the cryptographic wrapping key.
  3. Encrypt the key material that is supposed to be imported with the wrapping key.
  4. Import the new key.

Refer to Import Ethereum private keys to AWS KMS for additional information on automating the key import process.

Conclusion

In this post, we provided a brief introduction into different wallet types and discussed some of the pros and cons. We also explained why key management in general is challenging and why it can be beneficial to offload key management-related tasks to purpose-built services. Furthermore, we explained how private and public keys are being stored using the PKCS #8 and ASN.1 standard and how different formats are beneficial for different use cases, such as network transport. We ended the post with a demonstration of how to make raw elliptic curve private keys, as used by non-custodial wallets, compatible with AWS KMS.

You can use the instructions provided in this post to create your own private blockchain key and convert it to PKCS #8. Use the mechanism described in Import Ethereum private keys to AWS KMS to securely import the key the AWS KMS. As a last step, create and sign an Ethereum-compatible transaction, as described in How to sign Ethereum EIP-1559 transaction using AWS KMS.


About the Authors

David-Paul Dornseifer is a Blockchain Architect with the AWS Worldwide Specialist organization. He focuses on helping customers design, develop and scale blockchain transaction-management and key-custody solutions.

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.