passforios-gopenpgp/crypto/mime.go
Aron Wussler 78e3abb0d8 go vet and lint
* Naming
    * If this is not some OpenPGP standard I follow rule that `DES` should be
      upper case as it is abreviation and `Triple` should be camel-case as it
      is normal word hence `TripleDES`
    * rename `errors2` -> `errorsPGP`
* long lines
    * https://github.com/golang/go/wiki/CodeReviewComments#line-length
    * I bit improved long lines based on my folding
    * reuse type in definition if possible i.e. `a string, b string, c string` -> `a,b,c string`
    * `if long_statetent(); err!=nil {` -> `long_statement;↵ if err!=nil {`
    * spaces around operators (e.g. `a + b` -> `a+b`)
* removing empty lines on start and end of scope
* comments
    * on all exported functions
    * start with function name
* import:
    * order in alphabet
    * separate native, golang.org/x/ and our libs
2019-05-14 14:42:38 +00:00

90 lines
2.6 KiB
Go

package crypto
import (
"bytes"
"io/ioutil"
"net/mail"
"net/textproto"
"strings"
pmmime "github.com/ProtonMail/go-pm-mime"
"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/packet"
)
func (pm PmCrypto) parseMIME(
mimeBody string, verifierKey *KeyRing,
) (*pmmime.BodyCollector, int, []string, []string, error) {
mm, err := mail.ReadMessage(strings.NewReader(mimeBody))
if err != nil {
return nil, 0, nil, nil, err
}
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: pm.getTimeGenerator()}
h := textproto.MIMEHeader(mm.Header)
mmBodyData, err := ioutil.ReadAll(mm.Body)
if err != nil {
return nil, 0, nil, nil, err
}
printAccepter := pmmime.NewMIMEPrinter()
bodyCollector := pmmime.NewBodyCollector(printAccepter)
attachmentsCollector := pmmime.NewAttachmentsCollector(bodyCollector)
mimeVisitor := pmmime.NewMimeVisitor(attachmentsCollector)
var pgpKering openpgp.KeyRing
if verifierKey != nil {
pgpKering = verifierKey.entities
}
signatureCollector := newSignatureCollector(mimeVisitor, pgpKering, config)
err = pmmime.VisitAll(bytes.NewReader(mmBodyData), h, signatureCollector)
verified := signatureCollector.verified
body := bodyCollector
atts := attachmentsCollector.GetAttachments()
attHeaders := attachmentsCollector.GetAttHeaders()
return body, verified, atts, attHeaders, err
}
// MIMECallbacks defines a call back methods to process MIME message
type MIMECallbacks interface {
OnBody(body string, mimetype string)
OnAttachment(headers string, data []byte)
// Encrypted headers can be 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 (pm *PmCrypto) DecryptMIMEMessage(
encryptedText string, verifierKey, privateKeyRing *KeyRing,
passphrase string, callbacks MIMECallbacks, verifyTime int64,
) {
decsignverify, err := pm.DecryptMessageVerify(encryptedText, verifierKey, privateKeyRing, passphrase, verifyTime)
if err != nil {
callbacks.OnError(err)
return
}
body, verified, attachments, attachmentHeaders, err := pm.parseMIME(decsignverify.Plaintext, verifierKey)
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("")
if decsignverify.Verify == notSigned {
callbacks.OnVerified(verified)
} else {
callbacks.OnVerified(decsignverify.Verify)
}
}