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 }