github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/crypto/keys/client/generate.go (about)

     1  package client
     2  
     3  import (
     4  	"context"
     5  	"crypto/sha256"
     6  	"flag"
     7  	"fmt"
     8  
     9  	"github.com/gnolang/gno/tm2/pkg/commands"
    10  	"github.com/gnolang/gno/tm2/pkg/crypto/bip39"
    11  )
    12  
    13  type GenerateCfg struct {
    14  	RootCfg *BaseCfg
    15  
    16  	CustomEntropy bool
    17  }
    18  
    19  func NewGenerateCmd(rootCfg *BaseCfg, io commands.IO) *commands.Command {
    20  	cfg := &GenerateCfg{
    21  		RootCfg: rootCfg,
    22  	}
    23  
    24  	return commands.NewCommand(
    25  		commands.Metadata{
    26  			Name:       "generate",
    27  			ShortUsage: "generate [flags]",
    28  			ShortHelp:  "generates a bip39 mnemonic",
    29  		},
    30  		cfg,
    31  		func(_ context.Context, args []string) error {
    32  			return execGenerate(cfg, args, io)
    33  		},
    34  	)
    35  }
    36  
    37  func (c *GenerateCfg) RegisterFlags(fs *flag.FlagSet) {
    38  	fs.BoolVar(
    39  		&c.CustomEntropy,
    40  		"entropy",
    41  		false,
    42  		"supply custom entropy",
    43  	)
    44  }
    45  
    46  func execGenerate(cfg *GenerateCfg, args []string, io commands.IO) error {
    47  	customEntropy := cfg.CustomEntropy
    48  
    49  	if len(args) != 0 {
    50  		return flag.ErrHelp
    51  	}
    52  
    53  	var entropySeed []byte
    54  
    55  	if customEntropy {
    56  		// prompt the user to enter some entropy
    57  		inputEntropy, err := io.GetString(
    58  			"WARNING: Generate at least 256-bits of entropy and enter the results here:",
    59  		)
    60  		if err != nil {
    61  			return err
    62  		}
    63  		if len(inputEntropy) < 43 {
    64  			return fmt.Errorf("256-bits is 43 characters in Base-64, and 100 in Base-6. You entered %v, and probably want more", len(inputEntropy))
    65  		}
    66  		conf, err := io.GetConfirmation(
    67  			fmt.Sprintf("Input length: %d", len(inputEntropy)),
    68  		)
    69  		if err != nil {
    70  			return err
    71  		}
    72  		if !conf {
    73  			return nil
    74  		}
    75  
    76  		// hash input entropy to get entropy seed
    77  		hashedEntropy := sha256.Sum256([]byte(inputEntropy))
    78  		entropySeed = hashedEntropy[:]
    79  	} else {
    80  		// read entropy seed straight from crypto.Rand
    81  		var err error
    82  		entropySeed, err = bip39.NewEntropy(mnemonicEntropySize)
    83  		if err != nil {
    84  			return err
    85  		}
    86  	}
    87  
    88  	mnemonic, err := bip39.NewMnemonic(entropySeed[:])
    89  	if err != nil {
    90  		return err
    91  	}
    92  
    93  	io.Println(mnemonic)
    94  
    95  	return nil
    96  }