Skip to content

Rust library for signing EVM transaction with secp256k1 keys hosted in AWS KMS

License

Notifications You must be signed in to change notification settings

orlowskilp/evm-signer-kms

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Library for signing EVM transactions with AWS KMS

Crates.io Version evm-signer-kms codecov MIT License

EVM transaction signing library using key pairs generated and stored in AWS KMS.

Built for:

  • Security - AWS KMS managed keys which never leave HSM devices.
  • Speed and reliability - Implemented in Rust.

Features

  • Legacy (type 0) transactions
  • EIP-2930 (type 1) transactions
  • EIP-1559 (type 2) transactions
  • Easily expandable to future EIP-2718 typed transactions
  • EIP-55 address checksum validation if address has uppercase chars

Tool chain compatibility

Works with MUSL and GNU tool chains.

Building

I suggest using the provided Makefile to get things running fast. The default build target is x86_64-unknown-linux-gnu, so this command will build the library with the GNU tool chain:

make build

If you wish to build it with a different tool chain, it suffices to specify it with the TOOL_CHAIN environment variable, e.g.:

TOOL_CHAIN=x86_64-unknown-linux-musl make build

Setting up

The library communicates with AWS KMS API endpoints and thus requires authorization. Additionally it requires AWS region and KMS key ID to be specified in the environment. This is because it was designed with containers and container orchestration in mind.

There are good chances that you will want to inject some secrets into the client application in the container orchestration solution (e.g. using AWS Secrets Manager or HashiCorp Vault).

Key access policy

At the very least the key policy must allow these actions for the IAM role which you are going to use as the principal (see documentation for more details):

kms:DescribeKey
kms:GetPublicKey
kms:Sign
kms:Verify

Authorization

I suggest using STS to assume a role which is granted permissions to use the secp256k1 key pair in KMS. Once the IAM role is set up, you can assume it by e.g. setting the following environment variables:

export AWS_ACCESS_KEY_ID="[REDACTED]"
export AWS_SECRET_ACCESS_KEY="[REDACTED]"
export AWS_SESSION_TOKEN="[REDACTED]"

Region specification

The region needs to be inferred from the environment, e.g.:

export AWS_REGION="[REDACTED]"

KMS key ID

The KMS key which is going to be used for message digests signing can be identified using a key ID in the UUID format:

export KMS_KEY_ID="[REDACTED]"

Note: The library doesn't understand the KMS_KEY_ID variable itself, it is just a suggested way to pass the key ID to the library logic (see examples in the documentation) for more details.

Testing configuration

The easiest way to check whether everything works the way it should is by running tests.

Before running the tests you need to download the public key PEM file and copy it to ./tests/data/pub-key.pem and then decode it to ./tests/data/pub-key.der.

Makefile provides a directive for that:

make fetch-public-key

Once the PEM and DER files are there, run the tests with:

make test

Note: If you downloaded the PEM file using the management console it is going to have the following format:

-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----

You can use the supplied helper pem2der.sh shell script:

cd tests/data
./scripts/pem2der.sh ./pub-key.pem > pub-key.der

If the tests pass, you're all set!

What's needed

  • More more and better tests
  • Derivation paths support
  • ARM aarch64 support