Improve documentation and naming

- Rename pmmime to gomime
- Rename pmKeyObject to pgpKeyObject
This commit is contained in:
Daniel Huigens 2019-05-15 13:40:19 +02:00
parent 30ee92e63b
commit 7d9930b8e0
13 changed files with 108 additions and 99 deletions

View file

@ -15,7 +15,8 @@ import (
"golang.org/x/crypto/openpgp/packet" "golang.org/x/crypto/openpgp/packet"
) )
// AttachmentProcessor to encrypt an attachment // AttachmentProcessor keeps track of the progress of encrypting an attachment
// (optimized for encrypting large files).
type AttachmentProcessor struct { type AttachmentProcessor struct {
w *io.WriteCloser w *io.WriteCloser
pipe *io.PipeWriter pipe *io.PipeWriter
@ -25,14 +26,14 @@ type AttachmentProcessor struct {
err error err error
} }
// Process allows the attachment processor to write the encrypted attachment // Process writes attachment data to be encrypted
func (ap *AttachmentProcessor) Process(plainData []byte) { func (ap *AttachmentProcessor) Process(plainData []byte) {
if _, err := (*ap.w).Write(plainData); err != nil { if _, err := (*ap.w).Write(plainData); err != nil {
panic(err) panic(err)
} }
} }
// Finish attachment process // Finish closes the attachment and returns the encrypted data
func (ap *AttachmentProcessor) Finish() (*models.EncryptedSplit, error) { func (ap *AttachmentProcessor) Finish() (*models.EncryptedSplit, error) {
if ap.err != nil { if ap.err != nil {
return nil, ap.err return nil, ap.err
@ -46,12 +47,13 @@ func (ap *AttachmentProcessor) Finish() (*models.EncryptedSplit, error) {
return ap.split, nil return ap.split, nil
} }
// encryptAttachment takes input data from file // encryptAttachment creates an AttachmentProcessor which can be used to encrypt
// a file. It takes an estimatedSize and fileName as hints about the file.
func (pgp *GopenPGP) encryptAttachment( func (pgp *GopenPGP) encryptAttachment(
estimatedSize int, fileName string, publicKey *KeyRing, garbageCollector int, estimatedSize int, fileName string, publicKey *KeyRing, garbageCollector int,
) (*AttachmentProcessor, error) { ) (*AttachmentProcessor, error) {
attachmentProc := &AttachmentProcessor{} attachmentProc := &AttachmentProcessor{}
// you can also add these one at a time if you need to // You could also add these one at a time if needed.
attachmentProc.done.Add(1) attachmentProc.done.Add(1)
attachmentProc.garbageCollector = garbageCollector attachmentProc.garbageCollector = garbageCollector
@ -88,8 +90,7 @@ func (pgp *GopenPGP) encryptAttachment(
return attachmentProc, nil return attachmentProc, nil
} }
// EncryptAttachment encrypts attachment. Takes input data and key data in // EncryptAttachment encrypts a file. fileName
// binary form
func (pgp *GopenPGP) EncryptAttachment( func (pgp *GopenPGP) EncryptAttachment(
plainData []byte, fileName string, publicKey *KeyRing, plainData []byte, fileName string, publicKey *KeyRing,
) (*models.EncryptedSplit, error) { ) (*models.EncryptedSplit, error) {
@ -105,14 +106,18 @@ func (pgp *GopenPGP) EncryptAttachment(
return split, nil return split, nil
} }
// EncryptAttachmentLowMemory with garbage collected every megabyte // EncryptAttachmentLowMemory creates an AttachmentProcessor which can be used
// to encrypt a file. It takes an estimatedSize and fileName as hints about the
// file. It is optimized for low-memory environments and collects garbage every
// megabyte.
func (pgp *GopenPGP) EncryptAttachmentLowMemory( func (pgp *GopenPGP) EncryptAttachmentLowMemory(
estimatedSize int, fileName string, publicKey *KeyRing, estimatedSize int, fileName string, publicKey *KeyRing,
) (*AttachmentProcessor, error) { ) (*AttachmentProcessor, error) {
return pgp.encryptAttachment(estimatedSize, fileName, publicKey, 1<<20) return pgp.encryptAttachment(estimatedSize, fileName, publicKey, 1<<20)
} }
// SplitArmor is a Helper method. Splits armored pgp session into key and packet data // SplitArmor is a helper method which splits an armored message into its
// session key packet and symmetrically encrypted data packet.
func SplitArmor(encrypted string) (*models.EncryptedSplit, error) { func SplitArmor(encrypted string) (*models.EncryptedSplit, error) {
var err error var err error
@ -126,8 +131,9 @@ func SplitArmor(encrypted string) (*models.EncryptedSplit, error) {
return SeparateKeyAndData(nil, encryptedReader, len(encrypted), -1) return SeparateKeyAndData(nil, encryptedReader, len(encrypted), -1)
} }
// DecryptAttachment takes input data and key data in binary form. The // DecryptAttachment takes a session key packet and symmetrically encrypted data
// privateKeys can contains more keys. The passphrase is used to unlock keys // packet. privateKeys is a KeyRing that can contain multiple keys. The
// passphrase is used to unlock keys in privateKeys.
func (pgp *GopenPGP) DecryptAttachment( func (pgp *GopenPGP) DecryptAttachment(
keyPacket, dataPacket []byte, keyPacket, dataPacket []byte,
kr *KeyRing, passphrase string, kr *KeyRing, passphrase string,
@ -135,7 +141,7 @@ func (pgp *GopenPGP) DecryptAttachment(
privKeyEntries := kr.entities privKeyEntries := kr.entities
if err := kr.Unlock([]byte(passphrase)); err != nil { if err := kr.Unlock([]byte(passphrase)); err != nil {
err = fmt.Errorf("pm-crypto: cannot decrypt attachment: %v", err) err = fmt.Errorf("gopenpgp: cannot decrypt attachment: %v", err)
return nil, err return nil, err
} }

View file

@ -31,7 +31,7 @@ func TestAttachmentGetKey(t *testing.T) {
} }
func TestAttachmentSetKey(t *testing.T) { func TestAttachmentSetKey(t *testing.T) {
packets, err := SetKey(testPublicKeyRing, testSymmetricKey) packets, err := testPublicKeyRing.EncryptKey(testSymmetricKey)
if err != nil { if err != nil {
t.Fatal("Expected no error while encrypting attachment key, got:", err) t.Fatal("Expected no error while encrypting attachment key, got:", err)
} }

View file

@ -1,15 +1,11 @@
// Package crypto contains all methods and classes needed for manipulation // Package crypto provides a high-level API for common OpenPGP functionality.
// with underlying cryptographic operations. It uses low-level openpgp functions
// and provides higher level views. It uses models of messages, attachments
// and other higher-level entities
package crypto package crypto
import "time" import "time"
// GopenPGP structure is used to manage server time shift. It should be also used for any // GopenPGP is used as a "namespace" for many of the functions in this package.
// other specific general cryptographic entities. // It is a struct that keeps track of time skew between server and client.
type GopenPGP struct { type GopenPGP struct {
//latestServerTime unix time cache
latestServerTime int64 latestServerTime int64
latestClientTime time.Time latestClientTime time.Time
} }

View file

@ -23,15 +23,12 @@ import (
// SymmetricKey stores a decrypted session key. // SymmetricKey stores a decrypted session key.
type SymmetricKey struct { type SymmetricKey struct {
// The clear base64-encoded key. // The decrypted binary session key.
Key []byte Key []byte
// The algorithm used by this key. // The symmetric encryption algorithm used with this key.
Algo string Algo string
} }
// SymmetricallyEncryptedTag is 18 with the 2 highest order bits set to 1
const SymmetricallyEncryptedTag = 210
var symKeyAlgos = map[string]packet.CipherFunction{ var symKeyAlgos = map[string]packet.CipherFunction{
constants.ThreeDES: packet.Cipher3DES, constants.ThreeDES: packet.Cipher3DES,
constants.TripleDES: packet.Cipher3DES, constants.TripleDES: packet.Cipher3DES,
@ -41,18 +38,18 @@ var symKeyAlgos = map[string]packet.CipherFunction{
constants.AES256: packet.CipherAES256, constants.AES256: packet.CipherAES256,
} }
// GetCipherFunc returns function corresponding to an algorithm used in // GetCipherFunc returns the cipher function corresponding to the algorithm used
// this SymmetricKey // with this SymmetricKey.
func (sk *SymmetricKey) GetCipherFunc() packet.CipherFunction { func (sk *SymmetricKey) GetCipherFunc() packet.CipherFunction {
cf, ok := symKeyAlgos[sk.Algo] cf, ok := symKeyAlgos[sk.Algo]
if ok { if ok {
return cf return cf
} }
panic("pm-crypto: unsupported cipher function: " + sk.Algo) panic("gopenpgp: unsupported cipher function: " + sk.Algo)
} }
// GetBase64Key returns a key as base64 encoded string // GetBase64Key returns the session key as base64 encoded string.
func (sk *SymmetricKey) GetBase64Key() string { func (sk *SymmetricKey) GetBase64Key() string {
return base64.StdEncoding.EncodeToString(sk.Key) return base64.StdEncoding.EncodeToString(sk.Key)
} }
@ -66,7 +63,7 @@ func newSymmetricKey(ek *packet.EncryptedKey) *SymmetricKey {
} }
} }
if algo == "" { if algo == "" {
panic(fmt.Sprintf("pm-crypto: unsupported cipher function: %v", ek.CipherFunc)) panic(fmt.Sprintf("gopenpgp: unsupported cipher function: %v", ek.CipherFunc))
} }
return &SymmetricKey{ return &SymmetricKey{
@ -75,7 +72,8 @@ func newSymmetricKey(ek *packet.EncryptedKey) *SymmetricKey {
} }
} }
// DecryptAttKey and returns a symmetric key // DecryptAttKey decrypts a public-key encrypted session key and returns the
// decrypted symmetric session key.
func DecryptAttKey(kr *KeyRing, keyPacket string) (key *SymmetricKey, err error) { func DecryptAttKey(kr *KeyRing, keyPacket string) (key *SymmetricKey, err error) {
r := base64.NewDecoder(base64.StdEncoding, strings.NewReader(keyPacket)) r := base64.NewDecoder(base64.StdEncoding, strings.NewReader(keyPacket))
packets := packet.NewReader(r) packets := packet.NewReader(r)
@ -100,7 +98,7 @@ func DecryptAttKey(kr *KeyRing, keyPacket string) (key *SymmetricKey, err error)
} }
if decryptErr != nil { if decryptErr != nil {
err = fmt.Errorf("pm-crypto: cannot decrypt encrypted key packet: %v", decryptErr) err = fmt.Errorf("gopenpgp: cannot decrypt encrypted key packet: %v", decryptErr)
return return
} }
@ -108,7 +106,8 @@ func DecryptAttKey(kr *KeyRing, keyPacket string) (key *SymmetricKey, err error)
return return
} }
// SeparateKeyAndData from packets in a pgp session // SeparateKeyAndData reads a binary PGP message from r and splits it into its
// session key packet and symmetrically encrypted data packet.
func SeparateKeyAndData( func SeparateKeyAndData(
kr *KeyRing, r io.Reader, kr *KeyRing, r io.Reader,
estimatedLength, garbageCollector int, estimatedLength, garbageCollector int,
@ -118,7 +117,7 @@ func SeparateKeyAndData(
outSplit = &models.EncryptedSplit{} outSplit = &models.EncryptedSplit{}
gcCounter := 0 gcCounter := 0
// Save encrypted key and signature apart // Store encrypted key and symmetrically encrypted packet separately
var ek *packet.EncryptedKey var ek *packet.EncryptedKey
var decryptErr error var decryptErr error
for { for {
@ -199,18 +198,18 @@ func SeparateKeyAndData(
} }
} }
if decryptErr != nil { if decryptErr != nil {
err = fmt.Errorf("pm-crypto: cannot decrypt encrypted key packet: %v", decryptErr) err = fmt.Errorf("gopenpgp: cannot decrypt encrypted key packet: %v", decryptErr)
return nil, err return nil, err
} }
if ek == nil { if ek == nil {
err = errors.New("pm-crypto: packets don't include an encrypted key packet") err = errors.New("gopenpgp: packets don't include an encrypted key packet")
return nil, err return nil, err
} }
if kr == nil { if kr == nil {
var buf bytes.Buffer var buf bytes.Buffer
if err := ek.Serialize(&buf); err != nil { if err := ek.Serialize(&buf); err != nil {
err = fmt.Errorf("pm-crypto: cannot serialize encrypted key: %v", err) err = fmt.Errorf("gopenpgp: cannot serialize encrypted key: %v", err)
return nil, err return nil, err
} }
outSplit.KeyPacket = buf.Bytes() outSplit.KeyPacket = buf.Bytes()
@ -223,15 +222,15 @@ func SeparateKeyAndData(
return outSplit, nil return outSplit, nil
} }
// SetKey encrypts the provided key. // EncryptKey encrypts the provided key.
func SetKey(kr *KeyRing, symKey *SymmetricKey) (packets string, err error) { func (kr *KeyRing) EncryptKey(symKey *SymmetricKey) (packets string, err error) {
b := &bytes.Buffer{} b := &bytes.Buffer{}
w := base64.NewEncoder(base64.StdEncoding, b) w := base64.NewEncoder(base64.StdEncoding, b)
cf := symKey.GetCipherFunc() cf := symKey.GetCipherFunc()
if len(kr.entities) == 0 { if len(kr.entities) == 0 {
err = fmt.Errorf("pm-crypto: cannot set key: key ring is empty") err = fmt.Errorf("gopenpgp: cannot set key: key ring is empty")
return return
} }
@ -257,24 +256,24 @@ func SetKey(kr *KeyRing, symKey *SymmetricKey) (packets string, err error) {
} }
} }
if pub == nil { if pub == nil {
err = fmt.Errorf("pm-crypto: cannot set key: no public key available") err = fmt.Errorf("gopenpgp: cannot set key: no public key available")
return "", err return "", err
} }
if err = packet.SerializeEncryptedKey(w, pub, cf, symKey.Key, nil); err != nil { if err = packet.SerializeEncryptedKey(w, pub, cf, symKey.Key, nil); err != nil {
err = fmt.Errorf("pm-crypto: cannot set key: %v", err) err = fmt.Errorf("gopenpgp: cannot set key: %v", err)
return "", err return "", err
} }
if err = w.Close(); err != nil { if err = w.Close(); err != nil {
err = fmt.Errorf("pm-crypto: cannot set key: %v", err) err = fmt.Errorf("gopenpgp: cannot set key: %v", err)
return "", err return "", err
} }
return b.String(), nil return b.String(), nil
} }
// IsKeyExpiredBin checks if the given key is expired. Input in binary format // IsKeyExpiredBin checks whether the given (unarmored, binary) key is expired.
func (pgp *GopenPGP) IsKeyExpiredBin(publicKey []byte) (bool, error) { func (pgp *GopenPGP) IsKeyExpiredBin(publicKey []byte) (bool, error) {
now := pgp.getNow() now := pgp.getNow()
pubKeyReader := bytes.NewReader(publicKey) pubKeyReader := bytes.NewReader(publicKey)
@ -333,7 +332,7 @@ const (
failed = 3 failed = 3
) )
// IsKeyExpired checks if the given key is expired. Input in armored format // IsKeyExpired checks whether the given armored key is expired.
func (pgp *GopenPGP) IsKeyExpired(publicKey string) (bool, error) { func (pgp *GopenPGP) IsKeyExpired(publicKey string) (bool, error) {
rawPubKey, err := armor.Unarmor(publicKey) rawPubKey, err := armor.Unarmor(publicKey)
if err != nil { if err != nil {
@ -416,7 +415,7 @@ func (pgp *GopenPGP) generateKey(
return armor.ArmorWithType(serialized, constants.PrivateKeyHeader) return armor.ArmorWithType(serialized, constants.PrivateKeyHeader)
} }
// GenerateRSAKeyWithPrimes generates RSA key with given primes. // GenerateRSAKeyWithPrimes generates a RSA key using the given primes.
func (pgp *GopenPGP) GenerateRSAKeyWithPrimes( func (pgp *GopenPGP) GenerateRSAKeyWithPrimes(
userName, domain, passphrase string, userName, domain, passphrase string,
bits int, bits int,
@ -425,13 +424,16 @@ func (pgp *GopenPGP) GenerateRSAKeyWithPrimes(
return pgp.generateKey(userName, domain, passphrase, "rsa", bits, primeone, primetwo, primethree, primefour) return pgp.generateKey(userName, domain, passphrase, "rsa", bits, primeone, primetwo, primethree, primefour)
} }
// GenerateKey and generate primes // GenerateKey generates a key of the given keyType ("rsa" or "x25519"). If
// keyType is "rsa", bits is the RSA bitsize of the key. If keyType is "x25519",
// bits is unused.
func (pgp *GopenPGP) GenerateKey(userName, domain, passphrase, keyType string, bits int) (string, error) { func (pgp *GopenPGP) GenerateKey(userName, domain, passphrase, keyType string, bits int) (string, error) {
return pgp.generateKey(userName, domain, passphrase, keyType, bits, nil, nil, nil, nil) return pgp.generateKey(userName, domain, passphrase, keyType, bits, nil, nil, nil, nil)
} }
// UpdatePrivateKeyPassphrase decrypts the given private key with oldPhrase and // UpdatePrivateKeyPassphrase decrypts the given armored privateKey with
// re-encrypts with the newPassphrase // oldPassphrase, re-encrypts it with newPassphrase, and returns the new armored
// key.
func (pgp *GopenPGP) UpdatePrivateKeyPassphrase( func (pgp *GopenPGP) UpdatePrivateKeyPassphrase(
privateKey string, oldPassphrase string, newPassphrase string, privateKey string, oldPassphrase string, newPassphrase string,
) (string, error) { ) (string, error) {
@ -477,7 +479,8 @@ func (pgp *GopenPGP) UpdatePrivateKeyPassphrase(
return armor.ArmorWithType(serialized, constants.PrivateKeyHeader) return armor.ArmorWithType(serialized, constants.PrivateKeyHeader)
} }
// CheckKey prints out the key and subkey fingerprint // CheckKey is a debug helper function that prints the key and subkey
// fingerprints.
func (pgp *GopenPGP) CheckKey(pubKey string) (string, error) { func (pgp *GopenPGP) CheckKey(pubKey string) (string, error) {
pubKeyReader := strings.NewReader(pubKey) pubKeyReader := strings.NewReader(pubKey)
entries, err := openpgp.ReadArmoredKeyRing(pubKeyReader) entries, err := openpgp.ReadArmoredKeyRing(pubKeyReader)

View file

@ -88,7 +88,7 @@ func TestEncryptDecryptKeys(t *testing.T) {
Algo: constants.AES256, Algo: constants.AES256,
} }
packet, err := SetKey(rsaPublicKeyRing, testSymmetricKey) packet, err := rsaPublicKeyRing.EncryptKey(testSymmetricKey)
if err != nil { if err != nil {
t.Fatal("Cannot encrypt keypacket with RSA keyring", err) t.Fatal("Cannot encrypt keypacket with RSA keyring", err)
} }
@ -98,7 +98,7 @@ func TestEncryptDecryptKeys(t *testing.T) {
} }
assert.Exactly(t, testSymmetricKey, rsaTestSymmetricKey) assert.Exactly(t, testSymmetricKey, rsaTestSymmetricKey)
packet, err = SetKey(ecPublicKeyRing, testSymmetricKey) packet, err = ecPublicKeyRing.EncryptKey(testSymmetricKey)
if err != nil { if err != nil {
t.Fatal("Cannot encrypt keypacket with EC keyring", err) t.Fatal("Cannot encrypt keypacket with EC keyring", err)
} }

View file

@ -25,19 +25,18 @@ import (
) )
// A keypair contains a private key and a public key. // A keypair contains a private key and a public key.
type pmKeyObject struct { type pgpKeyObject struct {
ID string ID string
Version int Version int
Flags int Flags int
Fingerprint string Fingerprint string
PublicKey string `json:",omitempty"` PublicKey string `json:",omitempty"`
PrivateKey string PrivateKey string
//Activation string // Undocumented
Primary int Primary int
} }
// PrivateKeyReader // PrivateKeyReader
func (ko *pmKeyObject) PrivateKeyReader() io.Reader { func (ko *pgpKeyObject) PrivateKeyReader() io.Reader {
return strings.NewReader(ko.PrivateKey) return strings.NewReader(ko.PrivateKey)
} }
@ -61,7 +60,7 @@ type SignedString struct {
Signed *Signature Signed *Signature
} }
var errKeyringNotUnlocked = errors.New("pm-crypto: cannot sign message, key ring is not unlocked") var errKeyringNotUnlocked = errors.New("gopenpgp: cannot sign message, key ring is not unlocked")
// Err returns a non-nil error if the signature is invalid. // Err returns a non-nil error if the signature is invalid.
func (s *Signature) Err() error { func (s *Signature) Err() error {
@ -377,7 +376,7 @@ func (kr *KeyRing) DecryptArmored(r io.Reader) (decrypted io.Reader, signed *Sig
} }
if block.Type != constants.PGPMessageHeader { if block.Type != constants.PGPMessageHeader {
err = errors.New("pm-crypto: not an armored PGP message") err = errors.New("gopenpgp: not an armored PGP message")
return return
} }
@ -510,7 +509,7 @@ func (kr *KeyRing) readFrom(r io.Reader, armored bool) error {
} }
if len(entities) == 0 { if len(entities) == 0 {
return errors.New("pm-crypto: key ring doesn't contain any key") return errors.New("gopenpgp: key ring doesn't contain any key")
} }
kr.entities = append(kr.entities, entities...) kr.entities = append(kr.entities, entities...)
@ -547,7 +546,7 @@ func (pgp *GopenPGP) BuildKeyRingArmored(key string) (kr *KeyRing, err error) {
func (kr *KeyRing) UnmarshalJSON(b []byte) (err error) { func (kr *KeyRing) UnmarshalJSON(b []byte) (err error) {
kr.entities = nil kr.entities = nil
keyObjs := []pmKeyObject{} keyObjs := []pgpKeyObject{}
if err = json.Unmarshal(b, &keyObjs); err != nil { if err = json.Unmarshal(b, &keyObjs); err != nil {
return return
} }

View file

@ -121,11 +121,11 @@ func TestKeyRing_ArmoredPublicKeyString(t *testing.T) {
func TestCheckPassphrase(t *testing.T) { func TestCheckPassphrase(t *testing.T) {
encryptedKeyRing, _ := ReadArmoredKeyRing(strings.NewReader(readTestFile("keyring_privateKey", false))) encryptedKeyRing, _ := ReadArmoredKeyRing(strings.NewReader(readTestFile("keyring_privateKey", false)))
is_correct := encryptedKeyRing.CheckPassphrase("Wrong password") isCorrect := encryptedKeyRing.CheckPassphrase("Wrong password")
assert.Exactly(t, false, is_correct) assert.Exactly(t, false, isCorrect)
is_correct = encryptedKeyRing.CheckPassphrase(testMailboxPassword) isCorrect = encryptedKeyRing.CheckPassphrase(testMailboxPassword)
assert.Exactly(t, true, is_correct) assert.Exactly(t, true, isCorrect)
} }
func TestIdentities(t *testing.T) { func TestIdentities(t *testing.T) {

View file

@ -66,7 +66,7 @@ func decryptCore(
) (*openpgp.MessageDetails, error) { ) (*openpgp.MessageDetails, error) {
rawPwd := []byte(passphrase) rawPwd := []byte(passphrase)
if err := privKey.Unlock(rawPwd); err != nil { if err := privKey.Unlock(rawPwd); err != nil {
err = fmt.Errorf("pm-crypto: cannot decrypt passphrase: %v", err) err = fmt.Errorf("gopenpgp: cannot decrypt passphrase: %v", err)
return nil, err return nil, err
} }

View file

@ -7,7 +7,7 @@ import (
"net/textproto" "net/textproto"
"strings" "strings"
pmmime "github.com/ProtonMail/go-mime" gomime "github.com/ProtonMail/go-mime"
"golang.org/x/crypto/openpgp" "golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/packet" "golang.org/x/crypto/openpgp/packet"
@ -15,7 +15,7 @@ import (
func (pgp GopenPGP) parseMIME( func (pgp GopenPGP) parseMIME(
mimeBody string, verifierKey *KeyRing, mimeBody string, verifierKey *KeyRing,
) (*pmmime.BodyCollector, int, []string, []string, error) { ) (*gomime.BodyCollector, int, []string, []string, error) {
mm, err := mail.ReadMessage(strings.NewReader(mimeBody)) mm, err := mail.ReadMessage(strings.NewReader(mimeBody))
if err != nil { if err != nil {
return nil, 0, nil, nil, err return nil, 0, nil, nil, err
@ -28,10 +28,10 @@ func (pgp GopenPGP) parseMIME(
return nil, 0, nil, nil, err return nil, 0, nil, nil, err
} }
printAccepter := pmmime.NewMIMEPrinter() printAccepter := gomime.NewMIMEPrinter()
bodyCollector := pmmime.NewBodyCollector(printAccepter) bodyCollector := gomime.NewBodyCollector(printAccepter)
attachmentsCollector := pmmime.NewAttachmentsCollector(bodyCollector) attachmentsCollector := gomime.NewAttachmentsCollector(bodyCollector)
mimeVisitor := pmmime.NewMimeVisitor(attachmentsCollector) mimeVisitor := gomime.NewMimeVisitor(attachmentsCollector)
var pgpKering openpgp.KeyRing var pgpKering openpgp.KeyRing
if verifierKey != nil { if verifierKey != nil {
@ -40,7 +40,7 @@ func (pgp GopenPGP) parseMIME(
signatureCollector := newSignatureCollector(mimeVisitor, pgpKering, config) signatureCollector := newSignatureCollector(mimeVisitor, pgpKering, config)
err = pmmime.VisitAll(bytes.NewReader(mmBodyData), h, signatureCollector) err = gomime.VisitAll(bytes.NewReader(mmBodyData), h, signatureCollector)
verified := signatureCollector.verified verified := signatureCollector.verified
body := bodyCollector body := bodyCollector
@ -50,17 +50,17 @@ func (pgp GopenPGP) parseMIME(
return body, verified, atts, attHeaders, err return body, verified, atts, attHeaders, err
} }
// MIMECallbacks defines a call back methods to process MIME message // MIMECallbacks defines callback methods to process a MIME message.
type MIMECallbacks interface { type MIMECallbacks interface {
OnBody(body string, mimetype string) OnBody(body string, mimetype string)
OnAttachment(headers string, data []byte) OnAttachment(headers string, data []byte)
// Encrypted headers can be an attachment and thus be placed at the end of the mime structure // Encrypted headers can be in an attachment and thus be placed at the end of the mime structure.
OnEncryptedHeaders(headers string) OnEncryptedHeaders(headers string)
OnVerified(verified int) OnVerified(verified int)
OnError(err error) OnError(err error)
} }
// DecryptMIMEMessage decrypts a MIME message // DecryptMIMEMessage decrypts a MIME message.
func (pgp *GopenPGP) DecryptMIMEMessage( func (pgp *GopenPGP) DecryptMIMEMessage(
encryptedText string, verifierKey, privateKeyRing *KeyRing, encryptedText string, verifierKey, privateKeyRing *KeyRing,
passphrase string, callbacks MIMECallbacks, verifyTime int64, passphrase string, callbacks MIMECallbacks, verifyTime int64,

View file

@ -13,7 +13,7 @@ import (
"golang.org/x/crypto/openpgp/packet" "golang.org/x/crypto/openpgp/packet"
) )
// RandomToken with a default key size // RandomToken generates a random token with the key size of the default cipher.
func (pgp *GopenPGP) RandomToken() ([]byte, error) { func (pgp *GopenPGP) RandomToken() ([]byte, error) {
config := &packet.Config{DefaultCipher: packet.CipherAES256} config := &packet.Config{DefaultCipher: packet.CipherAES256}
keySize := config.DefaultCipher.KeySize() keySize := config.DefaultCipher.KeySize()
@ -24,7 +24,7 @@ func (pgp *GopenPGP) RandomToken() ([]byte, error) {
return symKey, nil return symKey, nil
} }
// RandomTokenWith a given key size // RandomTokenWith generates a random token with the given key size.
func (pgp *GopenPGP) RandomTokenWith(size int) ([]byte, error) { func (pgp *GopenPGP) RandomTokenWith(size int) ([]byte, error) {
config := &packet.Config{DefaultCipher: packet.CipherAES256} config := &packet.Config{DefaultCipher: packet.CipherAES256}
symKey := make([]byte, size) symKey := make([]byte, size)
@ -34,12 +34,13 @@ func (pgp *GopenPGP) RandomTokenWith(size int) ([]byte, error) {
return symKey, nil return symKey, nil
} }
// GetSessionFromKeyPacket gets session key no encoding in and out // GetSessionFromKeyPacket returns the decrypted session key from a binary
// public-key encrypted session key packet.
func (pgp *GopenPGP) GetSessionFromKeyPacket( func (pgp *GopenPGP) GetSessionFromKeyPacket(
keyPackage []byte, privateKey *KeyRing, passphrase string, keyPacket []byte, privateKey *KeyRing, passphrase string,
) (*SymmetricKey, ) (*SymmetricKey,
error) { error) {
keyReader := bytes.NewReader(keyPackage) keyReader := bytes.NewReader(keyPacket)
packets := packet.NewReader(keyReader) packets := packet.NewReader(keyReader)
var p packet.Packet var p packet.Packet
@ -72,7 +73,8 @@ func (pgp *GopenPGP) GetSessionFromKeyPacket(
return getSessionSplit(ek) return getSessionSplit(ek)
} }
// KeyPacketWithPublicKey returns binary packet from symmetric key and armored public key // KeyPacketWithPublicKey encrypts the session key with the armored publicKey
// and returns a binary public-key encrypted session key packet.
func (pgp *GopenPGP) KeyPacketWithPublicKey(sessionSplit *SymmetricKey, publicKey string) ([]byte, error) { func (pgp *GopenPGP) KeyPacketWithPublicKey(sessionSplit *SymmetricKey, publicKey string) ([]byte, error) {
pubkeyRaw, err := armor.Unarmor(publicKey) pubkeyRaw, err := armor.Unarmor(publicKey)
if err != nil { if err != nil {
@ -81,7 +83,8 @@ func (pgp *GopenPGP) KeyPacketWithPublicKey(sessionSplit *SymmetricKey, publicKe
return pgp.KeyPacketWithPublicKeyBin(sessionSplit, pubkeyRaw) return pgp.KeyPacketWithPublicKeyBin(sessionSplit, pubkeyRaw)
} }
// KeyPacketWithPublicKeyBin returns binary packet from symmetric key and binary public key // KeyPacketWithPublicKeyBin encrypts the session key with the unarmored
// publicKey and returns a binary public-key encrypted session key packet.
func (pgp *GopenPGP) KeyPacketWithPublicKeyBin(sessionSplit *SymmetricKey, publicKey []byte) ([]byte, error) { func (pgp *GopenPGP) KeyPacketWithPublicKeyBin(sessionSplit *SymmetricKey, publicKey []byte) ([]byte, error) {
publicKeyReader := bytes.NewReader(publicKey) publicKeyReader := bytes.NewReader(publicKey)
pubKeyEntries, err := openpgp.ReadKeyRing(publicKeyReader) pubKeyEntries, err := openpgp.ReadKeyRing(publicKeyReader)
@ -123,15 +126,16 @@ func (pgp *GopenPGP) KeyPacketWithPublicKeyBin(sessionSplit *SymmetricKey, publi
} }
if err = packet.SerializeEncryptedKey(outbuf, pub, cf, sessionSplit.Key, nil); err != nil { if err = packet.SerializeEncryptedKey(outbuf, pub, cf, sessionSplit.Key, nil); err != nil {
err = fmt.Errorf("pm-crypto: cannot set key: %v", err) err = fmt.Errorf("gopenpgp: cannot set key: %v", err)
return nil, err return nil, err
} }
return outbuf.Bytes(), nil return outbuf.Bytes(), nil
} }
// GetSessionFromSymmetricPacket extracts symmentric key from binary packet // GetSessionFromSymmetricPacket decrypts the binary symmetrically encrypted
func (pgp *GopenPGP) GetSessionFromSymmetricPacket(keyPackage []byte, password string) (*SymmetricKey, error) { // session key packet and returns the session key.
keyReader := bytes.NewReader(keyPackage) func (pgp *GopenPGP) GetSessionFromSymmetricPacket(keyPacket []byte, password string) (*SymmetricKey, error) {
keyReader := bytes.NewReader(keyPacket)
packets := packet.NewReader(keyReader) packets := packet.NewReader(keyReader)
var symKeys []*packet.SymmetricKeyEncrypted var symKeys []*packet.SymmetricKeyEncrypted
@ -167,7 +171,8 @@ func (pgp *GopenPGP) GetSessionFromSymmetricPacket(keyPackage []byte, password s
return nil, errors.New("password incorrect") return nil, errors.New("password incorrect")
} }
// SymmetricKeyPacketWithPassword return binary packet from symmetric key and password // SymmetricKeyPacketWithPassword encrypts the session key with the password and
// returns a binary symmetrically encrypted session key packet.
func (pgp *GopenPGP) SymmetricKeyPacketWithPassword(sessionSplit *SymmetricKey, password string) ([]byte, error) { func (pgp *GopenPGP) SymmetricKeyPacketWithPassword(sessionSplit *SymmetricKey, password string) ([]byte, error) {
outbuf := &bytes.Buffer{} outbuf := &bytes.Buffer{}

View file

@ -7,7 +7,7 @@ import (
"mime" "mime"
"net/textproto" "net/textproto"
"github.com/ProtonMail/go-mime" gomime "github.com/ProtonMail/go-mime"
"golang.org/x/crypto/openpgp" "golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/packet" "golang.org/x/crypto/openpgp/packet"
@ -17,13 +17,13 @@ import (
type SignatureCollector struct { type SignatureCollector struct {
config *packet.Config config *packet.Config
keyring openpgp.KeyRing keyring openpgp.KeyRing
target pmmime.VisitAcceptor target gomime.VisitAcceptor
signature string signature string
verified int verified int
} }
func newSignatureCollector( func newSignatureCollector(
targetAcceptor pmmime.VisitAcceptor, keyring openpgp.KeyRing, config *packet.Config, targetAcceptor gomime.VisitAcceptor, keyring openpgp.KeyRing, config *packet.Config,
) *SignatureCollector { ) *SignatureCollector {
return &SignatureCollector{ return &SignatureCollector{
target: targetAcceptor, target: targetAcceptor,
@ -39,10 +39,10 @@ func (sc *SignatureCollector) Accept(
) (err error) { ) (err error) {
parentMediaType, params, _ := mime.ParseMediaType(header.Get("Content-Type")) parentMediaType, params, _ := mime.ParseMediaType(header.Get("Content-Type"))
if parentMediaType == "multipart/signed" { if parentMediaType == "multipart/signed" {
newPart, rawBody := pmmime.GetRawMimePart(part, "--"+params["boundary"]) newPart, rawBody := gomime.GetRawMimePart(part, "--"+params["boundary"])
var multiparts []io.Reader var multiparts []io.Reader
var multipartHeaders []textproto.MIMEHeader var multipartHeaders []textproto.MIMEHeader
if multiparts, multipartHeaders, err = pmmime.GetMultipartParts(newPart, params); err == nil { if multiparts, multipartHeaders, err = gomime.GetMultipartParts(newPart, params); err == nil {
hasPlainChild := false hasPlainChild := false
for _, header := range multipartHeaders { for _, header := range multipartHeaders {
mediaType, _, _ := mime.ParseMediaType(header.Get("Content-Type")) mediaType, _, _ := mime.ParseMediaType(header.Get("Content-Type"))
@ -77,7 +77,7 @@ func (sc *SignatureCollector) Accept(
return err return err
} }
decodedPart := pmmime.DecodeContentEncoding( decodedPart := gomime.DecodeContentEncoding(
bytes.NewReader(partData), bytes.NewReader(partData),
multipartHeaders[1].Get("Content-Transfer-Encoding")) multipartHeaders[1].Get("Content-Transfer-Encoding"))
@ -85,7 +85,7 @@ func (sc *SignatureCollector) Accept(
if err != nil { if err != nil {
return err return err
} }
buffer, err = pmmime.DecodeCharset(buffer, params) buffer, err = gomime.DecodeCharset(buffer, params)
if err != nil { if err != nil {
return err return err
} }

View file

@ -1,9 +1,8 @@
package: proton/gopenpgp package: github.com/ProtonMail/gopenpgp
import: import:
- package: golang.org/x/crypto - package: golang.org/x/crypto
version: master
repo: https://github.com/ProtonMail/crypto.git repo: https://github.com/ProtonMail/crypto.git
version: 9e4251120d8c43f10024d798bc6dde21d40704a0 version: master
- package: github.com/ProtonMail/go-mime - package: github.com/ProtonMail/go-mime
repo: https://github.com/ProtonMail/go-mime.git repo: https://github.com/ProtonMail/go-mime.git
version: master

View file

@ -1,8 +1,9 @@
package internal package internal
import ( import (
"github.com/ProtonMail/gopenpgp/constants"
"regexp" "regexp"
"github.com/ProtonMail/gopenpgp/constants"
) )
// TrimNewlines removes a whitespace in the end of string (don't stop on linebreak) // TrimNewlines removes a whitespace in the end of string (don't stop on linebreak)
@ -15,7 +16,7 @@ func TrimNewlines(input string) string {
// created in the future, to compensate for clock skew // created in the future, to compensate for clock skew
const CreationTimeOffset = int64(60 * 60 * 24 * 2) const CreationTimeOffset = int64(60 * 60 * 24 * 2)
// ArmorHeaders from golang pm-crypto // ArmorHeaders from gopenpgp
var ArmorHeaders = map[string]string{ var ArmorHeaders = map[string]string{
"Version": constants.ArmorHeaderVersion, "Version": constants.ArmorHeaderVersion,
"Comment": constants.ArmorHeaderComment, "Comment": constants.ArmorHeaderComment,