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