github.com/mavryk-network/mvgo@v1.19.9/examples/key/main.go (about) 1 // Copyright (c) 2020-2021 Blockwatch Data Inc. 2 // Author: alex@blockwatch.cc 3 4 // Key examples 5 // 6 // # Private Keys 7 // mv1: edsk3nM41ygNfSxVU4w1uAW3G9EnTQEB5rjojeZedLTGmiGRcierVv 8 // mv2: spsk1zkqrmst1yg2c4xi3crWcZPqgdc9KtPtb9SAZWYHAdiQzdHy7j 9 // mv3: p2sk3PM77YMR99AvD3fSSxeLChMdiQ6kkEzqoPuSwQqhPsh29irGLC 10 // 11 // # Encrypted keys (pw: foo) 12 // mv1: edesk1uiM6BaysskGto8pRtzKQqFqsy1sea1QRjTzaQYuBxYNhuN6eqEU78TGRXZocsVRJYcN7AaU9JDykwUd8KW 13 // mv2: spesk246GnDVaqGoYZvKbjrWM1g6xUXnyETXtwZgEYFnP8BQXcaS4rfQQco7C94D1yBmcL1v46Sqy8fXrhBSM7TW 14 // mv3: p2esk27ocLPLp1JkTWfxByXysGyB7MBDURYJAzAGJLR3XSEV9Nq8wFFdDVXVTwvCwR7Ne2dcUveamjXbvZf3on6T 15 // 16 // # Signatures 17 // edsigtzLBGCyadERX1QsYHKpwnxSxEYQeGLnJGsSkHEsyY8vB5GcNdnvzUZDdFevJK7YZQ2ujwVjvQZn62ahCEcy74AwtbA8HuN 18 // spsig1RriZtYADyRhyNoQMa6AiPuJJ7AUDcrxWZfgqexzgANqMv4nXs6qsXDoXcoChBgmCcn2t7Y3EkJaVRuAmNh2cDDxWTdmsz 19 // sigUdRdXYCXW14xqT8mFTMkX4wSmDMBmcW1Vuz1vanGWqYTmuBodueUHGPUsbxgn73AroNwpEBHwPdhXUswzmvCzquiqtcHC 20 21 package main 22 23 import ( 24 "encoding/hex" 25 "flag" 26 "fmt" 27 "log" 28 "os" 29 "strings" 30 "syscall" 31 32 "github.com/mavryk-network/mvgo/mavryk" 33 "golang.org/x/term" 34 ) 35 36 var ( 37 flags = flag.NewFlagSet("key", flag.ContinueOnError) 38 verbose bool 39 password string 40 ) 41 42 func init() { 43 flags.Usage = func() {} 44 flags.BoolVar(&verbose, "v", false, "be verbose") 45 flags.StringVar(&password, "password", "", "password for encrypted keys (may also use env TEZOS_KEY_PASSPHRASE)") 46 } 47 48 func main() { 49 if err := flags.Parse(os.Args[1:]); err != nil { 50 if err == flag.ErrHelp { 51 fmt.Println("Usage: key <cmd> [args]") 52 fmt.Println("\nCommands") 53 fmt.Printf(" gen <type> generate a new key of type\n") 54 fmt.Printf(" normal: edsk [mv1], spsk [mv2], p2sk [mv3]\n") 55 fmt.Printf(" encrypted: edesk, spesk, p2esk\n") 56 fmt.Printf(" info <key> prints info about `key`\n") 57 fmt.Printf(" encrypt <key> encrypt private `key`\n") 58 fmt.Printf(" sign <sk> <msg> [generic] sign blake2b hash of message `msg` with key\n") 59 fmt.Printf(" outputs typed signature by default\n") 60 fmt.Printf(" use `generic` to create a generic signature\n") 61 fmt.Printf(" sign-digest <sk> <digest> [generic] sign blake2b digest with key\n") 62 fmt.Printf(" outputs typed signature by default\n") 63 fmt.Printf(" use `generic` to create a generic signature\n") 64 fmt.Printf(" verify <pk> <sig> <msg> verify signature `sig` using pubkey `pk` against blake2b hash of message `msg`\n") 65 flags.PrintDefaults() 66 os.Exit(0) 67 } 68 log.Fatalln("Error:", err) 69 } 70 71 if err := run(); err != nil { 72 log.Fatalln("Error:", err) 73 } 74 } 75 76 func run() error { 77 n := flags.NArg() 78 if n < 1 { 79 return fmt.Errorf("Command required") 80 } 81 switch cmd := flags.Arg(0); cmd { 82 case "info": 83 if n != 2 { 84 return fmt.Errorf("Missing key") 85 } 86 return info(flags.Arg(1)) 87 case "gen": 88 if n != 2 { 89 return fmt.Errorf("Missing key type") 90 } 91 return gen(flags.Arg(1)) 92 case "encrypt": 93 if n != 2 { 94 return fmt.Errorf("Missing key") 95 } 96 return encrypt(flags.Arg(1)) 97 case "sign": 98 if n < 3 { 99 return fmt.Errorf("Missing arguments") 100 } 101 generic := n == 4 && flags.Arg(3) == "generic" 102 return sign(flags.Arg(1), flags.Arg(2), generic) 103 case "sign-digest": 104 if n < 3 { 105 return fmt.Errorf("Missing arguments") 106 } 107 generic := n == 4 && flags.Arg(3) == "generic" 108 return signDigest(flags.Arg(1), flags.Arg(2), generic) 109 case "verify": 110 if n < 4 { 111 return fmt.Errorf("Missing arguments") 112 } 113 return verify(flags.Arg(1), flags.Arg(2), flags.Arg(3)) 114 default: 115 return fmt.Errorf("Unknown command %q", cmd) 116 } 117 } 118 119 func readPassword() mavryk.PassphraseFunc { 120 pwd := password 121 source := "command line" 122 if pwd == "" { 123 pwd = os.Getenv("TEZOS_KEY_PASSPHRASE") 124 source = "env TEZOS_KEY_PASSPHRASE" 125 } 126 127 if pwd != "" { 128 fmt.Printf("Using password from %s %s", source, strings.Repeat("*", len(pwd))) 129 return func() ([]byte, error) { return []byte(pwd), nil } 130 } else { 131 return func() ([]byte, error) { 132 fmt.Print("Enter Password: ") 133 buf, err := term.ReadPassword(int(syscall.Stdin)) 134 fmt.Println() 135 return buf, err 136 } 137 } 138 } 139 140 func info(val string) error { 141 if mavryk.IsPrivateKey(val) { 142 var ( 143 sk mavryk.PrivateKey 144 err error 145 ) 146 if mavryk.IsEncryptedKey(val) { 147 sk, err = mavryk.ParseEncryptedPrivateKey(val, readPassword()) 148 } else { 149 sk, err = mavryk.ParsePrivateKey(val) 150 } 151 if err != nil { 152 return err 153 } 154 if !sk.IsValid() { 155 return fmt.Errorf("Invalid private key") 156 } 157 158 pk := sk.Public() 159 if !pk.IsValid() { 160 return fmt.Errorf("Invalid public key") 161 } 162 163 fmt.Printf("Key Type %s\n", sk.Type) 164 fmt.Printf("Private Key %s\n", sk) 165 fmt.Printf("Public Key %s\n", pk) 166 fmt.Printf("Address %s\n", pk.Address()) 167 fmt.Printf("Private Key Hex %x (%d)\n", sk.Data, len(sk.Data)) 168 fmt.Printf("Public Key Hex %x (%d)\n", pk.Data, len(pk.Data)) 169 } else if mavryk.IsPublicKey(val) { 170 pk, err := mavryk.ParseKey(val) 171 if err != nil { 172 return err 173 } 174 if !pk.IsValid() { 175 return fmt.Errorf("Invalid public key") 176 } 177 fmt.Printf("Key Type %s\n", pk.Type) 178 fmt.Printf("Public Key %s\n", pk) 179 fmt.Printf("Public Key Hex %x (%d)\n", pk.Data, len(pk.Data)) 180 fmt.Printf("Address %s\n", pk.Address()) 181 } else if mavryk.IsSignature(val) { 182 sig, err := mavryk.ParseSignature(val) 183 if err != nil { 184 return err 185 } 186 if !sig.IsValid() { 187 return fmt.Errorf("Invalid signature") 188 } 189 fmt.Printf("Sig Type %s\n", sig.Type) 190 fmt.Printf("Sig Hex %x (%d)\n", sig.Data, len(sig.Data)) 191 192 } 193 return nil 194 } 195 196 func gen(val string) error { 197 if !mavryk.IsPrivateKey(val) { 198 return fmt.Errorf("unsupported private key type") 199 } 200 201 typ, doEncrypt := mavryk.ParseKeyType(val) 202 if !typ.IsValid() { 203 return fmt.Errorf("invalid private key type") 204 } 205 206 sk, err := mavryk.GenerateKey(typ) 207 if err != nil { 208 return err 209 } 210 pk := sk.Public() 211 212 fmt.Printf("Key Type %s\n", sk.Type.SkPrefix()) 213 fmt.Printf("Private Key %s\n", sk) 214 fmt.Printf("Public Key %s\n", pk) 215 fmt.Printf("Address %s\n", pk.Address()) 216 fmt.Printf("Private Key Hex %x (%d)\n", sk.Data, len(sk.Data)) 217 fmt.Printf("Public Key Hex %x (%d)\n", pk.Data, len(pk.Data)) 218 219 if doEncrypt { 220 enc, err := sk.Encrypt(readPassword()) 221 if err != nil { 222 return err 223 } 224 fmt.Printf("Encrypted Key %s\n", enc) 225 } 226 return nil 227 } 228 229 func encrypt(key string) error { 230 if !mavryk.IsPrivateKey(key) { 231 return fmt.Errorf("private key required") 232 } 233 234 sk, err := mavryk.ParseEncryptedPrivateKey(key, readPassword()) 235 if err != nil { 236 return err 237 } 238 pk := sk.Public() 239 240 fmt.Printf("Key Type %s\n", sk.Type.SkPrefix()) 241 fmt.Printf("Private Key %s\n", sk) 242 fmt.Printf("Public Key %s\n", pk) 243 fmt.Printf("Address %s\n", pk.Address()) 244 fmt.Printf("Private Key Hex %x (%d)\n", sk.Data, len(sk.Data)) 245 fmt.Printf("Public Key Hex %x (%d)\n", pk.Data, len(pk.Data)) 246 247 enc, err := sk.Encrypt(readPassword()) 248 if err != nil { 249 return err 250 } 251 fmt.Printf("Encrypted Key %s\n", enc) 252 return nil 253 } 254 255 func sign(key, msg string, generic bool) error { 256 sk, err := mavryk.ParseEncryptedPrivateKey(key, readPassword()) 257 if err != nil { 258 return err 259 } 260 pk := sk.Public() 261 digest := mavryk.Digest([]byte(msg)) 262 sig, err := sk.Sign(digest[:]) 263 if err != nil { 264 return err 265 } 266 267 fmt.Printf("Key Type %s\n", sk.Type) 268 fmt.Printf("Private Key %s\n", sk) 269 fmt.Printf("Public Key %s\n", pk) 270 fmt.Printf("Address %s\n", pk.Address()) 271 fmt.Printf("Msg digest %x\n", digest[:]) 272 fmt.Printf("Signature %s\n", sig) 273 fmt.Printf("Signature Hex %x\n", sig.Data) 274 if generic { 275 fmt.Printf("Generic Sig %s\n", sig.Generic()) 276 } 277 return nil 278 } 279 280 func signDigest(key, dgst string, generic bool) error { 281 sk, err := mavryk.ParseEncryptedPrivateKey(key, readPassword()) 282 if err != nil { 283 return err 284 } 285 pk := sk.Public() 286 digest, err := hex.DecodeString(dgst) 287 if err != nil { 288 return err 289 } 290 sig, err := sk.Sign(digest[:]) 291 if err != nil { 292 return err 293 } 294 295 fmt.Printf("Key Type %s\n", sk.Type) 296 fmt.Printf("Private Key %s\n", sk) 297 fmt.Printf("Public Key %s\n", pk) 298 fmt.Printf("Address %s\n", pk.Address()) 299 fmt.Printf("Msg digest %x\n", digest[:]) 300 fmt.Printf("Signature %s\n", sig) 301 fmt.Printf("Signature Hex %x\n", sig.Bytes()) 302 if generic { 303 fmt.Printf("Generic Sig %s\n", sig.Generic()) 304 } 305 return nil 306 } 307 func verify(key, sig, msg string) error { 308 pk, err := mavryk.ParseKey(key) 309 if err != nil { 310 return err 311 } 312 s, err := mavryk.ParseSignature(sig) 313 if err != nil { 314 return err 315 } 316 m := []byte(msg) 317 if strings.HasPrefix(msg, "0x") { 318 m, err = hex.DecodeString(msg) 319 if err != nil { 320 return err 321 } 322 } 323 digest := mavryk.Digest([]byte(m)) 324 if err := pk.Verify(digest[:], s); err == nil { 325 fmt.Println("Signature OK") 326 } else { 327 return err 328 } 329 return nil 330 }