-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Polycli KMS Ethereum Transaction Signing (#180)
* feat: basic local signing functions * feat: hacks on hacks - the creation of the gcp HSM key is working * feat: adding working kms sign * docs: updating * docs: adding some basic usage notes * fix: lints * feat: make gen * fix: generation versoin * fix: make gen * fix: minor comments and cleanup * feat: adding list command * feat: adding import * fix: issue with listing versioned keys * fix: elliptic lint * chore: update kms signing docs * docs: adding some docs for import * docs: make gen-doc --------- Co-authored-by: leovct <[email protected]>
- Loading branch information
1 parent
d5fb815
commit a51b5e3
Showing
20 changed files
with
1,552 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
The create subcommand will create a new key pair. By default, a hex private key will be written to `stdout`. | ||
```bash | ||
polycli signer create > private-key.txt | ||
``` | ||
|
||
If you need to work with a go-ethereum style keystore, a key can be added by setting a `--keystore` directory. When you run this command, you'll need to specify a password to encrypt the private key. | ||
|
||
```bash | ||
polycli signer create --keystore /tmp/keystore | ||
``` | ||
|
||
Polycli also has basic support for KMS with GCP. Creating a new key in the cloud can be accomplished with a command like this | ||
|
||
```bash | ||
# polycli assumes that there is default login that's been done already | ||
gcloud auth application-default login | ||
polycli signer create --kms GCP --gcp-project-id prj-polygonlabs-devtools-dev --key-id jhilliard-trash | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
It's possible to import a simple hex encoded private key into a local | ||
keystore or as a crypto key version in GCP KMS. | ||
|
||
In order to import into a local keystore, a command like this could be used: | ||
|
||
```bash | ||
polycli signer import --keystore /tmp/keystore --private-key cf42d151cec45693f2ac1201e803b056c5f9e2e5d1af627ce41ab3b6faceda25 | ||
``` | ||
|
||
### Importing into GCP KMS | ||
|
||
Importing into GCP KMS is a little bit more complicated. In order to run the import, a command like this would be used: | ||
|
||
```bash | ||
polycli signer import --private-key 42b6e34dc21598a807dc19d7784c71b2a7a01f6480dc6f58258f78e539f1a1fa --kms gcp --gcp-project-id prj-polygonlabs-devtools-dev --key-id jhilliard-code-quality --gcp-import-job-id test-import-job | ||
``` | ||
|
||
There are a few things going on here: | ||
|
||
1. We're specifying a `--private-key` that's hex encoded. That's the only format that `import` accepts at this time. | ||
2. We're using `--kms gcp` which tell polycli that we want to use gcp kms as our backend | ||
3. W've specifed `--gcp-project-id` which names a test project that we're using. We've left out `--gcp-location` and `--gcp-keyring-id` which means we're using the defaults. | ||
4. We've set `--gcp-import-job-id test-import-job` which names a job that will be used to import the key. Basically GCP will give us a public key that we use to encrypt our key for importing | ||
|
||
The `--key-id` is also important. This will set the name of the key that's going to be imported. Note, the key-id must have already been created in order for import to work. When we're doing the import, we're actually importing a new version of the key that already exists. For the time being, the `signer import` command will not create the first version of the key for you. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
After creating a few keys in the keystore or KMS, it's useful just to be able to list the keys. If you're using a keystore, the accounts can be listed using this command: | ||
|
||
```bash | ||
polycli signer list --keystore /tmp/keystore | ||
``` | ||
|
||
In the case of GCP KMS, the keyring will need to be provided and the keys can be listed with this command: | ||
|
||
```bash | ||
polycli signer list --kms GCP --gcp-project-id prj-polygonlabs-devtools-dev --gcp-keyring-id polycli-keyring | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
Currently, polycli only supports signing transactions. Message and arbitrary signing might happen in the future. In order to sign as message we first need to create some transaction data in a JSON file | ||
|
||
```json | ||
{ | ||
"from": "0xB41C20404dffA411fd3F5453a9EA4432Da64e70b", | ||
"to": "0xB41C20404dffA411fd3F5453a9EA4432Da64e70b", | ||
"gas": "0x8000", | ||
"gasPrice": "0x30000000", | ||
"maxFeePerGas": "0x30000000", | ||
"maxPriorityFeePerGas": "0x30000000", | ||
"value": "0x1", | ||
"nonce": "0x0", | ||
|
||
"input": "", | ||
|
||
"chainId": "0x539", | ||
"accessList": [] | ||
} | ||
``` | ||
|
||
The file format here is defined by [`SendTxArgs`](https://pkg.go.dev/github.com/ethereum/[email protected]/signer/core/apitypes#SendTxArgs) in go-ethereum. This is a lower level transaction format and it will require you to manually specify things like `nonce` and `gasPrice`. In other libraries these are often computed for you. | ||
The benefit here is that it gives us the ability to specify lower level options like `accessList` which aren't usually available in other libraries. | ||
|
||
Assuming we have valid transaction data in `tx.json` we can sign the transaction three different ways depending on where our private key is stored | ||
|
||
### Signing with Hex Key | ||
|
||
This is the easiest, but least secure way to sign. In this case, we're providing a private key as a command line argument to polycli and using that to sign the transaction data. The signed transaction is written to `stdout` | ||
```bash | ||
polycli signer sign --private-key $(cat private-key.txt) --data-file tx.json --chain-id 1337 | jq '.' | ||
``` | ||
|
||
This is the output that is generated. `signedTx` is the JSON formatted transaction which is readable but not readily usable. The `rawSignedTx` can be directly published. | ||
|
||
```json | ||
{ | ||
"rawSignedTx": "02f86c820539808430000000843000000082800094b41c20404dffa411fd3f5453a9ea4432da64e70b0180c080a0978b7e99d4941fddcbfc792632a53bd4ac4b690ae4395d8203ecec9836e53dd8a00e32626e8456afb6e59f1fb2a8835bd647a97fec4d9da6a46ecadbf310b345d6", | ||
"signedTx": { | ||
"type": "0x2", | ||
"chainId": "0x539", | ||
"nonce": "0x0", | ||
"to": "0xb41c20404dffa411fd3f5453a9ea4432da64e70b", | ||
"gas": "0x8000", | ||
"gasPrice": null, | ||
"maxPriorityFeePerGas": "0x30000000", | ||
"maxFeePerGas": "0x30000000", | ||
"value": "0x1", | ||
"input": "0x", | ||
"accessList": [], | ||
"v": "0x0", | ||
"r": "0x978b7e99d4941fddcbfc792632a53bd4ac4b690ae4395d8203ecec9836e53dd8", | ||
"s": "0xe32626e8456afb6e59f1fb2a8835bd647a97fec4d9da6a46ecadbf310b345d6", | ||
"yParity": "0x0", | ||
"hash": "0xc03d220111f2d10b6a2b6b22c98e0e7e728a869cac0d3730e33b8bff683d677d" | ||
} | ||
} | ||
``` | ||
|
||
### Signing with keystore | ||
|
||
Signing with a keystore requires that you specify the `--keystore` location and the `--key-id` which in this case is the address of the key that you'd like to use for signing | ||
|
||
```bash | ||
polycli signer sign --keystore /tmp/keystore --key-id 0x58ce4bE73Ee7D0dee75395Ef662e98F91AD2E740 --data-file tx.json --chain-id 1337 | ||
``` | ||
|
||
### Signing with GCP KMS | ||
|
||
The syntax for signing with KMS should look familiar. | ||
|
||
```bash | ||
# polycli assumes that there is default login that's been done already | ||
gcloud auth application-default login | ||
polycli signer sign --kms GCP --gcp-project-id prj-polygonlabs-devtools-dev --key-id jhilliard-trash --data-file tx.json --chain-id 1337 | ||
``` |
Oops, something went wrong.