github.com/theQRL/go-zond@v0.2.1/cmd/zondkey/message.go (about)

     1  // Copyright 2017 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // go-ethereum is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package main
    18  
    19  import (
    20  	"encoding/hex"
    21  	"fmt"
    22  	"os"
    23  
    24  	"github.com/theQRL/go-qrllib/dilithium"
    25  	"github.com/theQRL/go-zond/accounts"
    26  	"github.com/theQRL/go-zond/accounts/keystore"
    27  	"github.com/theQRL/go-zond/cmd/utils"
    28  	"github.com/theQRL/go-zond/common"
    29  	"github.com/theQRL/go-zond/crypto/pqcrypto"
    30  	"github.com/urfave/cli/v2"
    31  )
    32  
    33  type outputSign struct {
    34  	Signature string
    35  }
    36  
    37  var msgfileFlag = &cli.StringFlag{
    38  	Name:  "msgfile",
    39  	Usage: "file containing the message to sign/verify",
    40  }
    41  
    42  var commandSignMessage = &cli.Command{
    43  	Name:      "signmessage",
    44  	Usage:     "sign a message",
    45  	ArgsUsage: "<keyfile> <message>",
    46  	Description: `
    47  Sign the message with a keyfile.
    48  
    49  To sign a message contained in a file, use the --msgfile flag.
    50  `,
    51  	Flags: []cli.Flag{
    52  		passphraseFlag,
    53  		jsonFlag,
    54  		msgfileFlag,
    55  	},
    56  	Action: func(ctx *cli.Context) error {
    57  		message := getMessage(ctx, 1)
    58  
    59  		// Load the keyfile.
    60  		keyfilepath := ctx.Args().First()
    61  		keyjson, err := os.ReadFile(keyfilepath)
    62  		if err != nil {
    63  			utils.Fatalf("Failed to read the keyfile at '%s': %v", keyfilepath, err)
    64  		}
    65  
    66  		// Decrypt key with passphrase.
    67  		passphrase := getPassphrase(ctx, false)
    68  		key, err := keystore.DecryptKey(keyjson, passphrase)
    69  		if err != nil {
    70  			utils.Fatalf("Error decrypting key: %v", err)
    71  		}
    72  
    73  		signature, err := pqcrypto.Sign(accounts.TextHash(message), key.Dilithium)
    74  		if err != nil {
    75  			utils.Fatalf("Failed to sign message: %v", err)
    76  		}
    77  		out := outputSign{Signature: hex.EncodeToString(signature)}
    78  		if ctx.Bool(jsonFlag.Name) {
    79  			mustPrintJSON(out)
    80  		} else {
    81  			fmt.Println("Signature:", out.Signature)
    82  		}
    83  
    84  		return nil
    85  	},
    86  }
    87  
    88  type outputVerify struct {
    89  	Success bool
    90  }
    91  
    92  // TODO(now.youtrack.cloud/issue/TGZ-3)
    93  var commandVerifyMessage = &cli.Command{
    94  	Name:      "verifymessage",
    95  	Usage:     "verify the signature of a signed message",
    96  	ArgsUsage: "<signature> <publickey> <message>",
    97  	Description: `
    98  Verify the signature of the message.
    99  It is possible to refer to a file containing the message.`,
   100  	Flags: []cli.Flag{
   101  		jsonFlag,
   102  		msgfileFlag,
   103  	},
   104  	Action: func(ctx *cli.Context) error {
   105  		signatureHex := ctx.Args().First()
   106  		pubKeyHex := ctx.Args().Get(1)
   107  		message := getMessage(ctx, 2)
   108  
   109  		signature := common.FromHex(signatureHex)
   110  		publicKey := common.FromHex(pubKeyHex)
   111  
   112  		dilithiumPublicKey := [2592]uint8(publicKey)
   113  		out := outputVerify{
   114  			Success: dilithium.Verify(accounts.TextHash(message), [4595]uint8(signature), &dilithiumPublicKey),
   115  		}
   116  		if ctx.Bool(jsonFlag.Name) {
   117  			mustPrintJSON(out)
   118  		} else {
   119  			if out.Success {
   120  				fmt.Println("Signature verification successful!")
   121  			} else {
   122  				fmt.Println("Signature verification failed!")
   123  			}
   124  		}
   125  		return nil
   126  	},
   127  }
   128  
   129  func getMessage(ctx *cli.Context, msgarg int) []byte {
   130  	if file := ctx.String(msgfileFlag.Name); file != "" {
   131  		if ctx.NArg() > msgarg {
   132  			utils.Fatalf("Can't use --msgfile and message argument at the same time.")
   133  		}
   134  		msg, err := os.ReadFile(file)
   135  		if err != nil {
   136  			utils.Fatalf("Can't read message file: %v", err)
   137  		}
   138  		return msg
   139  	} else if ctx.NArg() == msgarg+1 {
   140  		return []byte(ctx.Args().Get(msgarg))
   141  	}
   142  	utils.Fatalf("Invalid number of arguments: want %d, got %d", msgarg+1, ctx.NArg())
   143  	return nil
   144  }