passforios-gopenpgp/crypto/mime.go

88 lines
2.4 KiB
Go
Raw Normal View History

package crypto
2018-09-02 15:02:26 +02:00
import (
"bytes"
"io/ioutil"
"net/mail"
"net/textproto"
"strings"
2019-03-07 17:39:34 +01:00
gomime "github.com/ProtonMail/go-mime"
2019-03-07 17:39:34 +01:00
"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/packet"
2018-09-02 15:02:26 +02:00
)
// MIMECallbacks defines callback methods to process a MIME message.
type MIMECallbacks interface {
OnBody(body string, mimetype string)
OnAttachment(headers string, data []byte)
// Encrypted headers can be in an attachment and thus be placed at the end of the mime structure.
OnEncryptedHeaders(headers string)
OnVerified(verified int)
OnError(err error)
}
// DecryptMIMEMessage decrypts a MIME message.
func (keyRing *KeyRing) DecryptMIMEMessage(
message *PGPMessage, verifyKey *KeyRing, callbacks MIMECallbacks, verifyTime int64,
) {
decryptedMessage, err := keyRing.Decrypt(message, verifyKey, verifyTime)
if err != nil {
callbacks.OnError(err)
return
}
body, attachments, attachmentHeaders, err := parseMIME(decryptedMessage.GetString(), verifyKey)
if err != nil {
callbacks.OnError(err)
return
}
bodyContent, bodyMimeType := body.GetBody()
callbacks.OnBody(bodyContent, bodyMimeType)
for i := 0; i < len(attachments); i++ {
callbacks.OnAttachment(attachmentHeaders[i], []byte(attachments[i]))
}
callbacks.OnEncryptedHeaders("")
}
// ----- INTERNAL FUNCTIONS -----
func parseMIME(
mimeBody string, verifierKey *KeyRing,
) (*gomime.BodyCollector, []string, []string, error) {
2018-09-02 15:02:26 +02:00
mm, err := mail.ReadMessage(strings.NewReader(mimeBody))
if err != nil {
return nil, nil, nil, err
2018-09-02 15:02:26 +02:00
}
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: getTimeGenerator()}
2018-09-02 15:02:26 +02:00
h := textproto.MIMEHeader(mm.Header)
mmBodyData, err := ioutil.ReadAll(mm.Body)
if err != nil {
return nil, nil, nil, err
}
2018-09-02 15:02:26 +02:00
printAccepter := gomime.NewMIMEPrinter()
bodyCollector := gomime.NewBodyCollector(printAccepter)
attachmentsCollector := gomime.NewAttachmentsCollector(bodyCollector)
mimeVisitor := gomime.NewMimeVisitor(attachmentsCollector)
2019-03-07 17:39:34 +01:00
var pgpKering openpgp.KeyRing
if verifierKey != nil {
pgpKering = verifierKey.entities
}
signatureCollector := newSignatureCollector(mimeVisitor, pgpKering, config)
err = gomime.VisitAll(bytes.NewReader(mmBodyData), h, signatureCollector)
if err == nil && verifierKey != nil {
err = signatureCollector.verified
}
2018-09-02 15:02:26 +02:00
return bodyCollector,
attachmentsCollector.GetAttachments(),
attachmentsCollector.GetAttHeaders(),
err
}