From e3053142f5dcf2d32b49563ee44296d39af12d65 Mon Sep 17 00:00:00 2001 From: Sudhi Herle Date: Sat, 13 Jan 2024 10:34:24 -0800 Subject: [PATCH] Teach sigtool verify to use public key as a command line string (in lieu of a file). - Reorganized the code a bit and split each of sigtool's commands into a separate file. - Added extra tests to validate verify's new capabilities - Updated README --- README.md | 4 + build | 2 +- sign/keys.go | 23 +++ sigtool.go | 360 --------------------------------------- crypt.go => src/crypt.go | 0 die.go => src/die.go | 0 src/gen.go | 100 +++++++++++ src/sign.go | 111 ++++++++++++ src/sigtool.go | 130 ++++++++++++++ src/verify.go | 96 +++++++++++ tests.sh | 11 +- 11 files changed, 475 insertions(+), 362 deletions(-) delete mode 100644 sigtool.go rename crypt.go => src/crypt.go (100%) rename die.go => src/die.go (100%) create mode 100644 src/gen.go create mode 100644 src/sign.go create mode 100644 src/sigtool.go create mode 100644 src/verify.go diff --git a/README.md b/README.md index f9f6fd9..1776de2 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,10 @@ e.g., to verify the signature of *archive.tar.gz* against sigtool verify /tmp/testkey.pub archive.sig archive.tar.gz +You can also pass a public key as a string (instead of a file): + + sigtool verify iF84Dymq/bAEnUMK6DRIHWAQDRD8FwDDDfsgFfzdjWM= archive.sig archive.tar.gz + Note that signing and verifying can also work with OpenSSH ed25519 keys. diff --git a/build b/build index 755108d..f347bf3 100755 --- a/build +++ b/build @@ -13,7 +13,7 @@ # # License: GPLv2 # -Progs=".:sigtool" +Progs="src:sigtool" # Relative path to protobuf sources # e.g. src/foo/a.proto diff --git a/sign/keys.go b/sign/keys.go index f0d0c93..a6869b8 100644 --- a/sign/keys.go +++ b/sign/keys.go @@ -369,6 +369,29 @@ func MakePublicKey(yml []byte) (*PublicKey, error) { return &pk, nil } +// Make a public key from a string +func MakePublicKeyFromString(s string) (*PublicKey, error) { + // first try to decode it as a openssh key + if pk2, err := parseEncPubKey([]byte(s), "command-line-pk"); err == nil { + return pk2, nil + } + + // Now try to decode as an sigtool key + b64 := base64.StdEncoding.DecodeString + + pkb, err := b64(s) + if err != nil { + return nil, err + } + + var pk PublicKey + err = makePublicKeyFromBytes(&pk, pkb) + if err != nil { + return nil, err + } + return &pk, nil +} + func makePublicKeyFromBytes(pk *PublicKey, b []byte) error { if len(b) != 32 { return fmt.Errorf("public key is malformed (len %d!)", len(b)) diff --git a/sigtool.go b/sigtool.go deleted file mode 100644 index 69a249c..0000000 --- a/sigtool.go +++ /dev/null @@ -1,360 +0,0 @@ -// sigtool.go -- Tool to generate, manage Ed25519 keys and -// signatures. -// -// (c) 2016 Sudhi Herle -// -// Licensing Terms: GPLv2 -// -// If you need a commercial license for this work, please contact -// the author. -// -// This software does not come with any express or implied -// warranty; it is provided "as is". No claim is made to its -// suitability for any purpose. - -package main - -import ( - "fmt" - "io" - "os" - "path" - "strings" - - "github.com/opencoff/go-utils" - flag "github.com/opencoff/pflag" - "github.com/opencoff/sigtool/sign" -) - -var Z string = path.Base(os.Args[0]) - -func main() { - - var ver, help, debug bool - - mf := flag.NewFlagSet(Z, flag.ExitOnError) - mf.SetInterspersed(false) - mf.BoolVarP(&ver, "version", "v", false, "Show version info and exit") - mf.BoolVarP(&help, "help", "h", false, "Show help info exit") - mf.BoolVarP(&debug, "debug", "", false, "Enable debug mode") - mf.Parse(os.Args[1:]) - - if ver { - fmt.Printf("%s - %s [%s; %s]\n", Z, ProductVersion, RepoVersion, Buildtime) - os.Exit(0) - } - - if help { - usage(0) - } - - args := mf.Args() - if len(args) < 1 { - Die("Insufficient arguments. Try '%s -h'", Z) - } - - cmds := map[string]func(args []string){ - "generate": gen, - "sign": signify, - "verify": verify, - "encrypt": encrypt, - "decrypt": decrypt, - - "help": func(_ []string) { - usage(0) - }, - } - - words := make([]string, 0, len(cmds)) - for k := range cmds { - words = append(words, k) - } - - ab := utils.Abbrev(words) - canon, ok := ab[strings.ToLower(args[0])] - if !ok { - Die("Unknown command %s", args[0]) - } - - cmd := cmds[canon] - if cmd == nil { - Die("can't map command %s", canon) - } - - if debug { - sign.Debug(1) - } - - cmd(args[1:]) - - // always call Exit so that at-exit handlers are called. - Exit(0) -} - -// Run the generate command -func gen(args []string) { - - var nopw, help, force bool - var comment string - var envpw string - - fs := flag.NewFlagSet("generate", flag.ExitOnError) - fs.BoolVarP(&help, "help", "h", false, "Show this help and exit") - fs.BoolVarP(&nopw, "no-password", "", false, "Don't ask for a password for the private key") - fs.StringVarP(&comment, "comment", "c", "", "Use `C` as the text comment for the keys") - fs.StringVarP(&envpw, "env-password", "E", "", "Use passphrase from environment variable `E`") - fs.BoolVarP(&force, "overwrite", "", false, "Overwrite the output file if it exists") - - fs.Parse(args) - - if help { - fs.SetOutput(os.Stdout) - fmt.Printf(`%s generate|gen|g [options] file-prefix - -Generate a new Ed25519 public+private key pair and write public key to -FILE-PREFIX.pub and private key to FILE-PREFIX.key. - -Options: -`, Z) - fs.PrintDefaults() - os.Exit(0) - } - - args = fs.Args() - if len(args) < 1 { - Die("Insufficient arguments to 'generate'. Try '%s generate -h' ..", Z) - } - - bn := args[0] - - pkn := fmt.Sprintf("%s.pub", path.Clean(bn)) - skn := fmt.Sprintf("%s.key", path.Clean(bn)) - - if !force { - if exists(pkn) || exists(skn) { - Die("Public/Private key files (%s, %s) exist. won't overwrite!", skn, pkn) - } - } - - var err error - var pw []byte - - if !nopw { - var pws string - if len(envpw) > 0 { - pws = os.Getenv(envpw) - } else { - pws, err = utils.Askpass("Enter passphrase for private key", true) - if err != nil { - Die("%s", err) - } - } - - pw = []byte(pws) - } - - sk, err := sign.NewPrivateKey() - if err != nil { - Die("%s", err) - } - - if err = sk.Serialize(skn, comment, force, pw); err != nil { - Die("%s", err) - } - - pk := sk.PublicKey() - if err = pk.Serialize(pkn, comment, force); err != nil { - Die("%s", err) - } -} - -// Run the 'sign' command. -func signify(args []string) { - var nopw, help, force bool - var output string - var envpw string - - fs := flag.NewFlagSet("sign", flag.ExitOnError) - fs.BoolVarP(&help, "help", "h", false, "Show this help and exit") - fs.BoolVarP(&nopw, "no-password", "", false, "Don't ask for a password for the private key") - fs.StringVarP(&envpw, "env-password", "E", "", "Use passphrase from environment variable `E`") - fs.StringVarP(&output, "output", "o", "", "Write signature to file `F`") - fs.BoolVarP(&force, "overwrite", "", false, "Overwrite previous signature file if it exists") - - fs.Parse(args) - - if help { - fs.SetOutput(os.Stdout) - fmt.Printf(`%s sign|s [options] privkey file - -Sign FILE with a Ed25519 private key PRIVKEY and write signature to FILE.sig - -Options: -`, Z) - fs.PrintDefaults() - os.Exit(0) - } - - args = fs.Args() - if len(args) < 2 { - Die("Insufficient arguments to 'sign'. Try '%s sign -h' ..", Z) - } - - kn := args[0] - fn := args[1] - outf := fmt.Sprintf("%s.sig", fn) - - var err error - - if len(output) > 0 { - outf = output - } - - var fd io.WriteCloser = os.Stdout - - if outf != "-" { - sf, err := utils.NewSafeFile(outf, force, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) - if err != nil { - Die("can't create sig file: %s", err) - } - - // we unlink and remove temp on any error - AtExit(sf.Abort) - defer sf.Abort() - fd = sf - } - - sk, err := sign.ReadPrivateKey(kn, func() ([]byte, error) { - if nopw { - return nil, nil - } - - var pws string - if len(envpw) > 0 { - pws = os.Getenv(envpw) - } else { - pws, err = utils.Askpass("Enter passphrase for private key", false) - if err != nil { - Die("%s", err) - } - } - - return []byte(pws), nil - }) - if err != nil { - Die("%s", err) - } - - sig, err := sk.SignFile(fn) - if err != nil { - Die("%s", err) - } - - sigbytes, err := sig.MarshalBinary(fmt.Sprintf("input=%s", fn)) - fd.Write(sigbytes) - fd.Close() -} - -// Verify signature on a given file -func verify(args []string) { - var help, quiet bool - - fs := flag.NewFlagSet("verify", flag.ExitOnError) - fs.BoolVarP(&help, "help", "h", false, "Show this help and exit") - fs.BoolVarP(&quiet, "quiet", "q", false, "Don't show any output; exit with status code only") - - fs.Parse(args) - - if help { - fs.SetOutput(os.Stdout) - fmt.Printf(`%s verify|v [options] pubkey sig file - -Verify an Ed25519 signature in SIG of FILE using a public key PUBKEY. - -Options: -`, Z) - fs.PrintDefaults() - os.Exit(0) - } - - args = fs.Args() - if len(args) < 3 { - Die("Insufficient arguments to 'verify'. Try '%s verify -h' ..", Z) - } - - pn := args[0] - sn := args[1] - fn := args[2] - - sig, err := sign.ReadSignature(sn) - if err != nil { - Die("Can't read signature '%s': %s", sn, err) - } - - pk, err := sign.ReadPublicKey(pn) - if err != nil { - Die("%s", err) - } - - if !sig.IsPKMatch(pk) { - Die("Wrong public key '%s' for verifying '%s'", pn, sn) - } - - ok, err := pk.VerifyFile(fn, sig) - if err != nil { - Die("%s", err) - } - - exit := 0 - if !ok { - exit = 1 - } - - if !quiet { - if ok { - fmt.Printf("%s: Signature %s verified\n", fn, sn) - } else { - fmt.Printf("%s: Signature %s verification failure\n", fn, sn) - } - } - - os.Exit(exit) -} - -func usage(c int) { - x := fmt.Sprintf(`%s is a tool to generate, sign and verify files with Ed25519 signatures. - -Usage: %s [global-options] command [options] arg [args..] - -Global options: - -h, --help Show help and exit - -v, --version Show version info and exit - --debug Enable debug (DANGEROUS) - -Commands: - generate, g Generate a new Ed25519 keypair - sign, s Sign a file with a private key - verify, v Verify a signature against a file and a public key - encrypt, e Encrypt an input file to one or more recipients - decrypt, d Decrypt a file with a private key -`, Z, Z) - - os.Stdout.Write([]byte(x)) - os.Exit(c) -} - -// Return true if $bn.key or $bn.pub exist; false otherwise -func exists(nm string) bool { - if _, err := os.Stat(nm); err == nil { - return true - } - - return false -} - -// This will be filled in by "build" -var RepoVersion string = "UNDEFINED" -var Buildtime string = "UNDEFINED" -var ProductVersion string = "UNDEFINED" - -// vim: ft=go:sw=8:ts=8:noexpandtab:tw=98: diff --git a/crypt.go b/src/crypt.go similarity index 100% rename from crypt.go rename to src/crypt.go diff --git a/die.go b/src/die.go similarity index 100% rename from die.go rename to src/die.go diff --git a/src/gen.go b/src/gen.go new file mode 100644 index 0000000..d99e16f --- /dev/null +++ b/src/gen.go @@ -0,0 +1,100 @@ +// gen.go -- generate keys +// +// (c) 2016 Sudhi Herle +// +// Licensing Terms: GPLv2 +// +// If you need a commercial license for this work, please contact +// the author. +// +// This software does not come with any express or implied +// warranty; it is provided "as is". No claim is made to its +// suitability for any purpose. + +package main + +import ( + "fmt" + "os" + "path" + + "github.com/opencoff/go-utils" + flag "github.com/opencoff/pflag" + "github.com/opencoff/sigtool/sign" +) + +// Run the generate command +func gen(args []string) { + var nopw, help, force bool + var comment string + var envpw string + + fs := flag.NewFlagSet("generate", flag.ExitOnError) + fs.BoolVarP(&help, "help", "h", false, "Show this help and exit") + fs.BoolVarP(&nopw, "no-password", "", false, "Don't ask for a password for the private key") + fs.StringVarP(&comment, "comment", "c", "", "Use `C` as the text comment for the keys") + fs.StringVarP(&envpw, "env-password", "E", "", "Use passphrase from environment variable `E`") + fs.BoolVarP(&force, "overwrite", "", false, "Overwrite the output file if it exists") + + fs.Parse(args) + + if help { + fs.SetOutput(os.Stdout) + fmt.Printf(`%s generate|gen|g [options] file-prefix + +Generate a new Ed25519 public+private key pair and write public key to +FILE-PREFIX.pub and private key to FILE-PREFIX.key. + +Options: +`, Z) + fs.PrintDefaults() + os.Exit(0) + } + + args = fs.Args() + if len(args) < 1 { + Die("Insufficient arguments to 'generate'. Try '%s generate -h' ..", Z) + } + + bn := args[0] + + pkn := fmt.Sprintf("%s.pub", path.Clean(bn)) + skn := fmt.Sprintf("%s.key", path.Clean(bn)) + + if !force { + if exists(pkn) || exists(skn) { + Die("Public/Private key files (%s, %s) exist. won't overwrite!", skn, pkn) + } + } + + var err error + var pw []byte + + if !nopw { + var pws string + if len(envpw) > 0 { + pws = os.Getenv(envpw) + } else { + pws, err = utils.Askpass("Enter passphrase for private key", true) + if err != nil { + Die("%s", err) + } + } + + pw = []byte(pws) + } + + sk, err := sign.NewPrivateKey() + if err != nil { + Die("%s", err) + } + + if err = sk.Serialize(skn, comment, force, pw); err != nil { + Die("%s", err) + } + + pk := sk.PublicKey() + if err = pk.Serialize(pkn, comment, force); err != nil { + Die("%s", err) + } +} diff --git a/src/sign.go b/src/sign.go new file mode 100644 index 0000000..9eb0bc4 --- /dev/null +++ b/src/sign.go @@ -0,0 +1,111 @@ +// sign.go -- 'sign' command implementation +// +// (c) 2016 Sudhi Herle +// +// Licensing Terms: GPLv2 +// +// If you need a commercial license for this work, please contact +// the author. +// +// This software does not come with any express or implied +// warranty; it is provided "as is". No claim is made to its +// suitability for any purpose. + +package main + +import ( + "fmt" + "io" + "os" + + "github.com/opencoff/go-utils" + flag "github.com/opencoff/pflag" + "github.com/opencoff/sigtool/sign" +) + +// Run the 'sign' command. +func signify(args []string) { + var nopw, help, force bool + var output string + var envpw string + + fs := flag.NewFlagSet("sign", flag.ExitOnError) + fs.BoolVarP(&help, "help", "h", false, "Show this help and exit") + fs.BoolVarP(&nopw, "no-password", "", false, "Don't ask for a password for the private key") + fs.StringVarP(&envpw, "env-password", "E", "", "Use passphrase from environment variable `E`") + fs.StringVarP(&output, "output", "o", "", "Write signature to file `F`") + fs.BoolVarP(&force, "overwrite", "", false, "Overwrite previous signature file if it exists") + + fs.Parse(args) + + if help { + fs.SetOutput(os.Stdout) + fmt.Printf(`%s sign|s [options] privkey file + +Sign FILE with a Ed25519 private key PRIVKEY and write signature to FILE.sig + +Options: +`, Z) + fs.PrintDefaults() + os.Exit(0) + } + + args = fs.Args() + if len(args) < 2 { + Die("Insufficient arguments to 'sign'. Try '%s sign -h' ..", Z) + } + + kn := args[0] + fn := args[1] + outf := fmt.Sprintf("%s.sig", fn) + + var err error + + if len(output) > 0 { + outf = output + } + + var fd io.WriteCloser = os.Stdout + + if outf != "-" { + sf, err := utils.NewSafeFile(outf, force, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) + if err != nil { + Die("can't create sig file: %s", err) + } + + // we unlink and remove temp on any error + AtExit(sf.Abort) + defer sf.Abort() + fd = sf + } + + sk, err := sign.ReadPrivateKey(kn, func() ([]byte, error) { + if nopw { + return nil, nil + } + + var pws string + if len(envpw) > 0 { + pws = os.Getenv(envpw) + } else { + pws, err = utils.Askpass("Enter passphrase for private key", false) + if err != nil { + Die("%s", err) + } + } + + return []byte(pws), nil + }) + if err != nil { + Die("%s", err) + } + + sig, err := sk.SignFile(fn) + if err != nil { + Die("%s", err) + } + + sigbytes, err := sig.MarshalBinary(fmt.Sprintf("input=%s", fn)) + fd.Write(sigbytes) + fd.Close() +} diff --git a/src/sigtool.go b/src/sigtool.go new file mode 100644 index 0000000..faae6f2 --- /dev/null +++ b/src/sigtool.go @@ -0,0 +1,130 @@ +// sigtool.go -- Tool to generate, manage Ed25519 keys and +// signatures. +// +// (c) 2016 Sudhi Herle +// +// Licensing Terms: GPLv2 +// +// If you need a commercial license for this work, please contact +// the author. +// +// This software does not come with any express or implied +// warranty; it is provided "as is". No claim is made to its +// suitability for any purpose. + +package main + +import ( + "fmt" + "os" + "path" + "strings" + + "github.com/opencoff/go-utils" + flag "github.com/opencoff/pflag" + "github.com/opencoff/sigtool/sign" +) + +var Z string = path.Base(os.Args[0]) + +func main() { + var ver, help, debug bool + + mf := flag.NewFlagSet(Z, flag.ExitOnError) + mf.SetInterspersed(false) + mf.BoolVarP(&ver, "version", "v", false, "Show version info and exit") + mf.BoolVarP(&help, "help", "h", false, "Show help info exit") + mf.BoolVarP(&debug, "debug", "", false, "Enable debug mode") + mf.Parse(os.Args[1:]) + + if ver { + fmt.Printf("%s - %s [%s; %s]\n", Z, ProductVersion, RepoVersion, Buildtime) + os.Exit(0) + } + + if help { + usage(0) + } + + args := mf.Args() + if len(args) < 1 { + Die("Insufficient arguments. Try '%s -h'", Z) + } + + cmds := map[string]func(args []string){ + "generate": gen, + "sign": signify, + "verify": verify, + "encrypt": encrypt, + "decrypt": decrypt, + + "help": func(_ []string) { + usage(0) + }, + } + + words := make([]string, 0, len(cmds)) + for k := range cmds { + words = append(words, k) + } + + ab := utils.Abbrev(words) + canon, ok := ab[strings.ToLower(args[0])] + if !ok { + Die("Unknown command %s", args[0]) + } + + cmd := cmds[canon] + if cmd == nil { + Die("can't map command %s", canon) + } + + if debug { + sign.Debug(1) + } + + cmd(args[1:]) + + // always call Exit so that at-exit handlers are called. + Exit(0) +} + +// Verify signature on a given file + +func usage(c int) { + x := fmt.Sprintf(`%s is a tool to generate, sign and verify files with Ed25519 signatures. + +Usage: %s [global-options] command [options] arg [args..] + +Global options: + -h, --help Show help and exit + -v, --version Show version info and exit + --debug Enable debug (DANGEROUS) + +Commands: + generate, g Generate a new Ed25519 keypair + sign, s Sign a file with a private key + verify, v Verify a signature against a file and a public key + encrypt, e Encrypt an input file to one or more recipients + decrypt, d Decrypt a file with a private key +`, Z, Z) + + os.Stdout.Write([]byte(x)) + os.Exit(c) +} + +// Return true if $bn.key or $bn.pub exist; false otherwise +func exists(nm string) bool { + if _, err := os.Stat(nm); err == nil { + return true + } + + return false +} + +// This will be filled in by "build" +var RepoVersion string = "UNDEFINED" +var Buildtime string = "UNDEFINED" +var ProductVersion string = "UNDEFINED" + +// vim: ft=go:sw=8:ts=8:noexpandtab:tw=98: diff --git a/src/verify.go b/src/verify.go new file mode 100644 index 0000000..87ebd48 --- /dev/null +++ b/src/verify.go @@ -0,0 +1,96 @@ +// verify.go -- Verify signatures +// +// (c) 2016 Sudhi Herle +// +// Licensing Terms: GPLv2 +// +// If you need a commercial license for this work, please contact +// the author. +// +// This software does not come with any express or implied +// warranty; it is provided "as is". No claim is made to its +// suitability for any purpose. + +package main + +import ( + "fmt" + "os" + + flag "github.com/opencoff/pflag" + "github.com/opencoff/sigtool/sign" +) + +func verify(args []string) { + var help, quiet bool + + fs := flag.NewFlagSet("verify", flag.ExitOnError) + fs.BoolVarP(&help, "help", "h", false, "Show this help and exit") + fs.BoolVarP(&quiet, "quiet", "q", false, "Don't show any output; exit with status code only") + + fs.Parse(args) + + if help { + fs.SetOutput(os.Stdout) + fmt.Printf(`%s verify|v [options] pubkey sig file + +Verify an Ed25519 signature in SIG of FILE using a public key PUBKEY. +The pubkey can be one of: + - a file: either OpenSSH ed25519 pubkey or a sigtool pubkey + - a string: the raw OpenSSH or sigtool pubkey + +%s will first parse it as a string before trying to parse it as a file. + +Options: +`, Z, Z) + fs.PrintDefaults() + os.Exit(0) + } + + args = fs.Args() + if len(args) < 3 { + Die("Insufficient arguments to 'verify'. Try '%s verify -h' ..", Z) + } + + pn := args[0] + sn := args[1] + fn := args[2] + + // We first try to read the public key as a base64/openssh string + pk, err := sign.MakePublicKeyFromString(pn) + if err != nil { + pk, err = sign.ReadPublicKey(pn) + if err != nil { + Die("%s", err) + } + } + + sig, err := sign.ReadSignature(sn) + if err != nil { + Die("Can't read signature '%s': %s", sn, err) + } + + if !sig.IsPKMatch(pk) { + Die("Wrong public key '%s' for verifying '%s'", pn, sn) + } + + ok, err := pk.VerifyFile(fn, sig) + if err != nil { + Die("%s", err) + } + + exit := 0 + if !ok { + exit = 1 + } + + if !quiet { + if ok { + fmt.Printf("%s: Signature %s verified\n", fn, sn) + } else { + fmt.Printf("%s: Signature %s verification failure\n", fn, sn) + } + } + + os.Exit(exit) +} diff --git a/tests.sh b/tests.sh index c1fa38b..00c3f6d 100755 --- a/tests.sh +++ b/tests.sh @@ -77,8 +77,12 @@ spk2=$ssk2.pub $keygen -q -C 'ssk1@foo' -t ed25519 -f $ssk1 -N "" $keygen -q -C 'ssk2@foo' -t ed25519 -f $ssk2 -N "" +# extract the pk string +spk1_str=$(cat $spk1 | awk '{ print $2 }') + $bin s --no-password $ssk1 -o $sig $0 || die "can't sign with $ssk1" $bin v -q $spk1 $sig $0 || die "can't verify with $spk2" +$bin v -q $spk1_str $sig $0 || die "can't verify with $spk2_str" $bin e --no-password -o $encout $spk2 $0 || die "can't encrypt to $spk2 with $ssk1" $bin d --no-password -o $decout $ssk2 $encout || die "can't decrypt with $ssk2" @@ -86,17 +90,22 @@ $bin d --no-password -o $decout $ssk2 $encout || die "can't decrypt with $ssk # cleanup state rm -f $sig $encout $decout - # generate keys $bin g -E FOO $bn || die "can't gen keypair $pk, $sk" $bin g -E FOO $bn 2>/dev/null && die "overwrote prev keypair" $bin g -E FOO --overwrite $bn || die "can't force gen keypair $pk, $sk" $bin g -E FOO $bn2 || die "can't force gen keypair $pk2, $sk2" +# extract pk string +pk_str=$(cat $pk | grep 'pk:' | sed -e 's/^pk: //g') +pk2_str=$(cat $pk2 | grep 'pk:' | sed -e 's/^pk: //g') + # sign and verify $bin s -E FOO $sk $0 -o $sig || die "can't sign $0" $bin v -q $pk $sig $0 || die "can't verify signature of $0" +$bin v -q $pk_str $sig $0 || die "can't verify signature of $0" $bin v -q $pk2 $sig $0 2>/dev/null && die "bad verification with wrong $pk2" +$bin v -q $pk2_str $sig $0 2>/dev/null && die "bad verification with wrong $pk2" # encrypt/decrypt $bin e -E FOO -o $encout $pk2 $0 || die "can't encrypt to $pk2"