From 54ac7c38f7e21d37550fb7f0d382ed671be28c63 Mon Sep 17 00:00:00 2001 From: John Hilliard Date: Thu, 4 Jan 2024 14:25:08 -0500 Subject: [PATCH] feat: adding import --- cmd/signer/signer.go | 252 +++++++++++++++++++++++++++++++++-- doc/polycli_signer.md | 28 ++-- doc/polycli_signer_create.md | 42 +++--- doc/polycli_signer_import.md | 173 ++++++++++++++++++++++++ doc/polycli_signer_list.md | 42 +++--- doc/polycli_signer_sign.md | 42 +++--- go.mod | 5 +- go.sum | 2 + 8 files changed, 500 insertions(+), 86 deletions(-) create mode 100644 doc/polycli_signer_import.md diff --git a/cmd/signer/signer.go b/cmd/signer/signer.go index a07ad3da..3e381fed 100644 --- a/cmd/signer/signer.go +++ b/cmd/signer/signer.go @@ -6,6 +6,11 @@ import ( "cloud.google.com/go/kms/apiv1/kmspb" "context" "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/sha1" + "crypto/x509" "crypto/x509/pkix" _ "embed" "encoding/asn1" @@ -19,6 +24,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/signer/core/apitypes" + "github.com/google/tink/go/kwp/subtle" "github.com/manifoldco/promptui" "github.com/maticnetwork/polygon-cli/gethkeystore" "github.com/rs/zerolog/log" @@ -46,6 +52,8 @@ type signerOpts struct { gcpProjectID *string gcpRegion *string gcpKeyRingID *string + gcpImportJob *string + gcpKeyVersion *int } var inputSignerOpts = signerOpts{} @@ -203,6 +211,45 @@ var ListCmd = &cobra.Command{ }, } +var ImportCmd = &cobra.Command{ + Use: "import", + Short: "Import a private key into the keyring / keystore", + Long: signerUsage, + Args: cobra.NoArgs, + PreRunE: func(cmd *cobra.Command, args []string) error { + if err := sanityCheck(cmd, args); err != nil { + return err + } + if err := cmd.MarkFlagRequired("private-key"); err != nil { + return err + } + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + if *inputSignerOpts.keystore != "" { + ks := keystore.NewKeyStore(*inputSignerOpts.keystore, keystore.StandardScryptN, keystore.StandardScryptP) + pk, err := crypto.HexToECDSA(*inputSignerOpts.privateKey) + if err != nil { + return err + } + pass, err := getKeystorePassword() + if err != nil { + return err + } + _, err = ks.ImportECDSA(pk, pass) + return err + } + if *inputSignerOpts.kms == "GCP" { + gcpKMS := GCPKMS{} + if err := gcpKMS.CreateImportJob(cmd.Context()); err != nil { + return err + } + return gcpKMS.ImportKey(cmd.Context()) + } + return fmt.Errorf("unable to import key") + }, +} + func getTxDataToSign() (*types.Transaction, error) { if *inputSignerOpts.dataFile == "" { return nil, fmt.Errorf("no datafile was specified to sign") @@ -281,8 +328,7 @@ func (g *GCPKMS) ListKeyRingKeys(ctx context.Context) error { if err != nil { return err } - // TODO This is another spot where I've hard coded the version - pubKey, err := getPublicKeyByName(ctx, c, resp.Name+"/cryptoKeyVersions/1") + pubKey, err := getPublicKeyByName(ctx, c, fmt.Sprintf("%s/cryptoKeyVersions/%d", resp.Name, *inputSignerOpts.gcpKeyVersion)) if err != nil { return err } @@ -379,15 +425,189 @@ func (g *GCPKMS) CreateKey(ctx context.Context) error { } +func (g *GCPKMS) CreateImportJob(ctx context.Context) error { + // parent := "projects/PROJECT_ID/locations/global/keyRings/my-key-ring" + // id := "my-import-job" + parent := fmt.Sprintf("projects/%s/locations/%s/keyRings/%s", *inputSignerOpts.gcpProjectID, *inputSignerOpts.gcpRegion, *inputSignerOpts.gcpKeyRingID) + id := *inputSignerOpts.gcpImportJob + + // Create the client. + client, err := kms.NewKeyManagementClient(ctx) + if err != nil { + return fmt.Errorf("failed to create kms client: %w", err) + } + defer client.Close() + + // Build the request. + req := &kmspb.CreateImportJobRequest{ + Parent: parent, + ImportJobId: id, + ImportJob: &kmspb.ImportJob{ + // See allowed values and their descriptions at + // https://cloud.google.com/kms/docs/algorithms#protection_levels + ProtectionLevel: kmspb.ProtectionLevel_HSM, + // See allowed values and their descriptions at + // https://cloud.google.com/kms/docs/key-wrapping#import_methods + ImportMethod: kmspb.ImportJob_RSA_OAEP_3072_SHA1_AES_256, + }, + } + + // Call the API. + result, err := client.CreateImportJob(ctx, req) + if err != nil { + if strings.Contains(err.Error(), "already exists") { + log.Info().Str("name", parent).Msg("import job already exists") + return nil + } + return fmt.Errorf("failed to create import job: %w", err) + } + log.Info().Str("name", result.Name).Msg("created import job") + + return nil +} + +func (g *GCPKMS) ImportKey(ctx context.Context) error { + name := fmt.Sprintf("projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s", *inputSignerOpts.gcpProjectID, *inputSignerOpts.gcpRegion, *inputSignerOpts.gcpKeyRingID, *inputSignerOpts.keyID) + importJob := fmt.Sprintf("projects/%s/locations/%s/keyRings/%s/importJobs/%s", *inputSignerOpts.gcpProjectID, *inputSignerOpts.gcpRegion, *inputSignerOpts.gcpKeyRingID, *inputSignerOpts.gcpImportJob) + client, err := kms.NewKeyManagementClient(ctx) + if err != nil { + return fmt.Errorf("failed to create kms client: %w", err) + } + defer client.Close() + + wrappedKey, err := wrapKeyForGCPKMS(ctx, client) + if err != nil { + return err + } + req := &kmspb.ImportCryptoKeyVersionRequest{ + Parent: name, + Algorithm: kmspb.CryptoKeyVersion_EC_SIGN_SECP256K1_SHA256, + WrappedKey: wrappedKey, + ImportJob: importJob, + } + + result, err := client.ImportCryptoKeyVersion(ctx, req) + if err != nil { + if strings.Contains(err.Error(), "already exists") { + log.Info().Str("name", name).Msg("key already exists") + return nil + } + return fmt.Errorf("failed to import key: %w", err) + } + log.Info().Str("name", result.Name).Msg("imported key") + return nil + +} + +func wrapKeyForGCPKMS(ctx context.Context, client *kms.KeyManagementClient) ([]byte, error) { + // Generate a ECDSA keypair, and format the private key as PKCS #8 DER. + key, err := crypto.HexToECDSA(*inputSignerOpts.privateKey) + if err != nil { + return nil, err + } + // These are a lot of hacks because the default x509 library doesn't seem to support the secp256k1 curve + // START HACKS + // keyBytes, err := x509.MarshalPKCS8PrivateKey(key) + // if err != nil { + // return nil, fmt.Errorf("failed to format private key: %w", err) + // } + + // https://docs.rs/k256/latest/src/k256/lib.rs.html#116 + oidNamedCurveP256K1 := asn1.ObjectIdentifier{1, 3, 132, 0, 10} + oidBytes, err := asn1.Marshal(oidNamedCurveP256K1) + if err != nil { + return nil, fmt.Errorf("x509: failed to marshal curve OID: %w", err) + } + var privKey pkcs8 + oidPublicKeyECDSA := asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} + privKey.Algo = pkix.AlgorithmIdentifier{ + Algorithm: oidPublicKeyECDSA, + Parameters: asn1.RawValue{ + FullBytes: oidBytes, + }, + } + privateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8) + privKey.PrivateKey, err = asn1.Marshal(ecPrivateKey{ + Version: 1, // This is not the GCP Cryptokey version! + PrivateKey: key.D.FillBytes(privateKey), + NamedCurveOID: nil, + PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)}, + }) + if err != nil { + return nil, fmt.Errorf("unable to marshal private key %w", err) + } + keyBytes, err := asn1.Marshal(privKey) + if err != nil { + return nil, fmt.Errorf("unable to marshal full private key") + } + // END HACKS + + // Generate a temporary 32-byte key for AES-KWP and wrap the key material. + kwpKey := make([]byte, 32) + if _, err := rand.Read(kwpKey); err != nil { + return nil, fmt.Errorf("failed to generate AES-KWP key: %w", err) + } + kwp, err := subtle.NewKWP(kwpKey) + if err != nil { + return nil, fmt.Errorf("failed to create KWP cipher: %w", err) + } + wrappedTarget, err := kwp.Wrap(keyBytes) + if err != nil { + return nil, fmt.Errorf("failed to wrap target key with KWP: %w", err) + } + + importJobName := fmt.Sprintf("projects/%s/locations/%s/keyRings/%s/importJobs/%s", *inputSignerOpts.gcpProjectID, *inputSignerOpts.gcpRegion, *inputSignerOpts.gcpKeyRingID, *inputSignerOpts.gcpImportJob) + + // Retrieve the public key from the import job. + importJob, err := client.GetImportJob(ctx, &kmspb.GetImportJobRequest{ + Name: importJobName, + }) + if err != nil { + return nil, fmt.Errorf("failed to retrieve import job: %w", err) + } + pubBlock, _ := pem.Decode([]byte(importJob.PublicKey.Pem)) + pubAny, err := x509.ParsePKIXPublicKey(pubBlock.Bytes) + if err != nil { + return nil, fmt.Errorf("failed to parse import job public key: %w", err) + } + pub, ok := pubAny.(*rsa.PublicKey) + if !ok { + return nil, fmt.Errorf("unexpected public key type %T, want *rsa.PublicKey", pubAny) + } + + // Wrap the KWP key using the import job key. + wrappedWrappingKey, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, pub, kwpKey, nil) + if err != nil { + return nil, fmt.Errorf("failed to wrap KWP key: %w", err) + } + + // Concatenate the wrapped KWP key and the wrapped target key. + combined := append(wrappedWrappingKey, wrappedTarget...) + return combined, nil + +} + +type ecPrivateKey struct { + Version int + PrivateKey []byte + NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"` + PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"` +} + type publicKeyInfo struct { Raw asn1.RawContent Algorithm pkix.AlgorithmIdentifier PublicKey asn1.BitString } +type pkcs8 struct { + Version int + Algo pkix.AlgorithmIdentifier + PrivateKey []byte + // optional attributes omitted. +} func (g *GCPKMS) Sign(ctx context.Context, tx *types.Transaction) error { - // TODO we might need to set a version as a parameter - name := fmt.Sprintf("projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/%d", *inputSignerOpts.gcpProjectID, *inputSignerOpts.gcpRegion, *inputSignerOpts.gcpKeyRingID, *inputSignerOpts.keyID, 1) + name := fmt.Sprintf("projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/%d", *inputSignerOpts.gcpProjectID, *inputSignerOpts.gcpRegion, *inputSignerOpts.gcpKeyRingID, *inputSignerOpts.keyID, *inputSignerOpts.gcpKeyVersion) client, err := kms.NewKeyManagementClient(ctx) if err != nil { @@ -518,11 +738,17 @@ func getKeystorePassword() (string, error) { } func sanityCheck(cmd *cobra.Command, args []string) error { + // Strip off the 0x if it's included in the private key hex + *inputSignerOpts.privateKey = strings.TrimPrefix(*inputSignerOpts.privateKey, "0x") + + // normalize the format of the kms argument + *inputSignerOpts.kms = strings.ToUpper(*inputSignerOpts.kms) + keyStoreMethods := 0 if *inputSignerOpts.kms != "" { keyStoreMethods += 1 } - if *inputSignerOpts.privateKey != "" { + if *inputSignerOpts.privateKey != "" && cmd.Name() != "import" { keyStoreMethods += 1 } if *inputSignerOpts.keystore != "" { @@ -552,6 +778,7 @@ func sanityCheck(cmd *cobra.Command, args []string) error { return fmt.Errorf("a key id is required") } } + return nil } @@ -586,6 +813,11 @@ func getSigner() (types.Signer, error) { } func init() { + SignerCmd.AddCommand(SignCmd) + SignerCmd.AddCommand(CreateCmd) + SignerCmd.AddCommand(ListCmd) + SignerCmd.AddCommand(ImportCmd) + inputSignerOpts.keystore = SignerCmd.PersistentFlags().String("keystore", "", "Use the keystore in the given folder or file") inputSignerOpts.privateKey = SignerCmd.PersistentFlags().String("private-key", "", "Use the provided hex encoded private key") inputSignerOpts.kms = SignerCmd.PersistentFlags().String("kms", "", "AWS or GCP if the key is stored in the cloud") @@ -602,12 +834,6 @@ func init() { inputSignerOpts.gcpRegion = SignerCmd.PersistentFlags().String("gcp-location", "europe-west2", "The GCP Region to use") // What is dead may never die https://cloud.google.com/kms/docs/faq#cannot_delete inputSignerOpts.gcpKeyRingID = SignerCmd.PersistentFlags().String("gcp-keyring-id", "polycli-keyring", "The GCP Keyring ID to be used") - - kmsOpt := *inputSignerOpts.kms - kmsOpt = strings.ToUpper(kmsOpt) - inputSignerOpts.kms = &kmsOpt - - SignerCmd.AddCommand(SignCmd) - SignerCmd.AddCommand(CreateCmd) - SignerCmd.AddCommand(ListCmd) + inputSignerOpts.gcpImportJob = SignerCmd.PersistentFlags().String("gcp-import-job-id", "", "The GCP Import Job ID to use when importing a key") + inputSignerOpts.gcpKeyVersion = SignerCmd.PersistentFlags().Int("gcp-key-version", 1, "The GCP crypto key version to use") } diff --git a/doc/polycli_signer.md b/doc/polycli_signer.md index 6873de4a..1d0a823e 100644 --- a/doc/polycli_signer.md +++ b/doc/polycli_signer.md @@ -134,18 +134,20 @@ polycli signer sign --kms GCP --gcp-project-id prj-polygonlabs-devtools-dev --ke ## Flags ```bash - --chain-id uint The chain id for the transactions. - --data-file string File name holding data to be signed - --gcp-keyring-id string The GCP Keyring ID to be used (default "polycli-keyring") - --gcp-location string The GCP Region to use (default "europe-west2") - --gcp-project-id string The GCP Project ID to use - -h, --help help for signer - --key-id string The id of the key to be used for signing - --keystore string Use the keystore in the given folder or file - --kms string AWS or GCP if the key is stored in the cloud - --private-key string Use the provided hex encoded private key - --type string The type of signer to use: latest, cancun, london, eip2930, eip155 (default "london") - --unsafe-password string A non-interactively specified password for unlocking the keystore + --chain-id uint The chain id for the transactions. + --data-file string File name holding data to be signed + --gcp-import-job-id string The GCP Import Job ID to use when importing a key + --gcp-key-version int The GCP crypto key version to use (default 1) + --gcp-keyring-id string The GCP Keyring ID to be used (default "polycli-keyring") + --gcp-location string The GCP Region to use (default "europe-west2") + --gcp-project-id string The GCP Project ID to use + -h, --help help for signer + --key-id string The id of the key to be used for signing + --keystore string Use the keystore in the given folder or file + --kms string AWS or GCP if the key is stored in the cloud + --private-key string Use the provided hex encoded private key + --type string The type of signer to use: latest, cancun, london, eip2930, eip155 (default "london") + --unsafe-password string A non-interactively specified password for unlocking the keystore ``` The command also inherits flags from parent commands. @@ -167,6 +169,8 @@ The command also inherits flags from parent commands. - [polycli](polycli.md) - A Swiss Army knife of blockchain tools. - [polycli signer create](polycli_signer_create.md) - Create a new key +- [polycli signer import](polycli_signer_import.md) - Import a private key into the keyring / keystore + - [polycli signer list](polycli_signer_list.md) - List the keys in the keyring / keystore - [polycli signer sign](polycli_signer_sign.md) - Sign tx data diff --git a/doc/polycli_signer_create.md b/doc/polycli_signer_create.md index b18c67bf..4900f439 100644 --- a/doc/polycli_signer_create.md +++ b/doc/polycli_signer_create.md @@ -144,26 +144,28 @@ polycli signer sign --kms GCP --gcp-project-id prj-polygonlabs-devtools-dev --ke The command also inherits flags from parent commands. ```bash - --chain-id uint The chain id for the transactions. - --config string config file (default is $HOME/.polygon-cli.yaml) - --data-file string File name holding data to be signed - --gcp-keyring-id string The GCP Keyring ID to be used (default "polycli-keyring") - --gcp-location string The GCP Region to use (default "europe-west2") - --gcp-project-id string The GCP Project ID to use - --key-id string The id of the key to be used for signing - --keystore string Use the keystore in the given folder or file - --kms string AWS or GCP if the key is stored in the cloud - --pretty-logs Should logs be in pretty format or JSON (default true) - --private-key string Use the provided hex encoded private key - --type string The type of signer to use: latest, cancun, london, eip2930, eip155 (default "london") - --unsafe-password string A non-interactively specified password for unlocking the keystore - -v, --verbosity int 0 - Silent - 100 Fatal - 200 Error - 300 Warning - 400 Info - 500 Debug - 600 Trace (default 400) + --chain-id uint The chain id for the transactions. + --config string config file (default is $HOME/.polygon-cli.yaml) + --data-file string File name holding data to be signed + --gcp-import-job-id string The GCP Import Job ID to use when importing a key + --gcp-key-version int The GCP crypto key version to use (default 1) + --gcp-keyring-id string The GCP Keyring ID to be used (default "polycli-keyring") + --gcp-location string The GCP Region to use (default "europe-west2") + --gcp-project-id string The GCP Project ID to use + --key-id string The id of the key to be used for signing + --keystore string Use the keystore in the given folder or file + --kms string AWS or GCP if the key is stored in the cloud + --pretty-logs Should logs be in pretty format or JSON (default true) + --private-key string Use the provided hex encoded private key + --type string The type of signer to use: latest, cancun, london, eip2930, eip155 (default "london") + --unsafe-password string A non-interactively specified password for unlocking the keystore + -v, --verbosity int 0 - Silent + 100 Fatal + 200 Error + 300 Warning + 400 Info + 500 Debug + 600 Trace (default 400) ``` ## See also diff --git a/doc/polycli_signer_import.md b/doc/polycli_signer_import.md new file mode 100644 index 00000000..e103a693 --- /dev/null +++ b/doc/polycli_signer_import.md @@ -0,0 +1,173 @@ +# `polycli signer import` + +> Auto-generated documentation. + +## Table of Contents + +- [Description](#description) +- [Usage](#usage) +- [Flags](#flags) +- [See Also](#see-also) + +## Description + +Import a private key into the keyring / keystore + +```bash +polycli signer import [flags] +``` + +## Usage + +This command is meant to allow for easy creation of signed transactions. A raw transaction can then be published with a call to +[`eth_sendRawTransaction`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendrawtransaction) or using [`cast publish`](https://book.getfoundry.sh/reference/cast/cast-publish). + +## Creating Keys + +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 +``` + +## Listing Keys + +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 +``` + +## Signing + +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/go-ethereum@v1.13.7/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 +``` + +## Flags + +```bash + -h, --help help for import +``` + +The command also inherits flags from parent commands. + +```bash + --chain-id uint The chain id for the transactions. + --config string config file (default is $HOME/.polygon-cli.yaml) + --data-file string File name holding data to be signed + --gcp-import-job-id string The GCP Import Job ID to use when importing a key + --gcp-key-version int The GCP crypto key version to use (default 1) + --gcp-keyring-id string The GCP Keyring ID to be used (default "polycli-keyring") + --gcp-location string The GCP Region to use (default "europe-west2") + --gcp-project-id string The GCP Project ID to use + --key-id string The id of the key to be used for signing + --keystore string Use the keystore in the given folder or file + --kms string AWS or GCP if the key is stored in the cloud + --pretty-logs Should logs be in pretty format or JSON (default true) + --private-key string Use the provided hex encoded private key + --type string The type of signer to use: latest, cancun, london, eip2930, eip155 (default "london") + --unsafe-password string A non-interactively specified password for unlocking the keystore + -v, --verbosity int 0 - Silent + 100 Fatal + 200 Error + 300 Warning + 400 Info + 500 Debug + 600 Trace (default 400) +``` + +## See also + +- [polycli signer](polycli_signer.md) - Utilities for security signing transactions diff --git a/doc/polycli_signer_list.md b/doc/polycli_signer_list.md index 3c3829bd..cb5a4609 100644 --- a/doc/polycli_signer_list.md +++ b/doc/polycli_signer_list.md @@ -144,26 +144,28 @@ polycli signer sign --kms GCP --gcp-project-id prj-polygonlabs-devtools-dev --ke The command also inherits flags from parent commands. ```bash - --chain-id uint The chain id for the transactions. - --config string config file (default is $HOME/.polygon-cli.yaml) - --data-file string File name holding data to be signed - --gcp-keyring-id string The GCP Keyring ID to be used (default "polycli-keyring") - --gcp-location string The GCP Region to use (default "europe-west2") - --gcp-project-id string The GCP Project ID to use - --key-id string The id of the key to be used for signing - --keystore string Use the keystore in the given folder or file - --kms string AWS or GCP if the key is stored in the cloud - --pretty-logs Should logs be in pretty format or JSON (default true) - --private-key string Use the provided hex encoded private key - --type string The type of signer to use: latest, cancun, london, eip2930, eip155 (default "london") - --unsafe-password string A non-interactively specified password for unlocking the keystore - -v, --verbosity int 0 - Silent - 100 Fatal - 200 Error - 300 Warning - 400 Info - 500 Debug - 600 Trace (default 400) + --chain-id uint The chain id for the transactions. + --config string config file (default is $HOME/.polygon-cli.yaml) + --data-file string File name holding data to be signed + --gcp-import-job-id string The GCP Import Job ID to use when importing a key + --gcp-key-version int The GCP crypto key version to use (default 1) + --gcp-keyring-id string The GCP Keyring ID to be used (default "polycli-keyring") + --gcp-location string The GCP Region to use (default "europe-west2") + --gcp-project-id string The GCP Project ID to use + --key-id string The id of the key to be used for signing + --keystore string Use the keystore in the given folder or file + --kms string AWS or GCP if the key is stored in the cloud + --pretty-logs Should logs be in pretty format or JSON (default true) + --private-key string Use the provided hex encoded private key + --type string The type of signer to use: latest, cancun, london, eip2930, eip155 (default "london") + --unsafe-password string A non-interactively specified password for unlocking the keystore + -v, --verbosity int 0 - Silent + 100 Fatal + 200 Error + 300 Warning + 400 Info + 500 Debug + 600 Trace (default 400) ``` ## See also diff --git a/doc/polycli_signer_sign.md b/doc/polycli_signer_sign.md index a890a034..f136bfa2 100644 --- a/doc/polycli_signer_sign.md +++ b/doc/polycli_signer_sign.md @@ -144,26 +144,28 @@ polycli signer sign --kms GCP --gcp-project-id prj-polygonlabs-devtools-dev --ke The command also inherits flags from parent commands. ```bash - --chain-id uint The chain id for the transactions. - --config string config file (default is $HOME/.polygon-cli.yaml) - --data-file string File name holding data to be signed - --gcp-keyring-id string The GCP Keyring ID to be used (default "polycli-keyring") - --gcp-location string The GCP Region to use (default "europe-west2") - --gcp-project-id string The GCP Project ID to use - --key-id string The id of the key to be used for signing - --keystore string Use the keystore in the given folder or file - --kms string AWS or GCP if the key is stored in the cloud - --pretty-logs Should logs be in pretty format or JSON (default true) - --private-key string Use the provided hex encoded private key - --type string The type of signer to use: latest, cancun, london, eip2930, eip155 (default "london") - --unsafe-password string A non-interactively specified password for unlocking the keystore - -v, --verbosity int 0 - Silent - 100 Fatal - 200 Error - 300 Warning - 400 Info - 500 Debug - 600 Trace (default 400) + --chain-id uint The chain id for the transactions. + --config string config file (default is $HOME/.polygon-cli.yaml) + --data-file string File name holding data to be signed + --gcp-import-job-id string The GCP Import Job ID to use when importing a key + --gcp-key-version int The GCP crypto key version to use (default 1) + --gcp-keyring-id string The GCP Keyring ID to be used (default "polycli-keyring") + --gcp-location string The GCP Region to use (default "europe-west2") + --gcp-project-id string The GCP Project ID to use + --key-id string The id of the key to be used for signing + --keystore string Use the keystore in the given folder or file + --kms string AWS or GCP if the key is stored in the cloud + --pretty-logs Should logs be in pretty format or JSON (default true) + --private-key string Use the provided hex encoded private key + --type string The type of signer to use: latest, cancun, london, eip2930, eip155 (default "london") + --unsafe-password string A non-interactively specified password for unlocking the keystore + -v, --verbosity int 0 - Silent + 100 Fatal + 200 Error + 300 Warning + 400 Info + 500 Debug + 600 Trace (default 400) ``` ## See also diff --git a/go.mod b/go.mod index 14883fb0..901f647b 100644 --- a/go.mod +++ b/go.mod @@ -151,4 +151,7 @@ require ( require cloud.google.com/go/kms v1.15.5 -require cloud.google.com/go/iam v1.1.3 // indirect +require ( + cloud.google.com/go/iam v1.1.3 // indirect + github.com/google/tink/go v1.7.0 // indirect +) diff --git a/go.sum b/go.sum index 8d46e5a1..9d82b622 100644 --- a/go.sum +++ b/go.sum @@ -242,6 +242,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/tink/go v1.7.0 h1:6Eox8zONGebBFcCBqkVmt60LaWZa6xg1cl/DwAh/J1w= +github.com/google/tink/go v1.7.0/go.mod h1:GAUOd+QE3pgj9q8VKIGTCP33c/B7eb4NhxLcgTJZStM= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=