gpgme在64位debian上加密失败

时间:2013-04-09 21:26:38

标签: encryption 64-bit gpgme

我正面临着一个问题,这个问题让我在使用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;
}

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

1 个答案:

答案 0 :(得分: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-----