Gpgme在64位debian上加密失败



我正面临一个问题,这给了我一些麻烦跟踪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 messagen", 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=%sn",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: %sn",p);
  /* get engine information */
  err = gpgme_get_engine_info(&enginfo);
  if(err != GPG_ERR_NO_ERROR) return 2;
  printf("file=%s, home=%sn",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: %sn", 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%sn", 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;
}
非常感谢你能给我的任何帮助!我还没有找到任何有用的东西来帮助我调试这个…

在提供的示例中,从未实际设置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 messagen", 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=%sn",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: %sn",p);
  /* get engine information */
  err = gpgme_get_engine_info(&enginfo);
  if(err != GPG_ERR_NO_ERROR) return 2;
  printf("file=%s, home=%sn",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: %sn", 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%sn", 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-----

最新更新