feat: migrate to gopenpgp v2

This commit is contained in:
James Houlahan
2020-06-05 09:33:37 +02:00
parent de16f6f2d1
commit c19bb0fa97
54 changed files with 928 additions and 684 deletions

View File

@ -0,0 +1,76 @@
// Copyright (c) 2020 Proton Technologies AG
//
// This file is part of ProtonMail Bridge.
//
// ProtonMail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ProtonMail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
package smtp
import (
"testing"
"github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/assert"
)
func TestThing(t *testing.T) {
// Load the key.
key, err := crypto.NewKeyFromArmored(testPublicKey)
if err != nil {
panic(err)
}
// Put it in a keyring.
keyRing, err := crypto.NewKeyRing(key)
if err != nil {
panic(err)
}
// Filter out expired ones.
validKeyRings, err := crypto.FilterExpiredKeys([]*crypto.KeyRing{keyRing})
if err != nil {
panic(err)
}
// Filtering shouldn't make them unequal.
assert.True(t, isEqual(keyRing, validKeyRings[0]))
}
func isEqual(a, b *crypto.KeyRing) bool {
if a == nil && b == nil {
return true
}
if a == nil && b != nil || a != nil && b == nil {
return false
}
aKeys, bKeys := a.GetKeys(), b.GetKeys()
if len(aKeys) != len(bKeys) {
return false
}
for i := range aKeys {
aFPs := aKeys[i].GetSHA256Fingerprints()
bFPs := bKeys[i].GetSHA256Fingerprints()
if !cmp.Equal(aFPs, bFPs) {
return false
}
}
return true
}

View File

@ -20,7 +20,7 @@ package smtp
import (
"errors"
pmcrypto "github.com/ProtonMail/gopenpgp/crypto"
"github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/ProtonMail/proton-bridge/internal/events"
"github.com/ProtonMail/proton-bridge/pkg/algo"
"github.com/ProtonMail/proton-bridge/pkg/listener"
@ -37,7 +37,7 @@ type SendingInfo struct {
Sign bool
Scheme int
MIMEType string
PublicKey *pmcrypto.KeyRing
PublicKey *crypto.KeyRing
}
func generateSendingInfo(
@ -46,10 +46,10 @@ func generateSendingInfo(
isInternal bool,
composeMode string,
apiKeys,
contactKeys []*pmcrypto.KeyRing,
contactKeys []*crypto.KeyRing,
settingsSign bool,
settingsPgpScheme int) (sendingInfo SendingInfo, err error) {
contactKeys, err = pmcrypto.FilterExpiredKeys(contactKeys)
contactKeys, err = crypto.FilterExpiredKeys(contactKeys)
if err != nil {
return
}
@ -72,7 +72,7 @@ func generateInternalSendingInfo(
contactMeta *ContactMetadata,
composeMode string,
apiKeys,
contactKeys []*pmcrypto.KeyRing,
contactKeys []*crypto.KeyRing,
settingsSign bool, //nolint[unparam]
settingsPgpScheme int) (sendingInfo SendingInfo, err error) { //nolint[unparam]
// If sending internally, there should always be a public key; if not, there's an error.
@ -125,7 +125,7 @@ func generateExternalSendingInfo(
contactMeta *ContactMetadata,
composeMode string,
apiKeys,
contactKeys []*pmcrypto.KeyRing,
contactKeys []*crypto.KeyRing,
settingsSign bool,
settingsPgpScheme int) (sendingInfo SendingInfo, err error) {
// The default settings, unless overridden by presence of a saved contact.
@ -230,14 +230,27 @@ func schemeAndMIME(contact *ContactMetadata, settingsScheme int, settingsMIMETyp
// checkContactKeysAgainstAPI keeps only those contact keys which are up to date and have
// an ID that matches an API key's ID.
func checkContactKeysAgainstAPI(contactKeys, apiKeys []*pmcrypto.KeyRing) (filteredKeys []*pmcrypto.KeyRing, err error) { //nolint[unparam]
func checkContactKeysAgainstAPI(contactKeys, apiKeys []*crypto.KeyRing) (filteredKeys []*crypto.KeyRing, err error) { //nolint[unparam]
keyIDsAreEqual := func(a, b interface{}) bool {
aKey, bKey := a.(*pmcrypto.KeyRing), b.(*pmcrypto.KeyRing)
return aKey.GetEntities()[0].PrimaryKey.KeyId == bKey.GetEntities()[0].PrimaryKey.KeyId
aKey, bKey := a.(*crypto.KeyRing), b.(*crypto.KeyRing)
aFirst, getKeyErr := aKey.GetKey(0)
if getKeyErr != nil {
err = errors.New("missing primary key")
return false
}
bFirst, getKeyErr := bKey.GetKey(0)
if getKeyErr != nil {
err = errors.New("missing primary key")
return false
}
return aFirst.GetKeyID() == bFirst.GetKeyID()
}
for _, v := range algo.SetIntersection(contactKeys, apiKeys, keyIDsAreEqual) {
filteredKeys = append(filteredKeys, v.(*pmcrypto.KeyRing))
filteredKeys = append(filteredKeys, v.(*crypto.KeyRing))
}
return

View File

@ -18,15 +18,15 @@
package smtp
import (
"strings"
"testing"
pmcrypto "github.com/ProtonMail/gopenpgp/crypto"
"github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/ProtonMail/proton-bridge/internal/events"
"github.com/ProtonMail/proton-bridge/internal/users"
"github.com/ProtonMail/proton-bridge/pkg/listener"
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
"github.com/golang/mock/gomock"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/assert"
)
@ -46,8 +46,8 @@ func initMocks(t *testing.T) mocks {
type args struct {
eventListener listener.Listener
contactMeta *ContactMetadata
apiKeys []*pmcrypto.KeyRing
contactKeys []*pmcrypto.KeyRing
apiKeys []*crypto.KeyRing
contactKeys []*crypto.KeyRing
composeMode string
settingsPgpScheme int
settingsSign bool
@ -68,18 +68,61 @@ func (tt *testData) runTest(t *testing.T) {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, gotSendingInfo, tt.wantSendingInfo)
assert.Equal(t, gotSendingInfo.Encrypt, tt.wantSendingInfo.Encrypt)
assert.Equal(t, gotSendingInfo.Sign, tt.wantSendingInfo.Sign)
assert.Equal(t, gotSendingInfo.Scheme, tt.wantSendingInfo.Scheme)
assert.Equal(t, gotSendingInfo.MIMEType, tt.wantSendingInfo.MIMEType)
assert.True(t, keyRingsAreEqual(gotSendingInfo.PublicKey, tt.wantSendingInfo.PublicKey))
}
})
}
func keyRingFromKey(publicKey string) *crypto.KeyRing {
key, err := crypto.NewKeyFromArmored(publicKey)
if err != nil {
panic(err)
}
kr, err := crypto.NewKeyRing(key)
if err != nil {
panic(err)
}
return kr
}
func keyRingsAreEqual(a, b *crypto.KeyRing) bool {
if a == nil && b == nil {
return true
}
if a == nil && b != nil || a != nil && b == nil {
return false
}
aKeys, bKeys := a.GetKeys(), b.GetKeys()
if len(aKeys) != len(bKeys) {
return false
}
for i := range aKeys {
aFPs := aKeys[i].GetSHA256Fingerprints()
bFPs := bKeys[i].GetSHA256Fingerprints()
if !cmp.Equal(aFPs, bFPs) {
return false
}
}
return true
}
func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
m := initMocks(t)
pubKey, err := pmcrypto.ReadArmoredKeyRing(strings.NewReader(testPublicKey))
if err != nil {
panic(err)
}
pubKey := keyRingFromKey(testPublicKey)
tests := []testData{
{
@ -88,8 +131,8 @@ func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
contactMeta: nil,
isInternal: true,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{pubKey},
contactKeys: []*pmcrypto.KeyRing{},
apiKeys: []*crypto.KeyRing{pubKey},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
@ -107,8 +150,8 @@ func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
contactMeta: nil,
isInternal: true,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{pubKey},
contactKeys: []*pmcrypto.KeyRing{},
apiKeys: []*crypto.KeyRing{pubKey},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPInlinePackage,
},
@ -126,8 +169,8 @@ func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
contactMeta: nil,
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{},
contactKeys: []*pmcrypto.KeyRing{},
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
@ -145,8 +188,8 @@ func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
contactMeta: nil,
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{},
contactKeys: []*pmcrypto.KeyRing{},
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPInlinePackage,
},
@ -164,8 +207,8 @@ func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
contactMeta: nil,
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{},
contactKeys: []*pmcrypto.KeyRing{},
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{},
settingsSign: false,
settingsPgpScheme: pmapi.PGPInlinePackage,
},
@ -183,8 +226,8 @@ func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
eventListener: m.eventListener,
contactMeta: nil,
isInternal: true,
apiKeys: []*pmcrypto.KeyRing{},
contactKeys: []*pmcrypto.KeyRing{pubKey},
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{pubKey},
},
wantSendingInfo: SendingInfo{},
wantErr: true,
@ -195,8 +238,8 @@ func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
contactMeta: nil,
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{pubKey},
contactKeys: []*pmcrypto.KeyRing{},
apiKeys: []*crypto.KeyRing{pubKey},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
@ -217,20 +260,11 @@ func TestGenerateSendingInfo_WithoutContact(t *testing.T) {
func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
m := initMocks(t)
pubKey, err := pmcrypto.ReadArmoredKeyRing(strings.NewReader(testPublicKey))
if err != nil {
panic(err)
}
pubKey := keyRingFromKey(testPublicKey)
preferredPubKey, err := pmcrypto.ReadArmoredKeyRing(strings.NewReader(testPublicKey))
if err != nil {
panic(err)
}
preferredPubKey := keyRingFromKey(testPublicKey)
differentPubKey, err := pmcrypto.ReadArmoredKeyRing(strings.NewReader(testDifferentPublicKey))
if err != nil {
panic(err)
}
differentPubKey := keyRingFromKey(testDifferentPublicKey)
m.eventListener.EXPECT().Emit(events.NoActiveKeyForRecipientEvent, "badkey@email.com")
@ -241,8 +275,8 @@ func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
isInternal: true,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{pubKey},
contactKeys: []*pmcrypto.KeyRing{},
apiKeys: []*crypto.KeyRing{pubKey},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
@ -260,8 +294,8 @@ func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
isInternal: true,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{pubKey},
contactKeys: []*pmcrypto.KeyRing{pubKey},
apiKeys: []*crypto.KeyRing{pubKey},
contactKeys: []*crypto.KeyRing{pubKey},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
@ -279,8 +313,8 @@ func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
isInternal: true,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{preferredPubKey},
contactKeys: []*pmcrypto.KeyRing{pubKey},
apiKeys: []*crypto.KeyRing{preferredPubKey},
contactKeys: []*crypto.KeyRing{pubKey},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
@ -299,8 +333,8 @@ func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
contactMeta: &ContactMetadata{Email: "badkey@email.com", Encrypt: true, Scheme: "pgp-mime"},
isInternal: true,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{pubKey},
contactKeys: []*pmcrypto.KeyRing{differentPubKey},
apiKeys: []*crypto.KeyRing{pubKey},
contactKeys: []*crypto.KeyRing{differentPubKey},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
@ -313,8 +347,8 @@ func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{pubKey},
contactKeys: []*pmcrypto.KeyRing{},
apiKeys: []*crypto.KeyRing{pubKey},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
@ -332,8 +366,8 @@ func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{pubKey},
contactKeys: []*pmcrypto.KeyRing{differentPubKey},
apiKeys: []*crypto.KeyRing{pubKey},
contactKeys: []*crypto.KeyRing{differentPubKey},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
@ -352,15 +386,9 @@ func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
}
func TestGenerateSendingInfo_Contact_External(t *testing.T) {
pubKey, err := pmcrypto.ReadArmoredKeyRing(strings.NewReader(testPublicKey))
if err != nil {
panic(err)
}
pubKey := keyRingFromKey(testPublicKey)
expiredPubKey, err := pmcrypto.ReadArmoredKeyRing(strings.NewReader(testExpiredPublicKey))
if err != nil {
panic(err)
}
expiredPubKey := keyRingFromKey(testExpiredPublicKey)
tests := []testData{
{
@ -369,8 +397,8 @@ func TestGenerateSendingInfo_Contact_External(t *testing.T) {
contactMeta: &ContactMetadata{},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{},
contactKeys: []*pmcrypto.KeyRing{},
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
@ -388,8 +416,8 @@ func TestGenerateSendingInfo_Contact_External(t *testing.T) {
contactMeta: &ContactMetadata{},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{},
contactKeys: []*pmcrypto.KeyRing{expiredPubKey},
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{expiredPubKey},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
@ -407,8 +435,8 @@ func TestGenerateSendingInfo_Contact_External(t *testing.T) {
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{},
contactKeys: []*pmcrypto.KeyRing{pubKey},
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{pubKey},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
@ -426,8 +454,8 @@ func TestGenerateSendingInfo_Contact_External(t *testing.T) {
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-inline"},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{},
contactKeys: []*pmcrypto.KeyRing{pubKey},
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{pubKey},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
@ -445,8 +473,8 @@ func TestGenerateSendingInfo_Contact_External(t *testing.T) {
contactMeta: &ContactMetadata{Encrypt: true},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{},
contactKeys: []*pmcrypto.KeyRing{pubKey},
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{pubKey},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
@ -464,8 +492,8 @@ func TestGenerateSendingInfo_Contact_External(t *testing.T) {
contactMeta: &ContactMetadata{},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{},
contactKeys: []*pmcrypto.KeyRing{},
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPInlinePackage,
},
@ -483,8 +511,8 @@ func TestGenerateSendingInfo_Contact_External(t *testing.T) {
contactMeta: &ContactMetadata{MIMEType: pmapi.ContentTypePlainText},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{},
contactKeys: []*pmcrypto.KeyRing{},
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPInlinePackage,
},
@ -502,8 +530,8 @@ func TestGenerateSendingInfo_Contact_External(t *testing.T) {
contactMeta: &ContactMetadata{SignMissing: true},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*pmcrypto.KeyRing{},
contactKeys: []*pmcrypto.KeyRing{},
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPInlinePackage,
},

View File

@ -20,13 +20,13 @@ package smtp
import (
"io"
pmcrypto "github.com/ProtonMail/gopenpgp/crypto"
"github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
)
type storeUserProvider interface {
CreateDraft(
kr *pmcrypto.KeyRing,
kr *crypto.KeyRing,
message *pmapi.Message,
attachmentReaders []io.Reader,
attachedPublicKey,

View File

@ -20,7 +20,6 @@
package smtp
import (
"bytes"
"encoding/base64"
"fmt"
"io"
@ -32,7 +31,7 @@ import (
"strings"
"time"
pmcrypto "github.com/ProtonMail/gopenpgp/crypto"
"github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/ProtonMail/proton-bridge/internal/events"
"github.com/ProtonMail/proton-bridge/pkg/listener"
"github.com/ProtonMail/proton-bridge/pkg/message"
@ -93,16 +92,26 @@ func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err
err = errors.New("backend: invalid email address: not owned by user")
return
}
kr := addr.KeyRing()
kr, err := su.client().KeyRingForAddressID(addr.ID)
if err != nil {
return
}
var attachedPublicKey string
var attachedPublicKeyName string
if mailSettings.AttachPublicKey > 0 {
attachedPublicKey, err = kr.GetArmoredPublicKey()
firstKey, err := kr.GetKey(0)
if err != nil {
return err
}
attachedPublicKeyName = "publickey - " + kr.Identities()[0].Name
attachedPublicKey, err = firstKey.GetArmoredPublicKey()
if err != nil {
return err
}
attachedPublicKeyName = "publickey - " + kr.GetIdentities()[0].Name
}
message, mimeBody, plainBody, attReaders, err := message.Parse(messageReader, attachedPublicKey, attachedPublicKeyName)
@ -171,7 +180,7 @@ func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err
atts = append(atts, message.Attachments...)
// Decrypt attachment keys, because we will need to re-encrypt them with the recipients' public keys.
attkeys := make(map[string]*pmcrypto.SymmetricKey)
attkeys := make(map[string]*crypto.SessionKey)
attkeysEncoded := make(map[string]pmapi.AlgoKey)
for _, att := range atts {
@ -203,7 +212,7 @@ func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err
// PMEL 3.
composeMode := message.MIMEType
var plainKey, htmlKey, mimeKey *pmcrypto.SymmetricKey
var plainKey, htmlKey, mimeKey *crypto.SessionKey
var plainData, htmlData, mimeData []byte
containsUnencryptedRecipients := false
@ -219,7 +228,7 @@ func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err
return err
}
var contactMeta *ContactMetadata
var contactKeys []*pmcrypto.KeyRing
var contactKeyRings []*crypto.KeyRing
for _, contactEmail := range contactEmails {
if contactEmail.Defaults == 1 { // WARNING: in doc it says _ignore for now, future feature_
continue
@ -236,12 +245,19 @@ func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err
if err != nil {
return err
}
contactKeyRing, err := crypto.NewKeyRing(nil)
if err != nil {
return err
}
for _, contactRawKey := range contactMeta.Keys {
contactKey, err := pmcrypto.ReadKeyRing(bytes.NewBufferString(contactRawKey))
contactKey, err := crypto.NewKeyFromArmored(contactRawKey)
if err != nil {
return err
}
contactKeys = append(contactKeys, contactKey)
if err := contactKeyRing.AddKey(contactKey); err != nil {
return err
}
contactKeyRings = append(contactKeyRings, contactKeyRing)
}
break // We take the first hit where Defaults == 0, see "How to find the right contact" of PMEL
@ -254,16 +270,22 @@ func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err
return err
}
var apiKeys []*pmcrypto.KeyRing
var apiKeyRings []*crypto.KeyRing
for _, apiRawKey := range apiRawKeyList {
var kr *pmcrypto.KeyRing
if kr, err = pmcrypto.ReadArmoredKeyRing(strings.NewReader(apiRawKey.PublicKey)); err != nil {
key, err := crypto.NewKeyFromArmored(apiRawKey.PublicKey)
if err != nil {
return err
}
apiKeys = append(apiKeys, kr)
kr, err := crypto.NewKeyRing(key)
if err != nil {
return err
}
apiKeyRings = append(apiKeyRings, kr)
}
sendingInfo, err := generateSendingInfo(su.eventListener, contactMeta, isInternal, composeMode, apiKeys, contactKeys, settingsSign, settingsPgpScheme)
sendingInfo, err := generateSendingInfo(su.eventListener, contactMeta, isInternal, composeMode, apiKeyRings, contactKeyRings, settingsSign, settingsPgpScheme)
if !sendingInfo.Encrypt {
containsUnencryptedRecipients = true
}
@ -284,7 +306,7 @@ func (su *smtpUser) Send(from string, to []string, messageReader io.Reader) (err
}
}
if sendingInfo.Scheme == pmapi.PGPMIMEPackage {
mimeBodyPacket, _, err := createPackets(sendingInfo.PublicKey, mimeKey, map[string]*pmcrypto.SymmetricKey{})
mimeBodyPacket, _, err := createPackets(sendingInfo.PublicKey, mimeKey, map[string]*crypto.SessionKey{})
if err != nil {
return err
}

View File

@ -21,7 +21,7 @@ import (
"encoding/base64"
"regexp"
pmcrypto "github.com/ProtonMail/gopenpgp/crypto"
"github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
)
@ -37,9 +37,9 @@ func looksLikeEmail(e string) bool {
}
func createPackets(
pubkey *pmcrypto.KeyRing,
bodyKey *pmcrypto.SymmetricKey,
attkeys map[string]*pmcrypto.SymmetricKey,
pubkey *crypto.KeyRing,
bodyKey *crypto.SessionKey,
attkeys map[string]*crypto.SessionKey,
) (bodyPacket string, attachmentPackets map[string]string, err error) {
// Encrypt message body keys.
packetBytes, err := pubkey.EncryptSessionKey(bodyKey)
@ -61,24 +61,33 @@ func createPackets(
}
func encryptSymmetric(
kr *pmcrypto.KeyRing,
kr *crypto.KeyRing,
textToEncrypt string,
canonicalizeText bool, // nolint[unparam]
) (key *pmcrypto.SymmetricKey, symEncryptedData []byte, err error) {
) (key *crypto.SessionKey, symEncryptedData []byte, err error) {
// We use only primary key to encrypt the message. Our keyring contains all keys (primary, old and deacivated ones).
pgpMessage, err := kr.FirstKey().Encrypt(pmcrypto.NewPlainMessageFromString(textToEncrypt), kr)
firstKey, err := kr.FirstKey()
if err != nil {
return
}
pgpMessage, err := firstKey.Encrypt(crypto.NewPlainMessageFromString(textToEncrypt), kr)
if err != nil {
return
}
pgpSplitMessage, err := pgpMessage.SeparateKeyAndData(len(textToEncrypt), 0)
if err != nil {
return
}
key, err = kr.DecryptSessionKey(pgpSplitMessage.GetBinaryKeyPacket())
if err != nil {
return
}
symEncryptedData = pgpSplitMessage.GetBinaryDataPacket()
return
}
@ -87,7 +96,7 @@ func buildPackage(
sharedScheme int,
mimeType string,
bodyData []byte,
bodyKey *pmcrypto.SymmetricKey,
bodyKey *crypto.SessionKey,
attKeys map[string]pmapi.AlgoKey,
) (pkg *pmapi.MessagePackage) {
if len(addressMap) == 0 {