package main import ( "bufio" "bytes" "errors" "fmt" "io" "io/ioutil" "os" "strings" ) type File struct { Comment string B64 []byte Body []byte } const ( commentHdr = "untrusted comment: " verifyWith = "verify with " pubKey = "%s public key" secKey = "%s secret key" sigFrom = "signature from %s" ) func Parse(r io.Reader) (File, error) { buf := bufio.NewReader(r) comment, err := buf.ReadString('\n') if err != nil { return File{}, err } if !strings.HasPrefix(comment, commentHdr) { return File{}, errors.New("expected untrusted header") } // Backward compatibility with original signify if len(comment) > 1024 { return File{}, errors.New("comment line too long") } comment = comment[len(commentHdr):] b64, err := buf.ReadBytes('\n') if err != nil { return File{}, err } body, err := ioutil.ReadAll(buf) if err != nil { return File{}, err } return File{ Comment: strings.TrimRight(comment, "\r\n"), B64: bytes.TrimRight(b64, "\r\n"), Body: body, }, nil } func ParseFile(fname string) (File, error) { fd, err := os.Open(fname) if err != nil { return File{}, err } defer fd.Close() return Parse(fd) } func (f File) Encode(w io.Writer) error { fmt.Fprintf(w, "%v%v\n", commentHdr, f.Comment) fmt.Fprintf(w, "%v\n", string(f.B64)) if f.Body != nil { fmt.Fprintf(w, "%v", string(f.Body)) } return nil } func (f File) EncodeFile(fname string) error { fd, err := os.Create(fname) if err != nil { return err } defer fd.Close() return f.Encode(fd) }