Key generation with GPGME and GnuPG hangs at gpgme_op_genkey
Robert J. Hansen
rjh at sixdemonbag.org
Wed Jan 27 15:42:54 CET 2016
> Yes, that was the problem. I installed haveged and it worked. But it seems
> that the key generation in my C++ application will not work, if a custom passphrase
> callback is set. The key generation code is unchanged, but with the callback I get an
> GPG_ERR_GENERAL error. The init and callback code is as follows:
I cleaned your code up a bit and it works fine.
Compile with:
$ g++ foo.cc -O2 -o foo -std=c++11 `gpgme-config --cflags --libs`
or
$ clang++ foo.cc -O2 -o foo -std=c++11 `gpgme-config --cflags --libs`
#include <string>
#include <iostream>
#include <gpgme.h>
#include <clocale>
using std::string;
using std::cin;
using std::cout;
using std::cerr;
using std::getline;
static gpgme_error_t passphrase_cb(void *hook,
const char *uid_hint,
const char *passphrase_info,
int prev_was_bad,
int fd)
{
string passphrase { "" };
size_t written { 0 };
cout << "Enter your passphrase: ";
getline(cin, passphrase);
if (passphrase.empty())
return GPG_ERR_CANCELED;
while (written < passphrase.size())
{
ssize_t bytesWritten = gpgme_io_write(fd,
&passphrase[0] + written,
passphrase.size() - written);
if (bytesWritten == 0)
break;
written += bytesWritten;
}
gpgme_io_write(fd, "\n", 1);
return GPG_ERR_NO_ERROR;
}
int main()
{
int rv = -1;
gpgme_ctx_t mContext;
gpgme_engine_info_t info;
gpgme_error_t error;
bool contextInitialized { false };
const char* def = "<GnupgKeyParms format=\"internal\"> \n"
" Key-Type: default \n"
" Subkey-Type: default \n"
" Name-Real: Joe Tester3 \n"
" Name-Comment: with stupid passphrase \n"
" Name-Email: joe3 at foo.bar \n"
" Expire-Date: 0 \n"
" Passphrase: abc \n"
" </GnupgKeyParms> \n";
gpgme_check_version(nullptr);
error = gpgme_new(&mContext);
if (GPG_ERR_NO_ERROR != gpgme_err_code(error))
{
cerr << "Couldn't create new context.\n";
goto BAIL_OUT;
}
contextInitialized = true;
error = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
if (GPG_ERR_NO_ERROR != gpgme_err_code(error))
{
cerr << "GPGME doesn't support OpenPGP.\n";
goto BAIL_OUT;
}
error = gpgme_get_engine_info(&info);
if (GPG_ERR_NO_ERROR != gpgme_err_code(error))
{
cerr << "Couldn't get engine information.\n";
goto BAIL_OUT;
}
error = gpgme_ctx_set_engine_info(mContext,
GPGME_PROTOCOL_OpenPGP,
nullptr,
nullptr);
if (GPG_ERR_NO_ERROR != gpgme_err_code(error))
{
cerr << "Couldn't set engine to OpenPGP.\n";
goto BAIL_OUT;
}
gpgme_set_passphrase_cb(mContext, passphrase_cb, nullptr);
error = gpgme_op_genkey(mContext, def, nullptr, nullptr);
if (GPG_ERR_INV_VALUE == gpgme_err_code(error))
cerr << "Value error\n";
else if (GPG_ERR_NOT_SUPPORTED == gpgme_err_code(error))
cerr << "Not supported error\n";
else if (GPG_ERR_GENERAL == gpgme_err_code(error))
cerr << "general error\n";
else if (GPG_ERR_NO_ERROR == gpgme_err_code(error))
{
gpgme_genkey_result_t res = gpgme_op_genkey_result(mContext);
if (res->primary && res->sub)
{
rv = 0;
}
}
BAIL_OUT:
if (contextInitialized) gpgme_release(mContext);
return rv;
}
More information about the Gnupg-users
mailing list