func decrypt(me *kindi.Identity, filename, server string) (string, string, error) { r, err := os.Open(filename) if err != nil { return "", "", err } defer r.Close() fid := make([]byte, len([]byte(fileIdentifier))) _, err = io.ReadFull(r, fid) if err != nil { return "", "", err } if string(fid) != fileIdentifier { return "", "", fmt.Errorf("file identifier mismatch for file %s. expected %s but got %s", filename, fileIdentifier, string(fid)) } cs, err := me.DecryptCipherStream(r) if err != nil { return "", "", err } abtr := util.NewAllButTailReader(r, cs.Hash.Size(), 65536) jsonMetadata, err := cs.DecryptMetadata(abtr) if err != nil { return "", "", err } var metadata KindiMetadata err = json.Unmarshal(jsonMetadata, &metadata) if err != nil { return "", "", err } outfilename := filepath.Join(filepath.Dir(filename), metadata.Filename) w, err := os.OpenFile(outfilename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { return "", "", err } defer w.Close() err = cs.DecryptPayload(w, abtr) if err != nil { return "", "", err } if !bytes.Equal(abtr.Tail(), cs.Hash.Sum(nil)) { return "", "", fmt.Errorf("hash mismatch. kindi file %s has been modified.", filename) } senderCerts, _, err := fetchCertificates(server, metadata.SenderEmail) err = kindi.VerifySignature(metadata.SenderEmail, metadata.SenderSignature, senderCerts) if err != nil { return "", "", fmt.Errorf("sender signature for %s did not verify.", metadata.SenderEmail) } return outfilename, metadata.SenderEmail, nil }
func encrypt(me *kindi.Identity, recipientEmails, filename, server string) error { certs, missing, err := fetchCertificates(server, recipientEmails) if err != nil { return err } if len(certs) == 0 { fmt.Fprintf(os.Stderr, "----------------------------------------------------\n") fmt.Fprintf(os.Stderr, "Warning: Couldn't find certificates for the following recipients: [%v]\n", recipientEmails) fmt.Fprintf(os.Stderr, "Those recipients will not be able to decrypt the file.\n") fmt.Fprintf(os.Stderr, "Please go to https://kindimonster.appspot.com/invite and invite them to join kindi.\n") fmt.Fprintf(os.Stderr, "----------------------------------------------------\n") return errors.New("no certificates fetched") } if len(missing) > 0 { fmt.Fprintf(os.Stderr, "----------------------------------------------------\n") fmt.Fprintf(os.Stderr, "Warning: Couldn't find certificates for the following recipients: %v\n", missing) fmt.Fprintf(os.Stderr, "Those recipients will not be able to decrypt the file.\n") fmt.Fprintf(os.Stderr, "Please go to https://kindimonster.appspot.com/invite and invite them to join kindi.\n") fmt.Fprintf(os.Stderr, "----------------------------------------------------\n") } r, err := os.Open(filename) if err != nil { return err } defer r.Close() w, err := os.OpenFile(filename+".kindi", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { return err } defer w.Close() _, err = w.Write([]byte(fileIdentifier)) if err != nil { return err } sig, err := me.Sign() if err != nil { return err } metadata := KindiMetadata{ Filename: filepath.Base(filename), SenderEmail: me.Email, SenderSignature: sig, } jsonMetadata, err := json.Marshal(metadata) if err != nil { return err } return me.Encrypt(w, jsonMetadata, r, certs) }