Merge sync
authorDamiano Boppart <damiano.boppart@pep.security>
Wed, 08 May 2019 16:11:20 +0200
branchsync
changeset 3652560a7beb5e14
parent 3651 f22ed667bb0d
parent 3650 94b4420599e9
child 3654 f0962656dd57
Merge
     1.1 --- a/src/pgp_sequoia.c	Wed May 08 16:11:01 2019 +0200
     1.2 +++ b/src/pgp_sequoia.c	Wed May 08 16:11:20 2019 +0200
     1.3 @@ -77,6 +77,48 @@
     1.4      }                                                               \
     1.5  } while(0)
     1.6  
     1.7 +int email_cmp(void *cookie, int a_len, const void *a, int b_len, const void *b)
     1.8 +{
     1.9 +    pgp_packet_t a_userid = pgp_user_id_from_raw (a, a_len);
    1.10 +    pgp_packet_t b_userid = pgp_user_id_from_raw (b, b_len);
    1.11 +
    1.12 +    T("(%.*s, %.*s)", a_len, a, b_len, b);
    1.13 +
    1.14 +    char *a_address = NULL;
    1.15 +    pgp_user_id_address_normalized(NULL, a_userid, &a_address);
    1.16 +
    1.17 +    char *b_address = NULL;
    1.18 +    pgp_user_id_address_normalized(NULL, b_userid, &b_address);
    1.19 +
    1.20 +    pgp_packet_free(a_userid);
    1.21 +    pgp_packet_free(b_userid);
    1.22 +
    1.23 +    // return an integer that is negative, zero, or positive if the
    1.24 +    // first string is less than, equal to, or greater than the
    1.25 +    // second, respectively.
    1.26 +    int result;
    1.27 +    if (!a_address && !b_address)
    1.28 +        result = 0;
    1.29 +    else if (!a_address)
    1.30 +        result = -1;
    1.31 +    else if (!b_address)
    1.32 +        result = 1;
    1.33 +    else
    1.34 +        result = strcmp(a_address, b_address);
    1.35 +
    1.36 +    if (true) {
    1.37 +        T("'%s' %s '%s'",
    1.38 +          a_address,
    1.39 +          result == 0 ? "==" : result < 0 ? "<" : ">",
    1.40 +          b_address);
    1.41 +    }
    1.42 +
    1.43 +    free(a_address);
    1.44 +    free(b_address);
    1.45 +
    1.46 +    return result;
    1.47 +}
    1.48 +
    1.49  PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
    1.50  {
    1.51      PEP_STATUS status = PEP_STATUS_OK;
    1.52 @@ -123,6 +165,17 @@
    1.53  
    1.54      sqlite3_busy_timeout(session->key_db, BUSY_WAIT_TIME);
    1.55  
    1.56 +    sqlite_result =
    1.57 +        sqlite3_create_collation(session->key_db,
    1.58 +                                "EMAIL",
    1.59 +                                SQLITE_UTF8,
    1.60 +                                /* pArg (cookie) */ NULL,
    1.61 +                                email_cmp);
    1.62 +    if (sqlite_result != SQLITE_OK)
    1.63 +        ERROR_OUT(NULL, PEP_INIT_CANNOT_OPEN_DB,
    1.64 +                  "registering EMAIL collation function: %s",
    1.65 +                  sqlite3_errmsg(session->key_db));
    1.66 +
    1.67      sqlite_result = sqlite3_exec(session->key_db,
    1.68                                   "CREATE TABLE IF NOT EXISTS keys (\n"
    1.69                                   "   primary_key TEXT UNIQUE PRIMARY KEY,\n"
    1.70 @@ -156,7 +209,7 @@
    1.71  
    1.72      sqlite_result = sqlite3_exec(session->key_db,
    1.73                                   "CREATE TABLE IF NOT EXISTS userids (\n"
    1.74 -                                 "   userid TEXT NOT NULL,\n"
    1.75 +                                 "   userid TEXT NOT NULL COLLATE EMAIL,\n"
    1.76                                   "   primary_key TEXT NOT NULL,\n"
    1.77                                   "   UNIQUE(userid, primary_key),\n"
    1.78                                   "   FOREIGN KEY (primary_key)\n"
    1.79 @@ -164,7 +217,7 @@
    1.80                                   "     ON DELETE CASCADE\n"
    1.81                                   ");\n"
    1.82                                   "CREATE INDEX IF NOT EXISTS userids_index\n"
    1.83 -                                 "  ON userids (userid, primary_key)\n",
    1.84 +                                 "  ON userids (userid COLLATE EMAIL, primary_key)\n",
    1.85                                   NULL, NULL, NULL);
    1.86      if (sqlite_result != SQLITE_OK)
    1.87          ERROR_OUT(NULL, PEP_INIT_CANNOT_OPEN_DB,
    1.88 @@ -324,59 +377,6 @@
    1.89  
    1.90  */
    1.91  
    1.92 -// Splits an OpenPGP user id into its name and email components.  A
    1.93 -// user id looks like:
    1.94 -//
    1.95 -//   Name (comment) <email>
    1.96 -//
    1.97 -// This function takes ownership of user_id!!!
    1.98 -//
    1.99 -// namep and emailp may be NULL if they are not required.
   1.100 -static void user_id_split(char *, char **, char **) __attribute__((nonnull(1)));
   1.101 -static void user_id_split(char *user_id, char **namep, char **emailp)
   1.102 -{
   1.103 -    if (namep)
   1.104 -        *namep = NULL;
   1.105 -    if (emailp)
   1.106 -        *emailp = NULL;
   1.107 -
   1.108 -    char *email = strchr(user_id, '<');
   1.109 -    if (email) {
   1.110 -        // NUL terminate the string here so that user_id now points at
   1.111 -        // most to: "Name (comment)"
   1.112 -        *email = 0;
   1.113 -
   1.114 -        if (emailp && email[1]) {
   1.115 -            email = email + 1;
   1.116 -            char *end = strchr(email, '>');
   1.117 -            if (end) {
   1.118 -                *end = 0;
   1.119 -                *emailp = strdup(email);
   1.120 -            }
   1.121 -        }
   1.122 -    }
   1.123 -
   1.124 -    if (!namep)
   1.125 -        return;
   1.126 -
   1.127 -    char *comment = strchr(user_id, '(');
   1.128 -    if (comment)
   1.129 -        *comment = 0;
   1.130 -
   1.131 -    // Kill any trailing white space.
   1.132 -    for (size_t l = strlen(user_id); l > 0 && user_id[l - 1] == ' '; l --)
   1.133 -        user_id[l - 1] = 0;
   1.134 -
   1.135 -    // Kill any leading whitespace.
   1.136 -    char *start = user_id;
   1.137 -    while (*start == ' ')
   1.138 -        start ++;
   1.139 -    if (start[0])
   1.140 -        *namep = strdup(start);
   1.141 -
   1.142 -    free(user_id);
   1.143 -}
   1.144 -
   1.145  // step statement and load the tpk and secret.
   1.146  static PEP_STATUS key_load(PEP_SESSION, sqlite3_stmt *, pgp_tpk_t *, int *)
   1.147      __attribute__((nonnull(1, 2)));
   1.148 @@ -626,6 +626,8 @@
   1.149      int tried_commit = 0;
   1.150      pgp_tpk_key_iter_t key_iter = NULL;
   1.151      pgp_user_id_binding_iter_t user_id_iter = NULL;
   1.152 +    char *email = NULL;
   1.153 +    char *name = NULL;
   1.154  
   1.155      sqlite3_stmt *stmt = session->sq_sql.begin_transaction;
   1.156      int sqlite_result = sqlite3_step(stmt);
   1.157 @@ -711,20 +713,27 @@
   1.158      pgp_user_id_binding_t binding;
   1.159      int first = 1;
   1.160      while ((binding = pgp_user_id_binding_iter_next(user_id_iter))) {
   1.161 -        char *user_id = pgp_user_id_binding_user_id(binding);
   1.162 -        if (!user_id || !*user_id)
   1.163 +        char *user_id_value = pgp_user_id_binding_user_id(binding);
   1.164 +        if (!user_id_value || !*user_id_value)
   1.165              continue;
   1.166  
   1.167          // Ignore bindings with a self-revocation certificate, but no
   1.168          // self-signature.
   1.169          if (!pgp_user_id_binding_selfsig(binding)) {
   1.170 -            free(user_id);
   1.171 +            free(user_id_value);
   1.172              continue;
   1.173          }
   1.174  
   1.175 -        char *name, *email;
   1.176 -        user_id_split(user_id, &name, &email); /* user_id is comsumed.  */
   1.177 -        // XXX: Correctly clean up name and email on error...
   1.178 +        free(name);
   1.179 +        name = NULL;
   1.180 +        free(email);
   1.181 +        email = NULL;
   1.182 +
   1.183 +        pgp_packet_t userid = pgp_user_id_new (user_id_value);
   1.184 +        pgp_user_id_name(NULL, userid, &name);
   1.185 +        pgp_user_id_address(NULL, userid, &email);
   1.186 +        pgp_packet_free(userid);
   1.187 +        free(user_id_value);
   1.188  
   1.189          if (email) {
   1.190              T("  userid: %s", email);
   1.191 @@ -737,7 +746,6 @@
   1.192  
   1.193              if (sqlite_result != SQLITE_DONE) {
   1.194                  pgp_user_id_binding_iter_free(user_id_iter);
   1.195 -                free(name);
   1.196                  ERROR_OUT(NULL, PEP_UNKNOWN_ERROR,
   1.197                            "Updating userids: %s", sqlite3_errmsg(session->key_db));
   1.198              }
   1.199 @@ -755,8 +763,6 @@
   1.200              if (*private_idents == NULL)
   1.201                  ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "identity_list_add");
   1.202          }
   1.203 -        free(email);
   1.204 -        free(name);
   1.205  
   1.206      }
   1.207      pgp_user_id_binding_iter_free(user_id_iter);
   1.208 @@ -780,6 +786,8 @@
   1.209  
   1.210      T("(%s) -> %s", fpr, pEp_status_to_string(status));
   1.211  
   1.212 +    free(email);
   1.213 +    free(name);
   1.214      if (user_id_iter)
   1.215          pgp_user_id_binding_iter_free(user_id_iter);
   1.216      if (key_iter)
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/test/include/LookupTests.h	Wed May 08 16:11:20 2019 +0200
     2.3 @@ -0,0 +1,22 @@
     2.4 +// This file is under GNU General Public License 3.0
     2.5 +// see LICENSE.txt
     2.6 +
     2.7 +#ifndef LOOKUP_H
     2.8 +#define LOOKUP_H
     2.9 +
    2.10 +#include <string>
    2.11 +#include "EngineTestSessionSuite.h"
    2.12 +
    2.13 +using namespace std;
    2.14 +
    2.15 +class LookupTests : public EngineTestSessionSuite {
    2.16 +    public:
    2.17 +        LookupTests(string test_suite, string test_home_dir);
    2.18 +	protected:
    2.19 +        void setup();
    2.20 +        void tear_down();
    2.21 +    private:
    2.22 +        void lookup();
    2.23 +};
    2.24 +
    2.25 +#endif
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/test/src/engine_tests/LookupTests.cc	Wed May 08 16:11:20 2019 +0200
     3.3 @@ -0,0 +1,97 @@
     3.4 +// This file is under GNU General Public License 3.0
     3.5 +// see LICENSE.txt
     3.6 +
     3.7 +#include <stdlib.h>
     3.8 +#include <string>
     3.9 +#include <iostream>
    3.10 +#include <fstream>
    3.11 +#include <cstring> // for strcmp()
    3.12 +#include "TestConstants.h"
    3.13 +
    3.14 +#include "pEpEngine.h"
    3.15 +#include "message_api.h"
    3.16 +#include "keymanagement.h"
    3.17 +#include "test_util.h"
    3.18 +
    3.19 +#include <cpptest.h>
    3.20 +#include "EngineTestSessionSuite.h"
    3.21 +#include "LookupTests.h"
    3.22 +
    3.23 +using namespace std;
    3.24 +
    3.25 +LookupTests::LookupTests(string suitename, string test_home_dir) :
    3.26 +    EngineTestSessionSuite::EngineTestSessionSuite(suitename, test_home_dir) {
    3.27 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("LookupTests::lookup"),
    3.28 +                                                                      static_cast<Func>(&LookupTests::lookup)));
    3.29 +}
    3.30 +
    3.31 +void LookupTests::setup() {
    3.32 +    EngineTestSessionSuite::setup();
    3.33 +}
    3.34 +
    3.35 +void LookupTests::tear_down() {
    3.36 +    EngineTestSessionSuite::tear_down();
    3.37 +}
    3.38 +
    3.39 +void LookupTests::lookup() {
    3.40 +    // 1. create original identity
    3.41 +    const char* expected_address = "hans@xn--bcher-kva.tld";
    3.42 +    const char* fpr = "00B5BB6769B1F451705445E208AD6E9400D38894";
    3.43 +    const char* userid = "Hans";
    3.44 +    const char* username = "SuperDuperHans";
    3.45 +    const string pub_key = slurp("test_keys/pub/hans@xn--bcher-kva.tld_-0x08AD6E9400D38894_pub.asc");
    3.46 +
    3.47 +    PEP_STATUS statuspub = import_key(session, pub_key.c_str(), pub_key.length(), NULL);
    3.48 +    TEST_ASSERT_MSG((statuspub == PEP_TEST_KEY_IMPORT_SUCCESS), "statuspub == PEP_STATUS_OK");
    3.49 +
    3.50 +    pEp_identity* hans = new_identity(expected_address, NULL, userid, username);
    3.51 +
    3.52 +    PEP_STATUS status = set_identity(session, hans);
    3.53 +    TEST_ASSERT_MSG((status == PEP_STATUS_OK), tl_status_string(status));
    3.54 +    free_identity(hans);
    3.55 +
    3.56 +    // Lookup using different spellings of the email address.
    3.57 +    const char *addresses[] = {
    3.58 +        // Check case folding.
    3.59 +        "hans@xn--bcher-kva.tld",
    3.60 +        "Hans@xn--bcher-kva.tld",
    3.61 +        "Hans@xn--Bcher-kva.tld",
    3.62 +
    3.63 +        // Check puny code normalization.  Note: only Sequoia does
    3.64 +        // puny code normalization.
    3.65 +#ifdef USE_SEQUOIA
    3.66 +        "hans@bücher.tld",
    3.67 +        "Hans@bücher.tld",
    3.68 +        "HANS@BÜCHER.TLD",
    3.69 +#endif
    3.70 +    };
    3.71 +
    3.72 +    for (int i = 0; i < sizeof(addresses) / sizeof(addresses[0]); i ++) {
    3.73 +        const char *address = addresses[i];
    3.74 +
    3.75 +        pEp_identity *hans = new_identity(address, NULL, NULL, NULL); 
    3.76 +        PEP_STATUS status = update_identity(session, hans);
    3.77 +        TEST_ASSERT_MSG((status == PEP_STATUS_OK), tl_status_string(status));
    3.78 +
    3.79 +        // We should always get the same fingerprint.
    3.80 +        TEST_ASSERT_MSG((hans->fpr), "hans->fpr");
    3.81 +        TEST_ASSERT_MSG((strcmp(hans->fpr, fpr) == 0), "strcmp(hans->fpr, fpr) == 0");
    3.82 +
    3.83 +        // We don't compare hans->username or hans->user_id in case
    3.84 +        // the engine doesn't have the same concept of equality (as of
    3.85 +        // 2019.5, this is the case: pgp_sequoia.c does puny code
    3.86 +        // normalization, but the engine doesn't).
    3.87 +        TEST_ASSERT_MSG((hans->username), "hans->username");
    3.88 +        TEST_ASSERT_MSG((hans->user_id), "hans->user_id");
    3.89 +
    3.90 +        // We should get the address that we looked up; no
    3.91 +        // normalization is done.
    3.92 +        TEST_ASSERT_MSG((strcmp(hans->address, address) == 0), "strcmp(hans->address, address) == 0");
    3.93 +
    3.94 +        TEST_ASSERT_MSG((!hans->me), "!hans->me"); 
    3.95 +        TEST_ASSERT_MSG((hans->comm_type == PEP_ct_OpenPGP_unconfirmed), "hans->comm_type == PEP_ct_OpenPGP_unconfirmed");
    3.96 +
    3.97 +        cout << "PASS: update_identity() correctly retrieved OpenPGP key for '" << expected_address << "' using '" << address << "'" << endl << endl;
    3.98 +        free_identity(hans);
    3.99 +    }
   3.100 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/test/test_keys/priv/hans@xn--bcher-kva.tld_-0x08AD6E9400D38894_priv.asc	Wed May 08 16:11:20 2019 +0200
     4.3 @@ -0,0 +1,138 @@
     4.4 +-----BEGIN PGP PRIVATE KEY BLOCK-----
     4.5 +
     4.6 +xcSYBFzR6V0BDACkJ2yRZAaR7tg6jAC87LLICjd39xnD/Ra9D3Elld5QTHZ2GXw+
     4.7 +8v1er/ZYcvS3JPZsjDvIeg5bRV24IpghWyfRvjBivLlAV9PCWSpfCqj0xnzM7HaU
     4.8 +UQbPg/Bwtf7m8A3YC16pBIbmGUHfIL6LUY7Fd4dLKu1UELuhKn/Tn6X9YuO4Isah
     4.9 +w2U4lbobzFvH7PKkBuG3+sYL7JhE/ArDTIWaSoszvPtxTg/hfSj1rZmfYrClzcB8
    4.10 +aqoilhmRdYX1DNk4c7bsg513XirqTm0lJMK23hOJithBsGoC6n6Tm3X9NC/a4hmE
    4.11 +Fly8U8Y3wW26WUUR0gPfp16c5GFhLlOuRwOdO0D+WnEOnw+Aq1IRd+LtLq4psNRv
    4.12 +D7dxI299tBuybn26fQAUXmMqF+MSOqyqKegi6IIiD1jFDAg3t0rSu77pphMm3ANS
    4.13 +uuTJ6xrhnS5YwRQ5/czJu6MFK33ycWw/6PLnaEgrNS7XjHXsgSPgjoEPB5+hAwDn
    4.14 +roW0DnRdmk2HhnsAEQEAAQAMAJdUZOkP3mKwXpRytsd0Kkjx6jrlCNK+QjUexD9T
    4.15 +DzTVmKu9SOY7WkrtStw1ddZU8/wTt5VUuGF57DExay/s+iOJAtAzjVB85xIW41Hk
    4.16 +4OdvCGReZd7LZ8zspD8z+H7rtMeDi8ujCb2ccTaC2EZVdJokXAx20X2bQ24LYPY2
    4.17 +Cm8yuB3rqVQ9btYgagbweXgwv2tpkLLsM6GQhrup4z4yEESyDewvf1nwDgHhQV5j
    4.18 +oOjnsVPY/2dzac8iswV+43SKV0hrh93JPKP1OPoIx8WvbAz1nkmUkaxKfJNrSOZT
    4.19 +57XNNJM6FXGJqJVUVnwe43sltWRoCJaAVQqbVf8bL9b+/FVInXGqYkrnbCvuzeIP
    4.20 +Dq8foWsZueu3jFO4OuxlizxWDuh4MHpcWKU2AYjs8H8kLlROcgFOXYme0GCx0GoH
    4.21 +fBcnA0U3emC5SUc9glnZT1UXuOVy0PBHZLQtosSl1VaS3zIXpWl7K5WEAt29EKHb
    4.22 +hSfrTXub2kIWZwC6lx//8PS/GQYAxxgOqSyvNTB8ZUxTsHmzkMGeL3QHiz5sObwk
    4.23 +xrYXkpUKIzgGUK8fAKNtVURgrNWCcj09WeILaUPeChpsnu+3TZZa8NNnzDMTgb/M
    4.24 +aBv8uR/SZxJBgbgNmyJjVPqjJLXi4CyYn4xIm7kiAusyVdWpeGxVnMAd7DNzNaoS
    4.25 +ESYYAlxZZ3QBSi8uGzTj7X4xi4luIlJgY8Fvp6V/FyEWvpDNfCqKszCn4JgB12pI
    4.26 +x++Hzwlxp7TNxXOhYYYBvKsqEfiVBgDTEsR28bf8xf0hr0Im+UeCvyMJ84OSCuvt
    4.27 +J9dQCef7tn0TB1iWO1Jl619YM3gaCgKN1GOMHlV9cjtJ4vIsYjY2fxhoIN9uwuKY
    4.28 +rRD5MDxct5Cx35Kg7kIZaEsGJqt5Bnm3K5DjxvoN50UYloRq+nbxT6THPTFUkBVR
    4.29 +OjzJVKThLoVWKLoQOZrTI9mk8Qv8cfc2mSni5t7bF4klRIVMoeeGqS9zDsOYqnHP
    4.30 +8leYLXRK7V1WfSt8XIFevf1oYkoR7s8F+wQnORG8JZWKYN1L4oRROg7RYUYaZMsh
    4.31 +tR0GTrQOap9Dv3nDqL306KZr12lf6IRF0CWhZtvqWe56wPQB5qvgU2hIwUk/3kG+
    4.32 +396HwoeyuzpuA/Za1CQ4Q1sHmNUiault1Jpmz5WwDQocby+EFwVaps48MaEMGCPS
    4.33 +Tjc5vV7kNdevYPNDh2ytDs61KVAxSJxzE8XIQmhTbJl1ifhbLkUzIgbBpKXPvA2C
    4.34 +aa4C97xEEb8rtbZ44usNbgXlS5pMMnThzc3hwsECBB8BCgA2Ah4DApsBBYJc0eld
    4.35 +BYkFn6YAFiEEALW7Z2mx9FFwVEXiCK1ulADTiJQJEAitbpQA04iUAhUKAACY6gwA
    4.36 +kN2XvosfWgZtQsAuHR5+amQvqvGj+yd45LVRRaNs3b/45vNfifjp84DWLl/TJiZh
    4.37 +LVxAWfaIO662ZeWFPgRQLFM0B3PXFGY8pF6Cfqt6NeXYa/yOU5KAwwcqpzPd0nA/
    4.38 +A4QH1glNC0tRQHKL/UVMYU7QILRC0GbbJNX9TqtG5zHFe3+JPxbBc465wxcJPZEO
    4.39 +6Fd5QM/nFJZrMCsWf2UpBg2dkf6M6Jv9pMSG/rVCDtYhNZt+GZu+/1sRi8ryZVAl
    4.40 +20GlOpji7B1PVyezusDs+NcDZ6u1cTpiNirXrpoH9AomukPVcPYyhV8Co5smX7pQ
    4.41 +IDR3LmwKXcE/JGN7ocH4C2FwwdcgNtJ4kz9EJ+d3v2iplocNa9Ev/0J2gtixzJ64
    4.42 +0J03zZ9XR1wgdr0Y06JDXqX7rJz8Vj9p853/2qdsCcBPylpm0RC+ymgHBHMOuRYx
    4.43 +nkFYN+1CzULKxLBHfhBuL2hRONieaeS6dYbNpM8haBgJlSINX0myWPh5fPqHRviU
    4.44 +zR1IYW5zIDxoYW5zQHhuLS1iY2hlci1rdmEudGxkPsLBAgQTAQoANgIeAwKbAQWJ
    4.45 +BZ+mAAIVCgWCXNHpXRYhBAC1u2dpsfRRcFRF4gitbpQA04iUCRAIrW6UANOIlAAA
    4.46 +FGQL/15QxKSU22xKtJfm0qPpehjRQVmykzsj6hbPYxpmFmRAN6UJi4u2w5/6VDxc
    4.47 +IuzSuIlV4JSuXiNYPPDKCvUnTEd9HE4PUjpswqXx86mcr2LNCoIcDl7FEFbMZxgg
    4.48 +5em9rZ9SgJAf6N0X421P32mNo6rAF1t8VEQcWUsuq1mq6DHBGj36Dr7y0S6wsgrb
    4.49 +mfoAPMnbCGo9zvwAaLR06yjUaRpIAu+GS4WvCrgoj4IFm2uufOypmGjRO0iL1pg0
    4.50 +MELqrWc0XgcNrbUoMLrb1KSqrKyV94jROv1Wv0lIyh5CJfnHMe2xGCvnDQS/DTAG
    4.51 +Fkcu60Qk+QqKb9WCauPAD8xqekCcWTZry0u/Wna2KoKAbqpDhTWNDzuL3dyTVce4
    4.52 +R/w+ZKnQUfVe/3ThSn7VID66HiiygNfrTPJBemjw5j8NvRGkgTJpprG8+zmZSbgr
    4.53 +krvRWLmo+YhNng+lhXZ1UH3y+8lkHrDOc0MsW71+r7naO552w/DkcJ0TQ6rHNOvh
    4.54 +jQ368MfEmARc0eleAQwA491l+GgZIIz8882KRUjhMWBguTA8EobBBpgiP/xiIE82
    4.55 +UGWlq8ORDdrmxiuoJ1nEf5pJ0JXCi3uujz8q6hZo6JS4ci447DIDaXVWSFQ3Goz5
    4.56 +7G6Gi7JfMMaH6dtShYru/np/+wNM2vxuxMhBrd5DWA0uTk33R8C/Jp2PhM9MVpiK
    4.57 +F+mt1/tJc9JCOAi+J2r9bk8nzT6gepPI+5u0eyp40ZzY6ydd5vGDD+X2dz07MLzz
    4.58 +VxKR8StdAmcoOGz8FZNMnkuy+J/M+KgvpnTNghH+4markQRCTkel+J8hBtdMDFxa
    4.59 +90wlr0PF+HaHKpCGHNTr1SSRTbxSWG2QG/Ym4srN07yHgJN5QiZc3dBG3OuIQx/S
    4.60 +zQz5d+lQs9KWKZpMj6C2mTksW5bYNGBFGqM6h9Wh3FI+Hw+naS+CN2aVhjJTHWGb
    4.61 +3DOMhkNpG7lkZeInjO6zo77ifqe+WvD9jkeGlM/QNEydo0BF1qonxEFDKgdAtL+1
    4.62 +cNs5K8B/7HeTGIN3Zq6pABEBAAEADACUDKSVSmWRDanIanJ9Y8XVBA60JA/T5bQC
    4.63 +qdQPCNdksLLUd8a1nCJiAylP9suRjbSrR77QBI3bfKfFMMCcSaUuAHr6zOd1J2Wq
    4.64 +Hm/KHNWUraYwpPtMRr+sfEGQg0zRsZxowYTnvZQw8DS0LHzoD/JngmDkxal1+Fj6
    4.65 +KQM3wkySMxf+Q3kNTJrD4wfdSmjqSYySIGH268ru+ZhrShZws/6+Co+x8ekEBUUn
    4.66 +jj2d6a3Mk+fzWgBy1r7esdGjH8SF7CZwlbv9d6U6k2CjOCzqR2MrlxgUsPZG/re7
    4.67 +qh+KWi1iea+nj4mhWtMjezEGKR7nxhP+PDQApkjQ9QjTo3zEO1p3XYuL999SWeon
    4.68 +g1+ClB2RSY31YYFJ6m1V1OIbHt9hYno74P72kqhwCEkrrBBON/9Hh6LHgZ/mGd9l
    4.69 +D4P2ePJkmz5jJI6aZgoRaHHy/kjpxHIB+nUQKAYg5F1eK1Y5AoRANcPiYpo/VAcB
    4.70 +v+aQ8D402z31Bwo6ag0v0nJgJzfLQwEGAORMYsPQ6VuUT+YEXVATUyfg6T642dAr
    4.71 +Ch83reqlnx7KWNeS16AuqaY8yMkWlB0X1ToQ834+9kF6AA8BeCU3jQN3bgY/CYVL
    4.72 +MgExuLxPHBBrzIFXHdQupd4IITXxeeCe/xWGjG7x+lbhrr2qGmTFLjy0Z/fDs0KZ
    4.73 +ZgxevYCFyTa4V94SAld9lpGlUHw+4WALqHmnUk0N7WWua3DLYvE+rtzKmH8qKxEi
    4.74 +Fhwg6J0pWAgqf4WVhB9r/Ahm9ZtBfmnd4QYA/4OLnD9/PaBYRB9rNWPKiNrtlGEF
    4.75 +kfzZQRVIDH+LoRWX/cjYUCqZzy85u/y5ugRI3u18iNolsOQyd/sVP37O1RdurxCw
    4.76 +0rPbgwxgpwHSRMG5gQK34JKyk72s8TNePwz/b0kPSFYdTnNwk9sekndTxLSdSlzY
    4.77 +Xt9snCkK158/Lf8hSehRg2BzOKdjsLCmy4Z3D33pmgGF02EJ0wb2KuTps6YXiXiS
    4.78 +jnioc+4dbS8yfWEfh0kaPZjtz/NiIOWOLJnJBf93vqn9L7zi3ugDAWL3tGsLyzyM
    4.79 +SCkKpXqvMVNx1DzqQLIOAXGA7oF9am3ZxMg/0s+wKQtKBJlyd5fr6hb3QulkooQS
    4.80 +3khDMDzGYdrwpQAN0ZH8upDGpvKuaXgJdqVdhrKJxtV3AFzaEKcO/oTeWsXSN6Fg
    4.81 +vP6K3ify9gdvLpylFamtm+m+qKqwWQCdW1Cc/UNBppuvvcd/u07HHQ8w7dKeMFm0
    4.82 +hIkJO4mMWwd3AxjCJsj5rC2czbK1FwVN3858Oqbb48LCuAQYAQoANgIeAwKbAgWJ
    4.83 +BZ+mAAIVCgWCXNHpXhYhBAC1u2dpsfRRcFRF4gitbpQA04iUCRAIrW6UANOIlAG2
    4.84 +wPSgBBkBCgAnBYJc0eleFiEEZ433xCA2cbfsXHpnQBe0N01yqsMJEEAXtDdNcqrD
    4.85 +AADRkQv/RBZvOZmo0wbGE6WTYRvUZJNdiTEYxo8YOxlEfw2GWCl0/QQ+Eh8XFh6J
    4.86 +nc4V70UiwwHuZ0YFFXxA1c6K8zhcBkq+n5EMMPTTCF/lmqF3qqbLGG7dwy0yVfry
    4.87 +ze79mvz24mAhD7vaZ3m9IdNvLIKd+LIWaD08GbpbTc+UNCb7iPYx/LN23lNs/grT
    4.88 +LHK1KTWMq4T11SSrdeT8j3d5Ax3UhvyRuWL+RKfd8WKpfl39ZbPl7lQYs2uyoKT3
    4.89 +RyMI66EKXKGTY2UNjbMo2OyBY3UIvdjNVt80kPv7MVzBOQlUkB7IEUuL9UHLFKug
    4.90 +IL2gBsWdJm/tnxm/OVzOjS9j6P1UqwUdNNh9nXlpIvQaifxy0my0SIs6vfnRVLOL
    4.91 +XUPQ+Mmi4midVq1plUUyPxrJd3mw8cEvHZY2xVRqInSCAtFHkA50mAykf/bOh9zP
    4.92 +2xujEdMjSVT//dUs8W6gTHvqXRMM1axpK95CA7ULZY77pHH2ZEYxZ6jxSiHfNhDk
    4.93 +1AKfaqhvX5wL/jEJ0e5p8ebT1Bei6ohPUcI02YN6LUWOqlRHub4u2uPrrYAbLtY/
    4.94 +u6p4x7bOyri3j5iaglVGCsQ2Yrq9ejED/2bb59Hi0PtIBcBsIR/Vop/rEADSsciu
    4.95 +Tb6odP+5JGnLPda/Xt24Cd1ZXXa9GI/4ZEQtqiMZZsf82Z4r3yYsfpViTPlps/Xa
    4.96 +9kKK0NMfrrXvqfmPsOzy+z+PpBIqViHkV4IzOS88xOBk3Ad6RWbzPfQabkI7UfJa
    4.97 +/aki/jKLxrQluQg+cBE4gclnBy+x3EoxmIjg0TucZO5jHkTRwUmFncyg+fQ71sDj
    4.98 +ilPzPdN9K5NKNepVJSy4v3N4gAcgvOPIXyucvbVvy45lQQgf9HIBgSu5oFKX2gnw
    4.99 +Gw9nxBwZ2XcQAX9XYn56AVVARqX5YvOgMXlclnUMm9JCTzBHyIt0oPlzWWwYCwLX
   4.100 ++8ToLbkq4mR1pMifp0ELrvnITG5lAx2IvB3D/UzZegR09e6MF28XqBEZnzfcn/ii
   4.101 +XCQjo5UhelrKIcfEmARc0eleAQwA8HDSEz2+Awzm3d0W5RKZeMOGMp+ts1DGZomp
   4.102 +SUS8ot1H2wD+StEJc4ryxZyWRaGzXRiJbld5WqcxK22iMPPPgmiW+5j2NamqDUZm
   4.103 +3G4QOFzDNc10urqB3jP2FqUca36OWHa6t9IQAy5HBz21S9urnUTcNJBha7xC5Blt
   4.104 +6Um8o8ah2eqf/CblNP75cqq4nxwlEsj+Rh64KsI9cLVfaCh7XJUMD6aphc32RqN4
   4.105 +a9j89+HXXF+Qc1XgFmAFI80iS4Kv/b6fI0FiTfUsE8KwtrgFU36Cw/jM4J/03FdO
   4.106 +KZo5/036I9WNg5KnDEKYYCsdbpB4ZxpHLmtBAv92DnrXZ+EYZJZ8ijfnsx2zZkgl
   4.107 +AzMSjzHZd3v4tuAlb9du1Q7YKsj0/YzWLJGraeRBJG1Zg4ZNLTg20ZfJJzWEjUhq
   4.108 +AlwxfKmB+thRL+BYOAlHDGy1YPAof9sQ3azIRR8gkF+qflawRnw2aCvs1E+EGt52
   4.109 +BEV7CPd26ZPXY90lp38k3eQkz2e9ABEBAAEAC/0TdJ2bDvjsGEQqGbS7jni6q9+V
   4.110 +AxS0GMolC+iV1CkLaKpizz7EYQvJvKmOUfBa7A2ub8jXE97u9e5lnDZujZvx6nKl
   4.111 +IyhxCSyIbHTwSzumw+LL3LcgUO0nRL8Z7/xPumrcP6c2Lpo7F6iJrnWYEMtfK25C
   4.112 +Fpi7df1XpbMeGGhaPD1me7S8W41ab3NR0vyja0yYq4jftaajVxpPn2176SKqSCk0
   4.113 +rwCyogrWhm29FE7L5AtgHx96Ja2/Qb/IuNWYlJdu4TuHms5u9I2w27n2c8a8yFLh
   4.114 +lhNLzAd1GoKmD7VtA45rG1aT8baWWEJAFNsXRENbthCcLd2Azbkv/5xdXPKd4K+n
   4.115 +ReukZhtwUQAsNovhv0imCHSPGsZsxYa/BYyGfGl77GA9CiKaBcKCsrVtIC90Upmv
   4.116 +CgMeaGtVvtgOL6zdbG+2oqL6mvSYzNbw/9/s3z93veCNmvBhfoVtQGY2ckzV/y4y
   4.117 +2irLtgvRnbC9Qtf0GHmbkArBrDJaVOAfmxdRJsUGAPNIT8PA4/ls56RtkDDml5Gu
   4.118 +xi16akTHsa8vF4PxCDWhiZ07kVto7IupunoinD5iRF5DUYEtXlLdZwxSh3V2C6eF
   4.119 +XmG02guivt2v87X+20GNb2naH3h5/HpIks46oNu0984lQ6NKWLvh3G88VHoOWMxj
   4.120 +mCiWF6Tx9tcZrXe5mXFpw2B3WVOIaRXQTFHvKT7kVV4kWjk78gA342s0AF7iFdAL
   4.121 +j9k+mtmjTjkISrRs9t0aWImWcwdd3Q/LMZClgCJ+CwYA/QJ6x50qrpCiyrI1g3cZ
   4.122 +DnfxBLTkke7LWj9AnMLaYD4o2rUhaUV18xygq4TyuVwVCyLtpsAAMyOm8SBUV1he
   4.123 +VLsde//MhDQk7rjmLRERTAqLTJPFql+FVJCShr4IGD2/eV4zB3NFJ72HM7Vh7NxK
   4.124 +Ft8L+KBEiGrD0cl3UHovhlWnkpb1MaXW6WHhZGCicrRiErthwJv+wCcofqG4wexD
   4.125 +Kvxxvo5t76Adwt42wVwBfrsAu4kI8W0t62ZmRLzu6PZXBf9FQxf4+OyNnxkSBdOl
   4.126 +5gwfshm2ds3k9oHRRYQULD+XtmK/D4w4IgeSbI7w2Zp+N9PQ3siRvwODWn+RfP4v
   4.127 +hZs+Cki4OhDsjD7d7UoSCmKKXmfBYx2QE8BIWEyUs3KyNRSMDs19vV3tmLqJ+kyi
   4.128 +dYQv9p979UV7NyAF8PIakEiXUM7JWQNT6lmd39CltHtRG0I0J9VbNZXOKisqXDax
   4.129 +U+al6mBfcNLCkVBqlEtHG/cIJctQx7fvLV3G/MmWdDn6xHrgw8LBAgQYAQoANgIe
   4.130 +AwKbDAWJBZ+mAAILCQWCXNHpXhYhBAC1u2dpsfRRcFRF4gitbpQA04iUCRAIrW6U
   4.131 +ANOIlAAAAjsL/AwrdiMqx6pImsSYZi6+pWCwn25Lir/vdT2INly2kx3KNym32IBf
   4.132 +s6QIeCYpPhReHSJUu99gfB3UiMZelYzARcSn1b+9qR3nW02zmd5NfDI/RX9oiZsY
   4.133 +Yw62x/mAvoKdjTus4gq30EJVKB98bZBftCl8PPSm//485WDN5zqbd1/KH+9HDCHZ
   4.134 +W2Yu80SOhGUc6F2pkSRkQh0YoOFFjYJklMb057BPQx3uN7hZz/Bk2lBGQzg0YHBp
   4.135 +a+/UIKSW/Y87PvJrjK5wG2wP0rxNfZS+Ph6+dYT+E7NLxnlqPN8hsYxpg2wOQ372
   4.136 +DCQcYhcyh2bsyFFjtQQb7tYGuM0R1myBa+j5ZEiPgfbhzmgd18Z5iOhTWnk/iO+A
   4.137 +knt5dIVvqyRQrvnfmVN5xgmGAGT3NwMGBLTyehe2nATAsq1hscxNXSE/x+SbbNSt
   4.138 +MT67Qq/lEyVrXxb1Xq6kTfN09f91oDdVU/9AJxiSzE56a5vfMqJHXMK5By2UI4kO
   4.139 +X3Q7oXjkZBenzg==
   4.140 +=ox8H
   4.141 +-----END PGP PRIVATE KEY BLOCK-----
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/test/test_keys/pub/hans@xn--bcher-kva.tld_-0x08AD6E9400D38894_pub.asc	Wed May 08 16:11:20 2019 +0200
     5.3 @@ -0,0 +1,77 @@
     5.4 +-----BEGIN PGP PUBLIC KEY BLOCK-----
     5.5 +
     5.6 +mQGNBFzR6V0BDACkJ2yRZAaR7tg6jAC87LLICjd39xnD/Ra9D3Elld5QTHZ2GXw+
     5.7 +8v1er/ZYcvS3JPZsjDvIeg5bRV24IpghWyfRvjBivLlAV9PCWSpfCqj0xnzM7HaU
     5.8 +UQbPg/Bwtf7m8A3YC16pBIbmGUHfIL6LUY7Fd4dLKu1UELuhKn/Tn6X9YuO4Isah
     5.9 +w2U4lbobzFvH7PKkBuG3+sYL7JhE/ArDTIWaSoszvPtxTg/hfSj1rZmfYrClzcB8
    5.10 +aqoilhmRdYX1DNk4c7bsg513XirqTm0lJMK23hOJithBsGoC6n6Tm3X9NC/a4hmE
    5.11 +Fly8U8Y3wW26WUUR0gPfp16c5GFhLlOuRwOdO0D+WnEOnw+Aq1IRd+LtLq4psNRv
    5.12 +D7dxI299tBuybn26fQAUXmMqF+MSOqyqKegi6IIiD1jFDAg3t0rSu77pphMm3ANS
    5.13 +uuTJ6xrhnS5YwRQ5/czJu6MFK33ycWw/6PLnaEgrNS7XjHXsgSPgjoEPB5+hAwDn
    5.14 +roW0DnRdmk2HhnsAEQEAAYkBwgQfAQoANgIeAwKbAQWCXNHpXQWJBZ+mABYhBAC1
    5.15 +u2dpsfRRcFRF4gitbpQA04iUCRAIrW6UANOIlAIVCgAAmOoMAJDdl76LH1oGbULA
    5.16 +Lh0efmpkL6rxo/sneOS1UUWjbN2/+ObzX4n46fOA1i5f0yYmYS1cQFn2iDuutmXl
    5.17 +hT4EUCxTNAdz1xRmPKRegn6rejXl2Gv8jlOSgMMHKqcz3dJwPwOEB9YJTQtLUUBy
    5.18 +i/1FTGFO0CC0QtBm2yTV/U6rRucxxXt/iT8WwXOOucMXCT2RDuhXeUDP5xSWazAr
    5.19 +Fn9lKQYNnZH+jOib/aTEhv61Qg7WITWbfhmbvv9bEYvK8mVQJdtBpTqY4uwdT1cn
    5.20 +s7rA7PjXA2ertXE6YjYq166aB/QKJrpD1XD2MoVfAqObJl+6UCA0dy5sCl3BPyRj
    5.21 +e6HB+AthcMHXIDbSeJM/RCfnd79oqZaHDWvRL/9CdoLYscyeuNCdN82fV0dcIHa9
    5.22 +GNOiQ16l+6yc/FY/afOd/9qnbAnAT8paZtEQvspoBwRzDrkWMZ5BWDftQs1CysSw
    5.23 +R34Qbi9oUTjYnmnkunWGzaTPIWgYCZUiDV9Jslj4eXz6h0b4lLQdSGFucyA8aGFu
    5.24 +c0B4bi0tYmNoZXIta3ZhLnRsZD6JAcIEEwEKADYCHgMCmwEFiQWfpgACFQoFglzR
    5.25 +6V0WIQQAtbtnabH0UXBUReIIrW6UANOIlAkQCK1ulADTiJQAABRkC/9eUMSklNts
    5.26 +SrSX5tKj6XoY0UFZspM7I+oWz2MaZhZkQDelCYuLtsOf+lQ8XCLs0riJVeCUrl4j
    5.27 +WDzwygr1J0xHfRxOD1I6bMKl8fOpnK9izQqCHA5exRBWzGcYIOXpva2fUoCQH+jd
    5.28 +F+NtT99pjaOqwBdbfFREHFlLLqtZqugxwRo9+g6+8tEusLIK25n6ADzJ2whqPc78
    5.29 +AGi0dOso1GkaSALvhkuFrwq4KI+CBZtrrnzsqZho0TtIi9aYNDBC6q1nNF4HDa21
    5.30 +KDC629SkqqyslfeI0Tr9Vr9JSMoeQiX5xzHtsRgr5w0Evw0wBhZHLutEJPkKim/V
    5.31 +gmrjwA/ManpAnFk2a8tLv1p2tiqCgG6qQ4U1jQ87i93ck1XHuEf8PmSp0FH1Xv90
    5.32 +4Up+1SA+uh4osoDX60zyQXpo8OY/Db0RpIEyaaaxvPs5mUm4K5K70Vi5qPmITZ4P
    5.33 +pYV2dVB98vvJZB6wznNDLFu9fq+52juedsPw5HCdE0OqxzTr4Y0N+vC5AY0EXNHp
    5.34 +XgEMAOPdZfhoGSCM/PPNikVI4TFgYLkwPBKGwQaYIj/8YiBPNlBlpavDkQ3a5sYr
    5.35 +qCdZxH+aSdCVwot7ro8/KuoWaOiUuHIuOOwyA2l1VkhUNxqM+exuhouyXzDGh+nb
    5.36 +UoWK7v56f/sDTNr8bsTIQa3eQ1gNLk5N90fAvyadj4TPTFaYihfprdf7SXPSQjgI
    5.37 +vidq/W5PJ80+oHqTyPubtHsqeNGc2OsnXebxgw/l9nc9OzC881cSkfErXQJnKDhs
    5.38 +/BWTTJ5LsvifzPioL6Z0zYIR/uJmq5EEQk5HpfifIQbXTAxcWvdMJa9Dxfh2hyqQ
    5.39 +hhzU69UkkU28UlhtkBv2JuLKzdO8h4CTeUImXN3QRtzriEMf0s0M+XfpULPSlima
    5.40 +TI+gtpk5LFuW2DRgRRqjOofVodxSPh8Pp2kvgjdmlYYyUx1hm9wzjIZDaRu5ZGXi
    5.41 +J4zus6O+4n6nvlrw/Y5HhpTP0DRMnaNARdaqJ8RBQyoHQLS/tXDbOSvAf+x3kxiD
    5.42 +d2auqQARAQABiQN4BBgBCgA2Ah4DApsCBYkFn6YAAhUKBYJc0eleFiEEALW7Z2mx
    5.43 +9FFwVEXiCK1ulADTiJQJEAitbpQA04iUAbbA9KAEGQEKACcFglzR6V4WIQRnjffE
    5.44 +IDZxt+xcemdAF7Q3TXKqwwkQQBe0N01yqsMAANGRC/9EFm85majTBsYTpZNhG9Rk
    5.45 +k12JMRjGjxg7GUR/DYZYKXT9BD4SHxcWHomdzhXvRSLDAe5nRgUVfEDVzorzOFwG
    5.46 +Sr6fkQww9NMIX+WaoXeqpssYbt3DLTJV+vLN7v2a/PbiYCEPu9pneb0h028sgp34
    5.47 +shZoPTwZultNz5Q0JvuI9jH8s3beU2z+CtMscrUpNYyrhPXVJKt15PyPd3kDHdSG
    5.48 +/JG5Yv5Ep93xYql+Xf1ls+XuVBiza7KgpPdHIwjroQpcoZNjZQ2NsyjY7IFjdQi9
    5.49 +2M1W3zSQ+/sxXME5CVSQHsgRS4v1QcsUq6AgvaAGxZ0mb+2fGb85XM6NL2Po/VSr
    5.50 +BR002H2deWki9BqJ/HLSbLRIizq9+dFUs4tdQ9D4yaLiaJ1WrWmVRTI/Gsl3ebDx
    5.51 +wS8dljbFVGoidIIC0UeQDnSYDKR/9s6H3M/bG6MR0yNJVP/91SzxbqBMe+pdEwzV
    5.52 +rGkr3kIDtQtljvukcfZkRjFnqPFKId82EOTUAp9qqG9fnAv+MQnR7mnx5tPUF6Lq
    5.53 +iE9RwjTZg3otRY6qVEe5vi7a4+utgBsu1j+7qnjHts7KuLePmJqCVUYKxDZiur16
    5.54 +MQP/Ztvn0eLQ+0gFwGwhH9Win+sQANKxyK5Nvqh0/7kkacs91r9e3bgJ3Vlddr0Y
    5.55 +j/hkRC2qIxlmx/zZnivfJix+lWJM+Wmz9dr2QorQ0x+ute+p+Y+w7PL7P4+kEipW
    5.56 +IeRXgjM5LzzE4GTcB3pFZvM99BpuQjtR8lr9qSL+MovGtCW5CD5wETiByWcHL7Hc
    5.57 +SjGYiODRO5xk7mMeRNHBSYWdzKD59DvWwOOKU/M9030rk0o16lUlLLi/c3iAByC8
    5.58 +48hfK5y9tW/LjmVBCB/0cgGBK7mgUpfaCfAbD2fEHBnZdxABf1difnoBVUBGpfli
    5.59 +86AxeVyWdQyb0kJPMEfIi3Sg+XNZbBgLAtf7xOgtuSriZHWkyJ+nQQuu+chMbmUD
    5.60 +HYi8HcP9TNl6BHT17owXbxeoERmfN9yf+KJcJCOjlSF6WsohuQGNBFzR6V4BDADw
    5.61 +cNITPb4DDObd3RblEpl4w4Yyn62zUMZmialJRLyi3UfbAP5K0QlzivLFnJZFobNd
    5.62 +GIluV3lapzErbaIw88+CaJb7mPY1qaoNRmbcbhA4XMM1zXS6uoHeM/YWpRxrfo5Y
    5.63 +drq30hADLkcHPbVL26udRNw0kGFrvELkGW3pSbyjxqHZ6p/8JuU0/vlyqrifHCUS
    5.64 +yP5GHrgqwj1wtV9oKHtclQwPpqmFzfZGo3hr2Pz34ddcX5BzVeAWYAUjzSJLgq/9
    5.65 +vp8jQWJN9SwTwrC2uAVTfoLD+Mzgn/TcV04pmjn/Tfoj1Y2DkqcMQphgKx1ukHhn
    5.66 +Gkcua0EC/3YOetdn4RhklnyKN+ezHbNmSCUDMxKPMdl3e/i24CVv127VDtgqyPT9
    5.67 +jNYskatp5EEkbVmDhk0tODbRl8knNYSNSGoCXDF8qYH62FEv4Fg4CUcMbLVg8Ch/
    5.68 +2xDdrMhFHyCQX6p+VrBGfDZoK+zUT4Qa3nYERXsI93bpk9dj3SWnfyTd5CTPZ70A
    5.69 +EQEAAYkBwgQYAQoANgIeAwKbDAWJBZ+mAAILCQWCXNHpXhYhBAC1u2dpsfRRcFRF
    5.70 +4gitbpQA04iUCRAIrW6UANOIlAAAAjsL/AwrdiMqx6pImsSYZi6+pWCwn25Lir/v
    5.71 +dT2INly2kx3KNym32IBfs6QIeCYpPhReHSJUu99gfB3UiMZelYzARcSn1b+9qR3n
    5.72 +W02zmd5NfDI/RX9oiZsYYw62x/mAvoKdjTus4gq30EJVKB98bZBftCl8PPSm//48
    5.73 +5WDN5zqbd1/KH+9HDCHZW2Yu80SOhGUc6F2pkSRkQh0YoOFFjYJklMb057BPQx3u
    5.74 +N7hZz/Bk2lBGQzg0YHBpa+/UIKSW/Y87PvJrjK5wG2wP0rxNfZS+Ph6+dYT+E7NL
    5.75 +xnlqPN8hsYxpg2wOQ372DCQcYhcyh2bsyFFjtQQb7tYGuM0R1myBa+j5ZEiPgfbh
    5.76 +zmgd18Z5iOhTWnk/iO+Aknt5dIVvqyRQrvnfmVN5xgmGAGT3NwMGBLTyehe2nATA
    5.77 +sq1hscxNXSE/x+SbbNStMT67Qq/lEyVrXxb1Xq6kTfN09f91oDdVU/9AJxiSzE56
    5.78 +a5vfMqJHXMK5By2UI4kOX3Q7oXjkZBenzg==
    5.79 +=M4t9
    5.80 +-----END PGP PUBLIC KEY BLOCK-----