You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows下用GPGME实现C语言PGP解密遇无效文件描述符错误求助

Windows下GPGME C语言PGP解密报错:无效文件描述符(错误码32779)

在Windows系统中尝试使用GPGME库通过C语言实现PGP解密功能,未找到完整可用的示例代码。调用gpgme_op_decrypt函数后程序报错:解密失败,错误码32779,对应“Bad file descriptor”(无效文件描述符)。以下是实现代码:

#include "pch.h"
#include <gpgme.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
#include <windows.h> 
#include "pgp.h"
#include <time.h>
#include <stddef.h> 
#include <gpg-error.h>

static gpgme_error_t passphrase_callback(void* hook_value, const char* uid_hint, const char* passphrase_info, int prev_was_bad, int fd) {

const char* passphrase = (const char*)hook_value;

gpgme_io_write(fd, passphrase, strlen(passphrase));
gpgme_io_write(fd, "\n", 1);

return 0;
}

int PGPDecryptFile(const char* fromFilepath, const char* toFilePath, const char* private_key_filepath, const char* logFilePath) {
    gpgme_ctx_t ctx;
    gpgme_data_t in, out;
    const uint8_t private_key_password [13] = { 33, 44, 55, 66, 55, 33, 22, 11, 33, 44, 55, 66, '\0' };
    // Initialize GPGME
    gpgme_check_version(NULL);
    gpgme_set_locale(NULL, 0, NULL);
    gpgme_check_version(NULL);
    // Create and initialize context
    gpgme_new(&ctx);
    gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP);

    FILE* private_key_file;
    if (fopen_s(&private_key_file, private_key_filepath, "r") != 0) {
        AppendLogToFile(logFilePath, private_key_filepath);
        AppendLogToFile(logFilePath, "Error: Failed to open private key file for reading");
        return 1;
    }

    if (!private_key_file) {
        AppendLogToFile(logFilePath, private_key_filepath);
        AppendLogToFile(logFilePath, "Error: Failed to open private key file for reading");
        return 1;
    }

    gpgme_data_t private_key_data;
    if (gpgme_data_new_from_fd(&private_key_data, _fileno(private_key_file)) != GPG_ERR_NO_ERROR) {
        AppendLogToFile(logFilePath, "Error: Failed to create data buffer for private key");
        fclose(private_key_file);
        return 1;
    }

    gpgme_set_passphrase_cb(ctx, passphrase_callback, (void*)private_key_password);

    // Set the private key in the context
    gpgme_error_t setProtocolResult = gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP);
    gpgme_error_t setEngineInfoResult = gpgme_ctx_set_engine_info(ctx, GPGME_PROTOCOL_OpenPGP, private_key_filepath, NULL);

    if (setProtocolResult != GPG_ERR_NO_ERROR || setEngineInfoResult != GPG_ERR_NO_ERROR) {
        AppendLogToFile(logFilePath, "Error: Failed to set private key in the context");

        if (setProtocolResult != GPG_ERR_NO_ERROR) {
            AppendLogToFile(logFilePath, "Error setting protocol");
        }

        if (setEngineInfoResult != GPG_ERR_NO_ERROR) {
            AppendLogToFile(logFilePath, "Error setting engine info");
        }

        gpgme_data_release(private_key_data);
        fclose(private_key_file);
        return 1;
    }

    // Prepare data for decryption
    FILE* file;
    if (fopen_s(&file, fromFilepath, "rb") != 0) {
        //fprintf(stderr, "Error: Failed to open file for reading.\n");
        AppendLogToFile(logFilePath, fromFilepath);
        AppendLogToFile(logFilePath, "Error: Failed to open file for reading");
        gpgme_data_release(private_key_data);
        fclose(private_key_file);
        return 1;
    }

    if (!file) {
        AppendLogToFile(logFilePath, fromFilepath);
        AppendLogToFile(logFilePath, "Error: Failed to open file for reading");
        gpgme_data_release(private_key_data);
        fclose(private_key_file);
        return 1;
    }

    gpgme_data_new_from_fd(&in, _fileno(file));
    gpgme_data_new(&out);

    // Decrypt data
    gpgme_error_t decryptResult = gpgme_op_decrypt(ctx,in , out);
    if (decryptResult != GPG_ERR_NO_ERROR) {
        int errCode = gpgme_err_code(decryptResult);
        char errorMessage[256];  
        snprintf(errorMessage, sizeof(errorMessage), "Error: Failed to decrypt data. Error code: %d", errCode);
        AppendLogToFile(logFilePath, errorMessage);
        fclose(file);
        gpgme_data_release(private_key_data);
        fclose(private_key_file);
        return 1;
    }

    char* decrypted_data = gpgme_data_release_and_get_mem(out, NULL);

    FILE* decrypted_file;
    if (fopen_s(&decrypted_file, toFilePath, "wb") != 0) {
        AppendLogToFile(logFilePath, toFilePath);
        AppendLogToFile(logFilePath, "Error: Failed to create decrypted file for writing");
        fclose(file);
        gpgme_data_release(private_key_data);
        fclose(private_key_file);
        free(decrypted_data);
        return 1;
    }

    fwrite(decrypted_data, 1, strlen(decrypted_data), decrypted_file);

    fclose(file);
    fclose(decrypted_file);
    gpgme_data_release(private_key_data);
    free(decrypted_data);
    gpgme_data_release(in);
    gpgme_release(ctx);
    fclose(private_key_file);

    return 0;
}

测试该代码需安装Gpg4win,同时在Visual Studio中需完成以下配置:

  • 将Gpg4win\include添加至“附加包含目录”属性(位于C/C++常规选项卡下)
  • 将Gpg4win\bin和Gpg4win\lib添加至“附加库目录”属性(位于链接器常规选项卡下)
  • 将libgpgme.imp添加至“附加依赖项”属性(位于链接器输入选项卡下)

内容的提问来源于stack exchange,提问作者Anas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 18:34:50