github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/cmd/ethkey/message.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2017 Go Ethereum作者 10 //此文件是Go以太坊的一部分。 11 // 12 //Go以太坊是免费软件:您可以重新发布和/或修改它 13 //根据GNU通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊的分布希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU通用公共许可证了解更多详细信息。 21 // 22 //你应该已经收到一份GNU通用公共许可证的副本 23 //一起去以太坊吧。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package main 26 27 import ( 28 "encoding/hex" 29 "fmt" 30 "io/ioutil" 31 32 "github.com/ethereum/go-ethereum/accounts/keystore" 33 "github.com/ethereum/go-ethereum/cmd/utils" 34 "github.com/ethereum/go-ethereum/common" 35 "github.com/ethereum/go-ethereum/crypto" 36 "gopkg.in/urfave/cli.v1" 37 ) 38 39 type outputSign struct { 40 Signature string 41 } 42 43 var msgfileFlag = cli.StringFlag{ 44 Name: "msgfile", 45 Usage: "file containing the message to sign/verify", 46 } 47 48 var commandSignMessage = cli.Command{ 49 Name: "signmessage", 50 Usage: "sign a message", 51 ArgsUsage: "<keyfile> <message>", 52 Description: ` 53 Sign the message with a keyfile. 54 55 To sign a message contained in a file, use the --msgfile flag. 56 `, 57 Flags: []cli.Flag{ 58 passphraseFlag, 59 jsonFlag, 60 msgfileFlag, 61 }, 62 Action: func(ctx *cli.Context) error { 63 message := getMessage(ctx, 1) 64 65 //加载密钥文件。 66 keyfilepath := ctx.Args().First() 67 keyjson, err := ioutil.ReadFile(keyfilepath) 68 if err != nil { 69 utils.Fatalf("Failed to read the keyfile at '%s': %v", keyfilepath, err) 70 } 71 72 //用密码短语解密密钥。 73 passphrase := getPassphrase(ctx) 74 key, err := keystore.DecryptKey(keyjson, passphrase) 75 if err != nil { 76 utils.Fatalf("Error decrypting key: %v", err) 77 } 78 79 signature, err := crypto.Sign(signHash(message), key.PrivateKey) 80 if err != nil { 81 utils.Fatalf("Failed to sign message: %v", err) 82 } 83 out := outputSign{Signature: hex.EncodeToString(signature)} 84 if ctx.Bool(jsonFlag.Name) { 85 mustPrintJSON(out) 86 } else { 87 fmt.Println("Signature:", out.Signature) 88 } 89 return nil 90 }, 91 } 92 93 type outputVerify struct { 94 Success bool 95 RecoveredAddress string 96 RecoveredPublicKey string 97 } 98 99 var commandVerifyMessage = cli.Command{ 100 Name: "verifymessage", 101 Usage: "verify the signature of a signed message", 102 ArgsUsage: "<address> <signature> <message>", 103 Description: ` 104 Verify the signature of the message. 105 It is possible to refer to a file containing the message.`, 106 Flags: []cli.Flag{ 107 jsonFlag, 108 msgfileFlag, 109 }, 110 Action: func(ctx *cli.Context) error { 111 addressStr := ctx.Args().First() 112 signatureHex := ctx.Args().Get(1) 113 message := getMessage(ctx, 2) 114 115 if !common.IsHexAddress(addressStr) { 116 utils.Fatalf("Invalid address: %s", addressStr) 117 } 118 address := common.HexToAddress(addressStr) 119 signature, err := hex.DecodeString(signatureHex) 120 if err != nil { 121 utils.Fatalf("Signature encoding is not hexadecimal: %v", err) 122 } 123 124 recoveredPubkey, err := crypto.SigToPub(signHash(message), signature) 125 if err != nil || recoveredPubkey == nil { 126 utils.Fatalf("Signature verification failed: %v", err) 127 } 128 recoveredPubkeyBytes := crypto.FromECDSAPub(recoveredPubkey) 129 recoveredAddress := crypto.PubkeyToAddress(*recoveredPubkey) 130 success := address == recoveredAddress 131 132 out := outputVerify{ 133 Success: success, 134 RecoveredPublicKey: hex.EncodeToString(recoveredPubkeyBytes), 135 RecoveredAddress: recoveredAddress.Hex(), 136 } 137 if ctx.Bool(jsonFlag.Name) { 138 mustPrintJSON(out) 139 } else { 140 if out.Success { 141 fmt.Println("Signature verification successful!") 142 } else { 143 fmt.Println("Signature verification failed!") 144 } 145 fmt.Println("Recovered public key:", out.RecoveredPublicKey) 146 fmt.Println("Recovered address:", out.RecoveredAddress) 147 } 148 return nil 149 }, 150 } 151 152 func getMessage(ctx *cli.Context, msgarg int) []byte { 153 if file := ctx.String("msgfile"); file != "" { 154 if len(ctx.Args()) > msgarg { 155 utils.Fatalf("Can't use --msgfile and message argument at the same time.") 156 } 157 msg, err := ioutil.ReadFile(file) 158 if err != nil { 159 utils.Fatalf("Can't read message file: %v", err) 160 } 161 return msg 162 } else if len(ctx.Args()) == msgarg+1 { 163 return []byte(ctx.Args().Get(msgarg)) 164 } 165 utils.Fatalf("Invalid number of arguments: want %d, got %d", msgarg+1, len(ctx.Args())) 166 return nil 167 }