diff --git a/ProposalChanges.md b/ProposalChanges.md index acb66ed..d8df1c5 100644 --- a/ProposalChanges.md +++ b/ProposalChanges.md @@ -38,31 +38,6 @@ crypto.PlainMessage struct { } ``` -### pmKeyObject -``` -type pmKeyObject struct { - ID string - Version int - Flags int - Fingerprint string - PublicKey string `json:",omitempty"` - PrivateKey string - Primary int -} -``` -is now -``` -type pgpKeyObject struct { - ID string - Version int - Flags int - PrivateKey string - Primary int - Token string `json:",omitempty"` - Signature string `json:",omitempty"` -} -``` - ### SignedString ``` // SignedString wraps string with Signature @@ -88,6 +63,20 @@ type Signature struct { md *openpgp.MessageDetails } ``` + +### pmKeyObject +``` +type pmKeyObject struct { + ID string + Version int + Flags int + Fingerprint string + PublicKey string `json:",omitempty"` + PrivateKey string + Primary int +} +``` + ## New ### PGPMessage ``` @@ -332,7 +321,7 @@ No change. No change. ### UnmarshalJSON -No change. +Dropped. ### Identities No change diff --git a/crypto/keyring.go b/crypto/keyring.go index b3f8aeb..641ec89 100644 --- a/crypto/keyring.go +++ b/crypto/keyring.go @@ -5,10 +5,8 @@ import ( "crypto/ecdsa" "crypto/rsa" "encoding/hex" - "encoding/json" "errors" "io" - "strings" "time" "golang.org/x/crypto/openpgp" @@ -28,22 +26,6 @@ type KeyRing struct { FirstKeyID string } -// A keypair contains a private key and a public key. -type pgpKeyObject struct { - ID string - Version int - Flags int - PrivateKey string - Primary int - Token *string `json:",omitempty"` - Signature *string `json:",omitempty"` -} - -// PrivateKeyReader -func (ko *pgpKeyObject) PrivateKeyReader() io.Reader { - return strings.NewReader(ko.PrivateKey) -} - // Identity contains the name and the email of a key holder. type Identity struct { Name string @@ -208,8 +190,8 @@ func (keyRing *KeyRing) CheckPassphrase(passphrase string) bool { return n != 0 } -// readFrom reads unarmored and armored keys from r and adds them to the keyring. -func (keyRing *KeyRing) readFrom(r io.Reader, armored bool) error { +// ReadFrom reads unarmored and armored keys from r and adds them to the keyring. +func (keyRing *KeyRing) ReadFrom(r io.Reader, armored bool) error { var err error var entities openpgp.EntityList if armored { @@ -264,7 +246,7 @@ func (keyRing *KeyRing) readFrom(r io.Reader, armored bool) error { func (pgp *GopenPGP) BuildKeyRing(binKeys []byte) (keyRing *KeyRing, err error) { keyRing = &KeyRing{} entriesReader := bytes.NewReader(binKeys) - err = keyRing.readFrom(entriesReader, false) + err = keyRing.ReadFrom(entriesReader, false) return } @@ -286,90 +268,6 @@ func (pgp *GopenPGP) BuildKeyRingArmored(key string) (keyRing *KeyRing, err erro return &KeyRing{entities: keyEntries}, err } -// UnmarshalJSON reads multiple keys from a json array and fills the keyring -func (keyRing *KeyRing) UnmarshalJSON(jsonData []byte) (err error) { - keyObjs, err := unmarshalJSON(jsonData) - if err != nil { - return err - } - - return keyRing.newKeyRingFromPGPKeyObject(keyObjs) -} - -// UnlockJSONKeyRing reads keys from a JSON array, creates a newKeyRing, -// then tries to unlock them with the provided keyRing using the token in the structure. -// If the token is not available it will fall back to just reading the keys, and leave them locked. -func (keyRing *KeyRing) UnlockJSONKeyRing(jsonData []byte) (newKeyRing *KeyRing, err error) { - keyObjs, err := unmarshalJSON(jsonData) - if err != nil { - return nil, err - } - - newKeyRing = &KeyRing{} - err = newKeyRing.newKeyRingFromPGPKeyObject(keyObjs) - if err != nil { - return nil, err - } - - for _, ko := range keyObjs { - if ko.Token == nil || ko.Signature == nil { - continue - } - - message, err := NewPGPMessageFromArmored(*ko.Token) - if err != nil { - return nil, err - } - - signature, err := NewPGPSignatureFromArmored(*ko.Signature) - if err != nil { - return nil, err - } - - token, err := keyRing.Decrypt(message, nil, 0) - if err != nil { - return nil, err - } - - err = keyRing.VerifyDetached(token, signature, 0) - if err != nil { - return nil, err - } - - err = newKeyRing.Unlock(token.GetBinary()) - if err != nil { - return nil, errors.New("gopenpgp: wrong token") - } - } - - return newKeyRing, nil -} - -// newKeyRingFromPGPKeyObject fills a KeyRing given an array of pgpKeyObject -func (keyRing *KeyRing) newKeyRingFromPGPKeyObject(keyObjs []pgpKeyObject) error { - keyRing.entities = nil - for i, ko := range keyObjs { - if i == 0 { - keyRing.FirstKeyID = ko.ID - } - err := keyRing.readFrom(ko.PrivateKeyReader(), true) - if err != nil { - return err - } - } - return nil -} - -// unmarshalJSON decodes key json from the API -func unmarshalJSON(jsonData []byte) ([]pgpKeyObject, error) { - keyObjs := []pgpKeyObject{} - if err := json.Unmarshal(jsonData, &keyObjs); err != nil { - return nil, err - } - - return keyObjs, nil -} - // Identities returns the list of identities associated with this key ring. func (keyRing *KeyRing) Identities() []*Identity { var identities []*Identity @@ -396,14 +294,14 @@ func (keyRing *KeyRing) KeyIds() []uint64 { // ReadArmoredKeyRing reads an armored data into keyring. func ReadArmoredKeyRing(r io.Reader) (keyRing *KeyRing, err error) { keyRing = &KeyRing{} - err = keyRing.readFrom(r, true) + err = keyRing.ReadFrom(r, true) return } // ReadKeyRing reads an binary data into keyring. func ReadKeyRing(r io.Reader) (keyRing *KeyRing, err error) { keyRing = &KeyRing{} - err = keyRing.readFrom(r, false) + err = keyRing.ReadFrom(r, false) return } @@ -454,7 +352,6 @@ func (keyRing *KeyRing) FirstKey() *KeyRing { return nil } newKeyRing := &KeyRing{} - newKeyRing.FirstKeyID = keyRing.FirstKeyID newKeyRing.entities = keyRing.entities[:1] return newKeyRing diff --git a/crypto/keyring_test.go b/crypto/keyring_test.go index e9a0194..51dc206 100644 --- a/crypto/keyring_test.go +++ b/crypto/keyring_test.go @@ -149,51 +149,6 @@ func TestKeyIds(t *testing.T) { assert.Exactly(t, assertKeyIDs, keyIDs) } -func TestUnmarshalJSON(t *testing.T) { - decodedKeyRing := &KeyRing{} - err = decodedKeyRing.UnmarshalJSON([]byte(readTestFile("keyring_jsonKeys", false))) - if err != nil { - t.Fatal("Expected no error while reading JSON, got:", err) - } - - fingerprint, err := decodedKeyRing.GetFingerprint() - if err != nil { - t.Fatal("Expected no error while extracting fingerprint, got:", err) - } - - assert.Exactly(t, "91eacacca6837890efa7000470e569d5c182bef6", fingerprint) -} - -func TestUnlockJson(t *testing.T) { - userKeyRing, err := pgp.BuildKeyRingArmored(readTestFile("keyring_userKey", false)) - if err != nil { - t.Fatal("Expected no error while creating keyring, got:", err) - } - - err = userKeyRing.UnlockWithPassphrase("testpassphrase") - if err != nil { - t.Fatal("Expected no error while decrypting keyring, got:", err) - } - - addressKeyRing, err := userKeyRing.UnlockJSONKeyRing([]byte(readTestFile("keyring_newJSONKeys", false))) - if err != nil { - t.Fatal("Expected no error while reading and decrypting JSON, got:", err) - } - - for _, e := range addressKeyRing.entities { - assert.Exactly(t, false, e.PrivateKey.Encrypted) - } - - addressKeyRing, err = userKeyRing.UnlockJSONKeyRing([]byte(readTestFile("keyring_jsonKeys", false))) - if err != nil { - t.Fatal("Expected no error while reading and decrypting JSON, got:", err) - } - - for _, e := range addressKeyRing.entities { - assert.Exactly(t, true, e.PrivateKey.Encrypted) - } -} - func TestMutlipleKeyRing(t *testing.T) { testPublicKeyRing, _ = pgp.BuildKeyRingArmored(readTestFile("keyring_publicKey", false)) assert.Exactly(t, 1, len(testPublicKeyRing.entities)) @@ -201,7 +156,7 @@ func TestMutlipleKeyRing(t *testing.T) { ids := testPublicKeyRing.KeyIds() assert.Exactly(t, uint64(0x3eb6259edf21df24), ids[0]) - err = testPublicKeyRing.readFrom(strings.NewReader(readTestFile("mime_publicKey", false)), true) + err = testPublicKeyRing.ReadFrom(strings.NewReader(readTestFile("mime_publicKey", false)), true) if err != nil { t.Fatal("Expected no error while adding a key to the keyring, got:", err) } diff --git a/crypto/message_test.go b/crypto/message_test.go index b8bf7cd..eb7719a 100644 --- a/crypto/message_test.go +++ b/crypto/message_test.go @@ -164,7 +164,7 @@ func TestMultipleKeyMessageEncryption(t *testing.T) { var message = NewPlainMessageFromString("plain text") testPublicKeyRing, _ = pgp.BuildKeyRingArmored(readTestFile("keyring_publicKey", false)) - err = testPublicKeyRing.readFrom(strings.NewReader(readTestFile("mime_publicKey", false)), true) + err = testPublicKeyRing.ReadFrom(strings.NewReader(readTestFile("mime_publicKey", false)), true) if err != nil { t.Fatal("Expected no error adding second public key, got:", err) } diff --git a/crypto/testdata/keyring_jsonKeys b/crypto/testdata/keyring_jsonKeys deleted file mode 100644 index f403bd2..0000000 --- a/crypto/testdata/keyring_jsonKeys +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "ID": "qpRBAbx3s0gw5fdpS4VHPmxFZG42NPWGZW2g0fDhwHeO7duCQgOdnxcSDUxTwfLjfpeIHuPzUQPKeEN8q4TsRA==", - "Primary": 1, - "Flags": 3, - "Version": 3, - "Activation": null, - "PrivateKey": "-----BEGIN PGP PRIVATE KEY BLOCK-----\nVersion: ProtonMail\nComment: https://protonmail.com\n\nxcMGBFzCDYwBCAC77HWfNvdpDnv8G8uvK59XGFL/LdFniH2DTqIpg2n1lzJ5\nwBmJcr9FJ2vsCGkIzHvgq5zbIbRDMV7M8kUjkEqBi/Xx+Ab3QVaQcQvvIvgq\niZ19w4jAfXdZzeWD01LKeteXlmcZ2u+13HZ5x9jbHuQ7Drb5KTVXdG/OU/WW\nKhHOvp1l8deLEiKbJogY2LWwNTjPSiKviJnajTW76E9R4y1AJ5nlb2Uumb32\nU7qMG7lFUbwm/Y3Y3VL3QWhh2woNkY5MMItLL/+hsduK9cai7LhVjyuX/bEk\n944tjS7b7S/ylsBgoZz5m84KWgrywHnaNpCyY+70PO5grZiK4ytwgsiVABEB\nAAH+CQMIK2E+0mv1lUZgSbZpPwnzwTDpsXZa/Am7Bez7rClliF+ULmbaKkAK\nHMlQu3Blu2XPnryGy4f/kyAXhsgRNMuhbFJnNWI6F0qYb5QxgZ1hODnUAdNm\nMasL5ZvTly07QG7wFFUqX0/Fr+cfqlAbjvZnjsHd6Hd1jrEL/D4AqAGaaV7g\nEhBLoXlEin0UitbxVM6FZhjf9MplICkUrZA/IVGHuiErMIDCtaWzL+582Fko\nCD7F3DjiIhStHF3TR+U/lmS6WIZ0ePzppD/+Mm7m1mUrIi2k60Qedu7KkW1p\n7GZrc+eDcsIvvpRSxnNtMQrg3Z/IrKVYvf5CdUXb/EdHzSblsfAevaTOHXdN\nAZaaJZQYh/NGRdV/yLKM5uYIFZQ/3obbUMKGkFQl6ETCfXwOj93ckx/tBQ2+\nJ3g7t65Ab7ba4ADchiECC5nQR1gvp2BTsBwHbUH5qHZlwFr3LYgje4WQKCCT\nOvnyskIwlzhxAzxMBC6Ke1jN6xRI2wEyaSxhuXkqX4eAWbb9iXLpsA4v0lWI\nj+t5iGdpCJFOA7N44PWgVB7uZxcLrimkdiWu2apAWprcFJ6InJk2T+IhwZjr\nek4wSmgrv1ZgEbEyrPITZ9y7Q/ub6r2rrdZdmO5VAyyZCwCp1kwGpbV0k/kM\nAz762e6rWWdXsN4rCwuYF5L/nwVggKErW9mNnnLZ0+afmuLt9a9FZ2xV+FlB\nmB0uLJ5u5LCjokBwdJ+iyGwL5FKZwP9HzCVDGm1rBFfhq2O82MwfO7iLcMqc\ncjysQDmn6nZQIY5URa25GLCNLAM700kpcyBKnZjjuffpypaPeswy851ukVI2\nfHR4LZXsiwNK+tMbMYVJlt0e6DIib/kSYgAobsO+3xGqbPeC9kN7pOfPu79L\n/NWt2PPHYOYlm16Grclv0mxWFEacaCifzTNlbGVjdHJvbkBwcm90b25tYWls\nLmJsdWUgPGVsZWN0cm9uQHByb3Rvbm1haWwuYmx1ZT7CwHUEEAEIAB8FAlza\nAdIGCwkHCAMCBBUICgIDFgIBAhkBAhsDAh4BAAoJEHDladXBgr72xzUH/199\nm0pKvEqpX1BxLLKhT4UHcCaDNFZ9KY++75f3SUVdnsK/YjsOpp1gbzQTGOgJ\nW4x8cQhNi/JoP1KudrxiIgIK7vISATIzXAMVWyvVRECLiLBXXa5+lCHIfs8v\n0jcuEuHRErRbFaVdMRkFkP7Pag36rvtsA9L3Bb8YwHTYlkbeGlyIR9EbZRWf\njnOLWXIvXxN2Yo4hDqyY/YmU5SeFdNO57vjtE99qVew6zMpfOfhQ1VNelgNt\nkVyLCa1Funx5TOUWe4eVgloGEtMWgOyfTMB+b+MuWIHAC6rEC10G8b36UqLF\nxDC18cApzhy60+S9SG49heI0tntoF8t4F/WdYKfHwwYEXMINjAEIAKnf8YXr\nYiYtmuVJR1uX14FAlDwXdEQWoXxE+BdC58qE19yT5SVDD9Ea9hiIFKl+zO7s\n3RCtMrqPhXFefbe7dPpF96xWcv+bmVZG96O07TC99uTT+rppqFKf6Stt0/33\ncjvnzvvilrDQJIiVaTn9iHpgct1u1XEq+/4+6nNc6HAZFZkBKMNX9sDR7FDF\nIvIi77Y0DPQaNOgym9TYP9vFJADgNdFqrdl6Yv3yzgfRRY0unavX+J9g75Ip\nMDBzE3Zz53ZaC+gD1r0XWm2BT8jPy/A7UY2Zssz1JVD5HLUA1SEYnNbFopQm\nSVscRk7qGu+KSRc+0Qa9hSzzhA6I4fwP4mEAEQEAAf4JAwgmHQjqlNKsjGCH\nTIlvmrDs44VDNKGxoEcutrItdfYjh8O8gCY1aBy6lGSjygXY4OLPazPYyXw3\nKFNigIvueUrmSPBXV/Un4iozcBUIPck7qrrQ3gnQKI2Y/h8PBUCiKfe0moR+\nCpHruqoximXXrzlW51tFnr1U/D8Gw9OXVkmwQ4m/KGEEqq6ILW352ibqf27+\nc/6muTfIxog5yk4jF4NVNrecPH2diaELNiuq6WUnbPeyZ6aciQ3QYhAIH1ox\n1PQq3StFZfWCBzPGj3SxSyz4zXAokvN0vkUQ90UVjDSWRIOF3N9J9USRrLjw\nsYIkXtZU0YYdHHJTeuG2M3QJhdezM/VKOLv2MxwmXhkYr1O6rKmP8MPw2l4U\nRuijWKDP48/342MSMCMrJEJgQm+PSSiUys6cn/DwBpw2vXlLaeG11LCBrTdB\nO46opGvgw6lKyuxkUfVCVjunGho1HZFt+uV+yPErrhCC0PJ/aXzO/dY+Vv7C\nm5sz77PMSYY+1atWcTnUr7O2WN1CSNauR/NChEXWXw1di1pnyO8CIJkOYO6C\n7lFNf16CuULo426Xcck/Jq9bP55JK61qMHdkbLCy7onv+WBoVelXnQKuObhL\nYhsha6Irx4i0yBpAC15yVmNbHA8upLBnTuDa709pIrK62kLidNmR6n90dIDD\nqh/7sx9bHakHDmYcpYRC6Xv2z/nF2hZuizyhBKuXZ7ChKz+AU4VzdJiqkHrE\nYvs3W6hPc6HmaM81spIG2zQGGP1KG3HGWgh0wnDh8x019gBYV2vvZ9++LUiT\n8pmHKdX/TUoNN3yigaU3tO/KY4yYpltc+iOVngdnOsbsNRKMb4KTo9zMwPoA\nQT9toJ06mgOBoi3k37fGlRKxLiM+fdAjU3GNbgl7VOk/TCtSqmeXPtMAYkjW\nODzZJdUCRNjCwF8EGAEIAAkFAlzaAdICGwwACgkQcOVp1cGCvvbVhAf+J9jN\nglboBPTjd2XOekOzK+pl8G/IpWwzXAPo3++Tf2p8Gc2HIN928Sl4BkiY/KPo\ncSnchOHYHmG9EigrGra0SjFwUHwz0Kp3ubV3O6XGoaqVnLgoZkyo75ZvAemY\nVLxi2jUqIs4Vq/PtxjZppxzxqnGIE3wT8LDSuQGiZMpj+lvjB/77CUYt4BMc\noYbA5dyl4Pj6QCDZhG7uTeoGtRdygRXjbYpFLe6HoN3tu0aB3yfHyFVMTMQ3\nm9XzkR6hzofDs3rc1hdm0G5LflOyWr7vzaSPPjW2kYKMa5MGh2vOAMunKQHT\nSmpbVZj1NSvPN4xFOnZaytD99Yt/8ZFonY9Rjg==\n=5ACd\n-----END PGP PRIVATE KEY BLOCK-----\n", - "Token": null, - "Signature": null - }, - { - "ID": "88xeHAObMEZp8b15R3643qJFbRoAXPm-FNuHxWO_VBVEqm294wuKCbIdoytQwHq2uwTxAXB-c4Jh0R47F34qig==", - "Primary": 0, - "Flags": 3, - "Version": 3, - "Activation": null, - "PrivateKey": "-----BEGIN PGP PRIVATE KEY BLOCK-----\nVersion: ProtonMail\nComment: https://protonmail.com\n\nxYYEXMcTAxYJKwYBBAHaRw8BAQdAjYhUufSrYtCsWhJMjCaEkdJb1Zuauh8P\nS0WipcZO2dD+CQMIxbf+ePNBNFVgXUTPHWmy2PpBS2FHQWgONx0UQLRi+JyT\nMJmxS/CToS54Eo0sWEjaZROZr8f5smCgBZqZsRWv4CA35qBG/RxJMkVH2lKQ\nuM0zZWxlY3Ryb25AcHJvdG9ubWFpbC5ibHVlIDxlbGVjdHJvbkBwcm90b25t\nYWlsLmJsdWU+wncEEBYKAB8FAlzaAdIGCwkHCAMCBBUICgIDFgIBAhkBAhsD\nAh4BAAoJEP7+7R3IrxGwxh0BAKbR76lG0OH83tI5quvyNf7yt+ck/uV8MrPZ\ntcBLHwO3AQCd5CHU3Rx7Huw0QsVkJYr7t3JEYfSaTK2wTxUFKudSDceLBFzH\nEwMSCisGAQQBl1UBBQEBB0Dijq86qjP8AEv98lTBqw69HAAxo0S4Eqh1P4qU\n1irhLwMBCAf+CQMIXvD746WZtFtglCNKwMqcHMFJ0sadSDo6ntYdiQwSM42E\n0jdfdM+JUIfDw9cOXflCcdW8yUJSRaBL1BXwtCcr686pkPZ/79qxuqYY6+Nq\nzMJhBBgWCAAJBQJc2gHSAhsMAAoJEP7+7R3IrxGwKzUA/j/00OybZkE3oTDO\n2fLjBZtlKa7T1n4+vZb+T8dvl2wnAP9Ln3wTzY9oXN/n/WgSi8Q5iT2to7zx\n25aU/PlFqHQmBQ==\n=3PyZ\n-----END PGP PRIVATE KEY BLOCK-----\n", - "Token": null, - "Signature": null - } -] diff --git a/crypto/testdata/keyring_newJSONKeys b/crypto/testdata/keyring_newJSONKeys deleted file mode 100644 index 21ad185..0000000 --- a/crypto/testdata/keyring_newJSONKeys +++ /dev/null @@ -1,12 +0,0 @@ -[ - { - "ID": "hKRtZeTDhvzfAaycb5BOVx6Y3hc3gs4QvET8H_YZBTwAQBPp3h6FI4nnkJePCYuM9CG0zf7TQzOJeB2rPi0YmQ==", - "Primary": 1, - "Flags": 3, - "Version": 3, - "Activation": null, - "PrivateKey": "-----BEGIN PGP PRIVATE KEY BLOCK-----\nVersion: ProtonMail\nComment: https://protonmail.com\n\nxcMGBFzGzj4BCADh9uuhG3mDhlbFMgQpvP6AReyJYa6KSV9a6AJsNI0/DkVz\nFenIodav/r4RBgSoblqxCa/QH6galbX0eB8Vtxx4xTXCcHHZzTM9oAb4s8r6\ndGchNsSkoLspVwmc2fYfDRCTcapmeza7Jym8gD9wFUSWSwpC49jDeT6VIcOd\n+qNXgIJX1V36BOAB53lKenMYnxfzzAyJDeL/sQ/SWE9h/X+wGdkVmk7gk3pa\nQ9URoxAf7MO808hHyQYcjTV4tOHD/9k+AZC6sqmr2KAefYCxCMoCDj1wQp3J\nN6MfK2Zvc1r5KFQM2YzUXrMNrycAjo7gGeZnsvz758Q+8ouSP7iXGRl/ABEB\nAAH+CQMIQt3QQIJZYjRgTVgIQNSEkhMn4GJ5lQQPBXD0/YyK3xP0bm/bsX8S\nz9dAm1nkP0l8Q9z3lR6OcAX2O/KsqJdQGmJEZAaadz2je+EEWo1FDYaL76E6\n6z+AuteP8UtP61jBt3pTfIlhW8o7o2SlM1lvytpvc5FQplZ/iUuwfsIltCiD\n9VDkprNOVrRsjoh8BV4TrrIvU8qga58Aeg7SjOmm+3oMZ7yPTYirr11Tx/m3\nj1uzdEDfiPk4LmvlzSsWwKZuy6fSul+n92+9qN81wmdts/I2ucuKvOINZim4\nlk/p2AOsPjWpAgkefpTVLZnu2IH+VAyaXt1Fl84badXx4N921nPs7ova1Ud5\n2RddBc7b/01DtOyBSWDoNskLGpsc2mqz9kdkwwQKNjChzZc9nmY9M+AIfgT3\n+2DSQIuoJYPX69DKi/bZDwRzoHmiwiHT6Us7qxd6kD1dzCIHTptxwZQp4Tow\nnN6lmtK4S6O2B47+ROn8s0N+EH9GR8F6mvOTayNLH5yicpR3M4Of0ClvFa0G\n+JUKBXIQXUvF03G3nTPU17nLibC81UmbK3zobfbrLfuU2gU+sY+OfE1E/+GO\nSFpZcrkoRqRr39CfLkLk+GjU7RCLNddb5LxgaurVZo5h0Y7Rr8VvOQMWjjl/\nvTAG7gU/HtXi24TijNC0fP6j9w43K4b6t1SZYn5us7RRlFlWGKMSPf5Q9j6/\nryo3xULUQv0lTCQPtfQQ5UWE5ZpQ4Kjt/k5+/YtfuOcMbrDU4qa+H+rrisBu\nko7f4Wn0iYjRwRIuWh1NfUM3rIbNhq7/wonasEFOeFdPwprzMaawx3rL0Pq5\n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\nV0GB3IX8qBHjAfPmqN9JPxBIn3/6ag==\n=U1yD\n-----END PGP PRIVATE KEY BLOCK-----\n", - "Token": "-----BEGIN PGP MESSAGE-----\nVersion: ProtonMail\nComment: https://protonmail.com\n\nwcBMAxW/uQhm1PKxAQf8D4BAoXqnYgoTr7jEiabP9NkeuD6Z88fZDgUzXte5\n6aYMmCtPr0Vef1eDl2x0S0q/YJgR+A5Icmjxk+jG9nMSnRPlAozJfTCXu/Oy\nfkI4CcClGQv7U1EzfknBVNEKmuPO8XlEkGZ5lW/TzWk8ZtQqJsVuqZlZ5qQE\n/p8FNYEZ5RHPhhKlotA+T6XKh23z9mcN/JNEsSNcx+guERbivtTwnd5JpxQJ\nMNWzUYh+K0W7LgxoAo2jevDd4CZ/0sAAViIl+QrShodseV9agbldGUUoIMzn\nHUuIV6VYi7X82eKQXDInrtPc9IHekbDDFoncLnsGGrEqD/8O/qOHHOPwNwU+\n+cHATAOUTDv/ccWq1QEIALl8SNOQBmCuanAceUTSwCkM1fC3Ddqa8ZmnMMyG\nnDWDI7XkFU31CO10lN20/kAWjdN2073B/NT+17cp8fCqbQ1pAFJHpabdqmbI\ntm3pCC5M6otTN+MhjgFYcBuxo0rq9qtuEzz5j4Ub9MIIJTurUHMEPMI462Dc\ndK/d8BvDkU7q67Lkp65vpe9e/pv0lMMrQjdohnTHNgbZhbI/Z5LU0ApD//Ye\ncSC26BRUMJITiGKb9pKGAi0/ig0jJfzykgEarzOsY/v0W7016AMka+NsHuNc\n7Qfyg2LApF5s9Z6aK+Uy851haUk+p+abjBdcWACziAmimVGjlRYm49ra4UJ7\nc6LSeAElM584e4Z3VnqajAJWbmWt2atgBQmcwEBBsdNAtzIagNydMbBBIELA\n5wGUbMXfQxrMOo/Mdac/5EMTHT0/kVQNIBHtpX5SknWvbc5DjIHoH3+BbL87\neaxhKW94hMubKNKT3dbm4PKHtsMiS3TGkFZ3GjvA0Cy/Kw==\n=b1N8\n-----END PGP MESSAGE-----\n", - "Signature": "-----BEGIN PGP SIGNATURE-----\nVersion: ProtonMail\nComment: https://protonmail.com\n\nwsBcBAEBCAAGBQJcxtSkAAoJEGfweL9m9sQefz8IAJhpEOvG7d+PVgq3bEL+\nXzY8yTUKB1ZXEMbcR/uHUWSfu0F8zy4CNtSG5HUVjNxx1xzzJVJcxWB/ljO+\n/bJSFOFexTyNh8i/xU+CiBfm5RhAFTYF9xFwfD3LKp5gaalJAhWhArk1/Wuh\nWTDpFpk39uzBRKNwcnSgiJYPxOjAZxj+w/hhHPwmco5cUwMiMR5MNrfzKf+x\nwX3Cfs9fsiiCDzohBzbK0FFsMnJ8aXNVsDBjEA1KrB7sdyaf8FnaM0RsFRDb\njxtIgfcFBbyNJh4414Unt4AYTIrIWhK4OOXI3AfsJy8p6KRBKQUcUkKcDxab\nPTXOPZsZ+UgQ5MevyVnP1zfCwFwEAQEIAAYFAlzG1KQACgkQm1DMMBzxetx/\nPwf9F04uHtix0zDpP1IvG4VYlor4rjYTdfXqxxiFXHO6MZXJoigS1E71E8r4\nsqZ6PoQ5/xCj2A01KRhuF1Bon3mEZEwaIUuBqTV91sLsVWfoxgyPAYpr6gK/\n1W9JhVNNrVRMGox42LQUjyiq0ESrfWmqC8SuMfZMoUoBZycHicA50RbyOUnT\nLO57ArL3JIVmYtyosaXM3idzmNHmaXSkcGt4cvTVysJZQrneaxmikfm5CH2O\n1z2goLBNnzsbRionoV6gCukZOiM/d14yiyeYtsFJ7u/vodkI5y0M0sF8VnN/\njL9keP4ZpHiJ4MBd6tyIH0pLueDRlurFL3fcHsEzD5SrOA==\n=wGCk\n-----END PGP SIGNATURE-----\n" - } -]