forked from Silverfish/proton-bridge
feat: migrate to gopenpgp v2
This commit is contained in:
76
internal/smtp/repro_test.go
Normal file
76
internal/smtp/repro_test.go
Normal 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
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
},
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user