我正面临着一个问题,这个问题让我在使用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;
}
非常感谢你能给我的任何帮助! 我还没有找到任何有用的东西来帮助我调试这个..
答案 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-----