merged in sync ENGINE-551
authorKrista 'DarthMama' Bennett <krista@pep.foundation>
Wed, 15 May 2019 14:35:22 +0200
branchENGINE-551
changeset 37063bcb75b270ed
parent 3674 6ff7f35d5e0a
parent 3683 c6914bf63ee4
child 3707 5e780ba44426
child 3709 c560e8fd8246
child 3712 2af31507d5d8
merged in sync
     1.1 --- a/src/etpan_mime.c	Mon May 13 09:37:13 2019 +0200
     1.2 +++ b/src/etpan_mime.c	Wed May 15 14:35:22 2019 +0200
     1.3 @@ -1853,7 +1853,7 @@
     1.4              status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode);
     1.5              break;
     1.6  
     1.7 -        case PEP_enc_pieces:
     1.8 +        case PEP_enc_inline:
     1.9              status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode);
    1.10              break;
    1.11  
     2.1 --- a/src/message.h	Mon May 13 09:37:13 2019 +0200
     2.2 +++ b/src/message.h	Wed May 15 14:35:22 2019 +0200
     2.3 @@ -30,7 +30,8 @@
     2.4  
     2.5  typedef enum _PEP_enc_format {
     2.6      PEP_enc_none = 0,                       // message is not encrypted
     2.7 -    PEP_enc_pieces,                         // inline PGP + PGP extensions
     2.8 +    PEP_enc_pieces = 1,                     // inline PGP + PGP extensions, was removed
     2.9 +    PEP_enc_inline = 1,                     // still there
    2.10      PEP_enc_S_MIME,                         // RFC5751
    2.11      PEP_enc_PGP_MIME,                       // RFC3156
    2.12      PEP_enc_PEP,                            // pEp encryption format
     3.1 --- a/src/message_api.c	Mon May 13 09:37:13 2019 +0200
     3.2 +++ b/src/message_api.c	Wed May 15 14:35:22 2019 +0200
     3.3 @@ -971,6 +971,32 @@
     3.4      return NULL;    
     3.5  }
     3.6  
     3.7 +static PEP_STATUS encrypt_PGP_inline(
     3.8 +        PEP_SESSION session,
     3.9 +        const message *src,
    3.10 +        stringlist_t *keys,
    3.11 +        message *dst
    3.12 +    )
    3.13 +{
    3.14 +    char *ctext = NULL;
    3.15 +    size_t csize = 0;
    3.16 +
    3.17 +    PEP_STATUS status = encrypt_and_sign(session, keys, src->longmsg,
    3.18 +            strlen(src->longmsg), &ctext, &csize);
    3.19 +    if (status)
    3.20 +        return status;
    3.21 +
    3.22 +    if (src->shortmsg) {
    3.23 +        dst->shortmsg = strdup(src->shortmsg);
    3.24 +        assert(dst->shortmsg);
    3.25 +        if (!dst->shortmsg)
    3.26 +            return PEP_OUT_OF_MEMORY;
    3.27 +    }
    3.28 +
    3.29 +    dst->longmsg = ctext;
    3.30 +    return PEP_STATUS_OK;
    3.31 +}
    3.32 +
    3.33  static PEP_STATUS encrypt_PGP_MIME(
    3.34      PEP_SESSION session,
    3.35      const message *src,
    3.36 @@ -1575,7 +1601,7 @@
    3.37      assert(msg);
    3.38  
    3.39      if (is_PGP_message_text(msg->longmsg)) {
    3.40 -        msg->enc_format = PEP_enc_pieces;
    3.41 +        msg->enc_format = PEP_enc_inline;
    3.42          return PEP_crypt_OpenPGP;
    3.43      }
    3.44      else if (msg->attachments && msg->attachments->next &&
    3.45 @@ -1914,9 +1940,9 @@
    3.46                  status = encrypt_PGP_MIME(session, _src, keys, msg, flags);
    3.47                  break;
    3.48  
    3.49 -            /* case PEP_enc_PEP:
    3.50 -                // TODO: implement
    3.51 -                NOT_IMPLEMENTED */
    3.52 +            case PEP_enc_inline:
    3.53 +                status = encrypt_PGP_inline(session, _src, keys, msg);
    3.54 +                break;
    3.55  
    3.56              default:
    3.57                  assert(0);
    3.58 @@ -2249,6 +2275,10 @@
    3.59                  _cleanup_src(src, false);
    3.60              break;
    3.61  
    3.62 +        case PEP_enc_inline:
    3.63 +            status = encrypt_PGP_inline(session, _src, keys, msg);
    3.64 +            break;
    3.65 +
    3.66          default:
    3.67              assert(0);
    3.68              status = PEP_ILLEGAL_VALUE;
    3.69 @@ -2589,7 +2619,7 @@
    3.70      
    3.71      switch (src->enc_format) {
    3.72          case PEP_enc_PGP_MIME:
    3.73 -        case PEP_enc_pieces:
    3.74 +        case PEP_enc_inline:
    3.75          case PEP_enc_PGP_MIME_Outlook1:
    3.76  //        case PEP_enc_none: // FIXME - this is wrong
    3.77  
    3.78 @@ -2681,7 +2711,7 @@
    3.79              *text_size = src->attachments->size;
    3.80              break;
    3.81  
    3.82 -        case PEP_enc_pieces:
    3.83 +        case PEP_enc_inline:
    3.84              *crypto_text = src->longmsg;
    3.85              *text_size = strlen(*crypto_text);
    3.86              break;
    3.87 @@ -3458,7 +3488,7 @@
    3.88                  }
    3.89                  break;
    3.90  
    3.91 -            case PEP_enc_pieces:
    3.92 +            case PEP_enc_inline:
    3.93                  status = PEP_STATUS_OK;
    3.94                  
    3.95                  _decrypt_in_pieces_status = _decrypt_in_pieces(session, src, &msg, ptext, psize);
     4.1 --- a/src/pgp_sequoia.c	Mon May 13 09:37:13 2019 +0200
     4.2 +++ b/src/pgp_sequoia.c	Wed May 15 14:35:22 2019 +0200
     4.3 @@ -126,7 +126,12 @@
     4.4      PEP_STATUS status = PEP_STATUS_OK;
     4.5  
     4.6      // Create the home directory.
     4.7 -    char *home_env = getenv("HOME");
     4.8 +    char *home_env = NULL;
     4.9 +#ifndef NDEBUG
    4.10 +    home_env = getenv("PEP_HOME");
    4.11 +#endif
    4.12 +    if (!home_env)
    4.13 +        home_env = getenv("HOME");
    4.14      if (!home_env)
    4.15          ERROR_OUT(NULL, PEP_INIT_GPGME_INIT_FAILED, "HOME unset");
    4.16  
    4.17 @@ -734,6 +739,49 @@
    4.18          pgp_packet_t userid = pgp_user_id_new (user_id_value);
    4.19          pgp_user_id_name(NULL, userid, &name);
    4.20          pgp_user_id_address(NULL, userid, &email);
    4.21 +                
    4.22 +        if (!email || email[0] == '\0') {
    4.23 +            size_t uid_value_len;
    4.24 +            const char* uid_value = (const char*)pgp_user_id_value(userid, &uid_value_len);
    4.25 +            if (!uid_value) {
    4.26 +                // We need some kind of an error here, maybe?
    4.27 +                 
    4.28 +            }
    4.29 +            else {
    4.30 +                const char* split = strstr(uid_value, "<");
    4.31 +                if (split != uid_value) {       
    4.32 +                    while (split) {
    4.33 +                        if (isspace(*(split - 1)))
    4.34 +                            break;
    4.35 +                        split = strstr(split + 1, "<");
    4.36 +                    }
    4.37 +                }
    4.38 +                if (split) {
    4.39 +                    char* stopchr = strrchr(split, '>');
    4.40 +                    if (stopchr) {
    4.41 +                        int email_len = stopchr - split - 1;
    4.42 +                        email = calloc(email_len + 1, 1); 
    4.43 +                        strlcpy(email, split + 1, email_len + 1);
    4.44 +                        const char* last = NULL;
    4.45 +                        if (split != uid_value) {
    4.46 +                            for (last = split - 1; last > uid_value; last--) {
    4.47 +                                if (!isspace(*last))
    4.48 +                                    break;
    4.49 +                            }
    4.50 +                            int name_len = (last - uid_value) + 1;
    4.51 +                            name = calloc(name_len + 1, 1);
    4.52 +                            strlcpy(name, uid_value, name_len + 1);
    4.53 +                        }
    4.54 +                    }
    4.55 +                    else  
    4.56 +                        split = NULL;
    4.57 +                }
    4.58 +                if (split == NULL) {
    4.59 +                    email = strdup(uid_value);
    4.60 +                }
    4.61 +            }
    4.62 +        }
    4.63 +        
    4.64          pgp_packet_free(userid);
    4.65          free(user_id_value);
    4.66  
    4.67 @@ -811,6 +859,8 @@
    4.68      stringlist_t *recipient_keylist;
    4.69      stringlist_t *signer_keylist;
    4.70      int good_checksums;
    4.71 +    int good_but_expired;
    4.72 +    int good_but_revoked;
    4.73      int missing_keys;
    4.74      int bad_checksums;
    4.75      int decrypted;
    4.76 @@ -1098,6 +1148,8 @@
    4.77                                            &tpk, NULL) != PEP_STATUS_OK)
    4.78                          ; // Soft error.  Ignore.
    4.79  
    4.80 +                    keyid_str = pgp_keyid_to_string (keyid);
    4.81 +
    4.82                      if (tpk) {
    4.83                          // Ok, we have a TPK.
    4.84  
    4.85 @@ -1107,27 +1159,79 @@
    4.86                              = pgp_tpk_fingerprint(tpk);
    4.87                          char *primary_fpr_str
    4.88                              = pgp_fingerprint_to_hex(primary_fpr);
    4.89 -                        stringlist_add_unique(cookie->signer_keylist,
    4.90 -                                              primary_fpr_str);
    4.91 -
    4.92 -                        T("Good signature from %s", primary_fpr_str);
    4.93 -
    4.94 -                        // XXX: Check that the TPK and the key used to make
    4.95 -                        // the signature and the signature itself are alive
    4.96 -                        // and not revoked.  Revoked =>
    4.97 -                        // PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH; Expired key
    4.98 -                        // or sig => PEP_DECRYPTED.
    4.99 -                        cookie->good_checksums ++;
   4.100 +
   4.101 +                        bool good = true;
   4.102 +
   4.103 +                        // Make sure the TPK is not revoked, it's
   4.104 +                        // creation time is <= now, and it hasn't
   4.105 +                        // expired.
   4.106 +                        pgp_revocation_status_t rs = pgp_tpk_revocation_status(tpk);
   4.107 +                        bool revoked = (pgp_revocation_status_variant(rs)
   4.108 +                                        == PGP_REVOCATION_STATUS_REVOKED);
   4.109 +                        pgp_revocation_status_free(rs);
   4.110 +                        if (revoked) {
   4.111 +                            T("TPK %s is revoked.", primary_fpr_str);
   4.112 +                            good = false;
   4.113 +                            cookie->good_but_revoked ++;
   4.114 +                        } else if (! pgp_tpk_alive(tpk)) {
   4.115 +                            T("TPK %s is not alive.", primary_fpr_str);
   4.116 +                            good = false;
   4.117 +                            cookie->good_but_expired ++;
   4.118 +                        }
   4.119 +
   4.120 +                        // Same thing for the signing key.
   4.121 +                        if (good) {
   4.122 +                            pgp_tpk_key_iter_t iter = pgp_tpk_key_iter_all(tpk);
   4.123 +                            pgp_key_t key;
   4.124 +                            pgp_signature_t sig;
   4.125 +                            while ((key = pgp_tpk_key_iter_next(iter, &sig, &rs))
   4.126 +                                   && good) {
   4.127 +                                pgp_keyid_t x = pgp_key_keyid(key);
   4.128 +                                if (pgp_keyid_equal(keyid, x)) {
   4.129 +                                    // Found the signing key.  Let's make
   4.130 +                                    // sure it is valid.
   4.131 +
   4.132 +                                    revoked = (pgp_revocation_status_variant(rs)
   4.133 +                                               == PGP_REVOCATION_STATUS_REVOKED);
   4.134 +                                    if (revoked) {
   4.135 +                                        T("TPK %s's signing key %s is revoked.",
   4.136 +                                          primary_fpr_str, keyid_str);
   4.137 +                                        good = false;
   4.138 +                                        cookie->good_but_revoked ++;
   4.139 +                                    } else if (! pgp_signature_key_alive(sig, key)) {
   4.140 +                                        T("TPK %s's signing key %s is expired.",
   4.141 +                                          primary_fpr_str, keyid_str);
   4.142 +                                        good = false;
   4.143 +                                        cookie->good_but_expired ++;
   4.144 +                                    }
   4.145 +                                }
   4.146 +                                pgp_keyid_free(x);
   4.147 +                                pgp_revocation_status_free(rs);
   4.148 +                                pgp_signature_free(sig);
   4.149 +                                pgp_key_free(key);
   4.150 +                            }
   4.151 +                            pgp_tpk_key_iter_free(iter);
   4.152 +                        }
   4.153 +
   4.154 +                        if (good) {
   4.155 +                            stringlist_add_unique(cookie->signer_keylist,
   4.156 +                                                  primary_fpr_str);
   4.157 +
   4.158 +                            T("Good signature from %s", primary_fpr_str);
   4.159 +
   4.160 +                            cookie->good_checksums ++;
   4.161 +                        }
   4.162  
   4.163                          free(primary_fpr_str);
   4.164                          pgp_fingerprint_free(primary_fpr);
   4.165                          pgp_tpk_free(tpk);
   4.166                      } else {
   4.167                          // If we get
   4.168 -                        // PGP_VERIFICATION_RESULT_CODE_GOOD_CHECKSUM, then the
   4.169 -                        // TPK should be available.  But, another process
   4.170 -                        // could have deleted the key from the store in the
   4.171 -                        // mean time, so be tolerant.
   4.172 +                        // PGP_VERIFICATION_RESULT_CODE_GOOD_CHECKSUM,
   4.173 +                        // then the TPK should be available.  But,
   4.174 +                        // another process could have deleted the key
   4.175 +                        // from the store in the mean time, so be
   4.176 +                        // tolerant.
   4.177                          T("Key to check signature from %s disappeared",
   4.178                            keyid_str);
   4.179                          cookie->missing_keys ++;
   4.180 @@ -1188,7 +1292,7 @@
   4.181      char** filename_ptr)
   4.182  {
   4.183      PEP_STATUS status = PEP_STATUS_OK;
   4.184 -    struct decrypt_cookie cookie = { session, 0, NULL, NULL, 0, 0, 0, };
   4.185 +    struct decrypt_cookie cookie = { session, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, };
   4.186      pgp_reader_t reader = NULL;
   4.187      pgp_writer_t writer = NULL;
   4.188      pgp_reader_t decryptor = NULL;
   4.189 @@ -1249,13 +1353,23 @@
   4.190  
   4.191   out:
   4.192      if (status == PEP_STATUS_OK) {
   4.193 -        if (cookie.bad_checksums) {
   4.194 -            // If there are any bad signatures, fail.
   4.195 -            status = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   4.196 -        } else if (cookie.good_checksums) {
   4.197 +        // **********************************
   4.198 +        // Sync changes with pgp_verify_text.
   4.199 +        // **********************************
   4.200 +
   4.201 +        if (cookie.good_checksums) {
   4.202              // If there is at least one signature that we can verify,
   4.203              // succeed.
   4.204              status = PEP_DECRYPTED_AND_VERIFIED;
   4.205 +        } else if (cookie.good_but_revoked) {
   4.206 +            // If there are any signatures from revoked keys, fail.
   4.207 +            status = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   4.208 +        } else if (cookie.bad_checksums) {
   4.209 +            // If there are any bad signatures, fail.
   4.210 +            status = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   4.211 +        } else if (cookie.good_but_expired) {
   4.212 +            // If there are any signatures from expired keys, fail.
   4.213 +            status = PEP_DECRYPTED;
   4.214          } else {
   4.215              // We couldn't verify any signatures (possibly because we
   4.216              // don't have the keys).
   4.217 @@ -1339,7 +1453,17 @@
   4.218  
   4.219   out:
   4.220      if (status == PEP_STATUS_OK) {
   4.221 -        if (cookie.bad_checksums) {
   4.222 +        // *****************************************
   4.223 +        // Sync changes with pgp_decrypt_and_verify.
   4.224 +        // *****************************************
   4.225 +
   4.226 +        if (cookie.good_but_expired) {
   4.227 +            // If there are any signatures from expired keys, fail.
   4.228 +            status = PEP_UNENCRYPTED;
   4.229 +        } else if (cookie.good_but_revoked) {
   4.230 +            // If there are any signatures from revoked keys, fail.
   4.231 +            status = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   4.232 +        } else if (cookie.bad_checksums) {
   4.233              // If there are any bad signatures, fail.
   4.234              status = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
   4.235          } else if (cookie.good_checksums) {
   4.236 @@ -1698,7 +1822,6 @@
   4.237      return PEP_STATUS_OK;
   4.238  }
   4.239  
   4.240 -// XXX: This also needs to handle revocation certificates.
   4.241  PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data,
   4.242                                size_t size, identity_list **private_idents)
   4.243  {
     5.1 --- a/test/include/KeyringImportTests.h	Mon May 13 09:37:13 2019 +0200
     5.2 +++ b/test/include/KeyringImportTests.h	Wed May 15 14:35:22 2019 +0200
     5.3 @@ -16,7 +16,8 @@
     5.4          void setup();
     5.5          void tear_down();
     5.6      private:
     5.7 -        void import();
     5.8 +        void import1();
     5.9 +        void import2();
    5.10  };
    5.11  
    5.12  #endif
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/test/include/URIAddressTests.h	Wed May 15 14:35:22 2019 +0200
     6.3 @@ -0,0 +1,20 @@
     6.4 +// This file is under GNU General Public License 3.0
     6.5 +// see LICENSE.txt
     6.6 +
     6.7 +#ifndef U_R_I_ADDRESS_H
     6.8 +#define U_R_I_ADDRESS_H
     6.9 +
    6.10 +#include <string>
    6.11 +#include "EngineTestIndividualSuite.h"
    6.12 +
    6.13 +using namespace std;
    6.14 +
    6.15 +class URIAddressTests : public EngineTestIndividualSuite {
    6.16 +    public:
    6.17 +        URIAddressTests(string test_suite, string test_home_dir);
    6.18 +    private:
    6.19 +        void check_uri_address_genkey();
    6.20 +        void check_uri_address_encrypt();        
    6.21 +};
    6.22 +
    6.23 +#endif
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/test/include/VerifyTests.h	Wed May 15 14:35:22 2019 +0200
     7.3 @@ -0,0 +1,23 @@
     7.4 +// This file is under GNU General Public License 3.0
     7.5 +// see LICENSE.txt
     7.6 +
     7.7 +#ifndef VERIFY_H
     7.8 +#define VERIFY_H
     7.9 +
    7.10 +#include <string>
    7.11 +#include "EngineTestIndividualSuite.h"
    7.12 +
    7.13 +using namespace std;
    7.14 +
    7.15 +class VerifyTests : public EngineTestIndividualSuite {
    7.16 +    public:
    7.17 +        VerifyTests(string test_suite, string test_home_dir);
    7.18 +    private:
    7.19 +        static constexpr const char *mary_fpr = "599B3D67800DB37E2DCE05C07F59F03CD04A226E";
    7.20 +        void check_revoked_tpk();
    7.21 +        void check_revoked_signing_key();
    7.22 +        void check_expired_tpk();
    7.23 +        void check_expired_signing_key();
    7.24 +};
    7.25 +
    7.26 +#endif
     8.1 --- a/test/src/SuiteMaker.cc	Mon May 13 09:37:13 2019 +0200
     8.2 +++ b/test/src/SuiteMaker.cc	Wed May 15 14:35:22 2019 +0200
     8.3 @@ -12,9 +12,11 @@
     8.4  #include "SuiteMaker.h"
     8.5  
     8.6  // Begin where we generate stuff
     8.7 +#include "URIAddressTests.h"
     8.8  #include "MimeTests.h"
     8.9  #include "OwnIdentitiesRetrieveTests.h"
    8.10  #include "ExpiredSubkeyTests.h"
    8.11 +#include "VerifyTests.h"
    8.12  #include "UserIdCollisionTests.h"
    8.13  #include "Engine463Tests.h"
    8.14  #include "BloblistTests.h"
    8.15 @@ -72,9 +74,11 @@
    8.16  
    8.17  
    8.18  const char* SuiteMaker::all_suites[] = {
    8.19 +    "URIAddressTests",
    8.20      "MimeTests",
    8.21      "OwnIdentitiesRetrieveTests",
    8.22      "ExpiredSubkeyTests",
    8.23 +    "VerifyTests",
    8.24      "UserIdCollisionTests",
    8.25      "Engine463Tests",
    8.26      "BloblistTests",
    8.27 @@ -132,15 +136,19 @@
    8.28  };
    8.29  
    8.30  // This file is generated, so magic constants are ok.
    8.31 -int SuiteMaker::num_suites = 57;
    8.32 +int SuiteMaker::num_suites = 59;
    8.33  
    8.34  void SuiteMaker::suitemaker_build(const char* test_class_name, const char* test_home, Test::Suite** test_suite) {
    8.35 -    if (strcmp(test_class_name, "MimeTests") == 0)
    8.36 +    if (strcmp(test_class_name, "URIAddressTests") == 0)
    8.37 +        *test_suite = new URIAddressTests(test_class_name, test_home);
    8.38 +    else if (strcmp(test_class_name, "MimeTests") == 0)
    8.39          *test_suite = new MimeTests(test_class_name, test_home);
    8.40      else if (strcmp(test_class_name, "OwnIdentitiesRetrieveTests") == 0)
    8.41          *test_suite = new OwnIdentitiesRetrieveTests(test_class_name, test_home);
    8.42      else if (strcmp(test_class_name, "ExpiredSubkeyTests") == 0)
    8.43          *test_suite = new ExpiredSubkeyTests(test_class_name, test_home);
    8.44 +    else if (strcmp(test_class_name, "VerifyTests") == 0)
    8.45 +        *test_suite = new VerifyTests(test_class_name, test_home);
    8.46      else if (strcmp(test_class_name, "UserIdCollisionTests") == 0)
    8.47          *test_suite = new UserIdCollisionTests(test_class_name, test_home);
    8.48      else if (strcmp(test_class_name, "Engine463Tests") == 0)
     9.1 --- a/test/src/engine_tests/KeyringImportTests.cc	Mon May 13 09:37:13 2019 +0200
     9.2 +++ b/test/src/engine_tests/KeyringImportTests.cc	Wed May 15 14:35:22 2019 +0200
     9.3 @@ -21,8 +21,10 @@
     9.4  
     9.5  KeyringImportTests::KeyringImportTests(string suitename, string test_home_dir) :
     9.6      EngineTestSessionSuite::EngineTestSessionSuite(suitename, test_home_dir) {
     9.7 -    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("KeyringImportTests::import"),
     9.8 -                                                                      static_cast<Func>(&KeyringImportTests::import)));
     9.9 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("KeyringImportTests::import1"),
    9.10 +                                                                      static_cast<Func>(&KeyringImportTests::import1)));
    9.11 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("KeyringImportTests::import2"),
    9.12 +                                                                      static_cast<Func>(&KeyringImportTests::import2)));
    9.13  }
    9.14  
    9.15  void KeyringImportTests::setup() {
    9.16 @@ -33,7 +35,7 @@
    9.17      EngineTestSessionSuite::tear_down();
    9.18  }
    9.19  
    9.20 -void KeyringImportTests::import() {
    9.21 +void KeyringImportTests::import1() {
    9.22      const string pub_key = slurp("test_keys/pub/pep-test-keyring.asc");
    9.23  
    9.24      PEP_STATUS statuspub = import_key(session, pub_key.c_str(), pub_key.length(), NULL);
    9.25 @@ -82,3 +84,68 @@
    9.26          free_identity(id);
    9.27      }
    9.28  }
    9.29 +
    9.30 +void KeyringImportTests::import2() {
    9.31 +    const string pub_key = slurp("test_keys/pub/pep-test-android-keyring.pgp");
    9.32 +
    9.33 +    PEP_STATUS statuspub = import_key(session, pub_key.c_str(), pub_key.length(), NULL);
    9.34 +    TEST_ASSERT_MSG((statuspub == PEP_TEST_KEY_IMPORT_SUCCESS), "statuspub == PEP_STATUS_OK");
    9.35 +
    9.36 +    struct entry {
    9.37 +        const char *fingerprint;
    9.38 +        const char *address;
    9.39 +    };
    9.40 +
    9.41 +    // Several addresses appear multiple times in the keyring.  To
    9.42 +    // avoid teaching this function how key election works, we just
    9.43 +    // don't test those.
    9.44 +    struct entry entries[] = {
    9.45 +      // { "1D600EA0BD575C846E0A8C1008BE097B1F15FB26",
    9.46 +      //   "android01@peptest.ch" },
    9.47 +      // { "51FBBE53E9643A69D6D1F60E74E8073E2DD1F4AC",
    9.48 +      //   "test010@peptest.ch" },
    9.49 +      { "DB92DA58C7F6D6A48F7EF9DC4EBB4CED0E93C7B3",
    9.50 +        "thomas@o365.peptest.ch" },
    9.51 +      { "667A749BEC0C6F844D499D57851E58B37BD4B02E",
    9.52 +        "iostest009@peptest.ch" },
    9.53 +      { "7FCCC380455A9C2F1B080E18CEFBF78746423688",
    9.54 +        "iostest006@peptest.ch" },
    9.55 +      // { "447C595819EDB241",
    9.56 +      //   "android02@peptest.ch" },
    9.57 +      // { "474D7DE519248C2A2EFD45A2148BBDB8A9C68A1C",
    9.58 +      //   "test010@peptest.ch" },
    9.59 +      { "DBA0A1A1001396838E3A3269DF2ED8AA4A3144AA",
    9.60 +        "sva@pep-security.net" },
    9.61 +      { "DBA0A1A1001396838E3A3269DF2ED8AA4A3144AA",
    9.62 +        "bernadette@pep-security.net" },
    9.63 +      { "DBA0A1A1001396838E3A3269DF2ED8AA4A3144AA",
    9.64 +        "bernadette.laengle@pep.foundation" },
    9.65 +      { "DBA0A1A1001396838E3A3269DF2ED8AA4A3144AA",
    9.66 +        "sva@pep.foundation" },
    9.67 +      { "1E02952E9E2048ABD510261AF43CDF9D0F14C2DB",
    9.68 +        "pepegrillodev@gmail.com" },
    9.69 +      // { "E3549B2DCD26832F4F30D8D051716A5DF1F4C2BF",
    9.70 +      //   "android01@peptest.ch" },
    9.71 +      { "5CC67646D67A33D8A2E4FF849E61B9BC790E6B02",
    9.72 +        "huss@pep-project.org" },
    9.73 +      // { "911BD458F82249F0",
    9.74 +      //   "android02@peptest.ch" },
    9.75 +    };
    9.76 +
    9.77 +    for (int i = 0; i < sizeof(entries) / sizeof(entries[0]); i ++) {
    9.78 +        const char *address = entries[i].address;
    9.79 +        const char *fpr = entries[i].fingerprint;
    9.80 +
    9.81 +        cout << "Looking up: " << address << ", should have fingerprint: " << fpr << endl;
    9.82 +        pEp_identity *id = new_identity(address, NULL, NULL, NULL);
    9.83 +        PEP_STATUS status = update_identity(session, id);
    9.84 +        TEST_ASSERT_MSG((status == PEP_STATUS_OK), tl_status_string(status));
    9.85 +        cout << "Got: " << (id->fpr ?: "NULL") << " (expected: " << fpr << ") -> " << (id->address ?: "NULL") << endl;
    9.86 +
    9.87 +        // We should always get the same fingerprint.
    9.88 +        TEST_ASSERT_MSG((id->fpr), "id->fpr");
    9.89 +        TEST_ASSERT_MSG((strcmp(id->fpr, fpr) == 0), "strcmp(id->fpr, fpr) == 0");
    9.90 +
    9.91 +        free_identity(id);
    9.92 +    }
    9.93 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/test/src/engine_tests/URIAddressTests.cc	Wed May 15 14:35:22 2019 +0200
    10.3 @@ -0,0 +1,85 @@
    10.4 +// This file is under GNU General Public License 3.0
    10.5 +// see LICENSE.txt
    10.6 +
    10.7 +#include <stdlib.h>
    10.8 +#include <cstring>
    10.9 +#include <string>
   10.10 +
   10.11 +#include <cpptest.h>
   10.12 +#include "test_util.h"
   10.13 +
   10.14 +#include "pEpEngine.h"
   10.15 +
   10.16 +#include "EngineTestIndividualSuite.h"
   10.17 +#include "URIAddressTests.h"
   10.18 +
   10.19 +using namespace std;
   10.20 +
   10.21 +URIAddressTests::URIAddressTests(string suitename, string test_home_dir) :
   10.22 +    EngineTestIndividualSuite::EngineTestIndividualSuite(suitename, test_home_dir) {
   10.23 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("URIAddressTests::check_uri_address_genkey"),
   10.24 +                                                                      static_cast<Func>(&URIAddressTests::check_uri_address_genkey)));
   10.25 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("URIAddressTests::check_uri_address_encrypt"),
   10.26 +                                                                      static_cast<Func>(&URIAddressTests::check_uri_address_encrypt)));
   10.27 +}
   10.28 +
   10.29 +// FIXME: URL, URN
   10.30 +void URIAddressTests::check_uri_address_genkey() {
   10.31 +    const char* uri_addr = "shark://grrrr/39874293847092837443987492834";
   10.32 +    const char* uname = "GRRRR, the angry shark";
   10.33 +    
   10.34 +    pEp_identity* me = new_identity(uri_addr, NULL, PEP_OWN_USERID, uname);
   10.35 +    
   10.36 +    PEP_STATUS status = myself(session, me);
   10.37 +    
   10.38 +    TEST_ASSERT(status == PEP_STATUS_OK);
   10.39 +    TEST_ASSERT(me->fpr && me->fpr[0] != '\0');
   10.40 +    
   10.41 +    char* keydata = NULL;
   10.42 +    size_t keysize = 0;
   10.43 +    status = export_key(session, me->fpr, 
   10.44 +                        &keydata, &keysize);
   10.45 +
   10.46 +    cout << keydata << endl;
   10.47 +
   10.48 +    free(keydata);
   10.49 +    free_identity(me);
   10.50 +}
   10.51 +
   10.52 +// FIXME: URL, URN
   10.53 +void URIAddressTests::check_uri_address_encrypt() {
   10.54 +    const char* uri_addr = "shark://grrrr/39874293847092837443987492834";
   10.55 +    const char* uname = "GRRRR, the angry shark";
   10.56 +    
   10.57 +    pEp_identity* me = new_identity(uri_addr, NULL, PEP_OWN_USERID, uname);
   10.58 +    
   10.59 +    PEP_STATUS status = myself(session, me);
   10.60 +    
   10.61 +    TEST_ASSERT(status == PEP_STATUS_OK);
   10.62 +    TEST_ASSERT(me->fpr && me->fpr[0] != '\0');
   10.63 +    
   10.64 +    const char* you_uri_addr = "shark://bait/8uyoi3lu4hl2..dfoif983j4b@%";
   10.65 +    const char* youname = "Nemo, the delicious fish";
   10.66 +    pEp_identity* you = new_identity(you_uri_addr, NULL, "Food for Shark", youname);
   10.67 +    status = generate_keypair(session, you);
   10.68 +    TEST_ASSERT(status == PEP_STATUS_OK);
   10.69 +
   10.70 +    stringlist_t* keylist = NULL;
   10.71 +    status = find_keys(session, you_uri_addr, &keylist);
   10.72 +    TEST_ASSERT(status == PEP_STATUS_OK);    
   10.73 +    TEST_ASSERT(keylist && keylist->value);
   10.74 +
   10.75 +    status = update_identity(session, you);
   10.76 +    TEST_ASSERT(status == PEP_STATUS_OK);
   10.77 +    TEST_ASSERT(you->fpr && you->fpr[0] != '\0');
   10.78 +    
   10.79 +    message* msg = new_message(PEP_dir_outgoing);
   10.80 +    
   10.81 +    msg->from = me;
   10.82 +    msg->to = new_identity_list(you);
   10.83 +    msg->shortmsg = strdup("Invitation");
   10.84 +    msg->longmsg = strdup("Yo Neems, wanna come over for dinner?");
   10.85 +
   10.86 +    message* enc_msg = NULL;
   10.87 +    status = encrypt_message(session, msg, NULL, &enc_msg, PEP_enc_PGP_MIME, 0);
   10.88 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/test/src/engine_tests/VerifyTests.cc	Wed May 15 14:35:22 2019 +0200
    11.3 @@ -0,0 +1,248 @@
    11.4 +// This file is under GNU General Public License 3.0
    11.5 +// see LICENSE.txt
    11.6 +
    11.7 +#include <stdlib.h>
    11.8 +#include <string>
    11.9 +#include <cstring>
   11.10 +#include <cpptest.h>
   11.11 +#include <fstream>
   11.12 +
   11.13 +#include "pEpEngine.h"
   11.14 +
   11.15 +#include "test_util.h"
   11.16 +#include "EngineTestIndividualSuite.h"
   11.17 +#include "VerifyTests.h"
   11.18 +
   11.19 +using namespace std;
   11.20 +
   11.21 +VerifyTests::VerifyTests(string suitename, string test_home_dir) :
   11.22 +    EngineTestIndividualSuite::EngineTestIndividualSuite(suitename, test_home_dir) {
   11.23 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("VerifyTests::check_revoked_tpk"),
   11.24 +                                                                      static_cast<Func>(&VerifyTests::check_revoked_tpk)));
   11.25 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("VerifyTests::check_revoked_signing_key"),
   11.26 +                                                                      static_cast<Func>(&VerifyTests::check_revoked_signing_key)));
   11.27 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("VerifyTests::check_expired_tpk"),
   11.28 +                                                                      static_cast<Func>(&VerifyTests::check_expired_tpk)));
   11.29 +    add_test_to_suite(std::pair<std::string, void (Test::Suite::*)()>(string("VerifyTests::check_expired_signing_key"),
   11.30 +                                                                      static_cast<Func>(&VerifyTests::check_expired_signing_key)));
   11.31 +}
   11.32 +
   11.33 +void VerifyTests::check_revoked_tpk() {
   11.34 +    slurp_and_import_key(session, "test_keys/priv/pep-test-mary-0x7F59F03CD04A226E_priv.asc");
   11.35 +
   11.36 +    string ciphertext = slurp("test_files/pep-test-mary-signed-encrypted-to-self.asc");
   11.37 +
   11.38 +    // Decrypt and verify it.
   11.39 +    char *plaintext = NULL;
   11.40 +    size_t plaintext_size = 0;
   11.41 +    stringlist_t *keylist = NULL;
   11.42 +    PEP_STATUS status = decrypt_and_verify(session,
   11.43 +                                           ciphertext.c_str(),
   11.44 +                                           ciphertext.size(),
   11.45 +                                           NULL, 0,
   11.46 +                                           &plaintext, &plaintext_size,
   11.47 +                                           &keylist, NULL);
   11.48 +
   11.49 +    TEST_ASSERT_MSG(status == PEP_DECRYPTED_AND_VERIFIED, tl_status_string(status));
   11.50 +    TEST_ASSERT(keylist);
   11.51 +    // Signer is mary.
   11.52 +    TEST_ASSERT(keylist->value);
   11.53 +    cout << "fpr: " << mary_fpr << "; got: " << keylist->value << endl;
   11.54 +    TEST_ASSERT(strcmp(mary_fpr, keylist->value) == 0);
   11.55 +    // Recipient is mary.
   11.56 +    TEST_ASSERT(keylist->next);
   11.57 +    TEST_ASSERT(keylist->next->value);
   11.58 +    TEST_ASSERT(strcmp(mary_fpr, keylist->next->value) == 0);
   11.59 +    // Content is returned.
   11.60 +    TEST_ASSERT(strcmp(plaintext, "tu was!\n") == 0);
   11.61 +
   11.62 +    // Import the revocation certificate.
   11.63 +    slurp_and_import_key(session, "test_keys/priv/pep-test-mary-0x7F59F03CD04A226E.rev");
   11.64 +
   11.65 +    plaintext = NULL;
   11.66 +    plaintext_size = 0;
   11.67 +    keylist = NULL;
   11.68 +    status = decrypt_and_verify(session,
   11.69 +                                ciphertext.c_str(), ciphertext.size(),
   11.70 +                                NULL, 0,
   11.71 +                                &plaintext, &plaintext_size,
   11.72 +                                &keylist, NULL);
   11.73 +
   11.74 +    // Now it should fail.
   11.75 +    TEST_ASSERT_MSG(status == PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH, tl_status_string(status));
   11.76 +    TEST_ASSERT(keylist);
   11.77 +    // No signer.
   11.78 +    TEST_ASSERT(strcmp(keylist->value, "") == 0);
   11.79 +    // Recipient is mary.
   11.80 +    TEST_ASSERT(keylist->next);
   11.81 +    TEST_ASSERT(keylist->next->value);
   11.82 +    TEST_ASSERT(strcmp(mary_fpr, keylist->next->value) == 0);
   11.83 +    // Content is returned.
   11.84 +    TEST_ASSERT(strcmp(plaintext, "tu was!\n") == 0);
   11.85 +
   11.86 +
   11.87 +    string text = slurp("test_files/pep-test-mary-signed.txt");
   11.88 +    string sig = slurp("test_files/pep-test-mary-signed.txt.sig");
   11.89 +
   11.90 +    plaintext = NULL;
   11.91 +    plaintext_size = 0;
   11.92 +    keylist = NULL;
   11.93 +    status = verify_text(session,
   11.94 +                         text.c_str(), text.size(),
   11.95 +                         sig.c_str(), sig.size(),
   11.96 +                         &keylist);
   11.97 +
   11.98 +    // Now it should fail.
   11.99 +    TEST_ASSERT_MSG(status == PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH, tl_status_string(status));
  11.100 +    TEST_ASSERT(keylist);
  11.101 +    // No signer.
  11.102 +    TEST_ASSERT(strcmp(keylist->value, "") == 0);
  11.103 +    TEST_ASSERT(! keylist->next);
  11.104 +}
  11.105 +
  11.106 +void VerifyTests::check_revoked_signing_key() {
  11.107 +    slurp_and_import_key(session, "test_keys/priv/pep-test-mary-0x7F59F03CD04A226E_priv.asc");
  11.108 +    slurp_and_import_key(session, "test_keys/pub/pep-test-mary-0x7F59F03CD04A226E_revoked_sig_key.asc");
  11.109 +
  11.110 +    string ciphertext = slurp("test_files/pep-test-mary-signed-encrypted-to-self.asc");
  11.111 +
  11.112 +    // Decrypt and verify it.
  11.113 +    char *plaintext = NULL;
  11.114 +    size_t plaintext_size = 0;
  11.115 +    stringlist_t *keylist = NULL;
  11.116 +    PEP_STATUS status = decrypt_and_verify(session,
  11.117 +                                           ciphertext.c_str(),
  11.118 +                                           ciphertext.size(),
  11.119 +                                           NULL, 0,
  11.120 +                                           &plaintext, &plaintext_size,
  11.121 +                                           &keylist, NULL);
  11.122 +
  11.123 +    // It should fail.
  11.124 +    TEST_ASSERT_MSG(status == PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH, tl_status_string(status));
  11.125 +    TEST_ASSERT(keylist);
  11.126 +    // No signer.
  11.127 +    TEST_ASSERT(strcmp(keylist->value, "") == 0);
  11.128 +    // Recipient is mary.
  11.129 +    TEST_ASSERT(keylist->next);
  11.130 +    TEST_ASSERT(keylist->next->value);
  11.131 +    TEST_ASSERT(strcmp(mary_fpr, keylist->next->value) == 0);
  11.132 +    // Content is returned.
  11.133 +    TEST_ASSERT(strcmp(plaintext, "tu was!\n") == 0);
  11.134 +
  11.135 +
  11.136 +    string text = slurp("test_files/pep-test-mary-signed.txt");
  11.137 +    string sig = slurp("test_files/pep-test-mary-signed.txt.sig");
  11.138 +
  11.139 +    plaintext = NULL;
  11.140 +    plaintext_size = 0;
  11.141 +    keylist = NULL;
  11.142 +    status = verify_text(session,
  11.143 +                         text.c_str(), text.size(),
  11.144 +                         sig.c_str(), sig.size(),
  11.145 +                         &keylist);
  11.146 +
  11.147 +    // Now it should fail.
  11.148 +    TEST_ASSERT_MSG(status == PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH, tl_status_string(status));
  11.149 +    TEST_ASSERT(keylist);
  11.150 +    // No signer.
  11.151 +    TEST_ASSERT(strcmp(keylist->value, "") == 0);
  11.152 +    TEST_ASSERT(! keylist->next);
  11.153 +}
  11.154 +
  11.155 +void VerifyTests::check_expired_tpk() {
  11.156 +    slurp_and_import_key(session, "test_keys/priv/pep-test-mary-0x7F59F03CD04A226E_priv.asc");
  11.157 +    slurp_and_import_key(session, "test_keys/pub/pep-test-mary-0x7F59F03CD04A226E_expired_pub.asc");
  11.158 +
  11.159 +    string ciphertext = slurp("test_files/pep-test-mary-signed-encrypted-to-self.asc");
  11.160 +
  11.161 +    // Decrypt and verify it.
  11.162 +    char *plaintext = NULL;
  11.163 +    size_t plaintext_size = 0;
  11.164 +    stringlist_t *keylist = NULL;
  11.165 +    PEP_STATUS status = decrypt_and_verify(session,
  11.166 +                                           ciphertext.c_str(),
  11.167 +                                           ciphertext.size(),
  11.168 +                                           NULL, 0,
  11.169 +                                           &plaintext, &plaintext_size,
  11.170 +                                           &keylist, NULL);
  11.171 +
  11.172 +    // It should fail.
  11.173 +    TEST_ASSERT_MSG(status == PEP_DECRYPTED, tl_status_string(status));
  11.174 +    TEST_ASSERT(keylist);
  11.175 +    // No signer.
  11.176 +    TEST_ASSERT(strcmp(keylist->value, "") == 0);
  11.177 +    // Recipient is mary.
  11.178 +    TEST_ASSERT(keylist->next);
  11.179 +    TEST_ASSERT(keylist->next->value);
  11.180 +    TEST_ASSERT(strcmp(mary_fpr, keylist->next->value) == 0);
  11.181 +    // Content is returned.
  11.182 +    TEST_ASSERT(strcmp(plaintext, "tu was!\n") == 0);
  11.183 +
  11.184 +
  11.185 +    string text = slurp("test_files/pep-test-mary-signed.txt");
  11.186 +    string sig = slurp("test_files/pep-test-mary-signed.txt.sig");
  11.187 +
  11.188 +    plaintext = NULL;
  11.189 +    plaintext_size = 0;
  11.190 +    keylist = NULL;
  11.191 +    status = verify_text(session,
  11.192 +                         text.c_str(), text.size(),
  11.193 +                         sig.c_str(), sig.size(),
  11.194 +                         &keylist);
  11.195 +
  11.196 +    // Now it should fail.
  11.197 +    TEST_ASSERT_MSG(status == PEP_UNENCRYPTED, tl_status_string(status));
  11.198 +    TEST_ASSERT(keylist);
  11.199 +    // No signer.
  11.200 +    TEST_ASSERT(strcmp(keylist->value, "") == 0);
  11.201 +    TEST_ASSERT(! keylist->next);
  11.202 +}
  11.203 +
  11.204 +void VerifyTests::check_expired_signing_key() {
  11.205 +    slurp_and_import_key(session, "test_keys/priv/pep-test-mary-0x7F59F03CD04A226E_priv.asc");
  11.206 +    slurp_and_import_key(session, "test_keys/pub/pep-test-mary-0x7F59F03CD04A226E_expired_sig_key.asc");
  11.207 +
  11.208 +    string ciphertext = slurp("test_files/pep-test-mary-signed-encrypted-to-self.asc");
  11.209 +
  11.210 +    // Decrypt and verify it.
  11.211 +    char *plaintext = NULL;
  11.212 +    size_t plaintext_size = 0;
  11.213 +    stringlist_t *keylist = NULL;
  11.214 +    PEP_STATUS status = decrypt_and_verify(session,
  11.215 +                                           ciphertext.c_str(),
  11.216 +                                           ciphertext.size(),
  11.217 +                                           NULL, 0,
  11.218 +                                           &plaintext, &plaintext_size,
  11.219 +                                           &keylist, NULL);
  11.220 +
  11.221 +    // It should fail.
  11.222 +    TEST_ASSERT_MSG(status == PEP_DECRYPTED, tl_status_string(status));
  11.223 +    TEST_ASSERT(keylist);
  11.224 +    // No signer.
  11.225 +    TEST_ASSERT(strcmp(keylist->value, "") == 0);
  11.226 +    // Recipient is mary.
  11.227 +    TEST_ASSERT(keylist->next);
  11.228 +    TEST_ASSERT(keylist->next->value);
  11.229 +    TEST_ASSERT(strcmp(mary_fpr, keylist->next->value) == 0);
  11.230 +    // Content is returned.
  11.231 +    TEST_ASSERT(strcmp(plaintext, "tu was!\n") == 0);
  11.232 +
  11.233 +
  11.234 +    string text = slurp("test_files/pep-test-mary-signed.txt");
  11.235 +    string sig = slurp("test_files/pep-test-mary-signed.txt.sig");
  11.236 +
  11.237 +    plaintext = NULL;
  11.238 +    plaintext_size = 0;
  11.239 +    keylist = NULL;
  11.240 +    status = verify_text(session,
  11.241 +                         text.c_str(), text.size(),
  11.242 +                         sig.c_str(), sig.size(),
  11.243 +                         &keylist);
  11.244 +
  11.245 +    // Now it should fail.
  11.246 +    TEST_ASSERT_MSG(status == PEP_UNENCRYPTED, tl_status_string(status));
  11.247 +    TEST_ASSERT(keylist);
  11.248 +    // No signer.
  11.249 +    TEST_ASSERT(strcmp(keylist->value, "") == 0);
  11.250 +    TEST_ASSERT(! keylist->next);
  11.251 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/test/test_files/pep-test-mary-signed-encrypted-to-self.asc	Wed May 15 14:35:22 2019 +0200
    12.3 @@ -0,0 +1,24 @@
    12.4 +-----BEGIN PGP MESSAGE-----
    12.5 +
    12.6 +hQGMA6aSYtgJ++dOAQv/f5Q5icNJ2cXMe9HJgWeTiBDDBflPwuIUEVyeCGa82kyl
    12.7 +DwwWG/vS/KMwkJOzzttdT4PDlUKotRy1ujYtxYGByM8QLDEgWwGSGkS+XN0iG4Uz
    12.8 +p8SHzJbGgDbvsZCbEXrcSeR8XBLCGHRzvu1l2Dg43Co8QO250BV8PvhFAJrjEOUT
    12.9 +BhiR++biD64OuEA///zp+7lhqN6ejZw9P8lhqcl8e8wpirUTmZjrpWhNK/nSkWs1
   12.10 +ghBcteVBVdDFQX/UYKgluGldyGNy/CmYGhOuUfx3cmPGxO9qef+p3OjMVNlyYViM
   12.11 +xoawV+fn8c5hv9IK/jkCYyQmzJflzO1boQLMTCGL7DyyL9B7x58ib2lbHqIqWVTC
   12.12 +0Lq/IxKDhOf/E/qMT88g+uRRD6AUV5/CtxnHXPsomOhRINnuq8FNQjSBqws3jeXd
   12.13 +6zzI24ys0bpKk1VX3SAxIyPOcyHbSQQ4xRUGdo0dWdcm6XanC0oeri2ZaMJzfDnv
   12.14 +dUgQ8pr1AGfiih7l2MjP0ukB9SIGGjlqf7P+KQiU6TgCd5ZOPrp0hDp4vsP0wVNK
   12.15 +2S5kfK6sv+coGpEUEnUoBO827JW19MU0vLLwWkXZFoCB3DmI2KDvSBett9t2bSbT
   12.16 +N2Djvi9dLDCt05oNdmfR1e1HVIwZQm5qetHHycxQy8OscTUp9ZYlGkyrQ6jlMMeE
   12.17 +40OxcxSCmuk2ln5N5EZqUImAFv6ynuWNiN1vmKVI1ozTrDvb7QVn72QWN1slS0z6
   12.18 +b5WVunNYso58fFOjnJ4CFVCuWt5XhEhn5ArQoZrzWeDdWwV2l+vfwXlu2SXZdg6l
   12.19 +jW6tIJaUtEjPLg6PeTG0coLGE6JrUDcWCiqGEBdrV/9txssKG/efVdPn+Q1JXqom
   12.20 +//jAWwjFcDkRkrMbWVgEbtaUFHt67mTRQTQojfueqh8JbkmEVcxDzyAVtPiAnl9G
   12.21 +EZmWUD/OGePlJJjbf/B8ddRmUWzSjgtLfEQLekj9ubjq0e6+095bYHv14BOGbpdo
   12.22 +sqlxEevCwtx1F8+NoRFZq3qi1y+5BZacfoUZip3M7BVDpvAXX2t+6lKVQiMUsnSZ
   12.23 +SmupON6y8n/m6WaxnPqZkGbL07+umdPYUh68UO51A/UrCUujfFweaL2rXOK8pNkB
   12.24 +179q9WmLOWhBRNghDJlEZHbw/+OsJDiss96oGrxVBYq8T2iBM7MpFj3gW3ZDoIOr
   12.25 +Qws8uwuXIkEkwe8t+Q==
   12.26 +=BXG/
   12.27 +-----END PGP MESSAGE-----
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/test/test_files/pep-test-mary-signed.txt	Wed May 15 14:35:22 2019 +0200
    13.3 @@ -0,0 +1,1 @@
    13.4 +was soll ich machen?
    14.1 Binary file test/test_files/pep-test-mary-signed.txt.sig has changed
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/test/test_keys/priv/pep-test-mary-0x7F59F03CD04A226E.rev	Wed May 15 14:35:22 2019 +0200
    15.3 @@ -0,0 +1,15 @@
    15.4 +-----BEGIN PGP PUBLIC KEY BLOCK-----
    15.5 +Comment: This is a revocation certificate
    15.6 +
    15.7 +iQG2BCABCAAgFiEEWZs9Z4ANs34tzgXAf1nwPNBKIm4FAlzakXgCHQAACgkQf1nw
    15.8 +PNBKIm6RXgv/X4oQggntl/bpPA31RJCrfND2bQUekpH8rG0BsoY5VdXww2JuGdS5
    15.9 +q7CluWviPshEYLOe1xcb9wPM1Yo2c1OQfXapDhnLXR69q32vA7yxdkcdVcvJRD5I
   15.10 +Lotm2bwe5DURW256G8dLcL4pmCweCt8UKJNppyXUk7FB4U7wQcYHdR6dAVIebovh
   15.11 +aCopH/gXEsIxKXl5/P3E+1cb4jJlsmGrP2SBymx8etvGmT48F/PG1L2lWnZrkUfc
   15.12 +Ldj/W2ds/ukhizswpL/RI7fT+nmRmDCY11tWRzMxGOBYb2/fZmeqOtaFZe/PnVC7
   15.13 +Zv3XyK/WA0wLnpHCBtM9TmWwHOwyVwI4/o2cGtZMAtVlIcWNgYYnpf5BZY7vJjM0
   15.14 +eaUjNbuCUCuiOFeW35qHNZAq1VJj5QrfwBvvLWQrEpVPzCSMNSe9YuFEhKH4z5b7
   15.15 +YHX0Na3sSEBuvtnSkPKtixkd8H6lMhJ8eEpIyKJTjDgNVFSkMsLmiK+jikuJgIpw
   15.16 ++IM1ZSCnyfCF
   15.17 +=kqka
   15.18 +-----END PGP PUBLIC KEY BLOCK-----
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/test/test_keys/priv/pep-test-mary-0x7F59F03CD04A226E_priv.asc	Wed May 15 14:35:22 2019 +0200
    16.3 @@ -0,0 +1,129 @@
    16.4 +-----BEGIN PGP PRIVATE KEY BLOCK-----
    16.5 +
    16.6 +lQVYBFzakXIBDADFQ/yauFR/q9HPFfszr8Cd2t4tZA9xBC46CtTnvetfL40EnCPV
    16.7 +umzsKCt0ZICiqMS538yMzgE5V7cUGCJJxabTt9Xnm/mqD6JJFiNxx49+BxapiJgN
    16.8 +VE7Uo5s2tXzy/BUGP3B5OeW2frFbse0zRWkgN/jvbkNr43LsHVYkBUQKSiqm3Ud7
    16.9 +1NZRaapAbkxisCOHNTZ2uyayX2WZlxKgufp/61wL75XRoPoQdnajaQvro1rr35sC
   16.10 +teG9k425WS60j80ie+AmGEIguPPc4Go5rhwf3SCqU7BfiYCxVAvX5ESr+HpyicEF
   16.11 +5iL+4wm/VMxj4zzFMQKQvQ0lHmw4I1SreS250sVfkXWdYtjiq+2XWGoQUWOnU/j4
   16.12 +nBol10pwOQVI0jL+ok8OlXfFZm6LIYY7Pmd9O4e5WbCid/UU+uc0UW1qDtkHie8t
   16.13 +25epIQGqmLOHgQJDWxdSnmNRcM7A9ckktGNMG3n53qJ8bvdfqlioRNJwm0IUF1cz
   16.14 +dHZuhDzoSFpPTbMAEQEAAQAL/ijRhZ6aT9nPOu3n9X/feTLwzBKGZu+S1uHpxd5i
   16.15 +HScoFr0CdiPOnKVNNpiyBzAhTfvMRG5KXlR4QwjkaYvsWzXqD1gKnWHENGd9Lj5n
   16.16 +9dg1LUpNWnE/pcQ4SnDKox1AbjVJwUNEaLUXiCmaKqP2U+d3zYn1vfvAJ9KVy3JO
   16.17 +qKKccDDxDs6f3u0fuTv11taA7gkXSLrOxRYZyVM7wH4DncMEd5p8q/qhnbz0Vl4/
   16.18 +6ViMB89RCKlJ63kn5CabPp/cNU+5X8bC700tgg30EcUfwE6a+GSnfLVwAquZAfPI
   16.19 ++6ikSjaA+4Ha0LiDYTqtVzW1LohKHbU9ZQgwuCngIVUn3LmFGk7NFN4QHIw4MmnA
   16.20 +un5bfoIELxBPbpGFPguZ1b+UwUjabrfXyoC6xEydIGNqV7vTYo8BW5JZqaMvMWQY
   16.21 +7RXGJpTZdxRV8FBA2PsnhmD1aGI0DR1/xjiTdiZLl+wvRj3b4s/0dvisYDAx6fbL
   16.22 +AWFqH+FxAlxdHE2qtvaHcNmK0QYAyKpbX7tb8rRpdM67yiYCT33jall0wewZn4pb
   16.23 +bJr54eoSCcpIS17AP+A3pk67ppvWJTQGGx6lMNYpy8kfgF1EsL4JD70lrAHMrXke
   16.24 +o6DbDxzG1tl+FBAvCtvVcC/wICiX97XTvsk85X/SsfGGYi4ZdrVMiLwLY0A++uHl
   16.25 +khe11Odope8ZLuGo43xi9Ug3G+1g5FsLmn2IyTuELOgyV8NBRTiewBTQcr1ON4HZ
   16.26 +rVCjWx3svk3c2kEOUWtGP/uE9hdJBgD7qZ7mI7LZaWF4la3icvMge80a1BfYC+kR
   16.27 +h5aKrlrS0QU61XHqt6n3IeXv5brm1xMBwyUiVB4JgWU9xo/BxJp1nKh0UAFG5TLc
   16.28 +7mvrtdE1AY0PjfXVaouCgsyYb+cW6HOsrMvqBMfrLz/ehZc3uKv+zRc4eHITOm4R
   16.29 +UqEH/SxKPje15IkhQf7QfqI4LwZU0HKeU5ehTqzNwm0I33eBbXQClGNbBtWfPH1e
   16.30 +aSFQmjWu5hlLH4uATnIffqBwQ3tXERsF/1rBF+nFczeJduKgzjQpNV5TBzKQrgWX
   16.31 ++12LSjcBYPsBPct9k9H36JoO8zPZ2N0Xa+YBn+dgp9g3g2mN4/D3Q0lKrEReRfnN
   16.32 +nN8/54LlbEIRTgkFlt+evH46t5lVNui4pegyBQMMUAGew4TATkf6wTcrG4644Z9C
   16.33 +wpGi2Lxe0xsM8DxngRAMtT7u87vuKTgwPZWPIlUNmyCepISHnTOxdqgRx4Dujvsb
   16.34 +h6f6XkSd8QJpnRBrZ5HGsgfSN/Qt/NNcrt+StElNYXJ5IFN1c2FuIE1hcmlhIEth
   16.35 +cmVuIExpc2EgTGluZGEgRG9ubmEgUGF0cmljaWEgU21pdGggPDE5NjBAZXhhbXBs
   16.36 +ZS5vcmc+iQHOBBMBCAA4FiEEWZs9Z4ANs34tzgXAf1nwPNBKIm4FAlzakXICGwEF
   16.37 +CwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQf1nwPNBKIm4ebgv/ax2NjqFViCSY
   16.38 +wpH0O2Mre+sdy+Qlk+IZlVs33WgLTF3+6UEtO2mSWriwTw0FJVKkKmFcC2JDnDCY
   16.39 +eR13FZVB1W7RPHHkpJzheqRTommYXvYLQN1squUVD1d1rrxsWCwMDB3j+nfmixds
   16.40 +T3GZYBdmaZbvSXnwyhm5XTUqzs9tYgftHOGwpE20ySSOSNDpJ0t6wOlp7CuuZlTp
   16.41 +BBfZl1PmiALKwbPSKhXOJyuEI/W7cJ2/LyKfGPW7lkGAbek9JowK6Y9DGos6kOf8
   16.42 +W8Api3ZBXJJeBaSPqCZ0Nk/LP93JFv8yAdgKZiLKrr7YWylSEGLD/PVwOcTW/mUR
   16.43 +vnecah3WAbBVSN6fRYzjV8sDzNCPRTmObXsLmxC7uM6F8sMlzFCUPhZTY3ghjmU6
   16.44 +jDQlXEJn/6I2Q38lsjOX6dPnvFy7221LwHz9KYBIB8GgVT9rxJ0pNlZwChUmAOTn
   16.45 +rRUFjx+zMh1G0uKk6cDsqaVBjwncOu/aQJ+nVaCp6uxDXrnuhUienQVYBFzakZYB
   16.46 +DAC2Goe/yDgr+5Nj+XwMEENhIgo0FnUJMcYXSZhb1Cp8I5k2j7ge8yet6BVVYlEj
   16.47 +VKZ7C2UWqh7h5WlaVBn/ICqoDUqkJl9LktXNVbeTswoTVJTyKagJ/FaUb7Ysb51+
   16.48 +iWsC7LZNKUY8h7CLHsaF442iHHks97iSwl5EMTv/0q1AeBa/c1wmJh3w1c0fEYjy
   16.49 +TRe/VREhYBsnHkcRns8qZKX+FyJxtgKlGh7LFxqOUEA8rKzS8157qaS+GG8HvN3X
   16.50 +r1d8cwf/XnADAwsfQahxEMeFZoUUWtclfgcBDAEJTU9davTZJrvd43IR3rqYHBCc
   16.51 +Kic0Do+Qvt43DM/Y2are2NuIo7uliEY380gSHZAI9EmVRuOe/TrwmIPyxHTocxUx
   16.52 +5oNLXN3b0G3gnzaCLv2bMGeFszIcOtmuev1zHiRRcMbIuQQbRaVsGG6Rsy7S3hmw
   16.53 +G427bbI4k+Kqmteuy0WGEgUdMZEr629focujrS0Qh2E30KM6H2P8pKFjK20QSQZ0
   16.54 +gNkAEQEAAQAL/0E4X0Ygv32BLNixkewAJyGyv1TIdkJEwV21zguVgWHUnhscfiUX
   16.55 +kS6H4JwkCktNFhMbkaj8ZPMi5wii9myZaK2nlQQVeivm+wv/lzAe/4zMzkus/7IT
   16.56 +3i5rlCN2FkIrlVgGz4PzNGSZdHFfJFrvlNpquDuSvVhSpNBnkcWd/s8IM51+A5Lm
   16.57 +M/L9n+lwrkuZsNel7+y0LwVjorB84FWelpTaVEvFlEztffne3HP76gXRElS7NSu1
   16.58 +Jnuu5JUw34NQGLnB4T77upRHa4ngZeK3+VV5UYX9vHWEiz+TrvGkHA4fFbik04jF
   16.59 +rBwxcc0lHFC2O+lxiEzWGAgxDbqHifE9TzWrpPxAUZSo4On1XnKzu9EHAZVpexHJ
   16.60 +9l8jH1H7XvxBQGbG42e/aRAL3rlbP6iZqXhJ6pUeF4KlsVRbFo1XqwKUYhcryKCp
   16.61 +6bEip5R8W4S8/3EfrSpmRymsei7cV8e572ROPYlx6tDwOUJMRNDBarvT75Z3vZ2Y
   16.62 +xfP1/4Uy7uwfwQYAwjFRDnNYC+ChfP5cdWDpfBGoulCKQ107+2TzKwnDqCi+a901
   16.63 +KxnK1iE7PVNEVL/SkF1RKJPgU2yAXJacd9AlrPRaXV8ftTaL8F8wZkSrybCodpcO
   16.64 +avOuMSztqvnldJjZk0ZJrKa+kgyKRESMDmPSe6WV7zl9S/qFox1vzncYfnCYD90X
   16.65 +DABxeqBukUEk+hWBSyZY+t0qnOcW2XP0LxFZHOix+ZWwIlRj50AS2s6uIlGKv99Z
   16.66 +fotRuwxRaxAFysiXBgDwEDWfdQX9vmw8vqzMxK0z4cj9NhMWHrDNH9QMeX4/K9V9
   16.67 +7LsTibsbTw6jpwPh/+s9zxC0RR1Ro+kZQnvleLz6+k0gqiJErHHvl4qmgFdq4T13
   16.68 +J7ISEPCH5sVO+1t1Di3oLBtEP1COY2UpNyC2Otjml3A1/CmYdGI9G6JyEVKQF4Ju
   16.69 +BwJ14RSz0b1i5pjotkD8PfGmNIVF2nOUATbFRYYnDP8MH8c8TzasIwjKrnPxY2Yx
   16.70 +k2kEOWGqm9d3TQabQA8F/2PKyMSbIjBwiGpi9PMC0MZCDjc+j2H4J/C06ycaMWiK
   16.71 +1ZPKE3yGv8bhA6zhQAAYuH02BUZBrRY2uTXHcgnyULcg0/+AWvJklaw4dbRy3iLT
   16.72 +O45J1N392Q5JFO9bOaIpemamEP+/MoD+VV8+U/Al9RSBMmxgq8BmRt0+F881d5n5
   16.73 +71g9dOjrdd1zX4Xl7eASS00kbAcGoZCb34oW0uRi9nYunzltXzM+s5INXvycoTjo
   16.74 +jEpb4FyLMeS6CPJwphAGvdy7iQNsBBgBCAAgFiEEWZs9Z4ANs34tzgXAf1nwPNBK
   16.75 +Im4FAlzakZYCGwIBwAkQf1nwPNBKIm7A9CAEGQEIAB0WIQQ0rQXUJuRMayXQhG++
   16.76 +0LH0HLDcUQUCXNqRlgAKCRC+0LH0HLDcUavFC/48V+NZzS3NlSa/R2mcBwAZyEZi
   16.77 +CGstMeualsNtpxeAI3dJD2YOptqF0EwCardYBrRYH4lvbPNCUC0/pPVBdlZGi+nX
   16.78 +7LqOffSlmYRyz9K6idLOWqLQcab7NZG8fgyygtx/zVyLvRtCcqsGuCj98vIZXgyA
   16.79 +QZnaDDaUXRPwlXlCUXXAYmEMr2zTVZzxmz18Kzr1bK7w0f6wxDHiN7gGpSX7ASp4
   16.80 +fh3glAIW7V6o03eUfzcIizXqVP+jNVrR2XbdFP6b3eW2UAXf1nAmUX7JKS1fGhk6
   16.81 +f+3Cdzmy1tGsCfB6bUQhxkzYhuWvzuLXwG5BVpKzjwMqGqwy2UnaIuq0Q8sU8N1u
   16.82 +AmphZm7+1x/4jVdQLm9if6okY51du/zPdoHucRo/sT+Sr+xAXn6QkB6SdzkwUXAC
   16.83 +/uRF3Zg2RBVyhcrrIG+mrIAW5FO12njOgrJAWP09zKilYnOGoDnbnexrqTUjpcZu
   16.84 +oaW/Yn2DobIJFAl/d6mTx2nlNfU0Ol1gwmWOA1YN4gwAhsnkzW5K5HEUPuYBxE2G
   16.85 +UAZgclQdh0/TWdUrxcooRShwZ3p0cVqmmz3xZlUUy8atx6w/hUnh173df82D/XfI
   16.86 +7HnaN27p6hA61GBhkGXXR5IYInesB+eKPgp2jzHtbxzhb4cuT+CNsyCYtlkmN278
   16.87 +9cxadYpskwhMDFWCPgGD3W16hFa7pCmgR4J8UYmZZP5LcOAgmRO3SzIroPnVj3TM
   16.88 +ftelH1Auq8GR6qysVtAlb1ckmS3m1l8jrCu53CS+UkG7HEK1LCb5L2e5DnzDLIkj
   16.89 +Z4IcByQVFvAkN/V0kx4/JWN9iZVFnhlJXkC/qgA26nM5VvCX5MoMLs9ksxdyJ4tm
   16.90 +BZCDjgefymve1y3dhNcmY8Gt0PxNYTrg22m0L7aNSz8RwShlrmlDOMn+r/x9Gt1/
   16.91 +664f6MlSmE8HXO6Ucos4z0gD9N3WCclVGJ1AXE8Q7fd/v5xiw0lARnH4++cQ0AMT
   16.92 +Ay8qn5qdai0FBVeEtrAbxdguCkcVbdbsxFOjldhDGbcdnQVYBFzakaUBDAC2L+tD
   16.93 +AJvji5xqrfPunpCa0/C+Q5zax4ypDYlNj+7KU2edPNd3Y7ZOXXU58nv2BbeKVqoZ
   16.94 +VUs5jbAe40a7XYUSoqTeechk9JxLIwsvpLh5E1bGD67U7FnXfZqvm9b7mKWeDriP
   16.95 +mPfJceWQy4b6s968BOeo0L1iR0tDu04u5mAgZDXTHmLr5oxhHixtMxOJkQUIlEaJ
   16.96 +P/NGS4R9rq1fgkS3kv+kNveiZRlxq2vGE2/g+uU4Cscq+j+19DdzTZgOu6JY02uX
   16.97 +tbPv0Z9Gaj9SUgTnUbFF/9qlV/FkAAHK1Q/j8XPoPFkeC+akeEAP3GyhLmnEgY+d
   16.98 +3MA5xWRDgsOe+0+xP3YhABIOMk0LTNb5NSXeIS+2t+9NzAA1BT9E1CTthDHC3waL
   16.99 +5Fk9w1MNwoyaAo96qEqLbFbpO1HB2k8ak3uCvdysWWkV2/zPRph3R1zcXWEm/vAD
  16.100 +Ja9sztx7dZDTy9AjDmquBWSk2/Fhs9noQsXI2xOPZd4rBwimTSNHX2xDEC8AEQEA
  16.101 +AQAL/RFyuGjT05owwjuzSjPVqsqxNpK6Pfjz+IQuQDKV8MwevcMg0w/jlE+gAryY
  16.102 +fQe8V24fy62ebhRmffIPWTRTig2VVw3ZgvgsNxW5Fvaqo2IxGHPih59rvVT2egyM
  16.103 +c8PnxCDFjyZtg3me91ntLBGxjUjbfWY9C44wfsRPWXcDaDxh7Ie6FsY578LTVXTl
  16.104 +2d6obV97d9/oKH/Ydqlkw8TsYHFmWiZbf07luNCalrlDHklhLfe2jImQqu5do7ve
  16.105 +uAvdK087vvm4G6THAEdOjLx+bs46QbeVDuCKQcI4CQbYtik4BtXlY6BNkORJczxd
  16.106 +8S9V2n61fp4TEFdzDQw/udDPXUkue6RW8as0EOT7VFiTlTvsCoK0d4L3bkYKJ2w5
  16.107 +cjt014i2959NFR4qOO+M36/mcEc2l12tA3dzZWnj/h8L9gZOcDwlgldCGY+FdIEe
  16.108 +pgwZ8hjMfNC94qhGyn/+RAbjUCgYthZx5RH6zf1WNSBMEkFRR+WJcFENCuPuXl4H
  16.109 +w536BQYAyn30zNYJlm2XsYgrM9B27ZavUNNehHu8K9yeD3oASa5E0gGk4Oj9JQm6
  16.110 +vDIbpP1ImbbiI1hUHkL+XK8tdvjxu8cKISi3KfUZvSxs12G2ax7tmUyWtnql4CHx
  16.111 +PJJOIagFlPY0f1LEuAXVGPd68hSZ5mzn3zuUbt/pLdbZ7YNTJ1aIawOZqWOBYltr
  16.112 +znrAKcjVs6OFzKeujNa+K2JYyawEU/eG4322OBVSDspEV0Z2X/z8sGgDhfAlyZmq
  16.113 +HdebYdSDBgDmVGUiErIVQAMp/LsuYr+GdrZDdAwkusAUcAS5JLt2MvLOhDjJ910t
  16.114 +ByUjU0uHWxYCZH4kcv0/aAeCF3lWuTYmGRbdFk89p7Y6zggf6W1jqWLQ7JIvZQsQ
  16.115 +KidKHP1dTb6aQp6v7tKcUoYaPlgLE+eFjdAX6f0CQ+FBYfszYbqWkRfoREW3NyDV
  16.116 +G8qlH0fZrMjYdvt3dTKRO11wh958O4eOM9yLiPxk/ZrFNcvfxzQLyjzZ65ub4JSi
  16.117 +M6zdK/pUfeUF/20iloJMsXlYTqXI1taYtKAmA1iwJ5kvpz3uPGOtNRSrISkLoSab
  16.118 +ocfojHAsOhRwZMvhrh7mXfycWZGFm58ZP6C3r0nYNeHsjDwI8UOvKUiD1w9xVSJl
  16.119 +kFR5gH3cqawPA0M8O6Ya8nnO4GayQgKwFMzB0Z6j87G0SViT3fS89DwcRjTC5QeY
  16.120 +Tj0fEeFz7/CX0buEsnsd0FM1w2We/DAK/kAQXMDirmabIOasYPDk3+BS3fWGaJf7
  16.121 +xICz4DJE99QSfd5GiQG2BBgBCAAgFiEEWZs9Z4ANs34tzgXAf1nwPNBKIm4FAlza
  16.122 +kaUCGwwACgkQf1nwPNBKIm6jJwwAhjrzhMBozPqmmprEolo2iPZFLBwVqXueIPjQ
  16.123 +S6YOVaitJxQePNOHpkWJqGaVRpmVlUg7z0oCsmfLjfQSV6FygdjjFRjbhm14ny1v
  16.124 +ZeSbYNROSwWVDWB/KoLnC3YFQh4BjhxqORsGvZ6BnWWKEtXyBN2vTCZC8+hGfo6p
  16.125 ++WbTbwCnzPWTvuhxqxFC/P9esgBfYzUDa/qRKggZvecQL+k0ebWeQzUwvTTWgfDa
  16.126 +Vh+Fl2OB3tt9kI9th46mfw1a6MXQssyH0Shd1J/cQtAZiZCCnKS41aLUKnMNjrGt
  16.127 +MdYjCq6f9WGTqB5tXhYYkMZBCiJBmXaXR1Vli8ERoZm5GXki9d54Gu1lAZ6QDM6O
  16.128 +iKngsknRFAyvQz4zDAHm0olGA4+SIdRT9iQ6I2NDR/R9kZzuQ/42CiUf8XX/4Tzb
  16.129 +vU/DhExIEyxN6S8khYaDfsDVoBrKOn4qF7Lj1PNN1xt0qNxYPy3tbQVnCOD6a0po
  16.130 +mCsddt0ANDA4BDMM32UW0FU2Ahu0
  16.131 +=EuxL
  16.132 +-----END PGP PRIVATE KEY BLOCK-----
    17.1 Binary file test/test_keys/pub/pep-test-android-keyring.pgp has changed
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/test/test_keys/pub/pep-test-mary-0x7F59F03CD04A226E_expired_pub.asc	Wed May 15 14:35:22 2019 +0200
    18.3 @@ -0,0 +1,68 @@
    18.4 +-----BEGIN PGP PUBLIC KEY BLOCK-----
    18.5 +
    18.6 +mQGNBFzakXIBDADFQ/yauFR/q9HPFfszr8Cd2t4tZA9xBC46CtTnvetfL40EnCPV
    18.7 +umzsKCt0ZICiqMS538yMzgE5V7cUGCJJxabTt9Xnm/mqD6JJFiNxx49+BxapiJgN
    18.8 +VE7Uo5s2tXzy/BUGP3B5OeW2frFbse0zRWkgN/jvbkNr43LsHVYkBUQKSiqm3Ud7
    18.9 +1NZRaapAbkxisCOHNTZ2uyayX2WZlxKgufp/61wL75XRoPoQdnajaQvro1rr35sC
   18.10 +teG9k425WS60j80ie+AmGEIguPPc4Go5rhwf3SCqU7BfiYCxVAvX5ESr+HpyicEF
   18.11 +5iL+4wm/VMxj4zzFMQKQvQ0lHmw4I1SreS250sVfkXWdYtjiq+2XWGoQUWOnU/j4
   18.12 +nBol10pwOQVI0jL+ok8OlXfFZm6LIYY7Pmd9O4e5WbCid/UU+uc0UW1qDtkHie8t
   18.13 +25epIQGqmLOHgQJDWxdSnmNRcM7A9ckktGNMG3n53qJ8bvdfqlioRNJwm0IUF1cz
   18.14 +dHZuhDzoSFpPTbMAEQEAAbRJTWFyeSBTdXNhbiBNYXJpYSBLYXJlbiBMaXNhIExp
   18.15 +bmRhIERvbm5hIFBhdHJpY2lhIFNtaXRoIDwxOTYwQGV4YW1wbGUub3JnPokB1AQT
   18.16 +AQgAPgIbAQULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgBYhBFmbPWeADbN+Lc4FwH9Z
   18.17 +8DzQSiJuBQJc2pITBQkAAVIhAAoJEH9Z8DzQSiJuT9oMAMDohz5ee4mz8d1GZxgn
   18.18 +IVmktrUxhr7PoJoLjyQF5VHCifYC1fdH3ax8EblRfnjI9G+JlGXcS+Vyae0UXlTe
   18.19 +zfVHBSyDM1VWZ4X+mSs4mXgU6IQOn/zGIFfEU1TgEl7FjK70zhjJNfr1LruVA/I/
   18.20 ++oLD2oH8AObOTrYF6ZsKqqnLyAC3H0NI+FoczkXJom7h27RoRXJsCO2FGElLGhak
   18.21 +zSJwSYTbGLBT9ELqpboCop5AIiL9daPqkcHktbONNKyC5sBbXn+nRU6cWirbLrsF
   18.22 +t9epabSVpI0QlnvWsTcr0jv6yCXx5vyS8kBqmXt3hi9UbC3nsg4+7V+8iBlOTjUL
   18.23 +R3CTZepj1b4mE0vRr+JBKHXfakwdAJYvQRuPYPC6w2Hmwk7MIio+ROVdD9yb/yOA
   18.24 +LoVNzLllGM9wmpX6921suFh7romAZXD1V4AH8UzBgcRSDZfcW0oxjcYfdlQpO5QW
   18.25 +eujvNxeUXqXui7ia5f6EjGT0wAgknZd3IY/M/DsR6jHqu7kBjQRc2pGWAQwAthqH
   18.26 +v8g4K/uTY/l8DBBDYSIKNBZ1CTHGF0mYW9QqfCOZNo+4HvMnregVVWJRI1Smewtl
   18.27 +Fqoe4eVpWlQZ/yAqqA1KpCZfS5LVzVW3k7MKE1SU8imoCfxWlG+2LG+dfolrAuy2
   18.28 +TSlGPIewix7GheONohx5LPe4ksJeRDE7/9KtQHgWv3NcJiYd8NXNHxGI8k0Xv1UR
   18.29 +IWAbJx5HEZ7PKmSl/hcicbYCpRoeyxcajlBAPKys0vNee6mkvhhvB7zd169XfHMH
   18.30 +/15wAwMLH0GocRDHhWaFFFrXJX4HAQwBCU1PXWr02Sa73eNyEd66mBwQnConNA6P
   18.31 +kL7eNwzP2Nmq3tjbiKO7pYhGN/NIEh2QCPRJlUbjnv068JiD8sR06HMVMeaDS1zd
   18.32 +29Bt4J82gi79mzBnhbMyHDrZrnr9cx4kUXDGyLkEG0WlbBhukbMu0t4ZsBuNu22y
   18.33 +OJPiqprXrstFhhIFHTGRK+tvX6HLo60tEIdhN9CjOh9j/KShYyttEEkGdIDZABEB
   18.34 +AAGJA2wEGAEIACAWIQRZmz1ngA2zfi3OBcB/WfA80EoibgUCXNqRlgIbAgHACRB/
   18.35 +WfA80EoibsD0IAQZAQgAHRYhBDStBdQm5ExrJdCEb77QsfQcsNxRBQJc2pGWAAoJ
   18.36 +EL7QsfQcsNxRq8UL/jxX41nNLc2VJr9HaZwHABnIRmIIay0x65qWw22nF4Ajd0kP
   18.37 +Zg6m2oXQTAJqt1gGtFgfiW9s80JQLT+k9UF2VkaL6dfsuo599KWZhHLP0rqJ0s5a
   18.38 +otBxpvs1kbx+DLKC3H/NXIu9G0Jyqwa4KP3y8hleDIBBmdoMNpRdE/CVeUJRdcBi
   18.39 +YQyvbNNVnPGbPXwrOvVsrvDR/rDEMeI3uAalJfsBKnh+HeCUAhbtXqjTd5R/NwiL
   18.40 +NepU/6M1WtHZdt0U/pvd5bZQBd/WcCZRfskpLV8aGTp/7cJ3ObLW0awJ8HptRCHG
   18.41 +TNiG5a/O4tfAbkFWkrOPAyoarDLZSdoi6rRDyxTw3W4CamFmbv7XH/iNV1Aub2J/
   18.42 +qiRjnV27/M92ge5xGj+xP5Kv7EBefpCQHpJ3OTBRcAL+5EXdmDZEFXKFyusgb6as
   18.43 +gBbkU7XaeM6CskBY/T3MqKVic4agOdud7GupNSOlxm6hpb9ifYOhsgkUCX93qZPH
   18.44 +aeU19TQ6XWDCZY4DVg3iDACGyeTNbkrkcRQ+5gHETYZQBmByVB2HT9NZ1SvFyihF
   18.45 +KHBnenRxWqabPfFmVRTLxq3HrD+FSeHXvd1/zYP9d8jsedo3bunqEDrUYGGQZddH
   18.46 +khgid6wH54o+CnaPMe1vHOFvhy5P4I2zIJi2WSY3bvz1zFp1imyTCEwMVYI+AYPd
   18.47 +bXqEVrukKaBHgnxRiZlk/ktw4CCZE7dLMiug+dWPdMx+16UfUC6rwZHqrKxW0CVv
   18.48 +VySZLebWXyOsK7ncJL5SQbscQrUsJvkvZ7kOfMMsiSNnghwHJBUW8CQ39XSTHj8l
   18.49 +Y32JlUWeGUleQL+qADbqczlW8Jfkygwuz2SzF3Ini2YFkIOOB5/Ka97XLd2E1yZj
   18.50 +wa3Q/E1hOuDbabQvto1LPxHBKGWuaUM4yf6v/H0a3X/rrh/oyVKYTwdc7pRyizjP
   18.51 +SAP03dYJyVUYnUBcTxDt93+/nGLDSUBGcfj75xDQAxMDLyqfmp1qLQUFV4S2sBvF
   18.52 +2C4KRxVt1uzEU6OV2EMZtx25AY0EXNqRpQEMALYv60MAm+OLnGqt8+6ekJrT8L5D
   18.53 +nNrHjKkNiU2P7spTZ50813djtk5ddTnye/YFt4pWqhlVSzmNsB7jRrtdhRKipN55
   18.54 +yGT0nEsjCy+kuHkTVsYPrtTsWdd9mq+b1vuYpZ4OuI+Y98lx5ZDLhvqz3rwE56jQ
   18.55 +vWJHS0O7Ti7mYCBkNdMeYuvmjGEeLG0zE4mRBQiURok/80ZLhH2urV+CRLeS/6Q2
   18.56 +96JlGXGra8YTb+D65TgKxyr6P7X0N3NNmA67oljTa5e1s+/Rn0ZqP1JSBOdRsUX/
   18.57 +2qVX8WQAAcrVD+Pxc+g8WR4L5qR4QA/cbKEuacSBj53cwDnFZEOCw577T7E/diEA
   18.58 +Eg4yTQtM1vk1Jd4hL7a3703MADUFP0TUJO2EMcLfBovkWT3DUw3CjJoCj3qoSots
   18.59 +Vuk7UcHaTxqTe4K93KxZaRXb/M9GmHdHXNxdYSb+8AMlr2zO3Ht1kNPL0CMOaq4F
   18.60 +ZKTb8WGz2ehCxcjbE49l3isHCKZNI0dfbEMQLwARAQABiQG2BBgBCAAgFiEEWZs9
   18.61 +Z4ANs34tzgXAf1nwPNBKIm4FAlzakaUCGwwACgkQf1nwPNBKIm6jJwwAhjrzhMBo
   18.62 +zPqmmprEolo2iPZFLBwVqXueIPjQS6YOVaitJxQePNOHpkWJqGaVRpmVlUg7z0oC
   18.63 +smfLjfQSV6FygdjjFRjbhm14ny1vZeSbYNROSwWVDWB/KoLnC3YFQh4BjhxqORsG
   18.64 +vZ6BnWWKEtXyBN2vTCZC8+hGfo6p+WbTbwCnzPWTvuhxqxFC/P9esgBfYzUDa/qR
   18.65 +KggZvecQL+k0ebWeQzUwvTTWgfDaVh+Fl2OB3tt9kI9th46mfw1a6MXQssyH0Shd
   18.66 +1J/cQtAZiZCCnKS41aLUKnMNjrGtMdYjCq6f9WGTqB5tXhYYkMZBCiJBmXaXR1Vl
   18.67 +i8ERoZm5GXki9d54Gu1lAZ6QDM6OiKngsknRFAyvQz4zDAHm0olGA4+SIdRT9iQ6
   18.68 +I2NDR/R9kZzuQ/42CiUf8XX/4TzbvU/DhExIEyxN6S8khYaDfsDVoBrKOn4qF7Lj
   18.69 +1PNN1xt0qNxYPy3tbQVnCOD6a0pomCsddt0ANDA4BDMM32UW0FU2Ahu0
   18.70 +=Lvco
   18.71 +-----END PGP PUBLIC KEY BLOCK-----
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/test/test_keys/pub/pep-test-mary-0x7F59F03CD04A226E_expired_sig_key.asc	Wed May 15 14:35:22 2019 +0200
    19.3 @@ -0,0 +1,68 @@
    19.4 +-----BEGIN PGP PUBLIC KEY BLOCK-----
    19.5 +
    19.6 +mQGNBFzakXIBDADFQ/yauFR/q9HPFfszr8Cd2t4tZA9xBC46CtTnvetfL40EnCPV
    19.7 +umzsKCt0ZICiqMS538yMzgE5V7cUGCJJxabTt9Xnm/mqD6JJFiNxx49+BxapiJgN
    19.8 +VE7Uo5s2tXzy/BUGP3B5OeW2frFbse0zRWkgN/jvbkNr43LsHVYkBUQKSiqm3Ud7
    19.9 +1NZRaapAbkxisCOHNTZ2uyayX2WZlxKgufp/61wL75XRoPoQdnajaQvro1rr35sC
   19.10 +teG9k425WS60j80ie+AmGEIguPPc4Go5rhwf3SCqU7BfiYCxVAvX5ESr+HpyicEF
   19.11 +5iL+4wm/VMxj4zzFMQKQvQ0lHmw4I1SreS250sVfkXWdYtjiq+2XWGoQUWOnU/j4
   19.12 +nBol10pwOQVI0jL+ok8OlXfFZm6LIYY7Pmd9O4e5WbCid/UU+uc0UW1qDtkHie8t
   19.13 +25epIQGqmLOHgQJDWxdSnmNRcM7A9ckktGNMG3n53qJ8bvdfqlioRNJwm0IUF1cz
   19.14 +dHZuhDzoSFpPTbMAEQEAAbRJTWFyeSBTdXNhbiBNYXJpYSBLYXJlbiBMaXNhIExp
   19.15 +bmRhIERvbm5hIFBhdHJpY2lhIFNtaXRoIDwxOTYwQGV4YW1wbGUub3JnPokBzgQT
   19.16 +AQgAOBYhBFmbPWeADbN+Lc4FwH9Z8DzQSiJuBQJc2pFyAhsBBQsJCAcCBhUICQoL
   19.17 +AgQWAgMBAh4BAheAAAoJEH9Z8DzQSiJuHm4L/2sdjY6hVYgkmMKR9DtjK3vrHcvk
   19.18 +JZPiGZVbN91oC0xd/ulBLTtpklq4sE8NBSVSpCphXAtiQ5wwmHkddxWVQdVu0Txx
   19.19 +5KSc4XqkU6JpmF72C0DdbKrlFQ9Xda68bFgsDAwd4/p35osXbE9xmWAXZmmW70l5
   19.20 +8MoZuV01Ks7PbWIH7RzhsKRNtMkkjkjQ6SdLesDpaewrrmZU6QQX2ZdT5ogCysGz
   19.21 +0ioVzicrhCP1u3Cdvy8inxj1u5ZBgG3pPSaMCumPQxqLOpDn/FvAKYt2QVySXgWk
   19.22 +j6gmdDZPyz/dyRb/MgHYCmYiyq6+2FspUhBiw/z1cDnE1v5lEb53nGod1gGwVUje
   19.23 +n0WM41fLA8zQj0U5jm17C5sQu7jOhfLDJcxQlD4WU2N4IY5lOow0JVxCZ/+iNkN/
   19.24 +JbIzl+nT57xcu9ttS8B8/SmASAfBoFU/a8SdKTZWcAoVJgDk560VBY8fszIdRtLi
   19.25 +pOnA7KmlQY8J3Drv2kCfp1WgqersQ1657oVInrkBjQRc2pGWAQwAthqHv8g4K/uT
   19.26 +Y/l8DBBDYSIKNBZ1CTHGF0mYW9QqfCOZNo+4HvMnregVVWJRI1SmewtlFqoe4eVp
   19.27 +WlQZ/yAqqA1KpCZfS5LVzVW3k7MKE1SU8imoCfxWlG+2LG+dfolrAuy2TSlGPIew
   19.28 +ix7GheONohx5LPe4ksJeRDE7/9KtQHgWv3NcJiYd8NXNHxGI8k0Xv1URIWAbJx5H
   19.29 +EZ7PKmSl/hcicbYCpRoeyxcajlBAPKys0vNee6mkvhhvB7zd169XfHMH/15wAwML
   19.30 +H0GocRDHhWaFFFrXJX4HAQwBCU1PXWr02Sa73eNyEd66mBwQnConNA6PkL7eNwzP
   19.31 +2Nmq3tjbiKO7pYhGN/NIEh2QCPRJlUbjnv068JiD8sR06HMVMeaDS1zd29Bt4J82
   19.32 +gi79mzBnhbMyHDrZrnr9cx4kUXDGyLkEG0WlbBhukbMu0t4ZsBuNu22yOJPiqprX
   19.33 +rstFhhIFHTGRK+tvX6HLo60tEIdhN9CjOh9j/KShYyttEEkGdIDZABEBAAGJA3IE
   19.34 +GAEIACYCGwIWIQRZmz1ngA2zfi3OBcB/WfA80EoibgUCXNqSVQUJAAFSPwHAwPQg
   19.35 +BBkBCAAdFiEENK0F1CbkTGsl0IRvvtCx9Byw3FEFAlzakZYACgkQvtCx9Byw3FGr
   19.36 +xQv+PFfjWc0tzZUmv0dpnAcAGchGYghrLTHrmpbDbacXgCN3SQ9mDqbahdBMAmq3
   19.37 +WAa0WB+Jb2zzQlAtP6T1QXZWRovp1+y6jn30pZmEcs/SuonSzlqi0HGm+zWRvH4M
   19.38 +soLcf81ci70bQnKrBrgo/fLyGV4MgEGZ2gw2lF0T8JV5QlF1wGJhDK9s01Wc8Zs9
   19.39 +fCs69Wyu8NH+sMQx4je4BqUl+wEqeH4d4JQCFu1eqNN3lH83CIs16lT/ozVa0dl2
   19.40 +3RT+m93ltlAF39ZwJlF+ySktXxoZOn/twnc5stbRrAnwem1EIcZM2Iblr87i18Bu
   19.41 +QVaSs48DKhqsMtlJ2iLqtEPLFPDdbgJqYWZu/tcf+I1XUC5vYn+qJGOdXbv8z3aB
   19.42 +7nEaP7E/kq/sQF5+kJAeknc5MFFwAv7kRd2YNkQVcoXK6yBvpqyAFuRTtdp4zoKy
   19.43 +QFj9PcyopWJzhqA5253sa6k1I6XGbqGlv2J9g6GyCRQJf3epk8dp5TX1NDpdYMJl
   19.44 +jgNWCRB/WfA80EoibqLdC/4ssznHmOhxlEmPHZOgOsJQgtQGt3Zz4EDqOY5ejxaj
   19.45 +B9Nl5zJdypDhx1Dfb6gCR9ZOsKelpZJeees2HjKA0mqwFkQ30s/HN1ocVCKaq3md
   19.46 +ozGQv0z5Cihw1Buj+CZwHztPRbtDPNAyrLUjgJN0Lg/jfU4G90aS1aQEGnnlksE3
   19.47 +qkBw+86RV2gHoVfWOGQGFCajlJgnz6X93YL1A7IJv19rP+4fHJKubq98gnXvo60Z
   19.48 +OBiUKmIkgja2lDlZo26qz/yHiS/WBo/ZWMBiH7brM7TikIAC3JgXrc+98m8vJqAQ
   19.49 ++Ak6yndQDaMmnfaj53E4YaZ937xGiNRZq5lEnPZqII5Ki+gvscpBOrVo/N1hVsAB
   19.50 +Zqiy29r67lcrZjYAWpYVtTWtQP1el6WyhClZnZiRJJ0blnhSWF+W6G9anjPerqnw
   19.51 ++hC1oVehym7tCm/NoIMwxaUHa90T8637jYh/pEutQD3xWFRUcEMa+l9rvW9yuIYW
   19.52 +kXTPWsuZllyaw37qSGCMUA+5AY0EXNqRpQEMALYv60MAm+OLnGqt8+6ekJrT8L5D
   19.53 +nNrHjKkNiU2P7spTZ50813djtk5ddTnye/YFt4pWqhlVSzmNsB7jRrtdhRKipN55
   19.54 +yGT0nEsjCy+kuHkTVsYPrtTsWdd9mq+b1vuYpZ4OuI+Y98lx5ZDLhvqz3rwE56jQ
   19.55 +vWJHS0O7Ti7mYCBkNdMeYuvmjGEeLG0zE4mRBQiURok/80ZLhH2urV+CRLeS/6Q2
   19.56 +96JlGXGra8YTb+D65TgKxyr6P7X0N3NNmA67oljTa5e1s+/Rn0ZqP1JSBOdRsUX/
   19.57 +2qVX8WQAAcrVD+Pxc+g8WR4L5qR4QA/cbKEuacSBj53cwDnFZEOCw577T7E/diEA
   19.58 +Eg4yTQtM1vk1Jd4hL7a3703MADUFP0TUJO2EMcLfBovkWT3DUw3CjJoCj3qoSots
   19.59 +Vuk7UcHaTxqTe4K93KxZaRXb/M9GmHdHXNxdYSb+8AMlr2zO3Ht1kNPL0CMOaq4F
   19.60 +ZKTb8WGz2ehCxcjbE49l3isHCKZNI0dfbEMQLwARAQABiQG2BBgBCAAgFiEEWZs9
   19.61 +Z4ANs34tzgXAf1nwPNBKIm4FAlzakaUCGwwACgkQf1nwPNBKIm6jJwwAhjrzhMBo
   19.62 +zPqmmprEolo2iPZFLBwVqXueIPjQS6YOVaitJxQePNOHpkWJqGaVRpmVlUg7z0oC
   19.63 +smfLjfQSV6FygdjjFRjbhm14ny1vZeSbYNROSwWVDWB/KoLnC3YFQh4BjhxqORsG
   19.64 +vZ6BnWWKEtXyBN2vTCZC8+hGfo6p+WbTbwCnzPWTvuhxqxFC/P9esgBfYzUDa/qR
   19.65 +KggZvecQL+k0ebWeQzUwvTTWgfDaVh+Fl2OB3tt9kI9th46mfw1a6MXQssyH0Shd
   19.66 +1J/cQtAZiZCCnKS41aLUKnMNjrGtMdYjCq6f9WGTqB5tXhYYkMZBCiJBmXaXR1Vl
   19.67 +i8ERoZm5GXki9d54Gu1lAZ6QDM6OiKngsknRFAyvQz4zDAHm0olGA4+SIdRT9iQ6
   19.68 +I2NDR/R9kZzuQ/42CiUf8XX/4TzbvU/DhExIEyxN6S8khYaDfsDVoBrKOn4qF7Lj
   19.69 +1PNN1xt0qNxYPy3tbQVnCOD6a0pomCsddt0ANDA4BDMM32UW0FU2Ahu0
   19.70 +=INdi
   19.71 +-----END PGP PUBLIC KEY BLOCK-----
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/test/test_keys/pub/pep-test-mary-0x7F59F03CD04A226E_revoked_sig_key.asc	Wed May 15 14:35:22 2019 +0200
    20.3 @@ -0,0 +1,77 @@
    20.4 +-----BEGIN PGP PUBLIC KEY BLOCK-----
    20.5 +
    20.6 +mQGNBFzakXIBDADFQ/yauFR/q9HPFfszr8Cd2t4tZA9xBC46CtTnvetfL40EnCPV
    20.7 +umzsKCt0ZICiqMS538yMzgE5V7cUGCJJxabTt9Xnm/mqD6JJFiNxx49+BxapiJgN
    20.8 +VE7Uo5s2tXzy/BUGP3B5OeW2frFbse0zRWkgN/jvbkNr43LsHVYkBUQKSiqm3Ud7
    20.9 +1NZRaapAbkxisCOHNTZ2uyayX2WZlxKgufp/61wL75XRoPoQdnajaQvro1rr35sC
   20.10 +teG9k425WS60j80ie+AmGEIguPPc4Go5rhwf3SCqU7BfiYCxVAvX5ESr+HpyicEF
   20.11 +5iL+4wm/VMxj4zzFMQKQvQ0lHmw4I1SreS250sVfkXWdYtjiq+2XWGoQUWOnU/j4
   20.12 +nBol10pwOQVI0jL+ok8OlXfFZm6LIYY7Pmd9O4e5WbCid/UU+uc0UW1qDtkHie8t
   20.13 +25epIQGqmLOHgQJDWxdSnmNRcM7A9ckktGNMG3n53qJ8bvdfqlioRNJwm0IUF1cz
   20.14 +dHZuhDzoSFpPTbMAEQEAAbRJTWFyeSBTdXNhbiBNYXJpYSBLYXJlbiBMaXNhIExp
   20.15 +bmRhIERvbm5hIFBhdHJpY2lhIFNtaXRoIDwxOTYwQGV4YW1wbGUub3JnPokBzgQT
   20.16 +AQgAOBYhBFmbPWeADbN+Lc4FwH9Z8DzQSiJuBQJc2pFyAhsBBQsJCAcCBhUICQoL
   20.17 +AgQWAgMBAh4BAheAAAoJEH9Z8DzQSiJuHm4L/2sdjY6hVYgkmMKR9DtjK3vrHcvk
   20.18 +JZPiGZVbN91oC0xd/ulBLTtpklq4sE8NBSVSpCphXAtiQ5wwmHkddxWVQdVu0Txx
   20.19 +5KSc4XqkU6JpmF72C0DdbKrlFQ9Xda68bFgsDAwd4/p35osXbE9xmWAXZmmW70l5
   20.20 +8MoZuV01Ks7PbWIH7RzhsKRNtMkkjkjQ6SdLesDpaewrrmZU6QQX2ZdT5ogCysGz
   20.21 +0ioVzicrhCP1u3Cdvy8inxj1u5ZBgG3pPSaMCumPQxqLOpDn/FvAKYt2QVySXgWk
   20.22 +j6gmdDZPyz/dyRb/MgHYCmYiyq6+2FspUhBiw/z1cDnE1v5lEb53nGod1gGwVUje
   20.23 +n0WM41fLA8zQj0U5jm17C5sQu7jOhfLDJcxQlD4WU2N4IY5lOow0JVxCZ/+iNkN/
   20.24 +JbIzl+nT57xcu9ttS8B8/SmASAfBoFU/a8SdKTZWcAoVJgDk560VBY8fszIdRtLi
   20.25 +pOnA7KmlQY8J3Drv2kCfp1WgqersQ1657oVInrkBjQRc2pGWAQwAthqHv8g4K/uT
   20.26 +Y/l8DBBDYSIKNBZ1CTHGF0mYW9QqfCOZNo+4HvMnregVVWJRI1SmewtlFqoe4eVp
   20.27 +WlQZ/yAqqA1KpCZfS5LVzVW3k7MKE1SU8imoCfxWlG+2LG+dfolrAuy2TSlGPIew
   20.28 +ix7GheONohx5LPe4ksJeRDE7/9KtQHgWv3NcJiYd8NXNHxGI8k0Xv1URIWAbJx5H
   20.29 +EZ7PKmSl/hcicbYCpRoeyxcajlBAPKys0vNee6mkvhhvB7zd169XfHMH/15wAwML
   20.30 +H0GocRDHhWaFFFrXJX4HAQwBCU1PXWr02Sa73eNyEd66mBwQnConNA6PkL7eNwzP
   20.31 +2Nmq3tjbiKO7pYhGN/NIEh2QCPRJlUbjnv068JiD8sR06HMVMeaDS1zd29Bt4J82
   20.32 +gi79mzBnhbMyHDrZrnr9cx4kUXDGyLkEG0WlbBhukbMu0t4ZsBuNu22yOJPiqprX
   20.33 +rstFhhIFHTGRK+tvX6HLo60tEIdhN9CjOh9j/KShYyttEEkGdIDZABEBAAGJAbYE
   20.34 +KAEIACAWIQRZmz1ngA2zfi3OBcB/WfA80EoibgUCXNqSlwIdAAAKCRB/WfA80Eoi
   20.35 +bh1TC/96wk38W5QoHEff/k09349xQv1+JwvSiQSyPwaOfFM03tymNhzA/hVTsm5t
   20.36 +qihmSNRRPAyeyIcoBxkDGdr6Kr2cfeOwCroKKGzLuwh4RVc8nnzIIG4NEox+pUUa
   20.37 +V8UvQRBOgsmzedfFHmfAn48VET1hShy8a25XvFS/foRrUO4zPZatLuFbfZFGDWEt
   20.38 +mQeXvxv3w34LTcMwLo6PGLZlj0qX0qkUBP5DM37iG+eVOh5GFmg24NDKFYdoNmyf
   20.39 +w32ThCbE6hsyo18k8jdbJ3mi2Llyl0pU7MTO9VPO1N16aj9dv2G2hg3tvFIXV1r0
   20.40 +t1P2iJ3697is4fmUpt7zNTvuzbt0h4ZSSXXm9mRY0zh6DaBjIvj+k98i3Yo0czY9
   20.41 +uZDsjE3eHD6fZG0Yzg92ifDXlXSkunEBp43ofBDUcZ1Zr4AcioxGd+KUwUt6CLn7
   20.42 +0deDKETnzokYeNt0jgePrz6QvevQnfDlEEXqEo/Hevp5UeGekI18ecN6Pi226NuH
   20.43 +mNc//saJA2wEGAEIACAWIQRZmz1ngA2zfi3OBcB/WfA80EoibgUCXNqRlgIbAgHA
   20.44 +CRB/WfA80EoibsD0IAQZAQgAHRYhBDStBdQm5ExrJdCEb77QsfQcsNxRBQJc2pGW
   20.45 +AAoJEL7QsfQcsNxRq8UL/jxX41nNLc2VJr9HaZwHABnIRmIIay0x65qWw22nF4Aj
   20.46 +d0kPZg6m2oXQTAJqt1gGtFgfiW9s80JQLT+k9UF2VkaL6dfsuo599KWZhHLP0rqJ
   20.47 +0s5aotBxpvs1kbx+DLKC3H/NXIu9G0Jyqwa4KP3y8hleDIBBmdoMNpRdE/CVeUJR
   20.48 +dcBiYQyvbNNVnPGbPXwrOvVsrvDR/rDEMeI3uAalJfsBKnh+HeCUAhbtXqjTd5R/
   20.49 +NwiLNepU/6M1WtHZdt0U/pvd5bZQBd/WcCZRfskpLV8aGTp/7cJ3ObLW0awJ8Hpt
   20.50 +RCHGTNiG5a/O4tfAbkFWkrOPAyoarDLZSdoi6rRDyxTw3W4CamFmbv7XH/iNV1Au
   20.51 +b2J/qiRjnV27/M92ge5xGj+xP5Kv7EBefpCQHpJ3OTBRcAL+5EXdmDZEFXKFyusg
   20.52 +b6asgBbkU7XaeM6CskBY/T3MqKVic4agOdud7GupNSOlxm6hpb9ifYOhsgkUCX93
   20.53 +qZPHaeU19TQ6XWDCZY4DVg3iDACGyeTNbkrkcRQ+5gHETYZQBmByVB2HT9NZ1SvF
   20.54 +yihFKHBnenRxWqabPfFmVRTLxq3HrD+FSeHXvd1/zYP9d8jsedo3bunqEDrUYGGQ
   20.55 +ZddHkhgid6wH54o+CnaPMe1vHOFvhy5P4I2zIJi2WSY3bvz1zFp1imyTCEwMVYI+
   20.56 +AYPdbXqEVrukKaBHgnxRiZlk/ktw4CCZE7dLMiug+dWPdMx+16UfUC6rwZHqrKxW
   20.57 +0CVvVySZLebWXyOsK7ncJL5SQbscQrUsJvkvZ7kOfMMsiSNnghwHJBUW8CQ39XST
   20.58 +Hj8lY32JlUWeGUleQL+qADbqczlW8Jfkygwuz2SzF3Ini2YFkIOOB5/Ka97XLd2E
   20.59 +1yZjwa3Q/E1hOuDbabQvto1LPxHBKGWuaUM4yf6v/H0a3X/rrh/oyVKYTwdc7pRy
   20.60 +izjPSAP03dYJyVUYnUBcTxDt93+/nGLDSUBGcfj75xDQAxMDLyqfmp1qLQUFV4S2
   20.61 +sBvF2C4KRxVt1uzEU6OV2EMZtx25AY0EXNqRpQEMALYv60MAm+OLnGqt8+6ekJrT
   20.62 +8L5DnNrHjKkNiU2P7spTZ50813djtk5ddTnye/YFt4pWqhlVSzmNsB7jRrtdhRKi
   20.63 +pN55yGT0nEsjCy+kuHkTVsYPrtTsWdd9mq+b1vuYpZ4OuI+Y98lx5ZDLhvqz3rwE
   20.64 +56jQvWJHS0O7Ti7mYCBkNdMeYuvmjGEeLG0zE4mRBQiURok/80ZLhH2urV+CRLeS
   20.65 +/6Q296JlGXGra8YTb+D65TgKxyr6P7X0N3NNmA67oljTa5e1s+/Rn0ZqP1JSBOdR
   20.66 +sUX/2qVX8WQAAcrVD+Pxc+g8WR4L5qR4QA/cbKEuacSBj53cwDnFZEOCw577T7E/
   20.67 +diEAEg4yTQtM1vk1Jd4hL7a3703MADUFP0TUJO2EMcLfBovkWT3DUw3CjJoCj3qo
   20.68 +SotsVuk7UcHaTxqTe4K93KxZaRXb/M9GmHdHXNxdYSb+8AMlr2zO3Ht1kNPL0CMO
   20.69 +aq4FZKTb8WGz2ehCxcjbE49l3isHCKZNI0dfbEMQLwARAQABiQG2BBgBCAAgFiEE
   20.70 +WZs9Z4ANs34tzgXAf1nwPNBKIm4FAlzakaUCGwwACgkQf1nwPNBKIm6jJwwAhjrz
   20.71 +hMBozPqmmprEolo2iPZFLBwVqXueIPjQS6YOVaitJxQePNOHpkWJqGaVRpmVlUg7
   20.72 +z0oCsmfLjfQSV6FygdjjFRjbhm14ny1vZeSbYNROSwWVDWB/KoLnC3YFQh4Bjhxq
   20.73 +ORsGvZ6BnWWKEtXyBN2vTCZC8+hGfo6p+WbTbwCnzPWTvuhxqxFC/P9esgBfYzUD
   20.74 +a/qRKggZvecQL+k0ebWeQzUwvTTWgfDaVh+Fl2OB3tt9kI9th46mfw1a6MXQssyH
   20.75 +0Shd1J/cQtAZiZCCnKS41aLUKnMNjrGtMdYjCq6f9WGTqB5tXhYYkMZBCiJBmXaX
   20.76 +R1Vli8ERoZm5GXki9d54Gu1lAZ6QDM6OiKngsknRFAyvQz4zDAHm0olGA4+SIdRT
   20.77 +9iQ6I2NDR/R9kZzuQ/42CiUf8XX/4TzbvU/DhExIEyxN6S8khYaDfsDVoBrKOn4q
   20.78 +F7Lj1PNN1xt0qNxYPy3tbQVnCOD6a0pomCsddt0ANDA4BDMM32UW0FU2Ahu0
   20.79 +=CDai
   20.80 +-----END PGP PUBLIC KEY BLOCK-----