From ab89164be02012f1bf159c971853b8610e966301 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Thu, 27 Oct 2016 18:48:51 +0200 Subject: [PATCH] g10: Improve and unify key selection for -r and --locate-keys. * g10/getkey.c (struct pubkey_cmp_cookie): New type. (key_is_ok, uid_is_ok, subkey_is_ok): New functions. (pubkey_cmp): Likewise. (get_best_pubkey_byname): Likewise. * g10/keydb.h (get_best_pubkey_byname): New prototype. * g10/keylist.c (locate_one): Use the new function. * g10/pkclist.c (find_and_check_key): Likewise. * tests/openpgp/Makefile.am (XTESTS): Add new test. (TEST_FILES): Add new files. * tests/openpgp/key-selection.scm: New file. * tests/openpgp/key-selection/0.asc: Likewise. * tests/openpgp/key-selection/1.asc: Likewise. * tests/openpgp/key-selection/2.asc: Likewise. * tests/openpgp/key-selection/3.asc: Likewise. * tests/openpgp/key-selection/4.asc: Likewise. -- When a name resembling a mail address is given to either --locate-keys or --recipient, rank the search results and use only the most relevant key. This also lets us query which key will be used for encryption using --locate-keys. However, note that --locate-keys may also return keys incapable of encryption, though it will prefer keys that have an encryption subkey. GnuPG-bug-id: 2359 Signed-off-by: Justus Winter --- g10/getkey.c | 205 ++++++++++++++++++++++++++++++ g10/keydb.h | 7 + g10/keylist.c | 2 +- g10/pkclist.c | 2 +- tests/openpgp/Makefile.am | 8 +- tests/openpgp/key-selection.scm | 82 ++++++++++++ tests/openpgp/key-selection/0.asc | 30 +++++ tests/openpgp/key-selection/1.asc | 30 +++++ tests/openpgp/key-selection/2.asc | 30 +++++ tests/openpgp/key-selection/3.asc | 43 +++++++ tests/openpgp/key-selection/4.asc | 18 +++ 11 files changed, 454 insertions(+), 3 deletions(-) create mode 100644 tests/openpgp/key-selection.scm create mode 100644 tests/openpgp/key-selection/0.asc create mode 100644 tests/openpgp/key-selection/1.asc create mode 100644 tests/openpgp/key-selection/2.asc create mode 100644 tests/openpgp/key-selection/3.asc create mode 100644 tests/openpgp/key-selection/4.asc diff --git a/g10/getkey.c b/g10/getkey.c index 5ef5fc3d4..926575ded 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -1461,6 +1461,211 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk, return rc; } + + +/* Comparison machinery for get_best_pubkey_byname. */ + +/* First we have a struct to cache computed information about the key + * in question. */ +struct pubkey_cmp_cookie +{ + int valid; /* Is this cookie valid? */ + PKT_public_key key; /* The key. */ + PKT_user_id *uid; /* The matching UID packet. */ + unsigned int validity; /* Computed validity of (KEY, UID). */ + u32 creation_time; /* Creation time of the newest subkey + capable of encryption. */ +}; + +/* Then we have a series of helper functions. */ +static int +key_is_ok (const PKT_public_key *key) +{ + return ! key->has_expired && ! key->flags.revoked + && key->flags.valid && ! key->flags.disabled; +} + +static int +uid_is_ok (const PKT_public_key *key, const PKT_user_id *uid) +{ + return key_is_ok (key) && ! uid->is_revoked; +} + +static int +subkey_is_ok (const PKT_public_key *sub) +{ + return ! sub->flags.revoked && sub->flags.valid && ! sub->flags.disabled; +} + +/* Finally this function compares a NEW key to the former candidate + * OLD. Returns < 0 if the old key is worse, > 0 if the old key is + * better, == 0 if it is a tie. */ +static int +pubkey_cmp (ctrl_t ctrl, const char *name, struct pubkey_cmp_cookie *old, + struct pubkey_cmp_cookie *new, KBNODE new_keyblock) +{ + KBNODE n; + + new->creation_time = 0; + for (n = find_next_kbnode (new_keyblock, PKT_PUBLIC_SUBKEY); + n; n = find_next_kbnode (n, PKT_PUBLIC_SUBKEY)) + { + PKT_public_key *sub = n->pkt->pkt.public_key; + + if ((sub->pubkey_usage & PUBKEY_USAGE_ENC) == 0) + continue; + + if (! subkey_is_ok (sub)) + continue; + + if (sub->timestamp > new->creation_time) + new->creation_time = sub->timestamp; + } + + for (n = find_next_kbnode (new_keyblock, PKT_USER_ID); + n; n = find_next_kbnode (n, PKT_USER_ID)) + { + PKT_user_id *uid = n->pkt->pkt.user_id; + char *mbox = mailbox_from_userid (uid->name); + int match = mbox ? strcasecmp (name, mbox) == 0 : 0; + + xfree (mbox); + if (! match) + continue; + + new->uid = uid; + new->validity = + get_validity (ctrl, &new->key, uid, NULL, 0) & TRUST_MASK; + new->valid = 1; + + if (! old->valid) + return -1; /* No OLD key. */ + + if (! uid_is_ok (&old->key, old->uid) && uid_is_ok (&new->key, uid)) + return -1; /* Validity of the NEW key is better. */ + + if (old->validity < new->validity) + return -1; /* Validity of the NEW key is better. */ + + if (old->validity == new->validity && uid_is_ok (&new->key, uid) + && old->creation_time < new->creation_time) + return -1; /* Both keys are of the same validity, but the + NEW key is newer. */ + } + + /* Stick with the OLD key. */ + return 1; +} + + +/* This function works like get_pubkey_byname, but if the name + * resembles a mail address, the results are ranked and only the best + * result is returned. */ +int +get_best_pubkey_byname (ctrl_t ctrl, GETKEY_CTX *retctx, PKT_public_key *pk, + const char *name, KBNODE *ret_keyblock, + int include_unusable, int no_akl) +{ + int rc; + struct getkey_ctx_s *ctx = NULL; + + rc = get_pubkey_byname (ctrl, &ctx, pk, name, ret_keyblock, + NULL, include_unusable, no_akl); + if (rc) + { + if (ctx) + getkey_end (ctx); + if (retctx) + *retctx = NULL; + return rc; + } + + if (is_valid_mailbox (name)) + { + /* Rank results and return only the most relevant key. */ + struct pubkey_cmp_cookie best = { 0 }, new; + while (getkey_next (ctx, &new.key, NULL) == 0) + { + KBNODE new_keyblock = get_pubkeyblock (pk_keyid (&new.key)); + int diff = pubkey_cmp (ctrl, name, &best, &new, new_keyblock); + release_kbnode (new_keyblock); + if (diff < 0) + { + /* New key is better. */ + release_public_key_parts (&best.key); + best = new; + } + else if (diff > 0) + { + /* Old key is better. */ + release_public_key_parts (&new.key); + } + else + { + /* A tie. Keep the old key. */ + release_public_key_parts (&new.key); + } + } + getkey_end (ctx); + ctx = NULL; + + if (best.valid) + { + if (retctx || ret_keyblock) + { + ctx = xtrycalloc (1, sizeof **retctx); + if (! ctx) + rc = gpg_error_from_syserror (); + else + { + ctx->kr_handle = keydb_new (); + if (! ctx->kr_handle) + { + xfree (ctx); + *retctx = NULL; + rc = gpg_error_from_syserror (); + } + else + { + u32 *keyid = pk_keyid (&best.key); + ctx->exact = 1; + ctx->nitems = 1; + ctx->items[0].mode = KEYDB_SEARCH_MODE_LONG_KID; + ctx->items[0].u.kid[0] = keyid[0]; + ctx->items[0].u.kid[1] = keyid[1]; + + if (ret_keyblock) + { + release_kbnode (*ret_keyblock); + *ret_keyblock = NULL; + rc = getkey_next (ctx, NULL, ret_keyblock); + } + } + } + } + + if (pk) + *pk = best.key; + else + release_public_key_parts (&best.key); + } + } + + if (rc && ctx) + { + getkey_end (ctx); + ctx = NULL; + } + + if (retctx && ctx) + *retctx = ctx; + else + getkey_end (ctx); + + return rc; +} + + /* Get a public key from a file. * diff --git a/g10/keydb.h b/g10/keydb.h index 35512bb07..6133202e6 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -324,6 +324,13 @@ int get_pubkey_byname (ctrl_t ctrl, KBNODE *ret_keyblock, KEYDB_HANDLE *ret_kdbhd, int include_unusable, int no_akl ); +/* Likewise, but only return the best match if NAME resembles a mail + * address. */ +int get_best_pubkey_byname (ctrl_t ctrl, + GETKEY_CTX *retctx, PKT_public_key *pk, + const char *name, KBNODE *ret_keyblock, + int include_unusable, int no_akl); + /* Get a public key directly from file FNAME. */ gpg_error_t get_pubkey_fromfile (ctrl_t ctrl, PKT_public_key *pk, const char *fname); diff --git a/g10/keylist.c b/g10/keylist.c index 212d77efe..51dc40905 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -650,7 +650,7 @@ locate_one (ctrl_t ctrl, strlist_t names) for (sl = names; sl; sl = sl->next) { - rc = get_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, NULL, 1, 0); + rc = get_best_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, 1, 0); if (rc) { if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY) diff --git a/g10/pkclist.c b/g10/pkclist.c index da4cc0647..eef343797 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -838,7 +838,7 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use, if (from_file) rc = get_pubkey_fromfile (ctrl, pk, name); else - rc = get_pubkey_byname (ctrl, NULL, pk, name, NULL, NULL, 0, 0); + rc = get_best_pubkey_byname (ctrl, NULL, pk, name, NULL, 0, 0); if (rc) { int code; diff --git a/tests/openpgp/Makefile.am b/tests/openpgp/Makefile.am index 5725e110c..75e2fd40f 100644 --- a/tests/openpgp/Makefile.am +++ b/tests/openpgp/Makefile.am @@ -83,6 +83,7 @@ XTESTS = \ export.scm \ ssh.scm \ quick-key-manipulation.scm \ + key-selection.scm \ issue2015.scm \ issue2346.scm \ issue2417.scm \ @@ -124,7 +125,12 @@ TEST_FILES = pubring.asc secring.asc plain-1o.asc plain-2o.asc plain-3o.asc \ tofu/cross-sigs/871C2247-3.gpg \ tofu/cross-sigs/871C2247-3.txt \ tofu/cross-sigs/871C2247-4.gpg \ - tofu/cross-sigs/README + tofu/cross-sigs/README \ + key-selection/0.asc \ + key-selection/1.asc \ + key-selection/2.asc \ + key-selection/3.asc \ + key-selection/4.asc data_files = data-500 data-9000 data-32000 data-80000 plain-large diff --git a/tests/openpgp/key-selection.scm b/tests/openpgp/key-selection.scm new file mode 100644 index 000000000..536f60773 --- /dev/null +++ b/tests/openpgp/key-selection.scm @@ -0,0 +1,82 @@ +#!/usr/bin/env gpgscm + +;; Copyright (C) 2016 g10 Code GmbH +;; +;; This file is part of GnuPG. +;; +;; GnuPG is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3 of the License, or +;; (at your option) any later version. +;; +;; GnuPG is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, see . + +(load (with-path "defs.scm")) + +;; This test assumes a fixed time of 2004-01-01. + + ;; Redefine gpg with a fixed time. +(define gpg `(,@gpg --faked-system-time=1072911600)) + +;; We have a number of keys for Mr. Acejlnu Acdipr . +(define mailbox "acdipr@example.org") + +;; The keys are sorted, from the least relevant to the most relevant +;; key. +(define keys + '(("ED087E9D3394340738E20A244892A3CF8F65EBAC" + "no encryption-capable subkey, created: 2003-11-30, expires: 2006-11-29" + 4) + ("D7388651A1B7466D03B538428178E04B0BAA385B" + "encryption-capable subkey, created: 2000-12-31, expired: 2001-12-31" + 0) + ("DDEF1BEC66C8BAC8D69CED2AEABED840EC98B024" + "encryption-capable subkey, created: 2001-12-31, expires: 2006-12-30" + 1) + ("03FCFEDE014027DD897AD2F23D32670A96A9C2BF" + "encryption-capable subkey, created: 2002-12-31, expires: 2005-12-30" + 2) + ("B95BD6175CB6339244355BA160B8117E6119CED6" + "encryption-capable subkeys, last created: 2003-05-31, expires: 2005-05-30" + 3))) + +;; Accessors for the elements of KEYS. +(define :fpr car) +(define :comment cadr) +(define :number caddr) +(define (:filename key) + (in-srcdir "key-selection" + (string-append (number->string (:number key)) ".asc"))) + +(define (delete-keys which) + (call-check `(,@gpg --delete-keys ,@(map :fpr which)))) + +(define (import-keys which) + (call-check `(,@gpg --import ,@(map :filename which)))) + +(for-each-p' + "Checking key selection" + (lambda (set) + (import-keys set) + (let ((fpr (list-ref (assoc "fpr" + (gpg-with-colons `(--locate-key ,mailbox))) + 9)) + (expected (:fpr (last set)))) + (unless (equal? fpr expected) + (display "Given keys ") + (apply echo (map :fpr set)) + (echo "This is what --locate-key says:") + (display (call-popen `(,@gpg --locate-key ,mailbox) "")) + (echo "This is the key we expected:") + (display (call-popen `(,@gpg --list-keys ,expected) "")) + (error "Expected" expected "but got" fpr))) + (delete-keys set)) + (lambda (set) + (length set)) + (filter (lambda (x) (not (null? x))) (powerset keys))) diff --git a/tests/openpgp/key-selection/0.asc b/tests/openpgp/key-selection/0.asc new file mode 100644 index 000000000..d40a98be7 --- /dev/null +++ b/tests/openpgp/key-selection/0.asc @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBDpPvC8BCACqDbU+2znCURAocNMmcwCSYVl5l4Zbx6jcy9ON7y12Ai7CRSbX +8Nb8kggit02pNFtb1l2NKad7DqR1f/WPqkQjZ6rvFHKEOsupqrUhpQ6dU3H94wuO +g4M2PGsaxKAcw24qIoKkTotecLgUFMhduIq7u8kTnalTOW1o/18moVuoVNkDdO4Y +I7n/dloVNv5Xkm5bS4VBdvUzJ9gvbqkynud/L6pSFeng0vVJQMN3tVbApcNzhLBs +G5Fvf9Rve4V8xTeBYQ+VRO7H9nvaS8YFf07kTwUDS69Vs8qIaLKOQJL3F75CileN +K7fb9OC3J4PNF0CDz+e2KkRRF6Q/xS8KXF9rABEBAAG0I0FjZWpsbnUgQWNkaXBy +IDxhY2RpcHJAZXhhbXBsZS5vcmc+iQFUBBMBCAA+FiEE1ziGUaG3Rm0DtThCgXjg +SwuqOFsFAjpPvC8CGwMFCQHhM4AFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQ +gXjgSwuqOFt7Lgf8DFDVQ4JykT8njX0+JkemSL2UUDH2iVRWkU6tKZPGneEnQGMm +iRfSX0im0pFHWxJ0vZsmUNq33Vr2sbvppT8Ti1rBx4TrdZ7PSEIEi1KTVSx6GKjr +2ObCax2u1p+u+tC35GfhV1Y1pUcSZXc45C1o259ivekRJY/fw9DrvR7154S3ygjp +lkEM4PC33216XMTqUG1sAWw40aDtKaiyp5J8zqLKXXjCnZsTWdj4uxB7E5WPjaEF +ylON/h+Hfw2RMzlYRGTbUu2G/Ma0TiycGJvT78myCpnc5akcKVZu1Wu4VDBqBC1N +dVcTzhJ5T4gwFCWHif3/MYqTVBnZSAVURtI3V7kBDQQ6T7wvAQgAuF5JaVAE9/Vv +K1U+VSAAhWMGSp6fwezgWdj0rn1GBx3DtqQkYXoLRjTrlBf1qOO6NPbBUi1gz8R+ +IQTHsesIXiUSlMige3/HxdSOsbzKipm1SGJedqUz3H03+yfr82NT+QvQmlEGX9k6 +goPY9t3r+O3F6ab4mc5NxFKhj2XvbRyf8I9J+3w6zXBWwsgLHacTCa13zGz6B0NH +dCk/2B6HTJeIJWpHdALQXp0/JcKWksw0Hsihpdu0QploUSPihZostRUKszOkugeu +W0t3fmt6on4fIFWveh9NSVDYIHKVMRU8cl5vRXNNRTsYQOarIvjmoUHv5u+UpZcc +iE/7wILNhQARAQABiQE8BBgBCAAmFiEE1ziGUaG3Rm0DtThCgXjgSwuqOFsFAjpP +vC8CGwwFCQHhM4AACgkQgXjgSwuqOFv9GAgAkACyK3Km4jFBqw7ah2xMxWCkdpgu +DdTi64ra6GyMQk/Lem8DzBO/ER/cavV9lg61qCOy7ecCNs7MhPiWZIod2bcV3JDZ +AglnGgTQ+lSpPXFCk3eoRktRsXesgQ1dE30uR9pypEqZ0BYNZZ2G2hRqAnRgUOOI +7THmf/X5w5KPKLlm3zOlGQomFy6lfOR9Zd5/QoKRNmuD9gNfSE+3vBvr+ISQPIev +Ch2qeC/N0BP5EoVE4SXp8l2oaaVJLi/Yx2J6vfximeeaBPxsKjuA+GJu6IIhegnY +X4kCxWStla+KuN0p0iNUh002pKybISuqyI9vgImH9Nh22Nf7mcRQWflR6A== +=nyjX +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/openpgp/key-selection/1.asc b/tests/openpgp/key-selection/1.asc new file mode 100644 index 000000000..fea379c16 --- /dev/null +++ b/tests/openpgp/key-selection/1.asc @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBDww7w4BCADCvhkDDCAAtDpLCUa2ryPqWxlSSVKdyY9ecqjgEswijsZ+2T6O +Xr/50POpLbW9IWvHdvcifXUk1YZg8wLcnVIMwiZsdNSDM3MycoPoNc7pL5MaPGL6 +e9u+8HWX6aowOo5st6Y57HUeaKReH1Peb0avoEUIE9l4xqVx41AYrKViS7Zp5p9A +67thNKMisZ8aYutlhmVQB/uDO7XiKal07vjftf6aZazNBC5ZBOj4G+/TLcKMox8h +AaUJTkqsJcSCZTc7cMVjikmWItgKm6wIceGTpUGSvvZ3TnWUtgq3ivaMQrpyN3RT +tVM5uO2Mh8Uzkq9YWh2V7IT+jGKztrpdPKu3ABEBAAG0I0FjZWpsbnUgQWNkaXBy +IDxhY2RpcHJAZXhhbXBsZS5vcmc+iQFUBBMBCAA+FiEE3e8b7GbIusjWnO0q6r7Y +QOyYsCQFAjww7w4CGwMFCQlmAYAFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQ +6r7YQOyYsCT0awf+NENO1grzmRfsyl8ODREmUlnnUAaRiZGQ0h+JkooXiwcm/p5O +DupjRc5OLluDtnjTLMBwNk5ysX6yqSNTni9qCCpm62PaIopG+r8RyFPp4aRjR1Q3 +mbwHkKifLRBxDxeCDKdrqFs7hkVCYOxjyiaEZ2BYogqFDwHFoiE6UwQvwZfpNWex +4Zx8nhoGpcegMMEiGREWCTi0H+zJrYOiVzV2jPQF5lkFkwYMQKNaNQv3L5v2/5AC +Nu6Kej+oYcw/EA+o3OXYLxwa+tijfKqUxtndFsQS/lYSUNszxrcm7dOAx52DCMpC +8MNHmwe3qmofO6G9svqG02bIZTdyJBob5nNBD7kBDQQ8MO8OAQgAttn9ru3Ou6+A +lAqbV7fAbpdeIF5bHy/QZtLxa2dpG8BTOXDcoMp9MUyKjafHbNr+z5unqqTfduXy +oRdJ1D/iXbSpcRkMKRJz4fa+uPNN5SiGzrjxHTcALPG8ctTUvdNrV+Z5VkssU+FW +LQD+s5SQWn848kYTacrDL22JshIpekmz3ztDoNGOZxVj2DwF/QXDeaRhXT9ngB3c +PY8x7e8yIvmAcg8olt9rKTpkGXZHWAyBpyGzBJkxM+wfiNreGMNUkv41G/R4d1Lv +xMlGF05xrBJX9YrV1pRM+EdS4WOs2gvFT3qnBzFAQBZ9nqaLAFVxw0Sl7C+wSQPk +7ZPIKYANFwARAQABiQE8BBgBCAAmFiEE3e8b7GbIusjWnO0q6r7YQOyYsCQFAjww +7w4CGwwFCQlmAYAACgkQ6r7YQOyYsCSDdwf/an06WTTAIwHj8PfXIkywnq3SWfSZ +yuRaFaDan9en8xAfyw2smNnrHnTk86CZWL6yPTij6JZYynv4OxtSafIoT9LxT7uX +VpEtSBpTnnojlHFivfRYMGJ9k/EXGgb941W2DTbvQqzafc2u4K3u8KnFOgzfEj5B +qjYzbt/L2uR2PLOAfYIUYzqTKjdzvSIX2DRvkepHhTwRbCjJrkF/zx0IXFoJeU/k +6tYK6cNNCFTWT0uLJCflAZMtGpf4KDvjlccNts3mZQbEov+Dymj/nZ9JRgjc2heH +Pxi5muPMQ8jAc2i4V8vTybozlZ5O/+JkOOOH0ciLpD3buhgYBY309DIVmA== +=zVE+ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/openpgp/key-selection/2.asc b/tests/openpgp/key-selection/2.asc new file mode 100644 index 000000000..4b697f77a --- /dev/null +++ b/tests/openpgp/key-selection/2.asc @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBD4SIdsBCACqRRWUd9mwgRzVzaDbVLRdNOdyswPYuBKWlHI6Yx0lpfiQK6/X +rnRoR18lYJ0wBqImd/BJbjNE4bYaMUd+p7HzYIKzv8/DuvZQgovt9VIBn+a3YyCa +hdAaWEz994fjl8U5IGbrrGuV4XXlFATA6S7KX7CgxgiK/jVnRl1NVcTjOSnasU2J +LIbh0lawUe0b3HlwT8uFGg/MK3vHGGIalOJRlgeTBAF7zcaTfqoDiAXbbsfaxT4a +zB1OTRut1VOGBLWCsr09VCAMyz8awQqF81uG6cuv9swo76SuTiMcMMBfdNw3etVa +kLgL4JnsnMGM7c1fx/mfMUIUHYndDVT5LzQjABEBAAG0I0FjZWpsbnUgQWNkaXBy +IDxhY2RpcHJAZXhhbXBsZS5vcmc+iQFUBBMBCAA+FiEEA/z+3gFAJ92JetLyPTJn +Cpapwr8FAj4SIdsCGwMFCQWjmoAFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQ +PTJnCpapwr/bGAgAjGWQ3F9RUpeI3ogLLhGMsXmsOxZX1ptNtjL9HiDsrUY5XCS1 +7vZUpRz0/2nscbu7or6Xy8yZtG0vLXwfzeOvHQz/F8tnzruIWBFSAU8WBidxKxmC +AUlQWg6bAp0aTxyyVi/r719J6k/G/ZOhjgXM243Ck9HNnY2a0h0ArKzPo56N8Cks +caXshdWxIh3M9uJKSxBCxfDTtqPcU7LjNApaUOFphpAPT9ypE/Zw9BZNTVN6vILr +I7upnG5PNXybMCDh2XhpXS2E5/rY9Y3/aFKthBws16JMAzBRKMQqWTTC9a8X+4pa +KcNtQih3X9eRzj4JBAh6cl5qXIbz+32EzXA8drkBDQQ+EiHbAQgAz017pYsm9Sf0 +z5HqOQLx1dwCclzVE5RhvI+qplPT5e9sLG+trbOVpGM6fjWAK/yuxaUJibm/44UX +cxsTuR7gpAwc+gvwrF3cG6kmT+g4kZ7/I4EyBMZjM9lhlIk77MCTLXcT9ONr7Pm4 +flQO+vM6ZYRFm7DtSHzP2z2Uu9USqgLJumn+V61xQXYj3E2ORczOV3blPVUoI7gl +aRnVdveEqrucw+miRWq3clykTdbuP39H2nRgY0KXGbOefWh5dRe2okxL5nlhINGL +lOyj9n4jM6fNp9K8jWeg8YJ7tKRsffrrNnIovslNlkXucYAzM2OveP+JxDdtosSK +fzWtUSzrmQARAQABiQE8BBgBCAAmFiEEA/z+3gFAJ92JetLyPTJnCpapwr8FAj4S +IdsCGwwFCQWjmoAACgkQPTJnCpapwr+p6wf/cO8apRVlpRrI2q92j5DJ0IQsBdUv +Srvp3w8UHZad0VkhgT+edbYHN8VS245ckyWoUBB78XEvxayMF1/Mx0N+u1MOM1dY +MrAiwbaQnE99yjifwVzZz6wJuJ94MMzWw38j22ZTbIBHPh/4nzSl84sN+KuEcP4f +C2h7mat4NDO/VRTf7xWuLInS5yGdDOACwROd85ua4YNxo54s5mcd6BVr4upHd1Hj +0TULgmWvqz49N40VY4GF+38OAC7+DSsdamHVNdTb0fT+KaxTQ0K5BCl+7Oe66CqH +RWxaXRUD4YMRh1jdgc+j4D3Sj4xhevu0Kd6+7BWxmxWZKdOCiu9TEDBjrg== +=YqE5 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/openpgp/key-selection/3.asc b/tests/openpgp/key-selection/3.asc new file mode 100644 index 000000000..ab2ff73ec --- /dev/null +++ b/tests/openpgp/key-selection/3.asc @@ -0,0 +1,43 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBD4SIZsBCADMR5w2TF16C1WaP+EIq+pg3InbyKr3VlGgxl2t/+PcRUmxhOh4 +zAs+k/FaKqH+h8JLGT6VlUMqKDqBrHhwVNz5nEYO/HeqaSsHjyNoIr4tS3oJMQWI +0QsRV8cPhlPHXQBS8K2KC7MfTyHIbfagjqakegY9ysZ2N6Qt3I3QSqO0khRHoNtZ +x8l/NHA9u8lRJD1OhfOg8gcY9800LPJbdzmyeOK5ezwyvjp6dXKNgXnwkrHQw7pD +hGITTRtNsRb0xF9e+1X6KRifk/ppJZjk3Lu8AJEyj6AfHZru6lYfv4LP77IW9Lw2 +x7pRwrMNtvffAOGGa4KYiVstgIaPmEm9v2UjABEBAAG0I0FjZWpsbnUgQWNkaXBy +IDxhY2RpcHJAZXhhbXBsZS5vcmc+iQFUBBMBCAA+FiEEuVvWF1y2M5JENVuhYLgR +fmEZztYFAj4SIZsCGwMFCQWjmoAFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQ +YLgRfmEZztapKAf/US2OkiyDX4D7cRrifnbkMj5YdHjiirqgd5Q9nhWIC/Pk494u +WDMt0XBeHk8aPp6NjQCMpWu8d9TxLCn43dI2eFRLKSk/9nUb3nPzIrtT8/dPEsvG +HEAJKxGMpZLu2UIDIpn2XY+9pS8CB03xVfuAfYrGOmVJS5rr6a592WfCB6XosHO1 +S2iKnMWgmo5C2WJaOq0AL5fzI6w1TAYN10KHFdNdimWJZ85WKk3iRXDUF4PJusWt +PLPHOgbvAMBHtJHu+09DlcoBRyWRvEzXHoBsgm76kvkLpkP23FhuWexfK6qJ+pZG +Ygaw2fGACGi9W7aASaiR5+PcD5WSPaOT2PuyRLkBDQQ+EiGbAQgA0Zt9F5Xhv1wf +zdvuXZeEaX/0uq3T/5IXcP0cjMzylWS3caRd8AB6S6+0NZDrAuO8jbzKuBdVb3so +zhq2g4uPkzCq9QkLwSJDURAstA/w6yV/h83DhEvmhE5MceY57Ev1g+cF3ec9Sshv +MQBPicXw6Umv8fyjmW6LIEXpNeXjz52hyjVk39EzEYFf8+ozC1Ifn5H1NWOnCiBc +5Q4Ud4W26xItyW1bBXWaMR520fotj6wSAX1Al2ynzvZ31RQUgBmm9aiwRKKXC4CW +6E6uDCBKL/Gpebc2Ty8fpJmCFtTByh0M7eeBfCDPTODPS39WjxwxbgIIHMDyXogW +D+Por5jYiQARAQABiQE8BBgBCAAmFiEEuVvWF1y2M5JENVuhYLgRfmEZztYFAj4S +IZsCGwwFCQWjmoAACgkQYLgRfmEZztbhGAf9GHVPYO7qsZkM5RnPRYAZLQGY9ygP +Wac2hX10UVOVFMgd8XVdoRMqj8LHyaf6UrdI6/3lNza2cnleskjxzaNbk9ENhyYs +/KSAyL6JbuZhEZ9Cx77RKRfbG+Z5EIrymgG0+HZuS8XZbJTze0kvQc90Avn78rNa +ta4VB7U6ID0BwbBq4ikeJFJ2si87ZUiVUbFihVCk39HyJMXdDeUJPELi6Z2Rkmov +0fwB1/QaSCvr41zQ1gCLpWC9x6tbas/4DsI0O2XG5W7XGIBt1NnaHMwgHr1Rw2JU +Df6q+bEEiXP4ZsnoeUYi7Q7LU55fn5zsLj8DF2eACSiN+f5emZkZT4wV2bkBDQQ+ +2SXpAQgArTgU5baUzto+s/aEp/z87F7jxeFXTUTgIglHUHvc5oAj59TgZf+6C4t2 +uY6DGST3u2XCRs7FK3iZjvzfEVyDYQd8V/Iew8oeHy2aGmWFbDuZa+8RWWGJ8wfv +V3pCm+86HIzfbqgJ3B3WnIhMqrBvGSlT0oYDVYIDZDbYYnIYNhF5xo/hH1WB9Ul6 +7Mx/KPUTqa2O1Pio7mFy0xFb12+5y5g3PruEG+mM3RLqZug3Z5M3E7gEG2HCnNjQ +CzjICJe9wwOzkoKJLogCEZ2iYhl2DcThxWtOu/EaU3b+iothX0HdO3azMc3v3tcX +t4q/fLUqmJ+P/HVlJtuPKSwnCHHVzwARAQABiQE8BBgBCAAmFiEEuVvWF1y2M5JE +NVuhYLgRfmEZztYFAj7ZJekCGwwFCQPCZwAACgkQYLgRfmEZztZv9wf/Q8HacUDx +AUJXfx/BfK/4zgogDfotz9yaFMmJYob2Mx/ny1Gteh551U5byuyoJW3gENg8Ql6v +s7uSfLAbk2qXYAdApbo1pcYmb5Rd2oDU3+1JONNHs096ZjJLD2WHxTnzWVLMDsPV +cUka+trg8Z1hqw6uGJmu6InggNjZ++1B6aa63Zdu7BudJB/3oWpjXyV7FqU4RtYa +sYN/lmGcir0704yfqRbVcP9fU5kYB17qiNJRtblDjImiiFHJ0PSxpmYU3lDIf1Rf +AC/HXoUetx9PKV1J8EKMQhV/GFa5FbmBCwXcIEj/Z9YEjSK2t9Pw0k0EuKhl7eHp +vlWlPNIJSTq1Bg== +=rf5l +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/openpgp/key-selection/4.asc b/tests/openpgp/key-selection/4.asc new file mode 100644 index 000000000..6a0ab9b5d --- /dev/null +++ b/tests/openpgp/key-selection/4.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBD/KdpABCAD2wlP1kYHldknjyGTnMOUq9r+3/fJR8n4qVt5TRRlDdyfK3ZxM +KWStsmkZuK9dMxo4VSOjVeiXdZlHeQU7RlzVPsCNiJ1Qc2HDgHFdmT7eUgOILA12 +36bueRUwVPGmrBEecs0TpNRQ5CVFbO7mC6cTLhT9nRMd+W+BSuuZ8Zm98ebaVh3I +ml3nPEVhs1UFmIop48RGCt45MZ2mYp77kuAmk8NBJjHy9J4H5UK19r0hla2WY4a3 +Z59hh7kFnNFCM/MhPxd6GwkeXzUF7WSnhzRVIkdv81u2AnIHbo1zD0BUp8Rf64Ns +3iFAeB1VuR6ZJpEypHiHUJtYPmr9okEmg8EDABEBAAG0I0FjZWpsbnUgQWNkaXBy +IDxhY2RpcHJAZXhhbXBsZS5vcmc+iQFUBBMBCAA+FiEE7Qh+nTOUNAc44gokSJKj +z49l66wFAj/KdpACGwMFCQWjmoAFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQ +SJKjz49l66xZ7QgA7dBJsQP09LhkYDIu8cJzRU6tqa2Y8dx0iFaCU8nqD/0q6xJf +fs2euwMEPsHWmA1WwGwxZpE/NGEksMSQ8TZSQUwCsURxBIiGww5MBtIGeO3ZzreR +Dn0Qhivbiup8ZPtPfFFomoK7ZtWjtGjZ8I5zyYbjT0eEB7P348dkpOtReWDiqGVd +taMnVau4OTDqTRo6fvAiVb37zoaWETsPWtq/TymgkqO/LEhzClzG8xJgpSl98cQW +BoHz5GDVYeVxPEKAN4DdS7gt0KTUC9ZQUcZP+1wTzFohDd/CeUAl4kTeP0QSJVJ3 +QC/WnHk4Y56q8/nngIY6w/wID/R/Cp+plw6F5w== +=BA1F +-----END PGP PUBLIC KEY BLOCK-----