awskms

package
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2023 License: MIT Imports: 17 Imported by: 0

README

AWS KMS signer for go-ethereum

This package uses the Amazon Web Services' Key Management Service to provide a signing interface for EVM-compatible transactions. Rather than directly accessing a private key to sign a transaction, the client makes calls to the remote AWS KMS to do so and the private key never leaves the KMS.

Import

import "github.com/LampardNguyen234/evm-kms/awskms"

Interact with the Code

Create a KMSSigner
ctx := context.Background()

cfg := Config{
    KeyID:   "KEY_ID",
    ChainID: 1,
}
awsCfg, err := config.LoadDefaultConfig(ctx,
    config.WithRegion("AWS_REGION"),
    config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(
        "ACCESS_KEY", "ACCESS_SECRET", "SESSION")))
if err != nil {
    panic(err)
}
kmsClient := kms.NewFromConfig(awsCfg)

c, err = NewAmazonKMSClient(ctx, cfg, kmsClient)
if err != nil {
    panic(err)
}

Or one can create a KMSSigner directly from a given config file:

cfg, err := LoadStaticCredentialsConfigConfigFromFile("./config-static-credentials-example.json")
c, err := NewAmazonKMSClientWithStaticCredentials(ctx, *cfg)
if err != nil {
    panic(err)
}

The config file looks like the following:

{
    "KeyID": "KEY_ID",
    "ChainID": 1,
    "Region": "AWS_REGION",
    "AccessKeyID": "ACCESS_KEY",
    "SecretAccessKey": "ACCESS_SECRET",
    "SessionToken": "SESSION"
}
Send ETH
Create a transaction
testTx := types.NewTx(&types.LegacyTx{
    To:       &common.HexToAddress("0x243e9517a24813a2d73e9a74cd2c1c699d0ff7a5"),
    Nonce:    9090,
    GasPrice: big.NewInt(1000000),
    Gas:      50000,
    Value:    big.NewInt(100),
    Data:     []byte{1, 2, 3},
})
Sign the transaction
signedTx, err := c.GetDefaultEVMTransactor().Signer(c.GetAddress(), testTx)
if err != nil {
    panic(err)
}
jsb, _ := json.Marshal(signedTx)
fmt.Println("signedTx", string(jsb))
Broadcast the transaction
err = evmClient.SendTransaction(ctx, signedTx)
if err != nil {
    panic(err)
}

See TestSendETH.

Send ERC20

The abigen tool generates .go binding files that are able to directly operate with the *bind.TransactOpts type. An example of this is here. The Transfer function takes as input a *bind.TransactOpts, which can be retrieved via the GetDefaultEVMTransactor function of the client, or can be constructed manually, as long as a bind.SignerFn is supplied.

transactor := &bind.TransactOpts{
    From:      c.GetAddress(),
    Nonce:     new(big.Int).SetUint64(90909),
    Signer:    c.GetEVMSignerFn(),
    GasPrice:  big.NewInt(1000000),
    GasLimit:  50000,
    Context:   ctx,
}

tx, err := erc20Instance.Transfer(transactor, common.HexToAddress("0x243e9517a24813a2d73e9a74cd2c1c699d0ff7a5"), new(big.Int).SetUint64(1000))
if err != nil {
    panic(err)
}

See TestSendERC20.

Documentation

Overview

Package awskms uses the Amazon Web Services' Key Management Service to provide a signing interface for EVM-compatible transactions.

Rather than directly accessing a private key to sign a transaction, the client makes calls to the remote AWS KMS to do so and the private key never leaves the KMS.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AmazonKMSClient

type AmazonKMSClient struct {
	// contains filtered or unexported fields
}

AmazonKMSClient implements basic functionalities of an Amazon Web Services' KMS client for signing transactions.

func NewAmazonKMSClient

func NewAmazonKMSClient(ctx context.Context, cfg Config, kmsClient *kms.Client, txSigner ...types.Signer) (*AmazonKMSClient, error)

NewAmazonKMSClient creates a new AWS KMS client with the given config.

If txSigner is not provided, the signer will be initiated as a types.NewLondonSigner(cfg.ChainID). Note that only the first value of txSigner is used.

Example:

ctx := context.Background()

cfg := Config{
	KeyID:   "YOUR_KEY_ID_HERE",
	ChainID: 1,
}

awsCfg, err := config.LoadDefaultConfig(ctx,
	config.WithRegion("AWS_REGION"),
	config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(
		"ACCESS_KEY_ID",
		"SECRET_ACCESS_KEY",
		"SESSION",
	)),
)
if err != nil {
	panic(err)
}
kmsClient := kms.NewFromConfig(awsCfg)

c, err = NewAmazonKMSClient(ctx, cfg, kmsClient)
if err != nil {
	panic(err)
}

func NewAmazonKMSClientWithStaticCredentials added in v0.2.0

func NewAmazonKMSClientWithStaticCredentials(ctx context.Context, cfg StaticCredentialsConfig, txSigner ...types.Signer) (*AmazonKMSClient, error)

NewAmazonKMSClientWithStaticCredentials is an alternative of NewAmazonKMSClient but uses a StaticCredentialsConfig.

func (AmazonKMSClient) GetAddress

func (c AmazonKMSClient) GetAddress() common.Address

GetAddress returns the EVM address of the current signer.

func (AmazonKMSClient) GetDefaultEVMTransactor

func (c AmazonKMSClient) GetDefaultEVMTransactor() *bind.TransactOpts

GetDefaultEVMTransactor returns the default KMS-backed instance of bind.TransactOpts. Only `Context`, `From`, and `Signer` fields are set.

func (AmazonKMSClient) GetEVMSignerFn

func (c AmazonKMSClient) GetEVMSignerFn() bind.SignerFn

GetEVMSignerFn returns the EVM signer using the AWS KMS.

func (AmazonKMSClient) GetPublicKey

func (c AmazonKMSClient) GetPublicKey() (*ecdsa.PublicKey, error)

GetPublicKey returns the public Key corresponding to the given keyId.

func (AmazonKMSClient) HasSignedTx

func (c AmazonKMSClient) HasSignedTx(tx *types.Transaction) (bool, error)

HasSignedTx checks if the given tx is signed by the current AmazonKMSClient.

func (AmazonKMSClient) SignHash

func (c AmazonKMSClient) SignHash(digest common.Hash) ([]byte, error)

SignHash calls the remote AWS KMS to sign a given digested message. Although the AWS KMS does not support keccak256 hash function (it uses SHA256 instead), it will not care about which hash function to use if you send the hash of message to the KMS.

func (*AmazonKMSClient) WithChainID added in v0.2.0

func (c *AmazonKMSClient) WithChainID(chainID *big.Int)

WithChainID assigns given chainID (and updates the corresponding signer) to the AmazonKMSClient.

func (*AmazonKMSClient) WithSigner added in v0.1.1

func (c *AmazonKMSClient) WithSigner(signer types.Signer)

WithSigner assigns the given signer to the AmazonKMSClient.

type Config

type Config struct {
	// KeyID is the ID of the working AWS KMS key.
	KeyID string `json:"KeyID"`

	// ChainID is the ID of the target EVM chain.
	//
	// See https://chainlist.org.
	ChainID uint64 `json:"ChainID"`
}

Config represents required information to create an AWS KMS client.

func LoadConfigFromFile

func LoadConfigFromFile(filePath string) (*Config, error)

LoadConfigFromFile loads the config from the given config file.

func (Config) IsValid

func (cfg Config) IsValid() (bool, error)

IsValid checks if a Config is valid.

type StaticCredentialsConfig added in v0.2.0

type StaticCredentialsConfig struct {
	Config

	// Region is the region of the AWS KMS Key.
	Region string `json:"Region"`

	// AccessKeyID is the access key ID of the given account for the sake of connecting to the remote AWS client.
	AccessKeyID string `json:"AccessKeyID"`

	// SecretAccessKey is the secret key for the AccessKeyID.
	SecretAccessKey string `json:"SecretAccessKey"`

	// SessionToken is the session ID.
	SessionToken string `json:"SessionToken,omitempty"`
}

StaticCredentialsConfig consists of AWS KMS Config with static credentials.

Example:

  scConfig = StaticCredentialsConfig{
 	KeyID: "KEY_ID",
		ChainID: 0,
		Region: "REGION_ID",
		AccessKeyID: "ACCESS_KEY_ID",
		SecretAccessKey: "SECRET_ACCESS_KEY",
		SessionToken: "SESSION_TOKEN",
 }

func LoadStaticCredentialsConfigConfigFromFile added in v0.2.0

func LoadStaticCredentialsConfigConfigFromFile(filePath string) (*StaticCredentialsConfig, error)

LoadStaticCredentialsConfigConfigFromFile loads a static credential config from the given config file.

func (StaticCredentialsConfig) IsValid added in v0.2.0

func (cfg StaticCredentialsConfig) IsValid() (bool, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL