Ошибка при генерации ключа с помощью GPGME

Я пытаюсь сгенерировать новый ключ с помощью GPGME, но, к сожалению, не могу заставить работать следующий код:

 std::string def = "<GnupgKeyParms format='internal'>"
                    " Key-Type: default "
                    " Subkey-Type: default"
                    " Name-Real: Joe Tester"
                    " Name-Comment: with stupid passphrase"
                    " Name-Email: [email protected]"
                    " Expire-Date: 0"
                    " Passphrase: abc"
                    " </GnupgKeyParms>";

            gpgme_error_t error = gpgme_op_genkey(mContext, def.c_str(), NULL, NULL);

            if(GPG_ERR_INV_VALUE  == error){
                std::cout << "Value error";
            }
            if(GPG_ERR_NOT_SUPPORTED == error){
                std::cout << "Not supported error";
            }
            if(GPG_ERR_GENERAL  ==  error){
                std::cout << "general error";
            }
            if(error == GPG_ERR_NO_ERROR){
                gpgme_genkey_result_t res = gpgme_op_genkey_result(mContext);
                if(res->primary && res->sub){
                    result = true;
                }
            }
        }

Условие error == GPG_ERR_NO_ERROR неверно. Действительно, ни одно из условий проверки ошибок не выполняется. Мой отладчик просто говорит мне, что значение error равно 117440567. Инициализация выглядит так:

gpgme_engine_info_t info;
    gpgme_error_t  error;
    const char * CONFIG_DIR = "/";

    // Initializes gpgme
    gpgme_check_version(NULL);

    // Initialize the locale environment.
    setlocale(LC_ALL, "");
    gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
#ifdef LC_MESSAGES
    gpgme_set_locale(NULL, LC_MESSAGES, setlocale(LC_MESSAGES, NULL));
#endif
    error = gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP, NULL,
                                  CONFIG_DIR);
    if(error)
        return false;
    error = gpgme_new(&mContext);
    if(error)
        return false;
    // Check OpenPGP
    error = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
    if(error)
        return false;
    // load engine info
    error = gpgme_get_engine_info(&info);
    if(error)
        return false;
    while(info && info->protocol != gpgme_get_protocol(mContext)) {
        info = info->next;
    }     

    if(error)
        return false;    

Я не получаю никаких ошибок здесь. Я прекрасно могу создавать ключи с помощью командной строки GnuPG. Так что же означает эта странная ошибка при создании ключа с помощью GPGME?

УДАПТЕ:

Благодаря ответу Auges я теперь могу сказать, что это GPG_ERR_INV_VALUE, что означает, что строка параметра искажена. Но почему? Должен ли я разделять значения чем-то большим, чем пробел?

ОБНОВЛЕНИЕ

Я изменил кавычки внутренних

GnupgKeyParms format=\"internal\"

Но теперь я получаю GPG_ERR_GENERAL.

ОБНОВЛЕНИЕ:

Теперь строка выглядит так:

std::string 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: [email protected] \n"
                    " Expire-Date: 0 \n"
                    " Passphrase: abc \n"
                    " </GnupgKeyParms>";

Но приложение зависает на gpgme_op_genkey.


person little_planet    schedule 25.01.2016    source источник


Ответы (2)


Если вы посмотрите на документацию, вы обнаружить, что gpgme_errot_t нельзя сравнивать с кодом ошибки:

... значение ошибки нельзя сравнивать напрямую с кодом ошибки, но необходимо использовать функции доступа, описанные ниже. Однако гарантируется, что для обозначения успеха используется только 0 (GPG_ERR_NO_ERROR), и что в этом случае все остальные части значения ошибки также устанавливаются равными 0.

Тем не менее значение error должно быть равно нулю. С этим я не могу тебе помочь

Вы можете попробовать использовать gpgme_err_code, чтобы узнать, какая ошибка произошла.

person Auge    schedule 25.01.2016
comment
Я обновил свой вопрос. Кажется, параметры искажены, но я не могу сказать, почему... - person little_planet; 25.01.2016
comment
Не уверен, что это поможет, но попробуйте разграничить параметры символом '\n' вместо пробелов. - person Auge; 25.01.2016
comment
попробуйте добавить \n в конце каждой строки, например: "<GnupgKeyParms format='internal'>\n" - person Auge; 25.01.2016
comment
Хм, теперь приложение висит на gpgme_op_genkey... может он пытается собрать "случайные данные" но не заканчивает? Или он ждет ввода пароля? (Я не знаю, почему это было сделано, потому что я предоставляю пароль в строке XML). - person little_planet; 25.01.2016
comment
Зависает на чем? Можете ли вы снова опубликовать std:string в его нынешнем виде? - person Auge; 25.01.2016
comment
Обновлен вопрос с текущей строкой параметров. - person little_planet; 25.01.2016
comment
Хммм... Теперь я потерян. Не уверен, почему он зависает. Извиняюсь. - person Auge; 25.01.2016

Программа остановилась во время генерации ключа, потому что в системе было доступно слишком мало энтропии (это виртуальная машина Debian). Для других, которые могут наткнуться на этот вопрос: вы можете увидеть, сколько энтропии доступно в debian (и других дистрибутивах Linux), просмотрев /proc/sys/kernel/random/entropy_avail. Я установил haveged (доступен в диспетчере пакетов) и повторно запустил код. Все работало нормально. Большое спасибо списку рассылки GnuPG, который помог мне найти это решение.

person little_planet    schedule 27.01.2016
comment
Спасибо! У меня была такая же проблема с зависанием кейгена в Ubuntu 16.04. Установка haveged устранила проблему. - person Jeroen; 21.10.2016