1

我遇到了一个问题,这给我用 gpgme 追踪带来了一些麻烦。我用一个简单的测试程序(从我找到的另一个简单示例开始)复制了它,我将其粘贴在下面。这适用于 32 位基于 debian 的系统,但在 64 位系统上失败。特别是在 64 位情况下,我可以成功读取和解密(示例中未显示),但在加密中出现了一个相当神秘的错误:

$ ./test2 C37DBF71 Ciao!
version=1.2.0
Protocol name: OpenPGP
file=/usr/bin/gpg, home=(null)
Error in encrypting data. Error 1: General error (Unspecified source)

libgpgme 的版本也如上所示。

这是 的输出uname,只是为了向您展示我在 64 位系统上运行:

$ uname -a
Linux spagan-laptop 3.2.0-39-generic #62-Ubuntu SMP Thu Feb 28 00:28:53 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

是的,我做的第一件事就是广泛尝试确保我正在定义_FILE_OFFSET_BITS=64;我还检查了off_t它的有效大小为 8。这就是我编译它的方式:

gcc -m64 -D_FILE_OFFSET_BITS=64 -g test2.c -lgpgme -L/usr/lib/x86_64-linux-gnu -lgpg-error -o test2

最后是测试程序:

#include <gpgme.h>   /* gpgme             */
#include <stdio.h>   /* printf            */
#include <unistd.h>  /* write             */
#include <errno.h>   /* errno             */
#include <locale.h>  /* locale support    */
#include <string.h>  /* string support    */
#include <stdlib.h>  /* memory management */

#define SIZE 1024

int main(int argc, char **argv)
{
  if (argc < 2) {
    printf("ERROR. Usage: %s key message\n", argv[0]);
    return -1;
  }

  char *m_key = argv[1];
  char *pSource = argv[2];
  char *pDest = malloc(65536);

  char *p;
  char buf[SIZE];
  size_t read_bytes;
  int tmp;
  gpgme_ctx_t ceofcontext;
  gpgme_error_t err;
  gpgme_data_t data;

  gpgme_engine_info_t enginfo;

  /* The function `gpgme_check_version' must be called before any other
   * function in the library, because it initializes the thread support
   * subsystem in GPGME. (from the info page) */
  setlocale (LC_ALL, "");
  p = (char *) gpgme_check_version(NULL);
  printf("version=%s\n",p);
  /* set locale, because tests do also */
  gpgme_set_locale(NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));

  /* check for OpenPGP support */
  err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
  if(err != GPG_ERR_NO_ERROR) return 1;

  p = (char *) gpgme_get_protocol_name(GPGME_PROTOCOL_OpenPGP);
  printf("Protocol name: %s\n",p);

  /* get engine information */
  err = gpgme_get_engine_info(&enginfo);
  if(err != GPG_ERR_NO_ERROR) return 2;
  printf("file=%s, home=%s\n",enginfo->file_name,enginfo->home_dir);

  /* create our own context */
  err = gpgme_new(&ceofcontext);
  if(err != GPG_ERR_NO_ERROR) return 3;

  /* set protocol to use in our context */
  err = gpgme_set_protocol(ceofcontext,GPGME_PROTOCOL_OpenPGP);
  if(err != GPG_ERR_NO_ERROR) return 4;

  /* set engine info in our context; I changed it for ceof like this:

   err = gpgme_ctx_set_engine_info (ceofcontext, GPGME_PROTOCOL_OpenPGP,
               "/usr/bin/gpg","/home/user/nico/.ceof/gpg/");

           but I'll use standard values for this example: */

  err = gpgme_ctx_set_engine_info (ceofcontext, GPGME_PROTOCOL_OpenPGP,
                               enginfo->file_name,enginfo->home_dir);
  if(err != GPG_ERR_NO_ERROR) return 5;

  /* do ascii armor data, so output is readable in console */
  gpgme_set_armor(ceofcontext, 1);

  gpgme_data_t source;
  gpgme_data_t dest;

  //get key to encrypt, get the first key
  gpgme_key_t key[2];
  err = gpgme_op_keylist_start(ceofcontext, m_key, 0);
  err = gpgme_op_keylist_next (ceofcontext, key);
  if (err) {
    printf("Key not found in current key-ring: %s\n", m_key);
    return 1;
  }
  key[1] = 0; //set to NULL the second entry

  //point to source buffer
  err = gpgme_data_new_from_mem(&source, pSource, strlen(pSource), 0);  
  if (err != GPG_ERR_NO_ERROR) {
    printf("Error in reading data to encrypt. Error %d: %s (%s)\n",
       gpgme_err_code(err), gpgme_strerror(err), gpgme_strsource(err));
    return 2;
  }

  //create dest buffer
  err = gpgme_data_new(&dest);
  if (err != GPG_ERR_NO_ERROR) {
    printf("Error in creating output data buffer to encrypt. Error %d: %s (%s)\n",
       gpgme_err_code(err), gpgme_strerror(err), gpgme_strsource(err));
    return 3;
  }

  //encrypt text
  gpgme_encrypt_flags_t flags;
  flags = GPGME_ENCRYPT_NO_ENCRYPT_TO; //only specified recipient, no defaults please
  err = gpgme_op_encrypt(ceofcontext, key, flags, source, dest);
  if (err != GPG_ERR_NO_ERROR) {
    printf("Error in encrypting data. Error %d: %s (%s)\n",
       gpgme_err_code(err), gpgme_strerror(err), gpgme_strsource(err));
    return 4;    
  }

  //retrieve result
  printf("Result: \n%s\n", pDest);

  //release key and buffers
  gpgme_key_release(key[0]);  
  gpgme_data_release(dest);
  gpgme_data_release(source);
  free(pDest);

  /* free context */
  gpgme_release(ceofcontext);

  return 0;
}

非常感谢您能给我的任何帮助!我还没有发现任何有用的东西来帮助我调试这个..

4

1 回答 1

0

在提供的示例中,pDest从未实际设置过 的值。

为了获得gpgme_data_t对象的值dest,使用gpgme_data_release_and_get_mem.

例子:

#include <gpgme.h>   /* gpgme             */
#include <stdio.h>   /* printf            */
#include <unistd.h>  /* write             */
#include <errno.h>   /* errno             */
#include <locale.h>  /* locale support    */
#include <string.h>  /* string support    */
#include <stdlib.h>  /* memory management */

#define SIZE 1024

int main(int argc, char **argv)
{
  if (argc < 2) {
    printf("ERROR. Usage: %s key message\n", argv[0]);
    return -1;
  }

  char *m_key = argv[1];
  char *pSource = argv[2];

  char *p;
  size_t read_bytes;
  gpgme_ctx_t ceofcontext;
  gpgme_error_t err;

  gpgme_engine_info_t enginfo;

  /* The function `gpgme_check_version' must be called before any other
   * function in the library, because it initializes the thread support
   * subsystem in GPGME. (from the info page) */
  setlocale (LC_ALL, "");
  p = (char *) gpgme_check_version(NULL);
  printf("version=%s\n",p);
  /* set locale, because tests do also */
  gpgme_set_locale(NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));

  /* check for OpenPGP support */
  err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
  if(err != GPG_ERR_NO_ERROR) return 1;

  p = (char *) gpgme_get_protocol_name(GPGME_PROTOCOL_OpenPGP);
  printf("Protocol name: %s\n",p);

  /* get engine information */
  err = gpgme_get_engine_info(&enginfo);
  if(err != GPG_ERR_NO_ERROR) return 2;
  printf("file=%s, home=%s\n",enginfo->file_name,enginfo->home_dir);

  /* create our own context */
  err = gpgme_new(&ceofcontext);
  if(err != GPG_ERR_NO_ERROR) return 3;

  /* set protocol to use in our context */
  err = gpgme_set_protocol(ceofcontext,GPGME_PROTOCOL_OpenPGP);
  if(err != GPG_ERR_NO_ERROR) return 4;

  /* set engine info in our context; I changed it for ceof like this:

   err = gpgme_ctx_set_engine_info (ceofcontext, GPGME_PROTOCOL_OpenPGP,
               "/usr/bin/gpg","/home/user/nico/.ceof/gpg/");

           but I'll use standard values for this example: */

  err = gpgme_ctx_set_engine_info (ceofcontext, GPGME_PROTOCOL_OpenPGP,
                               enginfo->file_name,enginfo->home_dir);
  if(err != GPG_ERR_NO_ERROR) return 5;

  /* do ascii armor data, so output is readable in console */
  gpgme_set_armor(ceofcontext, 1);

  gpgme_data_t source;
  gpgme_data_t dest;

  //get key to encrypt, get the first key
  gpgme_key_t key[2];
  err = gpgme_op_keylist_start(ceofcontext, m_key, 0);
  err = gpgme_op_keylist_next (ceofcontext, key);
  if (err) {
    printf("Key not found in current key-ring: %s\n", m_key);
    return 1;
  }
  key[1] = 0; //set to NULL the second entry

  //point to source buffer
  err = gpgme_data_new_from_mem(&source, pSource, strlen(pSource), 0);  
  if (err != GPG_ERR_NO_ERROR) {
    printf("Error in reading data to encrypt. Error %d: %s (%s)\n",
       gpgme_err_code(err), gpgme_strerror(err), gpgme_strsource(err));
    return 2;
  }

  //create dest buffer
  err = gpgme_data_new(&dest);
  if (err != GPG_ERR_NO_ERROR) {
    printf("Error in creating output data buffer to encrypt. Error %d: %s (%s)\n",
       gpgme_err_code(err), gpgme_strerror(err), gpgme_strsource(err));
    return 3;
  }

  //encrypt text
  gpgme_encrypt_flags_t flags;
  flags = GPGME_ENCRYPT_NO_ENCRYPT_TO; //only specified recipient, no defaults please
  err = gpgme_op_encrypt(ceofcontext, key, flags, source, dest);
  if (err != GPG_ERR_NO_ERROR) {
    printf("Error in encrypting data. Error %d: %s (%s)\n",
       gpgme_err_code(err), gpgme_strerror(err), gpgme_strsource(err));
    return 4;    
  }

  p = gpgme_data_release_and_get_mem(dest, &read_bytes);

  p[read_bytes] = 0;

  //retrieve result
  printf("Result: \n%s\n", p);

  //release key and buffers
  gpgme_key_release(key[0]);
  gpgme_data_release(source);

  /* free context */
  gpgme_release(ceofcontext);

  return 0;
}

编译gcc -Wall -m64 -D_FILE_OFFSET_BITS=64 -g test2.c -lgpgme -lgpg-error -o test2

结果是:

version=1.4.2
Protocol name: OpenPGP
file=/usr/bin/gpg, home=(null)
Result: 
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1

hQIMA33UcjHVsYaXARAAh1txbI4bSsterGLf2d1AhrjQaugDfqaqSX32itxPKv1K
<SNIP>
EHlJTb0rVRvnTGjp5yLMy/hlw4hEtTh7HA==
=LRyw
-----END PGP MESSAGE-----
于 2015-04-26T01:44:18.763 回答