github.com/iotexproject/iotex-core@v1.14.1-rc1/ioctl/newcmd/did/didgenerate.go (about)

     1  // Copyright (c) 2022 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package did
     7  
     8  import (
     9  	"crypto/sha256"
    10  	"encoding/hex"
    11  	"encoding/json"
    12  
    13  	"github.com/pkg/errors"
    14  	"github.com/spf13/cobra"
    15  
    16  	"github.com/iotexproject/iotex-core/ioctl"
    17  	"github.com/iotexproject/iotex-core/ioctl/config"
    18  	"github.com/iotexproject/iotex-core/ioctl/newcmd/account"
    19  	"github.com/iotexproject/iotex-core/ioctl/newcmd/action"
    20  	"github.com/iotexproject/iotex-core/pkg/util/addrutil"
    21  )
    22  
    23  // Multi-language support
    24  var (
    25  	_generateCmdShorts = map[config.Language]string{
    26  		config.English: "Generate DID document using private key from wallet",
    27  		config.Chinese: "用钱包中的私钥产生DID document",
    28  	}
    29  	_generateCmdUses = map[config.Language]string{
    30  		config.English: "generate [-s SIGNER]",
    31  		config.Chinese: "generate [-s 签署人]",
    32  	}
    33  )
    34  
    35  // NewDidGenerateCmd represents the did generate command
    36  func NewDidGenerateCmd(client ioctl.Client) *cobra.Command {
    37  	use, _ := client.SelectTranslation(_generateCmdUses)
    38  	short, _ := client.SelectTranslation(_generateCmdShorts)
    39  
    40  	cmd := &cobra.Command{
    41  		Use:   use,
    42  		Short: short,
    43  		Args:  cobra.ExactArgs(0),
    44  		RunE: func(cmd *cobra.Command, args []string) error {
    45  			cmd.SilenceUsage = true
    46  			signer, err := cmd.Flags().GetString("signer")
    47  			if err != nil {
    48  				return errors.Wrap(err, "failed to get flag signer")
    49  			}
    50  			addr, err := action.Signer(client, signer)
    51  			if err != nil {
    52  				return errors.Wrap(err, "failed to get signer addr")
    53  			}
    54  			cmd.Printf("Enter password #%s:\n", addr)
    55  			password, err := client.ReadSecret()
    56  			if err != nil {
    57  				return errors.Wrap(err, "failed to get password")
    58  			}
    59  			pri, err := account.PrivateKeyFromSigner(client, cmd, addr, password)
    60  			if err != nil {
    61  				return errors.Wrap(err, "failed to get private key from signer")
    62  			}
    63  			doc := newDIDDoc()
    64  			ethAddress, err := addrutil.IoAddrToEvmAddr(addr)
    65  			if err != nil {
    66  				return errors.Wrap(err, "failed to convert IoTeX address to EVM address")
    67  			}
    68  			doc.ID = DIDPrefix + ethAddress.String()
    69  			authentication := authenticationStruct{
    70  				ID:         doc.ID + DIDOwner,
    71  				Type:       DIDAuthType,
    72  				Controller: doc.ID,
    73  			}
    74  			uncompressed := pri.PublicKey().Bytes()
    75  			if len(uncompressed) == 33 && (uncompressed[0] == 2 || uncompressed[0] == 3) {
    76  				authentication.PublicKeyHex = hex.EncodeToString(uncompressed)
    77  			} else if len(uncompressed) == 65 && uncompressed[0] == 4 {
    78  				lastNum := uncompressed[64]
    79  				authentication.PublicKeyHex = hex.EncodeToString(uncompressed[1:33])
    80  				if lastNum%2 == 0 {
    81  					authentication.PublicKeyHex = "02" + authentication.PublicKeyHex
    82  				} else {
    83  					authentication.PublicKeyHex = "03" + authentication.PublicKeyHex
    84  				}
    85  			} else {
    86  				return errors.New("invalid public key")
    87  			}
    88  
    89  			doc.Authentication = append(doc.Authentication, authentication)
    90  			msg, err := json.MarshalIndent(doc, "", "  ")
    91  			if err != nil {
    92  				return err
    93  			}
    94  
    95  			sum := sha256.Sum256(msg)
    96  			cmd.Printf("%s\n\nThe hex encoded SHA256 hash of the DID doc is:%s\n", string(msg), hex.EncodeToString(sum[:]))
    97  			return nil
    98  		},
    99  	}
   100  	action.RegisterWriteCommand(client, cmd)
   101  	return cmd
   102  }