106 lines
2.4 KiB
Go
106 lines
2.4 KiB
Go
package pgpmime
|
|
|
|
import (
|
|
"io"
|
|
"mime"
|
|
"mime/multipart"
|
|
"net/textproto"
|
|
|
|
"golang.org/x/crypto/openpgp"
|
|
"golang.org/x/crypto/openpgp/armor"
|
|
"golang.org/x/crypto/openpgp/packet"
|
|
)
|
|
|
|
type encryptWriter struct {
|
|
multipart *multipart.Writer
|
|
armored io.WriteCloser
|
|
cleartext io.WriteCloser
|
|
|
|
h textproto.MIMEHeader
|
|
to []*openpgp.Entity
|
|
signed *openpgp.Entity
|
|
config *packet.Config
|
|
}
|
|
|
|
func (ew *encryptWriter) open() error {
|
|
// Create control information
|
|
h := make(textproto.MIMEHeader)
|
|
h.Add("Content-Type", "application/pgp-encrypted")
|
|
h.Add("Content-Description", "PGP/MIME version identification")
|
|
w, err := ew.multipart.CreatePart(h)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err := io.WriteString(w, "Version: 1\r\n"); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Create body part
|
|
h = make(textproto.MIMEHeader)
|
|
h.Add("Content-Type", "application/octet-stream; name=\"encrypted.asc\"")
|
|
h.Add("Content-Description", "OpenPGP encrypted message")
|
|
h.Add("Content-Disposition", "inline; filename=\"encrypted.asc\"")
|
|
w, err = ew.multipart.CreatePart(h)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Create encrypted part
|
|
ew.armored, err = armor.Encode(w, MessageType, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ew.cleartext, err = openpgp.Encrypt(ew.armored, ew.to, ew.signed, nil, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return writeMIMEHeader(ew.cleartext, ew.h)
|
|
}
|
|
|
|
func (ew *encryptWriter) Write(b []byte) (n int, err error) {
|
|
// Make sure parts required at the begining of the message have been written
|
|
if ew.cleartext == nil {
|
|
if err := ew.open(); err != nil {
|
|
return 0, err
|
|
}
|
|
}
|
|
|
|
return ew.cleartext.Write(b)
|
|
}
|
|
|
|
func (ew *encryptWriter) Close() error {
|
|
if ew.cleartext == nil {
|
|
if err := ew.open(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if err := ew.cleartext.Close(); err != nil {
|
|
return err
|
|
}
|
|
if err := ew.armored.Close(); err != nil {
|
|
return err
|
|
}
|
|
return ew.multipart.Close()
|
|
}
|
|
|
|
func (ew *encryptWriter) ContentType() string {
|
|
return mime.FormatMediaType("multipart/encrypted", map[string]string{
|
|
"boundary": ew.multipart.Boundary(),
|
|
"protocol": "application/pgp-encrypted",
|
|
})
|
|
}
|
|
|
|
// Encrypt creates a new encrypted PGP/MIME message writer.
|
|
func Encrypt(w io.Writer, h textproto.MIMEHeader, to []*openpgp.Entity, signed *openpgp.Entity, config *packet.Config) (cleartext Writer) {
|
|
return &encryptWriter{
|
|
multipart: multipart.NewWriter(w),
|
|
|
|
h: h,
|
|
to: to,
|
|
signed: signed,
|
|
config: config,
|
|
}
|
|
}
|