over on https://lists.gnupg.org/pipermail/gnupg-devel/2017-June/032926.html, i wrote:
the documentation for gpgme_op_import_keys() (in "info gpgme") describes this function:
- Function: gpgme_error_t gpgme_op_import_keys (gpgme_ctx_t CTX, gpgme_key_t *KEYS)
And it says:
The function ‘gpgme_op_import_keys’ adds the keys described by the ‘NULL’ terminated array KEYS to the key ring of the crypto engine used by CTX. This function is the general interface to move a key from one crypto engine to another as long as they are compatible. In particular it is used to actually import and make keys permanent which have been retrieved from an external source (i.e. using ‘GPGME_KEYLIST_MODE_EXTERN’). (1) Only keys of the currently selected protocol of CTX are considered for import. Other keys specified by the KEYS are ignored. As of now all considered keys must have been retrieved using the same method, that is the used key listing mode must be identical.
Even reading the footnote (which says "(1) Thus it is a replacement for
the usual workaround of exporting and then importing a key to make an
X.509 key permanent."), it's hard to tell what any of this means. It
looks like it means i am encourage to take a key listing from one gpgme
context (e.g. a gpgme_key_t object extracted from
gpgme_get_keylist_next(ctx0) or gpgme_get_key(ctx0)) and feed it into
But in practice, looking at src/engine-gpg.c, if i use the
gpgme_op_import_keys() form (instead of the keydata form), the backend
actually uses --recv-keys on the importing context. This doesn't work
at all if the keys are not on the public keyservers, or if the local
host is offline.
And even when keys are on the public keyservers and the local host is
online, in the case where the two contexts may have specialized
knowledge of the OpenPGP certificate (e.g. non-published certifications,
freshly-generated subkeys, etc) it has particularly strange failure
cases -- it'll result in different OpenPGP certificates held by the two
Additionally, using the keyservers for this represents a metadata
leakage, without any warning to the user that such a thing is planned.
Finally, Its final paragraph says:
The function returns the error code ‘GPG_ERR_NO_ERROR’ if the import was completed successfully, ‘GPG_ERR_INV_VALUE’ if KEYDATA if CTX or KEYDATA is not a valid pointer, ‘GPG_ERR_CONFLICT’ if the key listing mode does not match, and ‘GPG_ERR_NO_DATA’ if no keys are considered for export.
The mention of KEYDATA seems like it might be a copy/paste issue, since
there is no KEYDATA in the function signature.
Justus confirms that this is problematic, so i'm recording this here.