github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/cmd/ethkey/message.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:27</date> 10 //</624342589478277120> 11 12 13 package main 14 15 import ( 16 "encoding/hex" 17 "fmt" 18 "io/ioutil" 19 20 "github.com/ethereum/go-ethereum/accounts/keystore" 21 "github.com/ethereum/go-ethereum/cmd/utils" 22 "github.com/ethereum/go-ethereum/common" 23 "github.com/ethereum/go-ethereum/crypto" 24 "gopkg.in/urfave/cli.v1" 25 ) 26 27 type outputSign struct { 28 Signature string 29 } 30 31 var msgfileFlag = cli.StringFlag{ 32 Name: "msgfile", 33 Usage: "file containing the message to sign/verify", 34 } 35 36 var commandSignMessage = cli.Command{ 37 Name: "signmessage", 38 Usage: "sign a message", 39 ArgsUsage: "<keyfile> <message>", 40 Description: ` 41 Sign the message with a keyfile. 42 43 To sign a message contained in a file, use the --msgfile flag. 44 `, 45 Flags: []cli.Flag{ 46 passphraseFlag, 47 jsonFlag, 48 msgfileFlag, 49 }, 50 Action: func(ctx *cli.Context) error { 51 message := getMessage(ctx, 1) 52 53 //加载密钥文件。 54 keyfilepath := ctx.Args().First() 55 keyjson, err := ioutil.ReadFile(keyfilepath) 56 if err != nil { 57 utils.Fatalf("Failed to read the keyfile at '%s': %v", keyfilepath, err) 58 } 59 60 //用密码短语解密密钥。 61 passphrase := getPassphrase(ctx) 62 key, err := keystore.DecryptKey(keyjson, passphrase) 63 if err != nil { 64 utils.Fatalf("Error decrypting key: %v", err) 65 } 66 67 signature, err := crypto.Sign(signHash(message), key.PrivateKey) 68 if err != nil { 69 utils.Fatalf("Failed to sign message: %v", err) 70 } 71 out := outputSign{Signature: hex.EncodeToString(signature)} 72 if ctx.Bool(jsonFlag.Name) { 73 mustPrintJSON(out) 74 } else { 75 fmt.Println("Signature:", out.Signature) 76 } 77 return nil 78 }, 79 } 80 81 type outputVerify struct { 82 Success bool 83 RecoveredAddress string 84 RecoveredPublicKey string 85 } 86 87 var commandVerifyMessage = cli.Command{ 88 Name: "verifymessage", 89 Usage: "verify the signature of a signed message", 90 ArgsUsage: "<address> <signature> <message>", 91 Description: ` 92 Verify the signature of the message. 93 It is possible to refer to a file containing the message.`, 94 Flags: []cli.Flag{ 95 jsonFlag, 96 msgfileFlag, 97 }, 98 Action: func(ctx *cli.Context) error { 99 addressStr := ctx.Args().First() 100 signatureHex := ctx.Args().Get(1) 101 message := getMessage(ctx, 2) 102 103 if !common.IsHexAddress(addressStr) { 104 utils.Fatalf("Invalid address: %s", addressStr) 105 } 106 address := common.HexToAddress(addressStr) 107 signature, err := hex.DecodeString(signatureHex) 108 if err != nil { 109 utils.Fatalf("Signature encoding is not hexadecimal: %v", err) 110 } 111 112 recoveredPubkey, err := crypto.SigToPub(signHash(message), signature) 113 if err != nil || recoveredPubkey == nil { 114 utils.Fatalf("Signature verification failed: %v", err) 115 } 116 recoveredPubkeyBytes := crypto.FromECDSAPub(recoveredPubkey) 117 recoveredAddress := crypto.PubkeyToAddress(*recoveredPubkey) 118 success := address == recoveredAddress 119 120 out := outputVerify{ 121 Success: success, 122 RecoveredPublicKey: hex.EncodeToString(recoveredPubkeyBytes), 123 RecoveredAddress: recoveredAddress.Hex(), 124 } 125 if ctx.Bool(jsonFlag.Name) { 126 mustPrintJSON(out) 127 } else { 128 if out.Success { 129 fmt.Println("Signature verification successful!") 130 } else { 131 fmt.Println("Signature verification failed!") 132 } 133 fmt.Println("Recovered public key:", out.RecoveredPublicKey) 134 fmt.Println("Recovered address:", out.RecoveredAddress) 135 } 136 return nil 137 }, 138 } 139 140 func getMessage(ctx *cli.Context, msgarg int) []byte { 141 if file := ctx.String("msgfile"); file != "" { 142 if len(ctx.Args()) > msgarg { 143 utils.Fatalf("Can't use --msgfile and message argument at the same time.") 144 } 145 msg, err := ioutil.ReadFile(file) 146 if err != nil { 147 utils.Fatalf("Can't read message file: %v", err) 148 } 149 return msg 150 } else if len(ctx.Args()) == msgarg+1 { 151 return []byte(ctx.Args().Get(msgarg)) 152 } 153 utils.Fatalf("Invalid number of arguments: want %d, got %d", msgarg+1, len(ctx.Args())) 154 return nil 155 } 156