Secure an Ethereum Wallet with a KMS Provider — ECDSA signature algorithm

Jonathan Okz
9 min readDec 8, 2023

--

The security of Ethereum wallets is crucial for the protection of digital assets. The most vital aspect of this security is the management of private keys, which are at the heart of all transactions on the blockchain. A compromised private key can lead not only to substantial financial losses but also expose users to legal and regulatory risks.

This article details a sophisticated method for securing Ethereum private keys using key management services, also known as KMS, such as AWS, Google, HashiCorp Vault, or Azure Key Vault. These platforms offer a robust solution for key management, ensuring that the private key never leaves the secure infrastructure. This approach allows for enterprise-level security, including the use of FIPS 140–2 certified hardware security modules (HSMs).

The process described here enables the signing of an Ethereum transaction with a private key managed and protected by a KMS provider. By adopting this method, users can ensure that their private keys remain unassailable and safe from external attacks, while also facilitating key management and auditing within their organization.

The article provides a step-by-step guide in the setup and use process to secure an Ethereum private key, focusing on the creation, storage, and secure signing of transactions without exposing the private key. By adopting this approach, you can achieve a level of security comparable to services such as Ledger Enterprise.

1. ECDSA Key Generation

Just like Bitcoin, Ethereum uses the Elliptic Curve Digital Signature Algorithm (ECDSA). More specifically, it uses secp256k1 as defined in the “Standards for Efficient Cryptography” (SEC) by Certicom Research (https://www.secg.org/sec2-v2.pdf).

While a deep understanding of ECDSA is not necessary to follow this guide, a basic knowledge can be helpful. For those interested in delving deeper, there are numerous articles and educational resources on the subject.

To begin, let’s create an asymmetric ECDSA key pair using the secp256k1 curve. To illustrate this, I present two practical examples: one using AWS and the other GCP. It should be noted that other Key Management Service (KMS) providers, like HashiCorp or Azure, can also be used without altering the logic presented in this article.

AWS KMS :

Google KMS :

Once these steps are completed, you will obtain the ID of your key pair, which we will use in the rest of the article.

2. Retrieval of the Public Key and Calculation of the Ethereum Address

When using a Key Management Service (KMS) like AWS or GCP, it’s important to understand that the obtained public key does not immediately correspond to a standard Ethereum public key. The public key obtained is encoded in the DER (Distinguished Encoding Rules) format, which is a binary encoding method for structured data. This key is formatted as SubjectPublicKeyInfo (SPKI), as defined in the X.509 standard for public key certification and detailed in RFC 5280. To obtain the raw value of the public key necessary for generating the Ethereum address, one must first decode this DER format. The SubjectPublicKeyInfo format is further described in RFC 5480, section 2.

2.1 Retrieve the Public Key from the Provider

Here are two examples to retrieve the public key in DER format on AWS and GCP.

AWS KMS :

Google KMS :

The result of your public key in DER format will look like this (after conversion to hexadecimal):

3056301006072A8648CE3D020106052B8104000A03420004B8E9C055D6C601A803F4E301FACB1FAF1F3B9F6D1F5150A9068B678F5F6A58A20220F505AAAC12E4180EDF59B2466A30D1CF4D409FA028D4A3EDF8ACFE7AD597C

2.2 Decoding the Public Key

You’ve probably already realized that the public key you retrieved looks nothing like a standard Ethereum public key. Well, you’re absolutely right. To address this, we will use the asn1js library, an effective tool for decoding and interpreting the DER-encoded data of the public key (lines 11 to 19).

Furthermore, according to section 2.2 of RFC 5480, the first byte 0x04 indicates that it’s an uncompressed key. Once this first byte is removed (line 26), we obtain a standard Ethereum public key.

The result of your standard Ethereum public key will look like this (after conversion to hexadecimal):

0x03facdb512c802dbc6c4b4faa4709696f302f612a36e9d5e76939ead59e0c268cc

2.3 Calculation of the Ethereum Address

As explained in Chapter 2 of Mastering Ethereum, the address corresponds to the last 20 bytes of the keccak256 hash of the public key. Thus, the code to generate the Ethereum address is as follows:

The result of your Ethereum address will look like this (after conversion to hexadecimal):

0x5163678a8a0958626c7Fc6eBff87F946B7AcE0B5

In summary, to obtain the Ethereum address corresponding to your ECDSA key pair, you simply need to follow these steps:

3. Signing an Ethereum Transaction

Signing an Ethereum transaction using a KMS provider is a process that breaks down into several distinct steps, each playing an important role in creating a valid signature. Here is a detailed explanation of each step:

  1. Signing a Keccak-256 Hash :
    The starting point is to sign a Keccak-256 hash of the message (transaction) with a KMS provider.
  2. Decoding and Calculating the r and s Components of the Signature :
    After signing the message with your KMS provider, the obtained signature will be encoded in DER. This signature must be decoded to be used in the context of an Ethereum transaction. Once the DER signature is decoded, it is necessary to extract the r and s components. These two values are essential in the structure of the ECDSA signature and are required for the validation of the transaction on the Ethereum blockchain.
  3. Determining the v Value :
    The final step is to find the value of the recovery identifier v (explanation in the rest of the article).

3.1 Signing a Keccak-256 Hash:

We will return to the actual payload later. For now, you can simply sign an empty keccak256 hash that will be passed to this function in the form of a Bufferdigest.

Here are two examples allowing you to sign an arbitrary message with AWS and GCP.

AWS KMS :

Google KMS :

3.2 Decoding and Calculating the r and s Components of the Signature:

Our KMS provider returns a signature encoded in DER as per the ANS X9.62–2005 specifications. To process and use this signature in the context of Ethereum, a decoding step is necessary, as stipulated in section 2.2.3 of RFC 3279.

In this context, I have developed a specific parsing function to break down the DER signature into its essential components. This function focuses on extracting two integers, r and s, which are crucial for the representation of an ECDSA signature.

The result of this analysis targets a specific point on the elliptic curve where r represents the x-coordinate and s the y-coordinate. In the context of ECDSA cryptography, these two values are fundamental for the validation and verification of signatures. r and s together constitute the digital signature used to authenticate the transaction on the Ethereum blockchain, thereby ensuring that the transaction has indeed been signed by the holder of the corresponding private key without revealing the key itself.

According to EIP-2, allowing transactions with any value of s (from 0 to the maximum number on the secp256k1 curve n) presents a risk of transaction malleability. This is why a signature with an s value greater than half of the secp256k1 curve n (i.e., secp256k1n / 2) is considered invalid in the context of Ethereum. Although it is a valid ECDSA signature, from Ethereum’s perspective, it is on the “dark side” of the curve. The code above addresses this issue by checking if the s value is greater than secp256k1n / 2 (see line 38). If it is, we are on the “dark side” of the curve. It then becomes necessary to invert s (as indicated on line 41) to obtain a valid Ethereum signature. This method works because the s value does not define a distinct point on the curve. The value can be +s or -s, both signatures being valid from the perspective of ECDSA.

3.3 Determining the v Value:

The ECDSA signature used in Ethereum consists of three key elements: r, s, and a recovery identifier named v. Historically, before the implementation of EIP-155, the value of v could be either 27 or 28. However, since the adoption of EIP-155, the value of v is now determined based on the chain_id of the network where the transaction is being executed, thus altering the method of calculating this essential component of the signature.

For transactions on networks where EIP-155 is active, the value of v is calculated using the formula v = chain_id * 2 + 35 or v = chain_id * 2 + 36.

One of the primary motivations of EIP-155 is to prevent replay attacks. In a replay attack, a malicious actor captures a valid transaction — say, a fund transfer — from one blockchain and broadcasts it on another blockchain. Before EIP-155, if two chains had similar transaction histories (as was the case with Ethereum and Ethereum Classic after their split), a valid transaction on one chain could potentially be replayed on the other. This posed a significant security risk.

To identify the correct value of v in an Ethereum signature, one can use the function ecrecover(sig, v, r, s). This function returns the public key corresponding to an Ethereum signature. Since we calculated the Ethereum address in section 2.2, we already know what the result of this equation should be. Thus, it is possible to test the two potential values of v to determine which one is correct.

Caution: Due to the nature of the elliptic curve used in ECDSA, two solutions are valid for a given signature, corresponding to the positive and negative aspects of the curve. The value v is a recovery identifier that helps determine which half of the curve was used for the signature. The transaction validation mechanism on Ethereum will accept only one of the two values of v. Therefore, it is sometimes necessary to test both potential values to determine which one is correct.

5. Sending an Ethereum Transaction

You are now ready to send your first Ethereum transaction signed via KMS.

Firstly, let’s focus on preparing the payload, as mentioned in section 3.1. The initial step is to create a valid Ethereum transaction.

Once the transaction is defined as txData, it is hashed with Keccak-256 to create a “digest,” which is essentially a digital fingerprint of the transaction. This digest is then passed to our signDigest function.

We will use the fromTxData function from the @ethereumjs/tx library, which formats the transaction into the RLP format. For a deeper understanding of the internal mechanism of this process, it is recommended to consult the documentation of the @ethereumjs/tx library.

After retrieving the signature from the KMS as signedDigest, we use our decodeRS function to extract the r ands values from the signature. Concurrently, we employ our calculateV function to determine the correct value of v for our Ethereum signature.

Finally, we use the fromTxData function to obtain the hash of the signed transaction.

In summary, this process involves several key steps: creating and hashing the transaction, signing the digest with KMS, decoding the signature to obtain r ands, determining v, and finally, using @ethereumjs/tx to finalize and obtain the hash of the signed transaction.

If you have followed all the steps correctly and successfully signed your transaction with your KMS provider, congratulations! It’s a significant accomplishment, especially if it’s your first transaction of this kind.

6. Conclusion: Challenges and Perspectives of Integrating Ethereum Signatures into Existing Key Management Solutions

Although Ethereum uses the ECDSA secp256k1 algorithm for signatures, this does not guarantee seamless integration with existing key management solutions. Ethereum’s peculiarities, such as those introduced by EIP-2 and other specific standards, impose additional requirements that go beyond standard key management protocols. These requirements often necessitate meticulous byte-level adjustments, thereby increasing the complexity and risk of errors in developing compatible solutions.

This situation underscores a growing need for better alignment between blockchain technologies and traditional key management infrastructures. As blockchain gains popularity and adoption in the enterprise realm, there is increasing pressure on cloud providers and infrastructure companies to better support blockchain-specific standards.

In the meantime, blockchain-specialized engineers play a crucial role in bridging these gaps. They do so by developing libraries and tools that facilitate interoperability between blockchain platforms like Ethereum and conventional key management systems. These efforts are vital for ensuring secure and efficient integration of blockchain into enterprise environments, paving the way for broader adoption of this promising technology.

7. Github and npm package

For a deeper understanding and to enhance your projects, consider exploring this library that provides a comprehensive and advanced implementation of these mechanisms :

https://github.com/JonathanOkz/web3-kms-signer

https://www.npmjs.com/package/@web3-kms-signer/core

--

--

Jonathan Okz
Jonathan Okz

Written by Jonathan Okz

CTO, Software Architect and Entrepreneur, with management, design and hands-on development expertise in Blockchain and highly scalable distributed systems.

Responses (3)