aboutsummaryrefslogtreecommitdiff
path: root/signify/file.go
diff options
context:
space:
mode:
Diffstat (limited to 'signify/file.go')
-rw-r--r--signify/file.go220
1 files changed, 220 insertions, 0 deletions
diff --git a/signify/file.go b/signify/file.go
new file mode 100644
index 0000000..8c956ae
--- /dev/null
+++ b/signify/file.go
@@ -0,0 +1,220 @@
+package signify
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "strings"
+
+ "dim13.org/signify/sig"
+)
+
+type File struct {
+ Comment string
+ RawKey []byte
+ Message []byte
+}
+
+const commentHdr = "untrusted comment:"
+
+var (
+ ErrCommentSize = errors.New("comment line to long")
+ ErrUntrustedComment = errors.New("expected untrusted comment")
+)
+
+func checkComment(comment string) error {
+ // compatibility with original version
+ if len(comment) > 1024 {
+ return ErrCommentSize
+ }
+ if !strings.HasPrefix(comment, commentHdr) {
+ return ErrUntrustedComment
+ }
+ return nil
+}
+
+func (f *File) Embedded() bool {
+ return len(f.Message) > 0
+}
+
+func read(r io.Reader) (string, []byte, []byte, error) {
+ buf := bufio.NewReader(r)
+ comment, err := buf.ReadString('\n')
+ if err != nil {
+ return "", nil, nil, err
+ }
+ if err := checkComment(comment); err != nil {
+ return "", nil, nil, err
+ }
+ comment = strings.TrimSpace(comment[len(commentHdr):])
+ raw, err := buf.ReadString('\n')
+ if err != nil {
+ return "", nil, nil, err
+ }
+ rawKey, err := base64.StdEncoding.DecodeString(raw)
+ if err != nil {
+ return "", nil, nil, err
+ }
+ message, err := ioutil.ReadAll(buf)
+ if err != nil {
+ return "", nil, nil, err
+ }
+ return comment, rawKey, message, nil
+}
+
+func (f *File) ReadFrom(r io.Reader) (err error) {
+ f.Comment, f.RawKey, f.Message, err = read(r)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func Parse(b []byte) (*File, error) {
+ r := bytes.NewReader(b)
+ f := new(File)
+ return f, f.ReadFrom(r)
+}
+
+func ParseFile(fname string) (*File, error) {
+ fd, err := os.Open(fname)
+ if err != nil {
+ return nil, err
+ }
+ defer fd.Close()
+ f := new(File)
+ return f, f.ReadFrom(fd)
+}
+
+func (f File) Bytes() ([]byte, error) {
+ buf := new(bytes.Buffer)
+ err := f.WriteTo(buf)
+ if err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+func write(w io.Writer, comment string, key, message []byte) error {
+ fmt.Fprintln(w, commentHdr, comment)
+ fmt.Fprintln(w, base64.StdEncoding.EncodeToString(key))
+ if message != nil {
+ w.Write(message)
+ }
+ return nil
+}
+
+func (f File) WriteTo(w io.Writer) error {
+ return write(w, f.Comment, f.RawKey, f.Message)
+}
+
+const (
+ SecMode os.FileMode = 0600
+ PubMode os.FileMode = 0644
+)
+
+func (f File) WriteFile(fname string, perm os.FileMode) error {
+ fd, err := os.OpenFile(fname, os.O_WRONLY|os.O_CREATE, perm)
+ if err != nil {
+ return err
+ }
+ defer fd.Close()
+ return f.WriteTo(fd)
+}
+
+////////////////////////////////////////////////////////////////////////
+
+func WriteEnc(fname, comment string, key *EncKey) error {
+ fd, err := os.OpenFile(fname, os.O_WRONLY|os.O_CREATE, SecMode)
+ if err != nil {
+ return err
+ }
+ defer fd.Close()
+ b, err := Marshal(key)
+ if err != nil {
+ return err
+ }
+ block := &sig.Block{
+ Comment: comment + " secret key",
+ Bytes: b,
+ }
+ return sig.Encode(fd, block)
+}
+
+func WritePub(fname, comment string, key *PubKey) error {
+ fd, err := os.OpenFile(fname, os.O_WRONLY|os.O_CREATE, PubMode)
+ if err != nil {
+ return err
+ }
+ defer fd.Close()
+ b, err := Marshal(key)
+ if err != nil {
+ return err
+ }
+ block := &sig.Block{
+ Comment: comment + " public key",
+ Bytes: b,
+ }
+ return sig.Encode(fd, block)
+}
+
+func WriteSig(fname, comment string, message []byte, key *Sig) error {
+ fd, err := os.OpenFile(fname, os.O_WRONLY|os.O_CREATE, PubMode)
+ if err != nil {
+ return err
+ }
+ defer fd.Close()
+ b, err := Marshal(key)
+ if err != nil {
+ return err
+ }
+ block := &sig.Block{
+ Comment: "verify with " + comment,
+ Bytes: b,
+ Message: message,
+ }
+ return sig.Encode(fd, block)
+}
+
+////////////////////////////////////////////////////////////////////////
+
+func OpenEnc(fname string) (*EncKey, error) {
+ block, err := sig.DecodeFile(fname)
+ if err != nil {
+ return nil, err
+ }
+ key := new(EncKey)
+ if err := Unmarshal(block.Bytes, key); err != nil {
+ return nil, err
+ }
+ return key, nil
+}
+
+func OpenPub(fname string) (*PubKey, error) {
+ block, err := sig.DecodeFile(fname)
+ if err != nil {
+ return nil, err
+ }
+ key := new(PubKey)
+ if err := Unmarshal(block.Bytes, key); err != nil {
+ return nil, err
+ }
+ return key, nil
+}
+
+func OpenSig(fname string) (*Sig, error) {
+ block, err := sig.DecodeFile(fname)
+ if err != nil {
+ return nil, err
+ }
+ key := new(Sig)
+ if err := Unmarshal(block.Bytes, key); err != nil {
+ return nil, err
+ }
+ return key, nil
+}