From 8084465e13ee600c733b709059dfbaa753603674 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Fri, 4 Aug 2017 23:23:51 +0200 Subject: Rename file to b64file --- b64file/file.go | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++ b64file/file_test.go | 31 +++++++++++++++++ b64file/names.go | 72 ++++++++++++++++++++++++++++++++++++++ b64file/names_test.go | 65 ++++++++++++++++++++++++++++++++++ file/file.go | 96 --------------------------------------------------- file/file_test.go | 31 ----------------- file/names.go | 72 -------------------------------------- file/names_test.go | 65 ---------------------------------- generate.go | 8 ++--- sign.go | 14 ++++---- verify.go | 12 +++---- 11 files changed, 281 insertions(+), 281 deletions(-) create mode 100644 b64file/file.go create mode 100644 b64file/file_test.go create mode 100644 b64file/names.go create mode 100644 b64file/names_test.go delete mode 100644 file/file.go delete mode 100644 file/file_test.go delete mode 100644 file/names.go delete mode 100644 file/names_test.go diff --git a/b64file/file.go b/b64file/file.go new file mode 100644 index 0000000..ebca8fe --- /dev/null +++ b/b64file/file.go @@ -0,0 +1,96 @@ +// Package file implements signify file format +package b64file + +import ( + "bufio" + "bytes" + "encoding" + "encoding/base64" + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "strings" +) + +const ( + ModeSec os.FileMode = 0600 + ModePub os.FileMode = 0644 + ModeSig os.FileMode = 0644 + untrusted = "untrusted comment: " +) + +// Original Error: "invalid comment in %s; must start with 'untrusted comment: '" +var ErrUntrusted = errors.New("comment must start with 'untrusted comment: '") + +func DecodeFile(fname string, u encoding.BinaryUnmarshaler) (string, []byte, error) { + fd, err := os.Open(fname) + if err != nil { + return "", nil, err + } + defer fd.Close() + return Decode(fd, u) +} + +func DecodeString(data string, u encoding.BinaryUnmarshaler) (string, []byte, error) { + r := strings.NewReader(data) + return Decode(r, u) +} + +func DecodeBytes(data []byte, u encoding.BinaryUnmarshaler) (string, []byte, error) { + r := bytes.NewReader(data) + return Decode(r, u) +} + +func Decode(r io.Reader, u encoding.BinaryUnmarshaler) (string, []byte, error) { + buf := bufio.NewReader(r) + + comment, err := buf.ReadString('\n') + if err != nil { + return "", nil, err + } + if !strings.HasPrefix(comment, untrusted) { + return "", nil, ErrUntrusted + } + comment = strings.TrimSpace(comment[len(untrusted):]) + + raw, err := buf.ReadString('\n') + if err != nil { + return "", nil, err + } + b, err := base64.StdEncoding.DecodeString(raw) + if err != nil { + return "", nil, err + } + if err := u.UnmarshalBinary(b); err != nil { + return "", nil, err + } + + message, err := ioutil.ReadAll(buf) + if err != nil { + return "", nil, err + } + + return comment, message, nil +} + +func EncodeFile(fname string, perm os.FileMode, u encoding.BinaryMarshaler, comment string, msg []byte) error { + fd, err := os.OpenFile(fname, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm) + if err != nil { + return err + } + defer fd.Close() + return Encode(fd, u, comment, msg) +} + +func Encode(w io.Writer, u encoding.BinaryMarshaler, comment string, msg []byte) error { + raw, err := u.MarshalBinary() + if err != nil { + return err + } + fmt.Fprintf(w, "%s%s\n", untrusted, comment) + fmt.Fprintf(w, "%s\n", base64.StdEncoding.EncodeToString(raw)) + w.Write(msg) + return nil +} diff --git a/b64file/file_test.go b/b64file/file_test.go new file mode 100644 index 0000000..ac95c38 --- /dev/null +++ b/b64file/file_test.go @@ -0,0 +1,31 @@ +package b64file + +import ( + "bytes" + "testing" +) + +type moc struct{} + +func (moc) MarshalBinary() ([]byte, error) { return nil, nil } +func (moc) UnmarshalBinary(_ []byte) error { return nil } + +func TestSig(t *testing.T) { + comment := "untrusted comment: comment" + message := []byte{'t', 'e', 's', 't'} + buf := new(bytes.Buffer) + err := Encode(buf, moc{}, comment, message) + if err != nil { + t.Error(err) + } + comment2, message2, err := Decode(buf, moc{}) + if err != nil { + t.Error(err) + } + if comment != comment2 { + t.Errorf("got %v, want %v", comment2, comment) + } + if !bytes.Equal(message, message2) { + t.Errorf("got %v, want %v", message2, message) + } +} diff --git a/b64file/names.go b/b64file/names.go new file mode 100644 index 0000000..83d73d2 --- /dev/null +++ b/b64file/names.go @@ -0,0 +1,72 @@ +package b64file + +import ( + "errors" + "os" + "path" + "path/filepath" + "strings" +) + +var ErrNames = errors.New("please use naming scheme of keyname.pub and keyname.sec") + +const ( + extPub = ".pub" + extSec = ".sec" + extSig = ".sig" + verifyWith = "verify with " +) + +func splitNameExt(fname string) (string, string) { + _, file := path.Split(fname) + ext := filepath.Ext(file) + return file[:len(file)-len(ext)], ext +} + +func ValidateNames(pubFile, secFile string) error { + pubName, pubExt := splitNameExt(pubFile) + secName, secExt := splitNameExt(secFile) + if pubExt != extPub || secExt != extSec || pubName != secName { + return ErrNames + } + return nil +} + +func PubName(secFile string) string { + ext := filepath.Ext(secFile) + return filepath.Base(secFile[:len(ext)-1] + extPub) +} + +func SigName(msgFile string) string { + return msgFile + extSig +} + +func PubFile(comment string) string { + if strings.HasPrefix(comment, verifyWith) { + file := comment[len(verifyWith):] + if strings.HasSuffix(file, extPub) { + return FindFile(file) + } + } + return "" +} + +func VerifyWith(secFile string) string { + return verifyWith + PubName(secFile) +} + +var safePath = []string{ + "/etc/signify", + "$HOME/.signify", +} + +// FindFile locates keys in safe path. Falls back to current dir. +func FindFile(fname string) string { + for _, v := range safePath { + p := path.Join(os.Expand(v, os.Getenv), fname) + if _, err := os.Stat(p); err == nil { + return p + } + } + return fname +} diff --git a/b64file/names_test.go b/b64file/names_test.go new file mode 100644 index 0000000..0acabed --- /dev/null +++ b/b64file/names_test.go @@ -0,0 +1,65 @@ +package b64file + +import "testing" + +func TestCheckNames(t *testing.T) { + testCases := []struct { + pub, sec string + err error + }{ + {"key.pub", "key.sec", nil}, + {"testdata/key.pub", "key.sec", nil}, + {"key.pub", "testdata/key.sec", nil}, + {"foo.pub", "bar.sec", ErrNames}, + {"key.foo", "key.bar", ErrNames}, + } + for _, tc := range testCases { + t.Run(tc.pub+"+"+tc.sec, func(t *testing.T) { + err := ValidateNames(tc.pub, tc.sec) + if err != tc.err { + t.Errorf("got %v, want %v", err, tc.err) + } + }) + } +} + +func TestVerify(t *testing.T) { + testCases := []struct { + comment string + file string + }{ + {"verify with key.pub", "key.pub"}, + {"verify with s p a c e s.pub", "s p a c e s.pub"}, + {"verify with key.sec", ""}, + {"whatever", ""}, + } + for _, tc := range testCases { + t.Run(tc.comment, func(t *testing.T) { + file := PubFile(tc.comment) + if file != tc.file { + t.Errorf("got %v, want %v", file, tc.file) + } + }) + } +} + +func TestSplit(t *testing.T) { + testCases := []struct { + fname, name, ext string + }{ + {"testkey.pub", "testkey", ".pub"}, + {"testkey", "testkey", ""}, + {".pub", "", ".pub"}, + {".testkey.pub", ".testkey", ".pub"}, + {"", "", ""}, + {"path/key.pub", "key", ".pub"}, + } + for _, tc := range testCases { + t.Run(tc.fname, func(t *testing.T) { + name, ext := splitNameExt(tc.fname) + if name != tc.name || ext != tc.ext { + t.Errorf("got %q %q, want %q %q", name, tc.name, ext, tc.ext) + } + }) + } +} diff --git a/file/file.go b/file/file.go deleted file mode 100644 index 507cdd0..0000000 --- a/file/file.go +++ /dev/null @@ -1,96 +0,0 @@ -// Package file implements signify file format -package file - -import ( - "bufio" - "bytes" - "encoding" - "encoding/base64" - "errors" - "fmt" - "io" - "io/ioutil" - "os" - "strings" -) - -const ( - ModeSec os.FileMode = 0600 - ModePub os.FileMode = 0644 - ModeSig os.FileMode = 0644 - untrusted = "untrusted comment: " -) - -// Original Error: "invalid comment in %s; must start with 'untrusted comment: '" -var ErrUntrusted = errors.New("comment must start with 'untrusted comment: '") - -func DecodeFile(fname string, u encoding.BinaryUnmarshaler) (string, []byte, error) { - fd, err := os.Open(fname) - if err != nil { - return "", nil, err - } - defer fd.Close() - return Decode(fd, u) -} - -func DecodeString(data string, u encoding.BinaryUnmarshaler) (string, []byte, error) { - r := strings.NewReader(data) - return Decode(r, u) -} - -func DecodeBytes(data []byte, u encoding.BinaryUnmarshaler) (string, []byte, error) { - r := bytes.NewReader(data) - return Decode(r, u) -} - -func Decode(r io.Reader, u encoding.BinaryUnmarshaler) (string, []byte, error) { - buf := bufio.NewReader(r) - - comment, err := buf.ReadString('\n') - if err != nil { - return "", nil, err - } - if !strings.HasPrefix(comment, untrusted) { - return "", nil, ErrUntrusted - } - comment = strings.TrimSpace(comment[len(untrusted):]) - - raw, err := buf.ReadString('\n') - if err != nil { - return "", nil, err - } - b, err := base64.StdEncoding.DecodeString(raw) - if err != nil { - return "", nil, err - } - if err := u.UnmarshalBinary(b); err != nil { - return "", nil, err - } - - message, err := ioutil.ReadAll(buf) - if err != nil { - return "", nil, err - } - - return comment, message, nil -} - -func EncodeFile(fname string, perm os.FileMode, u encoding.BinaryMarshaler, comment string, msg []byte) error { - fd, err := os.OpenFile(fname, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm) - if err != nil { - return err - } - defer fd.Close() - return Encode(fd, u, comment, msg) -} - -func Encode(w io.Writer, u encoding.BinaryMarshaler, comment string, msg []byte) error { - raw, err := u.MarshalBinary() - if err != nil { - return err - } - fmt.Fprintf(w, "%s%s\n", untrusted, comment) - fmt.Fprintf(w, "%s\n", base64.StdEncoding.EncodeToString(raw)) - w.Write(msg) - return nil -} diff --git a/file/file_test.go b/file/file_test.go deleted file mode 100644 index 5a2aa8d..0000000 --- a/file/file_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package file - -import ( - "bytes" - "testing" -) - -type moc struct{} - -func (moc) MarshalBinary() ([]byte, error) { return nil, nil } -func (moc) UnmarshalBinary(_ []byte) error { return nil } - -func TestSig(t *testing.T) { - comment := "untrusted comment: comment" - message := []byte{'t', 'e', 's', 't'} - buf := new(bytes.Buffer) - err := Encode(buf, moc{}, comment, message) - if err != nil { - t.Error(err) - } - comment2, message2, err := Decode(buf, moc{}) - if err != nil { - t.Error(err) - } - if comment != comment2 { - t.Errorf("got %v, want %v", comment2, comment) - } - if !bytes.Equal(message, message2) { - t.Errorf("got %v, want %v", message2, message) - } -} diff --git a/file/names.go b/file/names.go deleted file mode 100644 index f893294..0000000 --- a/file/names.go +++ /dev/null @@ -1,72 +0,0 @@ -package file - -import ( - "errors" - "os" - "path" - "path/filepath" - "strings" -) - -var ErrNames = errors.New("please use naming scheme of keyname.pub and keyname.sec") - -const ( - extPub = ".pub" - extSec = ".sec" - extSig = ".sig" - verifyWith = "verify with " -) - -func splitNameExt(fname string) (string, string) { - _, file := path.Split(fname) - ext := filepath.Ext(file) - return file[:len(file)-len(ext)], ext -} - -func ValidateNames(pubFile, secFile string) error { - pubName, pubExt := splitNameExt(pubFile) - secName, secExt := splitNameExt(secFile) - if pubExt != extPub || secExt != extSec || pubName != secName { - return ErrNames - } - return nil -} - -func PubName(secFile string) string { - ext := filepath.Ext(secFile) - return filepath.Base(secFile[:len(ext)-1] + extPub) -} - -func SigName(msgFile string) string { - return msgFile + extSig -} - -func PubFile(comment string) string { - if strings.HasPrefix(comment, verifyWith) { - file := comment[len(verifyWith):] - if strings.HasSuffix(file, extPub) { - return FindFile(file) - } - } - return "" -} - -func VerifyWith(secFile string) string { - return verifyWith + PubName(secFile) -} - -var safePath = []string{ - "/etc/signify", - "$HOME/.signify", -} - -// FindFile locates keys in safe path. Falls back to current dir. -func FindFile(fname string) string { - for _, v := range safePath { - p := path.Join(os.Expand(v, os.Getenv), fname) - if _, err := os.Stat(p); err == nil { - return p - } - } - return fname -} diff --git a/file/names_test.go b/file/names_test.go deleted file mode 100644 index a24faee..0000000 --- a/file/names_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package file - -import "testing" - -func TestCheckNames(t *testing.T) { - testCases := []struct { - pub, sec string - err error - }{ - {"key.pub", "key.sec", nil}, - {"testdata/key.pub", "key.sec", nil}, - {"key.pub", "testdata/key.sec", nil}, - {"foo.pub", "bar.sec", ErrNames}, - {"key.foo", "key.bar", ErrNames}, - } - for _, tc := range testCases { - t.Run(tc.pub+"+"+tc.sec, func(t *testing.T) { - err := ValidateNames(tc.pub, tc.sec) - if err != tc.err { - t.Errorf("got %v, want %v", err, tc.err) - } - }) - } -} - -func TestVerify(t *testing.T) { - testCases := []struct { - comment string - file string - }{ - {"verify with key.pub", "key.pub"}, - {"verify with s p a c e s.pub", "s p a c e s.pub"}, - {"verify with key.sec", ""}, - {"whatever", ""}, - } - for _, tc := range testCases { - t.Run(tc.comment, func(t *testing.T) { - file := PubFile(tc.comment) - if file != tc.file { - t.Errorf("got %v, want %v", file, tc.file) - } - }) - } -} - -func TestSplit(t *testing.T) { - testCases := []struct { - fname, name, ext string - }{ - {"testkey.pub", "testkey", ".pub"}, - {"testkey", "testkey", ""}, - {".pub", "", ".pub"}, - {".testkey.pub", ".testkey", ".pub"}, - {"", "", ""}, - {"path/key.pub", "key", ".pub"}, - } - for _, tc := range testCases { - t.Run(tc.fname, func(t *testing.T) { - name, ext := splitNameExt(tc.fname) - if name != tc.name || ext != tc.ext { - t.Errorf("got %q %q, want %q %q", name, tc.name, ext, tc.ext) - } - }) - } -} diff --git a/generate.go b/generate.go index d912ada..607b566 100644 --- a/generate.go +++ b/generate.go @@ -4,7 +4,7 @@ import ( "flag" "dim13.org/signify/ask" - "dim13.org/signify/file" + "dim13.org/signify/b64file" "dim13.org/signify/key" ) @@ -23,7 +23,7 @@ func generate(args []string) error { opts.Usage() return nil } - if err := file.ValidateNames(*pubFile, *secFile); err != nil { + if err := b64file.ValidateNames(*pubFile, *secFile); err != nil { return err } @@ -37,10 +37,10 @@ func generate(args []string) error { return err } - if err := file.EncodeFile(*secFile, file.ModeSec, secKey, *comment+" secret key", nil); err != nil { + if err := b64file.EncodeFile(*secFile, b64file.ModeSec, secKey, *comment+" secret key", nil); err != nil { return err } - if err := file.EncodeFile(*pubFile, file.ModePub, pubKey, *comment+" public key", nil); err != nil { + if err := b64file.EncodeFile(*pubFile, b64file.ModePub, pubKey, *comment+" public key", nil); err != nil { return err } return nil diff --git a/sign.go b/sign.go index ba49418..1a9fec7 100644 --- a/sign.go +++ b/sign.go @@ -7,7 +7,7 @@ import ( "os" "dim13.org/signify/ask" - "dim13.org/signify/file" + "dim13.org/signify/b64file" "dim13.org/signify/key" "dim13.org/signify/zsig" ) @@ -29,7 +29,7 @@ func sign(args []string) error { return nil } if *sigFile == "" { - *sigFile = file.SigName(*msgFile) + *sigFile = b64file.SigName(*msgFile) } switch { @@ -62,8 +62,8 @@ func signPlain(secFile, msgFile, sigFile string) error { return err } sig := sec.Sign(msg) - comment := file.VerifyWith(secFile) - return file.EncodeFile(sigFile, file.ModeSig, sig, comment, nil) + comment := b64file.VerifyWith(secFile) + return b64file.EncodeFile(sigFile, b64file.ModeSig, sig, comment, nil) } func signEmbedded(secFile, msgFile, sigFile string) error { @@ -76,8 +76,8 @@ func signEmbedded(secFile, msgFile, sigFile string) error { return err } sig := sec.Sign(msg) - comment := file.VerifyWith(secFile) - return file.EncodeFile(sigFile, file.ModeSig, sig, comment, msg) + comment := b64file.VerifyWith(secFile) + return b64file.EncodeFile(sigFile, b64file.ModeSig, sig, comment, msg) } // TODO @@ -107,7 +107,7 @@ func signGzip(secFile, msgFile, sigFile string) error { func openSec(fname string) (*key.Sec, error) { sec := new(key.Sec) - if _, _, err := file.DecodeFile(fname, sec); err != nil { + if _, _, err := b64file.DecodeFile(fname, sec); err != nil { return nil, err } if err := sec.Crypt(ask.Passphrase{}); err != nil { diff --git a/verify.go b/verify.go index bf73af5..25615a1 100644 --- a/verify.go +++ b/verify.go @@ -6,7 +6,7 @@ import ( "io/ioutil" "os" - "dim13.org/signify/file" + "dim13.org/signify/b64file" "dim13.org/signify/key" "dim13.org/signify/zsig" ) @@ -30,7 +30,7 @@ func verify(args []string) error { return nil } if *sigFile == "" { - *sigFile = file.SigName(*msgFile) + *sigFile = b64file.SigName(*msgFile) } _ = keyType // TODO @@ -103,7 +103,7 @@ func verifyGzip(pubFile, sigFile string) error { } sig := new(key.Sig) - _, msg, err := file.DecodeString(z.Comment, sig) + _, msg, err := b64file.DecodeString(z.Comment, sig) if err != nil { return err } @@ -129,7 +129,7 @@ func verifyGzip(pubFile, sigFile string) error { func openPub(fname string) (*key.Pub, error) { pub := new(key.Pub) - if _, _, err := file.DecodeFile(fname, pub); err != nil { + if _, _, err := b64file.DecodeFile(fname, pub); err != nil { return nil, err } if err := pub.Validate(); err != nil { @@ -140,13 +140,13 @@ func openPub(fname string) (*key.Pub, error) { func openSig(fname string) (*key.Sig, []byte, string, error) { sig := new(key.Sig) - comment, msg, err := file.DecodeFile(fname, sig) + comment, msg, err := b64file.DecodeFile(fname, sig) if err != nil { return nil, nil, "", err } if err := sig.Validate(); err != nil { return nil, nil, "", err } - pubKey := file.PubFile(comment) + pubKey := b64file.PubFile(comment) return sig, msg, pubKey, nil } -- cgit v1.2.3