Fixed the engine part of IOS-1938/ENGINE-656 - now burden goes on to Enigmail/pEp sender-fpr-and-friends
authorKrista 'DarthMama' Bennett <krista@pep.foundation>
Mon, 18 Nov 2019 14:44:24 +0100
branchsender-fpr-and-friends
changeset 4202a3ea9bc50b6c
parent 4200 bbbe91e9849e
child 4203 771130f714c4
Fixed the engine part of IOS-1938/ENGINE-656 - now burden goes on to Enigmail/pEp
src/aux_mime_msg.c
test/src/UnencryptedPepMailTest.cc
test/src/test_util.cc
test/src/test_util.h
test/test_mails/unenc_pep_msg_test_1.eml
     1.1 --- a/src/aux_mime_msg.c	Fri Nov 15 20:01:14 2019 +0100
     1.2 +++ b/src/aux_mime_msg.c	Mon Nov 18 14:44:24 2019 +0100
     1.3 @@ -205,16 +205,23 @@
     1.4                               enc_format,
     1.5                               flags);
     1.6                               
     1.7 -    if (status != PEP_STATUS_OK)
     1.8 +    message* ret_msg = NULL;                         
     1.9 +    if (status == PEP_STATUS_OK || status == PEP_UNENCRYPTED)
    1.10 +        ret_msg = (status == PEP_STATUS_OK ? enc_msg : tmp_msg);
    1.11 +    else                                
    1.12          goto pEp_error;
    1.13  
    1.14 -
    1.15 -    if (!enc_msg) {
    1.16 +    if (status == PEP_STATUS_OK && !enc_msg) {
    1.17          status = PEP_UNKNOWN_ERROR;
    1.18          goto pEp_error;
    1.19      }
    1.20 -
    1.21 -    status = _mime_encode_message_internal(enc_msg, false, mime_ciphertext, false, false);
    1.22 +    
    1.23 +    PEP_STATUS tmp_status = _mime_encode_message_internal(
    1.24 +                                    ret_msg, 
    1.25 +                                    false, 
    1.26 +                                    mime_ciphertext, 
    1.27 +                                    false, 
    1.28 +                                    false);
    1.29  
    1.30  pEp_error:
    1.31      free_message(tmp_msg);
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/test/src/UnencryptedPepMailTest.cc	Mon Nov 18 14:44:24 2019 +0100
     2.3 @@ -0,0 +1,204 @@
     2.4 +#include <stdlib.h>
     2.5 +#include <string>
     2.6 +#include <cstring>
     2.7 +#include <fstream>
     2.8 +#include <iostream>
     2.9 +
    2.10 +#include "pEpEngine.h"
    2.11 +#include "test_util.h"
    2.12 +#include "TestConstants.h"
    2.13 +#include "Engine.h"
    2.14 +
    2.15 +
    2.16 +#include <gtest/gtest.h>
    2.17 +
    2.18 +
    2.19 +namespace {
    2.20 +
    2.21 +	//The fixture for UnencryptedPepMailTest
    2.22 +    class UnencryptedPepMailTest : public ::testing::Test {
    2.23 +        public:
    2.24 +            Engine* engine;
    2.25 +            PEP_SESSION session;
    2.26 +
    2.27 +        protected:
    2.28 +            // You can remove any or all of the following functions if its body
    2.29 +            // is empty.
    2.30 +            UnencryptedPepMailTest() {
    2.31 +                // You can do set-up work for each test here.
    2.32 +                test_suite_name = ::testing::UnitTest::GetInstance()->current_test_info()->GTEST_SUITE_SYM();
    2.33 +                test_name = ::testing::UnitTest::GetInstance()->current_test_info()->name();
    2.34 +                test_path = get_main_test_home_dir() + "/" + test_suite_name + "/" + test_name;
    2.35 +            }
    2.36 +
    2.37 +            ~UnencryptedPepMailTest() override {
    2.38 +                // You can do clean-up work that doesn't throw exceptions here.
    2.39 +            }
    2.40 +
    2.41 +            // If the constructor and destructor are not enough for setting up
    2.42 +            // and cleaning up each test, you can define the following methods:
    2.43 +
    2.44 +            void SetUp() override {
    2.45 +                // Code here will be called immediately after the constructor (right
    2.46 +                // before each test).
    2.47 +
    2.48 +                // Leave this empty if there are no files to copy to the home directory path
    2.49 +                std::vector<std::pair<std::string, std::string>> init_files = std::vector<std::pair<std::string, std::string>>();
    2.50 +
    2.51 +                // Get a new test Engine.
    2.52 +                engine = new Engine(test_path);
    2.53 +                ASSERT_NE(engine, nullptr);
    2.54 +
    2.55 +                // Ok, let's initialize test directories etc.
    2.56 +                engine->prep(NULL, NULL, init_files);
    2.57 +
    2.58 +                // Ok, try to start this bugger.
    2.59 +                engine->start();
    2.60 +                ASSERT_NE(engine->session, nullptr);
    2.61 +                session = engine->session;
    2.62 +
    2.63 +                // Engine is up. Keep on truckin'
    2.64 +            }
    2.65 +
    2.66 +            void TearDown() override {
    2.67 +                // Code here will be called immediately after each test (right
    2.68 +                // before the destructor).
    2.69 +                engine->shut_down();
    2.70 +                delete engine;
    2.71 +                engine = NULL;
    2.72 +                session = NULL;
    2.73 +            }
    2.74 +
    2.75 +        private:
    2.76 +            const char* test_suite_name;
    2.77 +            const char* test_name;
    2.78 +            string test_path;
    2.79 +            // Objects declared here can be used by all tests in the UnencryptedPepMailTest suite.
    2.80 +
    2.81 +    };
    2.82 +
    2.83 +}  // namespace
    2.84 +
    2.85 +// Check to see if a first unencrypted mail is pEpified
    2.86 +TEST_F(UnencryptedPepMailTest, check_unencrypted_pep_mail_outgoing) {
    2.87 +    pEp_identity* alice = NULL;
    2.88 +    pEp_identity* dave = NULL;
    2.89 +
    2.90 +    PEP_STATUS status = set_up_preset(session, ALICE,
    2.91 +                                      true, true, true, true, true, &alice);
    2.92 +
    2.93 +    ASSERT_EQ(status, PEP_STATUS_OK);
    2.94 +    ASSERT_NE(alice, nullptr);
    2.95 +/*
    2.96 +PEP_STATUS set_up_preset(PEP_SESSION session,
    2.97 +                         pEp_test_ident_preset preset_name,
    2.98 +                         bool set_ident,
    2.99 +                         bool set_pep,
   2.100 +                         bool trust,
   2.101 +                         bool set_own,
   2.102 +                         bool setup_private,
   2.103 +                         pEp_identity** ident) {
   2.104 +*/
   2.105 +
   2.106 +
   2.107 +    dave = new_identity("pep-test-dave@pep-project.org", NULL, NULL, "The Hoff");
   2.108 +    
   2.109 +    message* msg = new_message(PEP_dir_outgoing);
   2.110 +    
   2.111 +    msg->from = alice;
   2.112 +    msg->to = new_identity_list(dave);
   2.113 +    msg->shortmsg = strdup("No, I will *not* get into your car");
   2.114 +    msg->longmsg = strdup("Look, Dave... it's creepy. I'm not getting into your car.\n\n" 
   2.115 +                          "I do not want a cup of 'Hoffee', and you are not singlehandedly\n" 
   2.116 +                          "responsible for bringing down the Berlin Wall.\n\nGo away. - Alice");
   2.117 +
   2.118 +    PEP_encrypt_flags_t flags = 0;
   2.119 +    message* enc_msg = NULL;
   2.120 +    
   2.121 +    status = encrypt_message(session, msg, NULL, &enc_msg, PEP_enc_PGP_MIME, flags);
   2.122 +    ASSERT_EQ(status, PEP_UNENCRYPTED);
   2.123 +    ASSERT_TRUE(is_pEpmsg(msg));
   2.124 +    
   2.125 +    // char* outmsg = NULL;
   2.126 +    // mime_encode_message(msg, false, &outmsg);
   2.127 +    // ofstream outfile;
   2.128 +    // outfile.open("tmp/unenc_pep_msg_test_1.eml");
   2.129 +    // outfile << outmsg;
   2.130 +    // outfile.close();
   2.131 +    free_message(msg);
   2.132 +}
   2.133 +
   2.134 +// Check to see if a first unencrypted mail is pEpified
   2.135 +TEST_F(UnencryptedPepMailTest, check_unencrypted_pep_mail_outgoing_MIME) {
   2.136 +    pEp_identity* alice = NULL;
   2.137 +    pEp_identity* dave = NULL;
   2.138 +
   2.139 +    PEP_STATUS status = set_up_preset(session, ALICE,
   2.140 +                                      true, true, true, true, true, &alice);
   2.141 +
   2.142 +    ASSERT_EQ(status, PEP_STATUS_OK);
   2.143 +    ASSERT_NE(alice, nullptr);
   2.144 +/*
   2.145 +PEP_STATUS set_up_preset(PEP_SESSION session,
   2.146 +                         pEp_test_ident_preset preset_name,
   2.147 +                         bool set_ident,
   2.148 +                         bool set_pep,
   2.149 +                         bool trust,
   2.150 +                         bool set_own,
   2.151 +                         bool setup_private,
   2.152 +                         pEp_identity** ident) {
   2.153 +*/
   2.154 +
   2.155 +
   2.156 +    dave = new_identity("pep-test-dave@pep-project.org", NULL, NULL, "The Hoff");
   2.157 +    
   2.158 +    message* msg = new_message(PEP_dir_outgoing);
   2.159 +    
   2.160 +    msg->from = alice;
   2.161 +    msg->to = new_identity_list(dave);
   2.162 +    msg->shortmsg = strdup("No, I will *not* get into your car");
   2.163 +    msg->longmsg = strdup("Look, Dave... it's creepy. I'm not getting into your car.\n\n" 
   2.164 +                          "I do not want a cup of 'Hoffee', and you are not singlehandedly\n" 
   2.165 +                          "responsible for bringing down the Berlin Wall.\n\nGo away. - Alice");
   2.166 +    char* outmsg = NULL;
   2.167 +    mime_encode_message(msg, false, &outmsg);
   2.168 +    char* encmsg = NULL;
   2.169 +        
   2.170 +    status = MIME_encrypt_message(session, outmsg, strlen(outmsg), NULL, &encmsg, PEP_enc_PGP_MIME, 0);
   2.171 +    ASSERT_EQ(status, PEP_UNENCRYPTED);
   2.172 +    ASSERT_NE(encmsg, nullptr);
   2.173 +    
   2.174 +    const char* contains = NULL;
   2.175 +    
   2.176 +    contains = strstr(encmsg, "X-pEp-Version");
   2.177 +    ASSERT_NE(encmsg, nullptr);
   2.178 +    
   2.179 +    // char* outmsg = NULL;
   2.180 +    // mime_encode_message(msg, false, &outmsg);
   2.181 +    // ofstream outfile;
   2.182 +    // outfile.open("tmp/unenc_pep_msg_test_1.eml");
   2.183 +    // outfile << outmsg;
   2.184 +    // outfile.close();
   2.185 +    free_message(msg);
   2.186 +}
   2.187 +
   2.188 +TEST_F(UnencryptedPepMailTest, check_unencrypted_pep_message_rcpt) {
   2.189 +    string msgstr = slurp("test_mails/unenc_pep_msg_test_1.eml");
   2.190 +    PEP_STATUS status = set_up_preset(session, DAVE,
   2.191 +                                      true, true, true, true, true, NULL);
   2.192 +    ASSERT_EQ(status, PEP_STATUS_OK);
   2.193 +    message* dec_msg = NULL;
   2.194 +    message* enc_msg = NULL;
   2.195 +    stringlist_t* keylist = NULL;
   2.196 +    PEP_rating rating;
   2.197 +    PEP_decrypt_flags_t flags = 0;
   2.198 +    
   2.199 +    mime_decode_message(msgstr.c_str(), msgstr.size(), &enc_msg);
   2.200 +    ASSERT_TRUE(is_pEpmsg(enc_msg));
   2.201 +    
   2.202 +    status = decrypt_message(session, enc_msg, &dec_msg, &keylist, &rating, &flags);
   2.203 +    ASSERT_TRUE(is_pEpmsg(enc_msg));    
   2.204 +    status = update_identity(session, enc_msg->from);
   2.205 +    ASSERT_EQ(enc_msg->from->comm_type, PEP_ct_pEp_unconfirmed);
   2.206 +    
   2.207 +}
     3.1 --- a/test/src/test_util.cc	Fri Nov 15 20:01:14 2019 +0100
     3.2 +++ b/test/src/test_util.cc	Mon Nov 18 14:44:24 2019 +0100
     3.3 @@ -57,6 +57,15 @@
     3.4      return _main_test_home_dir;
     3.5  }
     3.6  
     3.7 +bool is_pEpmsg(const message *msg)
     3.8 +{
     3.9 +    for (stringpair_list_t *i = msg->opt_fields; i && i->value ; i=i->next) {
    3.10 +        if (strcasecmp(i->value->key, "X-pEp-Version") == 0)
    3.11 +            return true;
    3.12 +    }
    3.13 +    return false;
    3.14 +}
    3.15 +
    3.16  PEP_STATUS read_file_and_import_key(PEP_SESSION session, const char* fname) {
    3.17      const std::string key = slurp(fname);
    3.18      PEP_STATUS status = (key.empty() ? PEP_KEY_NOT_FOUND : PEP_STATUS_OK);
    3.19 @@ -608,7 +617,7 @@
    3.20      return status;
    3.21  }
    3.22  
    3.23 -PEP_STATUS MIME_encrypt_message(
    3.24 +DYNAMIC_API PEP_STATUS MIME_encrypt_message(
    3.25      PEP_SESSION session,
    3.26      const char *mimetext,
    3.27      size_t size,
    3.28 @@ -631,34 +640,34 @@
    3.29          char* own_id = NULL;
    3.30          status = get_default_own_userid(session, &own_id);
    3.31          free(tmp_msg->from->user_id);
    3.32 -
    3.33 +        
    3.34          if (status != PEP_STATUS_OK || !own_id) {
    3.35              tmp_msg->from->user_id = strdup(PEP_OWN_USERID);
    3.36          }
    3.37          else {
    3.38              tmp_msg->from->user_id = own_id; // ownership transfer
    3.39          }
    3.40 -
    3.41 +            
    3.42          status = myself(session, tmp_msg->from);
    3.43          if (status != PEP_STATUS_OK)
    3.44              goto pEp_error;
    3.45      }
    3.46 -
    3.47 +    
    3.48      // Own identities can be retrieved here where they would otherwise
    3.49      // fail because we lack all other information. This is ok and even
    3.50      // desired. FIXME: IS it?
    3.51      status = update_identity_recip_list(session, tmp_msg->to);
    3.52      if (status != PEP_STATUS_OK)
    3.53          goto pEp_error;
    3.54 -
    3.55 +    
    3.56      status = update_identity_recip_list(session, tmp_msg->cc);
    3.57      if (status != PEP_STATUS_OK)
    3.58          goto pEp_error;
    3.59 -
    3.60 +    
    3.61      status = update_identity_recip_list(session, tmp_msg->bcc);
    3.62      if (status != PEP_STATUS_OK)
    3.63          goto pEp_error;
    3.64 -
    3.65 +    
    3.66      // This isn't incoming, though... so we need to reverse the direction
    3.67      tmp_msg->dir = PEP_dir_outgoing;
    3.68      status = encrypt_message(session,
    3.69 @@ -667,17 +676,24 @@
    3.70                               &enc_msg,
    3.71                               enc_format,
    3.72                               flags);
    3.73 -
    3.74 -    if (status != PEP_STATUS_OK)
    3.75 +                             
    3.76 +    message* ret_msg = NULL;                         
    3.77 +    if (status == PEP_STATUS_OK || status == PEP_UNENCRYPTED)
    3.78 +        ret_msg = (status == PEP_STATUS_OK ? enc_msg : tmp_msg);
    3.79 +    else                                
    3.80          goto pEp_error;
    3.81  
    3.82 -
    3.83 -    if (!enc_msg) {
    3.84 +    if (status == PEP_STATUS_OK && !enc_msg) {
    3.85          status = PEP_UNKNOWN_ERROR;
    3.86          goto pEp_error;
    3.87      }
    3.88 -
    3.89 -    status = _mime_encode_message_internal(enc_msg, false, mime_ciphertext, false, false);
    3.90 +    
    3.91 +    PEP_STATUS tmp_status = _mime_encode_message_internal(
    3.92 +                                    ret_msg, 
    3.93 +                                    false, 
    3.94 +                                    mime_ciphertext, 
    3.95 +                                    false, 
    3.96 +                                    false);
    3.97  
    3.98  pEp_error:
    3.99      free_message(tmp_msg);
     4.1 --- a/test/src/test_util.h	Fri Nov 15 20:01:14 2019 +0100
     4.2 +++ b/test/src/test_util.h	Mon Nov 18 14:44:24 2019 +0100
     4.3 @@ -10,10 +10,13 @@
     4.4  #include "pEpEngine.h"
     4.5  #include "message_api.h"
     4.6  #include "aux_mime_msg.h"
     4.7 +#include "mime.h"
     4.8  
     4.9  void test_init();
    4.10  
    4.11  bool file_exists(std::string filename);
    4.12 +bool is_pEpmsg(const message *msg); // duplicates static func in message_api.c, fyi
    4.13 +
    4.14  
    4.15  extern std::string _main_test_home_dir;
    4.16  
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/test/test_mails/unenc_pep_msg_test_1.eml	Mon Nov 18 14:44:24 2019 +0100
     5.3 @@ -0,0 +1,66 @@
     5.4 +From: Alice Spivak Hyatt <pep.test.alice@pep-project.org>
     5.5 +To: The Hoff <pep-test-dave@pep-project.org>
     5.6 +Subject: No, I will *not* get into your car
     5.7 +X-pEp-Version: 2.1
     5.8 +MIME-Version: 1.0
     5.9 +Content-Type: multipart/mixed; boundary="6b8b4567327b23c6643c986966334873"
    5.10 +
    5.11 +--6b8b4567327b23c6643c986966334873
    5.12 +Content-Type: text/plain; charset="utf-8"
    5.13 +Content-Transfer-Encoding: quoted-printable
    5.14 +Content-Disposition: inline; filename="msg.txt"
    5.15 +
    5.16 +Look, Dave... it's creepy. I'm not getting into your car.
    5.17 +
    5.18 +I do not want a cup of 'Hoffee', and you are not singlehandedly
    5.19 +responsible for bringing down the Berlin Wall.
    5.20 +
    5.21 +Go away. - Alice
    5.22 +--6b8b4567327b23c6643c986966334873
    5.23 +Content-Type: application/pgp-keys
    5.24 +Content-Disposition: attachment; filename="pEpkey.asc"
    5.25 +
    5.26 +-----BEGIN PGP PUBLIC KEY BLOCK-----
    5.27 +
    5.28 +xsBNBFV4PbEBCADTmjGDsoti/VPoZ3w2oCjLBNq1jWIGMkbiUgCGUQjVsNrSZ80U
    5.29 +7RmA3Pcu3hhiVQNBGA32vL6NPhSJPanVd77s6XVZg+Gq7llbGGkuIxSkJvVrWzYc
    5.30 +kjMsAInlJ8Ll0kHHbgATOlO5OtQ21bLCfWZPSq74HEVzQAPtCGYFvOgpCktKTjms
    5.31 +GXe9ysiYN8CEWMVNbDqXmvFhi4UifpITeQBVM7dtlBw5SoeLZpsHIlKF5i5WPkNw
    5.32 +7nuMag/+lRpOqvPumhOmqybWHuAR/Dq0pOOPh6BzZ4OzOBL96aWUe1dcnIZeBEm8
    5.33 +oRxYC3nN95YsjtrLK4BQZTYDTzeh8FIccsLdABEBAAHNRHBFcCBUZXN0IEFsaWNl
    5.34 +ICh0ZXN0IGtleSBkb24ndCB1c2UpIDxwZXAudGVzdC5hbGljZUBwZXAtcHJvamVj
    5.35 +dC5vcmc+wsB4BBMBAgAiBQJVeD2xAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIX
    5.36 +gAAKCRCpQR0Xb/AOl5JjCADEBoordVBCmphG6EY+u5yjj/xeQN4Kc1Rl06Ii6m18
    5.37 +4hnF/osxnTicr+A6Hpwf8whXULuSwXvfuOsVOQdIc2e+1zrecTqyNUWuRs3T7uZ2
    5.38 +5dvROg1XZuajMPf3wh5lX2rPRhOt3UNXJjQfc1MSYXpmT+PoqFXBzMqJUo2DYcw6
    5.39 +MSZekoWkIzFXG2s2YNwILwPnLnMesFtzU6mn9qhfoFsQA6aku8AbG+SNehNZvGuu
    5.40 +UiBmu+4UYNoc/RJa7vNWECv9qZQsT820CuoOZS9MFV7nQlgkGoPerlGXil0vkOG1
    5.41 +gsuQD8QkuaTQpn1vYvRcC0P27qLfrqlPv2Ih2hoIV9tJwsB4BBMBCAAiAhsDBgsJ
    5.42 +CAcDAgYVCAIJCgsEFgIDAQIeAQIXgAUCWV9iIwAKCRCpQR0Xb/AOl4oaCACZrLPy
    5.43 +c/lGHNJ8TT3KxIls/Ss62nWq4wB7dura+IUPVqLMNefJamQqG4BSGDR+WhC6Luf4
    5.44 +K5JgauVbHbIUm3y9LLqAJunePoOAQEQmGAIcuJzHM/IKXJoTdudjT7FJ+dxjOHLh
    5.45 +zYOIJw6I301sJUx25LxxTihj3ClUzL1uH1IrH3ctD1yL9lPIixQ3JocGUYZsZ9sw
    5.46 +CWlFzhYelAUmJuINJtKMeWkFvkVQ9xMU4ZGU4RGFdYcXVmSii47dNQEiW8XzcQ6D
    5.47 +TFCuaS0WWy2tJfRQSlaOCBs/DYtlrWWWBApinb35QVWNyAmTwCm8FlvjFA6kr/UE
    5.48 +9VMfP8bhbhspQLihzsBNBFV4PbEBCADQwKB97t2B2nweprfpbH8QgLCzJYaAMrpc
    5.49 +aUaJqm+J3C9eaepRXTXGtst1zaLbooG2b3QHfDzI2CEYMxO5ynmmSBOe06VKw/Pa
    5.50 +gBzK5ur/eOycl0ZPFSXdlDj30BQPvRdJvLS4OTMdoKoGpsZDY4hOYj67oHo3TFtr
    5.51 +LJCvZruPARkI/pXiOX9FqH4wquNNaYW1qwk/Wq3k/gOMwp0xjvc01MbadaiiVquJ
    5.52 +k6jjPrd2wP4FYxIADAllzMpwFAJSWvgCfmqVbukYOnaCp3QRQXQkc78TdqGXbD5u
    5.53 +wJzkxxiEsMmiGT+7RDLIKwXheKmmGXSwgi8m+EndUiqMTvOdjyUBABEBAAHCwF8E
    5.54 +GAECAAkFAlV4PbECGwwACgkQqUEdF2/wDpeQVQgArnfQ7uvG0po/CPepbrdytI2n
    5.55 +63U5dm/MFMsvXpZYVYLO/mROc+akZCPwS0yxtSMKK+tYM9leQx58r89c+K1GeZok
    5.56 +o7xziwmZbt5zEITiJp5L6gg7k6CczskPMx07gY8ooscBC3cFJhz1A0o73BKPR7J0
    5.57 +iupaNmI3sTd1/RNQm6573kGGwc4m2bcQttvN5ox8yimn2QnK3D+6A+Mmzi3Rd11t
    5.58 +F+tAWJIsfaEgDJZn9mOdUkV2ckoSk1K5PptpXSsKLOL+e2WuxSMIr8AVeRqkbYYK
    5.59 +6UzX6qIgQIrMOuaXqtRaNxNccnzIS1YtdtYERSnTaBotNp/FF2wfI7BNFP6r0MLA
    5.60 +XwQYAQgACQIbDAUCWV9iOQAKCRCpQR0Xb/AOl5ckB/9UBwdhKEro2dSkE23KY64I
    5.61 +/dNXljndLOHK8fARd1B1LWh9YHOXHtY4+h0TC8PL0IsK4j5PK8H51XqhMKKVYDVG
    5.62 +lhLUQp4qcDNcuO4dW6dS/HqAfARpLSKgwEEWW1bFzDmiOYGnQjxuEsFPlXADFTws
    5.63 +YqVX3lvZO93nU0fa5QRK65nWiMomC0Ym09hZuznvk07kyZtqAlSNgPUQNADpTJVH
    5.64 +teDbVo/oct8oRqo7ajO+psOVTaQHfEeHiFvPo0/MUWGeBhL96pRHIeO83cSipjh4
    5.65 +q46bEcclS/gTGHtFweVOiqRnR4H5YEjurCd84h8zF8MAArhxBhAtbg1nYgeHjkKX
    5.66 +=t2WB
    5.67 +-----END PGP PUBLIC KEY BLOCK-----
    5.68 +
    5.69 +--6b8b4567327b23c6643c986966334873--