Files
proton-bridge/internal/smtp/sending_info_test.go
2020-06-16 07:34:46 +00:00

633 lines
19 KiB
Go

// 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/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"
)
type mocks struct {
t *testing.T
eventListener *users.MockListener
}
func initMocks(t *testing.T) mocks {
mockCtrl := gomock.NewController(t)
return mocks{
t: t,
eventListener: users.NewMockListener(mockCtrl),
}
}
type args struct {
eventListener listener.Listener
contactMeta *ContactMetadata
apiKeys []*crypto.KeyRing
contactKeys []*crypto.KeyRing
composeMode string
settingsPgpScheme int
settingsSign bool
isInternal bool
}
type testData struct {
name string
args args
wantSendingInfo SendingInfo
wantErr bool
}
func (tt *testData) runTest(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
gotSendingInfo, err := generateSendingInfo(tt.args.eventListener, tt.args.contactMeta, tt.args.isInternal, tt.args.composeMode, tt.args.apiKeys, tt.args.contactKeys, tt.args.settingsSign, tt.args.settingsPgpScheme)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
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 := keyRingFromKey(testPublicKey)
tests := []testData{
{
name: "internal, PGP_MIME",
args: args{
contactMeta: nil,
isInternal: true,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{pubKey},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
wantSendingInfo: SendingInfo{
Encrypt: true,
Sign: true,
Scheme: pmapi.InternalPackage,
MIMEType: pmapi.ContentTypeHTML,
PublicKey: pubKey,
},
},
{
name: "internal, PGP_INLINE",
args: args{
contactMeta: nil,
isInternal: true,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{pubKey},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPInlinePackage,
},
wantSendingInfo: SendingInfo{
Encrypt: true,
Sign: true,
Scheme: pmapi.InternalPackage,
MIMEType: pmapi.ContentTypeHTML,
PublicKey: pubKey,
},
},
{
name: "external, PGP_MIME",
args: args{
contactMeta: nil,
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
wantSendingInfo: SendingInfo{
Encrypt: false,
Sign: true,
Scheme: pmapi.ClearMIMEPackage,
MIMEType: pmapi.ContentTypeMultipartMixed,
PublicKey: nil,
},
},
{
name: "external, PGP_INLINE",
args: args{
contactMeta: nil,
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPInlinePackage,
},
wantSendingInfo: SendingInfo{
Encrypt: false,
Sign: true,
Scheme: pmapi.ClearPackage,
MIMEType: pmapi.ContentTypePlainText,
PublicKey: nil,
},
},
{
name: "external, PGP_MIME, Unsigned",
args: args{
contactMeta: nil,
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{},
settingsSign: false,
settingsPgpScheme: pmapi.PGPInlinePackage,
},
wantSendingInfo: SendingInfo{
Encrypt: false,
Sign: false,
Scheme: pmapi.ClearPackage,
MIMEType: pmapi.ContentTypeHTML,
PublicKey: nil,
},
},
{
name: "internal, error no valid public key",
args: args{
eventListener: m.eventListener,
contactMeta: nil,
isInternal: true,
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{pubKey},
},
wantSendingInfo: SendingInfo{},
wantErr: true,
},
{
name: "external, no pinned key but receive one via WKD",
args: args{
contactMeta: nil,
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{pubKey},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
wantSendingInfo: SendingInfo{
Encrypt: true,
Sign: true,
Scheme: pmapi.PGPMIMEPackage,
MIMEType: pmapi.ContentTypeMultipartMixed,
PublicKey: pubKey,
},
},
}
for _, tt := range tests {
tt.runTest(t)
}
}
func TestGenerateSendingInfo_Contact_Internal(t *testing.T) {
m := initMocks(t)
pubKey := keyRingFromKey(testPublicKey)
preferredPubKey := keyRingFromKey(testPublicKey)
differentPubKey := keyRingFromKey(testDifferentPublicKey)
m.eventListener.EXPECT().Emit(events.NoActiveKeyForRecipientEvent, "badkey@email.com")
tests := []testData{
{
name: "PGP_MIME, contact wants pgp-mime, no pinned key",
args: args{
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
isInternal: true,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{pubKey},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
wantSendingInfo: SendingInfo{
Encrypt: true,
Sign: true,
Scheme: pmapi.InternalPackage,
MIMEType: pmapi.ContentTypeHTML,
PublicKey: pubKey,
},
},
{
name: "PGP_MIME, contact wants pgp-mime, pinned key",
args: args{
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
isInternal: true,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{pubKey},
contactKeys: []*crypto.KeyRing{pubKey},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
wantSendingInfo: SendingInfo{
Encrypt: true,
Sign: true,
Scheme: pmapi.InternalPackage,
MIMEType: pmapi.ContentTypeHTML,
PublicKey: pubKey,
},
},
{
name: "PGP_MIME, contact wants pgp-mime, pinned key but prefer api key",
args: args{
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
isInternal: true,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{preferredPubKey},
contactKeys: []*crypto.KeyRing{pubKey},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
wantSendingInfo: SendingInfo{
Encrypt: true,
Sign: true,
Scheme: pmapi.InternalPackage,
MIMEType: pmapi.ContentTypeHTML,
PublicKey: preferredPubKey,
},
},
{
name: "internal, found no active key for recipient",
args: args{
eventListener: m.eventListener,
contactMeta: &ContactMetadata{Email: "badkey@email.com", Encrypt: true, Scheme: "pgp-mime"},
isInternal: true,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{pubKey},
contactKeys: []*crypto.KeyRing{differentPubKey},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
wantSendingInfo: SendingInfo{},
wantErr: true,
},
{
name: "external, contact saved, no pinned key but receive one via WKD",
args: args{
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{pubKey},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
wantSendingInfo: SendingInfo{
Encrypt: true,
Sign: true,
Scheme: pmapi.PGPMIMEPackage,
MIMEType: pmapi.ContentTypeMultipartMixed,
PublicKey: pubKey,
},
},
{
name: "external, contact saved, pinned key but receive different one via WKD",
args: args{
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{pubKey},
contactKeys: []*crypto.KeyRing{differentPubKey},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
wantSendingInfo: SendingInfo{
Encrypt: true,
Sign: true,
Scheme: pmapi.PGPMIMEPackage,
MIMEType: pmapi.ContentTypeMultipartMixed,
PublicKey: differentPubKey,
},
},
}
for _, tt := range tests {
tt.runTest(t)
}
}
func TestGenerateSendingInfo_Contact_External(t *testing.T) {
pubKey := keyRingFromKey(testPublicKey)
expiredPubKey := keyRingFromKey(testExpiredPublicKey)
tests := []testData{
{
name: "PGP_MIME, no pinned key",
args: args{
contactMeta: &ContactMetadata{},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
wantSendingInfo: SendingInfo{
Encrypt: false,
Sign: false,
Scheme: pmapi.ClearPackage,
MIMEType: pmapi.ContentTypeHTML,
PublicKey: nil,
},
},
{
name: "PGP_MIME, pinned key but it's expired",
args: args{
contactMeta: &ContactMetadata{},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{expiredPubKey},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
wantSendingInfo: SendingInfo{
Encrypt: false,
Sign: false,
Scheme: pmapi.ClearPackage,
MIMEType: pmapi.ContentTypeHTML,
PublicKey: nil,
},
},
{
name: "PGP_MIME, contact wants pgp-mime, pinned key",
args: args{
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-mime"},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{pubKey},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
wantSendingInfo: SendingInfo{
Encrypt: true,
Sign: true,
Scheme: pmapi.PGPMIMEPackage,
MIMEType: pmapi.ContentTypeMultipartMixed,
PublicKey: pubKey,
},
},
{
name: "PGP_MIME, contact wants pgp-inline, pinned key",
args: args{
contactMeta: &ContactMetadata{Encrypt: true, Scheme: "pgp-inline"},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{pubKey},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
wantSendingInfo: SendingInfo{
Encrypt: true,
Sign: true,
Scheme: pmapi.PGPInlinePackage,
MIMEType: pmapi.ContentTypePlainText,
PublicKey: pubKey,
},
},
{
name: "PGP_MIME, contact wants default scheme, pinned key",
args: args{
contactMeta: &ContactMetadata{Encrypt: true},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{pubKey},
settingsSign: true,
settingsPgpScheme: pmapi.PGPMIMEPackage,
},
wantSendingInfo: SendingInfo{
Encrypt: true,
Sign: true,
Scheme: pmapi.PGPMIMEPackage,
MIMEType: pmapi.ContentTypeMultipartMixed,
PublicKey: pubKey,
},
},
{
name: "PGP_INLINE, contact wants default scheme, no pinned key",
args: args{
contactMeta: &ContactMetadata{},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPInlinePackage,
},
wantSendingInfo: SendingInfo{
Encrypt: false,
Sign: false,
Scheme: pmapi.ClearPackage,
MIMEType: pmapi.ContentTypeHTML,
PublicKey: nil,
},
},
{
name: "PGP_INLINE, contact wants plain text, no pinned key",
args: args{
contactMeta: &ContactMetadata{MIMEType: pmapi.ContentTypePlainText},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPInlinePackage,
},
wantSendingInfo: SendingInfo{
Encrypt: false,
Sign: false,
Scheme: pmapi.ClearPackage,
MIMEType: pmapi.ContentTypePlainText,
PublicKey: nil,
},
},
{
name: "PGP_INLINE, contact sign missing, no pinned key",
args: args{
contactMeta: &ContactMetadata{SignMissing: true},
isInternal: false,
composeMode: pmapi.ContentTypeHTML,
apiKeys: []*crypto.KeyRing{},
contactKeys: []*crypto.KeyRing{},
settingsSign: true,
settingsPgpScheme: pmapi.PGPInlinePackage,
},
wantSendingInfo: SendingInfo{
Encrypt: false,
Sign: true,
Scheme: pmapi.ClearPackage,
MIMEType: pmapi.ContentTypePlainText,
PublicKey: nil,
},
},
}
for _, tt := range tests {
tt.runTest(t)
}
}
const testPublicKey = `
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: OpenPGP.js v0.7.1
Comment: http://openpgpjs.org
xsBNBFRJbc0BCAC0mMLZPDBbtSCWvxwmOfXfJkE2+ssM3ux21LhD/bPiWefE
WSHlCjJ8PqPHy7snSiUuxuj3f9AvXPvg+mjGLBwu1/QsnSP24sl3qD2onl39
vPiLJXUqZs20ZRgnvX70gjkgEzMFBxINiy2MTIG+4RU8QA7y8KzWev0btqKi
MeVa+GLEHhgZ2KPOn4Jv1q4bI9hV0C9NUe2tTXS6/Vv3vbCY7lRR0kbJ65T5
c8CmpqJuASIJNrSXM/Q3NnnsY4kBYH0s5d2FgbASQvzrjuC2rngUg0EoPsrb
DEVRA2/BCJonw7aASiNCrSP92lkZdtYlax/pcoE/mQ4WSwySFmcFT7yFABEB
AAHNBlVzZXJJRMLAcgQQAQgAJgUCVEltzwYLCQgHAwIJED62JZ7fId8kBBUI
AgoDFgIBAhsDAh4BAAD0nQf9EtH9TC0JqSs8q194Zo244jjlJFM3EzxOSULq
0zbywlLORfyoo/O8jU/HIuGz+LT98JDtnltTqfjWgu6pS3ZL2/L4AGUKEoB7
OI6oIdRwzMc61sqI+Qpbzxo7rzufH4CiXZc6cxORUgL550xSCcqnq0q1mds7
h5roKDzxMW6WLiEsc1dN8IQKzC7Ec5wA7U4oNGsJ3TyI8jkIs0IhXrRCd26K
0TW8Xp6GCsfblWXosR13y89WVNgC+xrrJKTZEisc0tRlneIgjcwEUvwfIg2n
9cDUFA/5BsfzTW5IurxqDEziIVP0L44PXjtJrBQaGMPlEbtP5i2oi3OADVX2
XbvsRc7ATQRUSW3PAQgAkPnu5fps5zhOB/e618v/iF3KiogxUeRhA68TbvA+
xnFfTxCx2Vo14aOL0CnaJ8gO5yRSqfomL2O1kMq07N1MGbqucbmc+aSfoElc
+Gd5xBE/w3RcEhKcAaYTi35vG22zlZup4x3ElioyIarOssFEkQgNNyDf5AXZ
jdHLA6qVxeqAb/Ff74+y9HUmLPSsRU9NwFzvK3Jv8C/ubHVLzTYdFgYkc4W1
Uug9Ou08K+/4NEMrwnPFBbZdJAuUjQz2zW2ZiEKiBggiorH2o5N3mYUnWEmU
vqL3EOS8TbWo8UBIW3DDm2JiZR8VrEgvBtc9mVDUj/x+5pR07Fy1D6DjRmAc
9wARAQABwsBfBBgBCAATBQJUSW3SCRA+tiWe3yHfJAIbDAAA/iwH/ik9RKZM
B9Ir0x5mGpKPuqhugwrc3d04m1sOdXJm2NtD4ddzSEvzHwaPNvEvUl5v7FVM
zf6+6mYGWHyNP4+e7RtwYLlRpud6smuGyDSsotUYyumiqP6680ZIeWVQ+a1T
ThNs878mAJy1FhvQFdTmA8XIC616hDFpamQKPlpoO1a0wZnQhrPwT77HDYEE
a+hqY4Jr/a7ui40S+7xYRHKL/7ZAS4/grWllhU3dbNrwSzrOKwrA/U0/9t73
8Ap6JL71YymDeaL4sutcoaahda1pTrMWePtrCltz6uySwbZs7GXoEzjX3EAH
+6qhkUJtzMaE3YEFEoQMGzcDTUEfXCJ3zJw=
=yT9U
-----END PGP PUBLIC KEY BLOCK-----
`
const testDifferentPublicKey = `
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBF2Ix1EBCACwkUAn/5+sO1feDcS+aQ9BskESOyf1tBS8EDyz4deHFqnzoVCx
pJNvF7jb5J0AFCO/I5Mg7ddJb1udd/Eq+aZKfNYgjlvpdnW2Lo6Y0a5I5sm8R+vW
6EPQGxdgT7QG0VbeekGuy+F4o0KrgvJ4Sl3020q/Vix5B8ovtS6LGB22NWn5FGbL
+ssmq3tr3o2Q2jmHEIMTN4LOk1C4oHCljwrl7UP2MrER/if+czva3dB2jQgto6ia
o0+myIHkIjEKz5q7EGaGn9b7TEWk6+qNFRlKSa3GEFy4DXuQuysb+imjuP8uFxwb
/ib4QoOd/lAkrAVrcUHoWWhtBinsGEBXlG0LABEBAAG0GmphbWVzLXRlc3RAcHJv
dG9ubWFpbC5ibHVliQFUBBMBCAA+FiEEIwbxzW52iRgG0YMKojP3Zu/mCXIFAl2I
x1ECGwMFCQPCZwAFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQojP3Zu/mCXJu
iQf+PiGA0sLEHx0gn2TRoYe7NOn9cnbi+KMLPIFJLGG4mAdVnEVNgaEvMGsNnC14
3FNIVaSdIR5/4ebtplZIlJWb8zxyaNTFkOJexnzwLw2p2cMF78Vsc4sAVLL5Y068
0v6KUzSK2cI1D4kvCyVK57jZL5dURCyISQrekYN/qhQb/TXbbUuznIJURTnLIq6k
v3E6SPB0hKksPgYlQaRocICw7ybbFur7gavyYlyZwD22JSGjwkJBSBi9dj14OD5Q
Egrd7E0qMd6BPzdlV9bctRabyUQLVjWFq8Nw4cC8AW7j7ENq6QIsuM2iKPf9M/HR
5U+Q9hUxcaG/Sv72QI7M4Qc4DrkBDQRdiMdRAQgA7Qufpv+RrZzcxYyfRf4SWZu5
Geo4Zke/AzlkTsw3MgMJHxiSXxEZdU4u/NRQeK53sEQ9J5iIuuzdjLbs5ECT4PjI
G8Lw6LtsCQ6WW9Gc7RUQNsXErIYidfk+v2zsJTHkP9aGkAgEe92bu87SSGXKO1In
w3e04wPjXeZ3ZYw2NovtPFNKVqBrglmN2WMTUXqOXNtcHCn/x5hQfuyo41wTol1m
YrZCiWu+Nxt6nEWQHA3hw0Dp8byCd/9yhIbn21cCZbX2aITYZL4pFbemMGfeteZF
eDVDxAXPFtat9pzgFe8wmF1kDrvnEsjvbb5UjmtlWZr0EWGoBkiioVh4/pyVMwAR
AQABiQE2BBgBCAAgFiEEIwbxzW52iRgG0YMKojP3Zu/mCXIFAl2Ix1ECGwwACgkQ
ojP3Zu/mCXLJZAf9Hbfu7FraFdl2DwYO815XFukMCAIUzhIMrLhUFO1WWg/m44bm
6OZ8NockPl8Mx3CjSG5Kjuk9h5AOG/doOVQL+i8ktQ7VsF4G9tBEgcxjacoGvNZH
VP1gFScmnI4rSfduhHf8JKToTJvK/KOFnko4/2fzM2WH3VLu7qZgT3RufuUn5LLn
C7eju/gf4WQZUtMTJODzs/EaHOkFevrJ7c6IIAUWD12sA6WHEC3l/mQuc9iXlyJw
HyMl6JQldr4XCcdTu73uSvVJ/1IkvLiHPuPP9ma9+FClaUGOmUws7rNQ3ODX52tx
bIYA5I4XbBMze46izlbEAKt6wHhQWTGlSpts0A==
=cOfs
-----END PGP PUBLIC KEY BLOCK-----`
const testExpiredPublicKey = `
-----BEGIN PGP PRIVATE KEY BLOCK-----
xcA4BAAAAAEBAgCgONc0J8rfO6cJw5YTP38x1ze2tAYIO7EcmRCNYwMkXngb
0Qdzg34Q5RW0rNiR56VB6KElPUhePRPVklLFiIvHABEBAAEAAf9qabYMzsz/
/LeRVZSsTgTljmJTdzd2ambUbpi+vt8MXJsbaWh71vjoLMWSXajaKSPDjVU5
waFNt9kLqwGGGLqpAQD5ZdMH2XzTq6GU9Ka69iZs6Pbnzwdz59Vc3i8hXlUj
zQEApHargCTsrtvSrm+hK/pN51/BHAy9lxCAw9f2etx+AeMA/RGrijkFZtYt
jeWdv/usXL3mgHvEcJv63N5zcEvDX5X4W1bND3Rlc3QxIDxhQGIuY29tPsJ7
BBABCAAvBQIAAAABBQMAAAU5BgsJBwgDAgkQzcF99nGrkAkEFQgKAgMWAgEC
GQECGwMCHgEAABAlAfwPehmLZs+gOhOTTaSslqQ50bl/REjmv42Nyr1ZBlQS
DECl1Qu4QyeXin29uEXWiekMpNlZVsEuc8icCw6ABhIZ
=/7PI
-----END PGP PRIVATE KEY BLOCK-----`