package main import ( "context" "flag" "io/ioutil" "log" "dim13.org/signify/ask" "dim13.org/signify/b64file" "dim13.org/signify/key" "dim13.org/signify/zsig" "github.com/google/subcommands" ) // Usage: signify -S [-ez] [-x sigfile] -s seckey -m message type signCommand struct { embedded bool zip bool sigFile string secFile string msgFile string } func (s *signCommand) Name() string { return "sign" } func (s *signCommand) Synopsis() string { return "sign file" } func (s *signCommand) Usage() string { return "sign [-ez] [-x sigfile] -s seckey -m message\n" } func (s *signCommand) SetFlags(f *flag.FlagSet) { f.BoolVar(&s.embedded, "e", false, "embed the message") f.BoolVar(&s.zip, "z", false, "sign gzip archive") // TODO f.StringVar(&s.sigFile, "x", "", "signature file") f.StringVar(&s.secFile, "s", "", "secret file (required)") f.StringVar(&s.msgFile, "m", "", "message file (required)") } func (s *signCommand) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus { if s.secFile == "" || s.msgFile == "" { f.Usage() return subcommands.ExitUsageError } if s.sigFile == "" { s.sigFile = SigName(s.msgFile) } switch { case s.zip && s.embedded: return subcommands.ExitUsageError case s.zip: if err := signGzip(s.secFile, s.msgFile, s.sigFile); err != nil { log.Println(err) return subcommands.ExitFailure } case s.embedded: if err := signEmbedded(s.secFile, s.msgFile, s.sigFile); err != nil { log.Println(err) return subcommands.ExitFailure } default: if err := signPlain(s.secFile, s.msgFile, s.sigFile); err != nil { log.Println(err) return subcommands.ExitFailure } } return subcommands.ExitSuccess } func signPlain(secFile, msgFile, sigFile string) error { sec, err := openSec(secFile) if err != nil { return err } msg, err := ioutil.ReadFile(msgFile) if err != nil { return err } sig := sec.Sign(msg) comment := VerifyWith(secFile) fd, err := Create(sigFile, ModeSig) if err != nil { return err } defer fd.Close() return b64file.Encode(fd, sig, comment, nil) } func signEmbedded(secFile, msgFile, sigFile string) error { sec, err := openSec(secFile) if err != nil { return err } msg, err := ioutil.ReadFile(msgFile) if err != nil { return err } sig := sec.Sign(msg) comment := VerifyWith(secFile) fd, err := Create(sigFile, ModeSig) if err != nil { return err } fd.Close() return b64file.Encode(fd, sig, comment, msg) } // TODO func signGzip(secFile, msgFile, sigFile string) error { fd, err := Open(msgFile) if err != nil { return err } defer fd.Close() z, err := zsig.NewReader(fd) if err != nil { return err } log.Println(z) zhead, err := zsig.NewHeader(z) if err != nil { return err } log.Println(zhead) body, err := zhead.MarshalText() if err != nil { return err } log.Println(body) return nil } func openSec(fname string) (*key.Sec, error) { sec := new(key.Sec) fd, err := Open(fname) if err != nil { return nil, err } defer fd.Close() if _, _, err := b64file.Decode(fd, sec); err != nil { return nil, err } if err := sec.Crypt(ask.Passphrase{}); err != nil { return nil, err } if err := sec.Validate(); err != nil { return nil, err } return sec, nil }