aboutsummaryrefslogtreecommitdiff
path: root/cmd_sign.go
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2018-02-13 01:22:10 +0100
committerDimitri Sokolyuk <demon@dim13.org>2018-02-13 01:22:10 +0100
commit8bb62c061174bc9098d7ccf1b6772783f1336ba9 (patch)
treebc2bcddefe55e52b931924664617b0df5b1f9e48 /cmd_sign.go
parentc32d9bf24c3b670c3a56ea55aeefb6232f3d4ec8 (diff)
combine
Diffstat (limited to 'cmd_sign.go')
-rw-r--r--cmd_sign.go152
1 files changed, 152 insertions, 0 deletions
diff --git a/cmd_sign.go b/cmd_sign.go
new file mode 100644
index 0000000..91b58ea
--- /dev/null
+++ b/cmd_sign.go
@@ -0,0 +1,152 @@
+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
+}