code.vegaprotocol.io/vega@v0.79.0/cmd/vegawallet/commands/message_verify.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package cmd 17 18 import ( 19 "context" 20 "encoding/base64" 21 "errors" 22 "fmt" 23 "io" 24 "os" 25 26 "code.vegaprotocol.io/vega/cmd/vegawallet/commands/cli" 27 "code.vegaprotocol.io/vega/cmd/vegawallet/commands/flags" 28 "code.vegaprotocol.io/vega/cmd/vegawallet/commands/printer" 29 "code.vegaprotocol.io/vega/wallet/api" 30 31 "github.com/spf13/cobra" 32 ) 33 34 var ( 35 verifyMessageLong = cli.LongDesc(` 36 Verify a message against a signature. 37 38 The signature has to be generated by Ed25519 cryptographic algorithm. 39 `) 40 41 verifyMessageExample = cli.Examples(` 42 # Verify the signature of a message 43 {{.Software}} message verify --message MESSAGE --signature SIGNATURE --pubkey PUBKEY 44 `) 45 ) 46 47 type VerifyMessageHandler func(api.AdminVerifyMessageParams) (api.AdminVerifyMessageResult, error) 48 49 func NewCmdVerifyMessage(w io.Writer, rf *RootFlags) *cobra.Command { 50 h := func(params api.AdminVerifyMessageParams) (api.AdminVerifyMessageResult, error) { 51 verifyMessage := api.NewAdminVerifyMessage() 52 rawResult, errorDetails := verifyMessage.Handle(context.Background(), params) 53 if errorDetails != nil { 54 return api.AdminVerifyMessageResult{}, errors.New(errorDetails.Data) 55 } 56 return rawResult.(api.AdminVerifyMessageResult), nil 57 } 58 return BuildCmdVerifyMessage(w, h, rf) 59 } 60 61 func BuildCmdVerifyMessage(w io.Writer, handler VerifyMessageHandler, rf *RootFlags) *cobra.Command { 62 f := &VerifyMessageFlags{} 63 64 cmd := &cobra.Command{ 65 Use: "verify", 66 Short: "Verify a message against a signature", 67 Long: verifyMessageLong, 68 Example: verifyMessageExample, 69 RunE: func(_ *cobra.Command, _ []string) error { 70 req, err := f.Validate() 71 if err != nil { 72 return err 73 } 74 75 resp, err := handler(req) 76 if err != nil { 77 return err 78 } 79 80 switch rf.Output { 81 case flags.InteractiveOutput: 82 PrintVerifyMessageResponse(w, resp.IsValid) 83 case flags.JSONOutput: 84 return printer.FprintJSON(w, struct { 85 IsValid bool `json:"isValid"` 86 }{ 87 IsValid: resp.IsValid, 88 }) 89 } 90 91 return nil 92 }, 93 } 94 95 cmd.Flags().StringVarP(&f.PubKey, 96 "pubkey", "k", 97 "", 98 "Public key associated to the signature (hex-encoded)", 99 ) 100 cmd.Flags().StringVarP(&f.Message, 101 "message", "m", 102 "", 103 "Message to be verified (base64-encoded)", 104 ) 105 cmd.Flags().StringVarP(&f.Signature, 106 "signature", "s", 107 "", 108 "Signature of the message (base64-encoded)", 109 ) 110 111 return cmd 112 } 113 114 type VerifyMessageFlags struct { 115 Signature string 116 Message string 117 PubKey string 118 } 119 120 func (f *VerifyMessageFlags) Validate() (api.AdminVerifyMessageParams, error) { 121 req := api.AdminVerifyMessageParams{} 122 123 if len(f.PubKey) == 0 { 124 return api.AdminVerifyMessageParams{}, flags.MustBeSpecifiedError("pubkey") 125 } 126 req.PublicKey = f.PubKey 127 128 if len(f.Signature) == 0 { 129 return api.AdminVerifyMessageParams{}, flags.MustBeSpecifiedError("signature") 130 } 131 _, err := base64.StdEncoding.DecodeString(f.Signature) 132 if err != nil { 133 return api.AdminVerifyMessageParams{}, flags.MustBase64EncodedError("signature") 134 } 135 req.EncodedSignature = f.Signature 136 137 if len(f.Message) == 0 { 138 return api.AdminVerifyMessageParams{}, flags.MustBeSpecifiedError("message") 139 } 140 _, err = base64.StdEncoding.DecodeString(f.Message) 141 if err != nil { 142 return api.AdminVerifyMessageParams{}, flags.MustBase64EncodedError("message") 143 } 144 req.EncodedMessage = f.Message 145 146 return req, nil 147 } 148 149 func PrintVerifyMessageResponse(w io.Writer, isValid bool) { 150 p := printer.NewInteractivePrinter(w) 151 152 str := p.String() 153 defer p.Print(str) 154 155 if isValid { 156 str.CheckMark().SuccessText("Valid signature").NextSection() 157 } else { 158 str.CrossMark().DangerText("Invalid signature").NextSection() 159 } 160 161 str.BlueArrow().InfoText("Sign a message").NextLine() 162 str.Text("To sign a message, see the following command:").NextSection() 163 str.Code(fmt.Sprintf("%s sign --help", os.Args[0])).NextLine() 164 }