2015-06-12 3 views
9

Использование gpgme (библиотека разработки для gpg/gnupg), я пытаюсь подписать некоторые данные. В ключевом кольце у меня есть более 1 закрытого ключа, поэтому я хочу правильно выбрать . Это не удается: «Необязательный секретный ключ (117440566)». Ключ был сгенерирован с помощью самой gnupg2. При использовании gnupg проблема также возникает.gpgme: выбор секретного ключа при подписи данных

sec 1024R/14B7E8E6 2015-05-27 
     Key fingerprint = 95C7 6C5E F839 43DA 2F32 2CF4 D2C2 5144 14B7 E8E6 
uid     testkey2 (testkey2) <[email protected]> 
ssb 1024R/ED8059EA 2015-05-27 

pub rsa1024/14B7E8E6 
    created: 2015-05-27 expires: never  usage: SC 
    trust: ultimate  validity: ultimate 
sub rsa1024/ED8059EA 
    created: 2015-05-27 expires: never  usage: E 
sub rsa1024/74D6F5C6 
    created: 2015-05-31 expires: never  usage: S 

Сначала я проверить, есть ли секретный ключ для ключа отмеченного:

gpgme_op_keylist_start(..., ..., 1); 
if (gpgme_op_keylist_nex() == GPG_ERR_NO_ERROR) { proceed } 

сделать подписание:

gpgme_new() 
gpgme_set_pinentry_mode(GPGME_PINENTRY_MODE_LOOPBACK) // yes i installed v2.1 
gpgme_set_passphrase_cb() 
/* ...binary to gpgme_data_t... */ 
gpgme_data_set_encoding(GPGME_DATA_ENCODING_BINARY) 
gpgme_signers_clear() 
gpgme_signers_add() // <- that key that I checked for existance earlier 
if (gpgme_signers_count() != 1) { fail(); } // sanity check 
gpgme_op_encrypt_sign(ctx, recipient, GPGME_ENCRYPT_ALWAYS_TRUST /* FIXME */, data_in, sig); 

Теперь, когда gpgme_op_encrypt_sign всегда терпит неудачу с этим «непригодным для использования секретного ключа (117440566) ". Любые советы/подсказки?

версии программного обеспечения:

gnupg 1.4.18-7 
gnupg-agent  2.1.4-1 
gnupg2 2.1.4-1 
libgpgme++2  4:4.14.2-2+b1 
libgpgme11:amd64   1.5.1-6 
libgpgme11-dev 1.5.1-6 
python-gnupginterface 0.3.2-9.1 

Я включил отладку трассировки, но это не помогает мне много:

<0x1927> gpgme_debug: level=4 
<0x1927> gpgme_check_version: call: 0=(nil), req_version=(null), VERSION=1.5.1 
<0x1927> gpgme_check_version_internal: call: 0=(nil), req_version=(null), offset_sig_validity=60 
<0x1927> gpgme_set_locale: enter: ctx=(nil), category=0, value=C 
<0x1927> gpgme_set_locale: leave 
<0x1927> gpgme_set_locale: enter: ctx=(nil), category=5, value=C 
<0x1927> gpgme_set_locale: leave 
<0x1927> gpgme-dinfo: gpgconf='/usr/bin/gpgconf' 
<0x1927> gpgme-dinfo:  gpg='/usr/bin/gpg2' 
<0x1927> gpgme-dinfo: gpgsm='/usr/bin/gpgsm' 
<0x1927> gpgme-dinfo: homedir='/home/folkert/.gnupg' 
<0x1927> gpgme-dinfo: agent='/home/folkert/.gnupg/S.gpg-agent' 
<0x1927> gpgme-dinfo: uisrv='/home/folkert/.gnupg/S.uiserver' 
<0x1927> gpgme_new: enter: r_ctx=0x7fff5afd07a8 
<0x1927> gpgme_new: leave: ctx=0x20c0810 
<0x1927> gpgme_op_keylist_start: enter: ctx=0x20c0810, pattern=0BF38589, secret_only=1 
<0x1927> _gpgme_add_io_cb: call: ctx=0x20c0810, fd 4, dir=1 -> tag=0x20c26b0 
<0x1927> _gpgme_add_io_cb: call: ctx=0x20c0810, fd 6, dir=1 -> tag=0x20c2800 
<0x1927> gpgme:gpg_io_event: call: gpg=0x20c0c10, event 0x7fd8b1a20ad0, type 0, type_data (nil) 
<0x1927> gpgme_op_keylist_start: leave 
<0x1927> gpgme_op_keylist_next: enter: ctx=0x20c0810 
<0x1927> _gpgme_run_io_cb: call: item=0x20c2820, need to check 
<0x1927> _gpgme_run_io_cb: call: item=0x20c2820, handler (0x20c0c10, 6) 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c0810, key = (nil), line = sec:u:2048:1:CC73A8A60BF38589:1433443717:::u:::scESC:::::: 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c0810, key = 0x20c2850, line = fpr:::::::::20CD3FF80DA6C1E46CD9F135CC73A8A60BF38589: 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c0810, key = 0x20c2850, line = uid:u::::1433443717::9963CFDE0C8920AD077B06A281992C4008E67E4F::testkey3 (testkey3) <[email protected]>: 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c0810, key = 0x20c2850, line = ssb:u:2048:1:22317805D48C1491:1433443717::::::e:::::: 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c0810, key = 0x20c2850, line = fpr:::::::::FB6FFB7D8BEC710A745DE86C22317805D48C1491: 
<0x1927> _gpgme_run_io_cb: call: item=0x20c26d0, need to check 
<0x1927> _gpgme_run_io_cb: call: item=0x20c26d0, handler (0x20c0c10, 4) 
<0x1927>  _gpgme_remove_io_cb: call: data=0x20c26b0, setting fd 0x4 (item=0x20c26d0) done 
<0x1927> _gpgme_run_io_cb: call: item=0x20c2820, need to check 
<0x1927> _gpgme_run_io_cb: call: item=0x20c2820, handler (0x20c0c10, 6) 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c0810, key = 0x20c2850, line = (null) 
<0x1927> gpgme:gpg_io_event: call: gpg=0x20c0c10, event 0x7fd8b1a20ad0, type 2, type_data 0x20c2850 
<0x1927>  _gpgme_remove_io_cb: call: data=0x20c2800, setting fd 0x6 (item=0x20c2820) done 
<0x1927> gpgme:gpg_io_event: call: gpg=0x20c0c10, event 0x7fd8b1a20ad0, type 1, type_data 0x7fff5afd0700 
<0x1927> gpgme_op_keylist_next: leave: key=0x20c2850 (20CD3FF80DA6C1E46CD9F135CC73A8A60BF38589) 
<0x1927> gpgme_release: call: ctx=0x20c0810 
<0x1927> gpgme_new: enter: r_ctx=0x7fff5afd0818 
<0x1927> gpgme_new: leave: ctx=0x20c2210 
<0x1927> gpgme_op_keylist_start: enter: ctx=0x20c2210, pattern=4BE78BDCF3F5352CF624A6DF3AD6F8118300CC02, secret_only=0 
<0x1927> _gpgme_add_io_cb: call: ctx=0x20c2210, fd 4, dir=1 -> tag=0x20c1f50 
<0x1927> _gpgme_add_io_cb: call: ctx=0x20c2210, fd 6, dir=1 -> tag=0x20c1fa0 
<0x1927> gpgme:gpg_io_event: call: gpg=0x20c0c10, event 0x7fd8b1a20ad0, type 0, type_data (nil) 
<0x1927> gpgme_op_keylist_start: leave 
<0x1927> gpgme_op_keylist_next: enter: ctx=0x20c2210 
<0x1927> _gpgme_run_io_cb: call: item=0x20c1fc0, need to check 
<0x1927> _gpgme_run_io_cb: call: item=0x20c1fc0, handler (0x20c0c10, 6) 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c2210, key = (nil), line = tru::0:1433443869:2410285847:3:1:5 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c2210, key = (nil), line = pub:-:1024:17:3AD6F8118300CC02:1039074767:::-:::scESC:::::: 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c2210, key = 0x20c2b70, line = fpr:::::::::4BE78BDCF3F5352CF624A6DF3AD6F8118300CC02: 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c2210, key = 0x20c2b70, line = uid:-::::1203999932::275AAD3E991F1962AD510CC96760907BE70FE668::Bla <[email protected]>: 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c2210, key = 0x20c2b70, line = uid:-::::1203999938::59689891229F1817EF66BFC63D9D0BB2F45F5209::Bla <[email protected]>: 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c2210, key = 0x20c2b70, line = uid:r::::::8A709552E7AB85B53DDAE18A48C0978E5EBF5547::Bla <[email protected]>: 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c2210, key = 0x20c2b70, line = sub:-:2048:16:942E547C12A6B1C2:1039075030::::::e:::::: 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c2210, key = 0x20c2b70, line = fpr:::::::::E69EF5226BBF7EC14F1D7D96942E547C12A6B1C2: 
<0x1927> _gpgme_run_io_cb: call: item=0x20c1f70, need to check 
<0x1927> _gpgme_run_io_cb: call: item=0x20c1f70, handler (0x20c0c10, 4) 
<0x1927>  _gpgme_remove_io_cb: call: data=0x20c1f50, setting fd 0x4 (item=0x20c1f70) done 
<0x1927> _gpgme_run_io_cb: call: item=0x20c1fc0, need to check 
<0x1927> _gpgme_run_io_cb: call: item=0x20c1fc0, handler (0x20c0c10, 6) 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c2210, key = 0x20c2b70, line = (null) 
<0x1927> gpgme:gpg_io_event: call: gpg=0x20c0c10, event 0x7fd8b1a20ad0, type 2, type_data 0x20c2b70 
<0x1927>  _gpgme_remove_io_cb: call: data=0x20c1fa0, setting fd 0x6 (item=0x20c1fc0) done 
<0x1927> gpgme:gpg_io_event: call: gpg=0x20c0c10, event 0x7fd8b1a20ad0, type 1, type_data 0x7fff5afd0760 
<0x1927> gpgme_op_keylist_next: leave: key=0x20c2b70 (4BE78BDCF3F5352CF624A6DF3AD6F8118300CC02) 
<0x1927> gpgme_release: call: ctx=0x20c2210 
<0x1927> gpgme_new: enter: r_ctx=0x7fff5afd07c8 
<0x1927> gpgme_new: leave: ctx=0x20c2550 
<0x1927> gpgme_set_passphrase_cb: call: ctx=0x20c2550, passphrase_cb=(nil)/(nil) 
<0x1927> gpgme_set_pinentry_mode: call: ctx=0x20c2550, pinentry_mode=4 
<0x1927> gpgme_set_passphrase_cb: call: ctx=0x20c2550, passphrase_cb=0x403420/0x20c0058 
<0x1927> gpgme_set_passphrase_cb: call: ctx=0x20c2550, passphrase_cb=0x403420/0x20c0058 
<0x1927> gpgme_new: enter: r_ctx=0x7fff5afd0768 
<0x1927> gpgme_new: leave: ctx=0x20c0810 
<0x1927> gpgme_op_keylist_start: enter: ctx=0x20c0810, pattern=0BF38589, secret_only=0 
<0x1927> _gpgme_add_io_cb: call: ctx=0x20c0810, fd 4, dir=1 -> tag=0x20c4fd0 
<0x1927> _gpgme_add_io_cb: call: ctx=0x20c0810, fd 6, dir=1 -> tag=0x20c5120 
<0x1927> gpgme:gpg_io_event: call: gpg=0x20c1d50, event 0x7fd8b1a20ad0, type 0, type_data (nil) 
<0x1927> gpgme_op_keylist_start: leave 
<0x1927> gpgme_op_keylist_next: enter: ctx=0x20c0810 
<0x1927> _gpgme_run_io_cb: call: item=0x20c5140, need to check 
<0x1927> _gpgme_run_io_cb: call: item=0x20c5140, handler (0x20c1d50, 6) 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c0810, key = (nil), line = tru::0:1433443869:2410285847:3:1:5 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c0810, key = (nil), line = pub:u:2048:1:CC73A8A60BF38589:1433443717:::u:::scESC:::::: 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c0810, key = 0x20c5170, line = fpr:::::::::20CD3FF80DA6C1E46CD9F135CC73A8A60BF38589: 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c0810, key = 0x20c5170, line = uid:u::::1433443717::9963CFDE0C8920AD077B06A281992C4008E67E4F::testkey3 (testkey3) <[email protected]>: 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c0810, key = 0x20c5170, line = sub:u:2048:1:22317805D48C1491:1433443717::::::e:::::: 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c0810, key = 0x20c5170, line = fpr:::::::::FB6FFB7D8BEC710A745DE86C22317805D48C1491: 
<0x1927> _gpgme_run_io_cb: call: item=0x20c4ff0, need to check 
<0x1927> _gpgme_run_io_cb: call: item=0x20c4ff0, handler (0x20c1d50, 4) 
<0x1927>  _gpgme_remove_io_cb: call: data=0x20c4fd0, setting fd 0x4 (item=0x20c4ff0) done 
<0x1927> _gpgme_run_io_cb: call: item=0x20c5140, need to check 
<0x1927> _gpgme_run_io_cb: call: item=0x20c5140, handler (0x20c1d50, 6) 
<0x1927> gpgme:keylist_colon_handler: call: ctx=0x20c0810, key = 0x20c5170, line = (null) 
<0x1927> gpgme:gpg_io_event: call: gpg=0x20c1d50, event 0x7fd8b1a20ad0, type 2, type_data 0x20c5170 
<0x1927>  _gpgme_remove_io_cb: call: data=0x20c5120, setting fd 0x6 (item=0x20c5140) done 
<0x1927> gpgme:gpg_io_event: call: gpg=0x20c1d50, event 0x7fd8b1a20ad0, type 1, type_data 0x7fff5afd06c0 
<0x1927> gpgme_op_keylist_next: leave: key=0x20c5170 (20CD3FF80DA6C1E46CD9F135CC73A8A60BF38589) 
<0x1927> gpgme_release: call: ctx=0x20c0810 
<0x1927> gpgme_signers_clear: call: ctx=0x20c2550 
<0x1927> gpgme_signers_add: enter: ctx=0x20c2550, key=0x20c2850 (20CD3FF80DA6C1E46CD9F135CC73A8A60BF38589) 
<0x1927> gpgme_signers_add: leave 
<0x1927> gpgme_op_encrypt_sign: enter: ctx=0x20c2550, flags=0x1, plain=0x20c2ed0, cipher=0x20c3f20 
<0x1927> gpgme_op_encrypt_sign: check: ctx=0x20c2550, recipient[0] = 0x20c5170 (20CD3FF80DA6C1E46CD9F135CC73A8A60BF38589) 
<0x1927> gpgme_sig_notation_get: call: ctx=0x20c2550, ctx->sig_notations=(nil) 
<0x1927> _gpgme_add_io_cb: call: ctx=0x20c2550, fd 4, dir=1 -> tag=0x20c2070 
<0x1927> _gpgme_add_io_cb: call: ctx=0x20c2550, fd 8, dir=1 -> tag=0x20c21c0 
<0x1927> _gpgme_add_io_cb: call: ctx=0x20c2550, fd 11, dir=0 -> tag=0x20c2210 
<0x1927> gpgme:gpg_io_event: call: gpg=0x20c1d50, event 0x7fd8b1a20ad0, type 0, type_data (nil) 
<0x1927> _gpgme_run_io_cb: call: item=0x20c2230, need to check 
<0x1927> _gpgme_run_io_cb: call: item=0x20c2230, handler (0x20c2ed0, 11) 
<0x1927> _gpgme_data_outbound_handler: enter: dh=0x20c2ed0, fd=0xb 
<0x1927> _gpgme_data_outbound_handler: leave 
<0x1927> _gpgme_run_io_cb: call: item=0x20c2230, need to check 
<0x1927> _gpgme_run_io_cb: call: item=0x20c2230, handler (0x20c2ed0, 11) 
<0x1927> _gpgme_data_outbound_handler: enter: dh=0x20c2ed0, fd=0xb 
<0x1927>  _gpgme_remove_io_cb: call: data=0x20c2210, setting fd 0xb (item=0x20c2230) done 
<0x1927> _gpgme_data_outbound_handler: leave 
<0x1927> _gpgme_run_io_cb: call: item=0x20c2090, need to check 
<0x1927> _gpgme_run_io_cb: call: item=0x20c2090, handler (0x20c1d50, 4) 
<0x1927> _gpgme_run_io_cb: call: item=0x20c2090, need to check 
<0x1927> _gpgme_run_io_cb: call: item=0x20c2090, handler (0x20c1d50, 4) 
<0x1927> _gpgme_cancel_with_err: enter: ctx=0x20c2550, ctx_err=117440566, op_err=0 
<0x1927>  _gpgme_remove_io_cb: call: data=0x20c2070, setting fd 0x4 (item=0x20c2090) done 
<0x1927>  _gpgme_remove_io_cb: call: data=0x20c21c0, setting fd 0x8 (item=0x20c21e0) done 
<0x1927>  gpgme:gpg_io_event: call: gpg=0x20c1d50, event 0x7fd8b1a20ad0, type 1, type_data 0x7fff5afd06c0 
<0x1927> _gpgme_cancel_with_err: leave 
<0x1927> gpgme_op_encrypt_sign: error: Unusable secret key <GPGME> 
<0x1927> gpgme_release: call: ctx=0x20c2550 

EDIT

По просьбе @kylehuff, вот код для выбора ключа:

search_key_result_t gpgme::find_key(const std::string & key_id, const bool priv_key_only, gpgme_key_t *k, std::string *const error) 
    { 
      error -> clear(); 

      *k = NULL; 

      gpgme_ctx_t ctx = NULL; 
      if (!my_gpgme_new(&ctx, false, error)) 
        return SK_ERROR; 

      gpgme_error_t err = gpgme_op_keylist_start(ctx, key_id.c_str(), priv_key_only ? 1 : 0); 
      if (err != GPG_ERR_NO_ERROR) 
      { 
        error -> append(format("Problem searching for %s: %s (%d)", key_id.c_str(), gpg_strerror(err), err)); 
        gpgme_release(ctx); 
        return SK_ERROR; 
      } 

      err = gpgme_op_keylist_next(ctx, k); 
      if (err == GPG_ERR_EOF) 
        return SK_NOT_FOUND; 

      if (err != GPG_ERR_NO_ERROR) 
      { 
        error -> append(format("Problem finding %s: %s (%d)", key_id.c_str(), gpg_strerror(err), err)); 
        gpgme_release(ctx); 
        return SK_ERROR; 
      } 

      gpgme_release(ctx); 

      return SK_FOUND; 
    } 

Тогда в конструкторе я:

std::string error; 
    if (find_key(my_key_id, true, &my_key, &error) != SK_FOUND) 
      error_exit(false, "Cannot find key %s: %s", my_key_id.c_str(), error.c_str()); 

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

  if (find_key(target_uid, false, &recipient[0], error) != SK_FOUND) 
        break; 

      gpgme_signers_clear(ctx); 
      err = gpgme_signers_add(ctx, my_key); 
      if (err != GPG_ERR_NO_ERROR) 
      { 
        error -> append(format("gpgme_signers_add(%s) failed: %s (%d)", my_key_id.c_str(), gpg_strerror(err), err)); 
        break; 
      } 

      int n_signers = gpgme_signers_count(ctx); 
      if (n_signers != 1) 
      { 
        error -> append(format("Number of signers (%d) not expected number (1)", n_signers)); 
        break; 
      } 

      err = gpgme_op_encrypt_sign(ctx, recipient, GPGME_ENCRYPT_ALWAYS_TRUST /* FIXME */, data_in, sig); 
      if (err != GPG_ERR_NO_ERROR) 
      { 
        error -> append(format("gpgme_op_encrypt failed: %s (%d)", gpg_strerror(err), err)); 
        break; 
      } 

@kylehuff, это то, что вы просили? Благодаря

EDIT

Вот список для 20CD3FF80DA6C1E46CD9F135CC73A8A60BF38589:

tru::0:1433443869:2410285847:3:1:5 
pub:u:2048:1:CC73A8A60BF38589:2015-06-04:::u:testkey3 (testkey3) <[email protected]>::scESC: 
sub:u:2048:1:22317805D48C1491:2015-06-04::::::e: 

EDIT

Folkert @ TravelMate: ~ $ gpg2 --local пользователь 14B7E8E6 --sign бла .txt

folkert @travelmate: ~ $ GPG --verify bla.txt.gpg GPG: Подпись сделал чт 18 июня 2015 7:18:17 PM UTC с использованием RSA ключа ID 74D6F5C6 GPG: Хорошая подпись "testkey2 (testkey2)"

и редактирования ключа я могу видеть, что 74d6f5c6 действительно знак под-ключ:

суб 1024R/74D6F5C6 создано: 2015-05-31 Expires: никогда использование: S

Так что я немного удивлен что это не работает для gpgme. Не выполняя поиск, но непосредственно gpgme_get_key() дает ту же ошибку.

+0

Не могли бы вы опубликовать фактический код для 'gpgme_signers_add' метода и выбора клавиши? В выведенном вами отладочном выпуске выбранный ключ не соответствует ни одному из ключей, перечисленных в верхней части вашего вопроса. Операция 'gpgme_signers_add' использует ключ« 20CD3FF80DA6C1E46CD9F135CC73A8A60BF38589 », это ключ, который у вас есть как для публичной, так и для частной части, и просто не указан? – kylehuff

+0

Можете ли вы указать, какой именно ключ вы добавляете? Возможно ли, что это только знак или шифрование? Вы выбираете секретный ключ или один из подразделов (ов)? –

+0

@NickolayOlshevsky Я использую ключ, указанный вверху: 14B7E8E6 –

ответ

2

Трудно сказать, что происходит, даже с образцом, но вот несколько возможных сценариев -

Что-то делается в методе my_gpgme_new(&ctx, false, error) может быть своенравным. Что именно делает эта функция? Почему бы не использовать стандартный метод gpgme_new?

В предоставленном образце вы используете функцию search_key_result_t gpgme::find_key(); есть ли необходимость в нескольких подписывающих лицах? если это так, по крайней мере для тестирования, почему бы не упростить его и просто использовать gpgme_get_key()? то есть

gpgme_error_t err; 
    gpgme_key_t key; 

    err = gpgme_get_key (ctx, key_string, &key, 1); 
    if (err) { 
    // .. error handling 
    } 
    gpgme_signers_clear(); 
    err = gpgme_signers_add (ctx, key); 
    gpgme_key_unref (key); 

    int n_signers = gpgme_signers_count(ctx); 
    if (n_signers != 1) { 
    // .. error handling 
    } 

    err = gpgme_op_encrypt_sign(ctx, recipient, ....); 

Кроме того, этот метод, похоже, вы добавляете к методу gpgme namesapce. Возможно ли, что вы попираете встроенный метод в пространстве имен gpgme?

Что касается объекта-получателя, как это устроено? Он должен быть нулевым завершенным gpgme_key_t структурой gpgme_key_t s, даже если это только один получатель. т.е.

gpgme_key_t recipients[2] = { NULL, NULL }; 
    err = gpgme_get_key (ctx, recipient_fpr.c_str(), &recipients[0], 0); 
    if (err) { // .. error handling } 

С другой стороны, если получатели представлены в виде массива:

gpgme_key_t recipients = new gpgme_key_t[recip_array.size()]; 
    err = gpgme_get_key (ctx, recipient_fpr.c_str(), &recipients[0], 0); 
    if (err) { // .. error handling } 
    recipients[recip_array.size()] = NULL; // null terminate the array 
+0

my_gpgme_new - это wapper вокруг gpgme_new, который вызывает gpgme_new, но также вызывает gpgme_set_pinentry_mode и gpgme_set_passphrase_cb, если применимо. Что касается find_key: этот метод ищет ключ любым понятым поисковым запросом gpgme. Надеемся, это позволит людям искать по ключевым словам, а также по электронной почте. Пространство имен: my_gpgme_new и find_key являются частью моего класса gpgme, поэтому они не должны конфликтовать с библиотекой gpgme (которая является простой c afaik). –

+0

Для объекта-получателя: это действительно массив из двух элементов, последний из которых имеет значение NULL. Чтобы помочь вам помочь людям, я загрузил код на http://vps001.vanheusden.com/~folkert/gpgme.cpp и http://vps001.vanheusden.com/~folkert/gpgme.h В любом случае законченный будет открытым исходным кодом. –

+0

Хорошо, увидев, что фактическое должно помочь, если ничего другого, чтобы я не догадывался. Не могли бы вы также предоставить вывод 'gpg --with-colons -list-keys 20CD3FF80DA6C1E46CD9F135CC73A8A60BF38589' для полноты? – kylehuff

Смежные вопросы