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

如何在C项目中通过Assuan协议使用GnuPG pinentry?求最小可行示例

最小可行示例:C项目通过Assuan协议调用GnuPG Pinentry

以下是完整的最小可行代码,包含Assuan上下文初始化、连接Pinentry、获取用户输入密码的核心流程,代码附带详细注释帮助理解关键步骤:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assuan.h>

int main() {
    assuan_context_t ctx = NULL;
    assuan_error_t err;
    const char* gpg_agent_info;
    char socket_path[256];
    char* pin = NULL;

    // 1. 初始化Assuan通信上下文
    err = assuan_init(&ctx);
    if (err != ASSUAN_NO_ERROR) {
        fprintf(stderr, "Assuan初始化失败: %s\n", assuan_strerror(err));
        return 1;
    }

    // 2. 从环境变量获取GPG Agent的套接字路径(Pinentry通过Agent间接通信)
    gpg_agent_info = getenv("GPG_AGENT_INFO");
    if (!gpg_agent_info) {
        fprintf(stderr, "未找到GPG_AGENT_INFO环境变量,请确保GPG Agent已运行\n");
        assuan_release(ctx);
        return 1;
    }

    // 提取套接字路径(GPG_AGENT_INFO格式为 socket_path:pid:1)
    strncpy(socket_path, gpg_agent_info, sizeof(socket_path)-1);
    socket_path[strcspn(socket_path, ":")] = '\0';

    // 3. 建立到GPG Agent的Assuan连接
    err = assuan_socket_connect(ctx, socket_path);
    if (err != ASSUAN_NO_ERROR) {
        fprintf(stderr, "连接到GPG Agent失败: %s\n", assuan_strerror(err));
        assuan_release(ctx);
        return 1;
    }

    // 4. 发送命令启动Pinentry会话
    err = assuan_transact(ctx, "ASSUAN_PINENTRY_START", NULL, NULL, NULL, NULL);
    if (err != ASSUAN_NO_ERROR) {
        fprintf(stderr, "启动Pinentry会话失败: %s\n", assuan_strerror(err));
        assuan_release(ctx);
        return 1;
    }

    // 5. 设置Pinentry界面参数:提示文本、描述、窗口标题
    err = assuan_transact(ctx, "SET PROMPT 请输入密码:", NULL, NULL, NULL, NULL);
    if (err != ASSUAN_NO_ERROR) goto cleanup;

    err = assuan_transact(ctx, "SET DESCRIPTION 测试密码输入框", NULL, NULL, NULL, NULL);
    if (err != ASSUAN_NO_ERROR) goto cleanup;

    err = assuan_transact(ctx, "SET TITLE Pinentry调用测试", NULL, NULL, NULL, NULL);
    if (err != ASSUAN_NO_ERROR) goto cleanup;

    // 6. 请求用户输入密码,响应返回PIN值
    err = assuan_transact(ctx, "GETPIN", NULL, NULL, (const void**)&pin, NULL);
    if (err != ASSUAN_NO_ERROR) {
        fprintf(stderr, "获取密码失败: %s\n", assuan_strerror(err));
        goto cleanup;
    }

    if (pin) {
        printf("用户输入的密码: %s\n", pin);
        // 使用后必须释放密码内存
        assuan_free(pin);
    }

cleanup:
    // 7. 释放Assuan上下文资源
    assuan_release(ctx);
    return err == ASSUAN_NO_ERROR ? 0 : 1;
}

关键步骤解析

  • 上下文初始化:assuan_init创建并初始化Assuan通信上下文,这是所有Assuan操作的基础载体。
  • 套接字路径获取:Pinentry不直接暴露套接字,需通过GPG Agent中转,因此从GPG_AGENT_INFO环境变量提取Agent的套接字路径。
  • 连接建立:assuan_socket_connect完成与Agent的Assuan协议连接,后续所有命令都通过该连接传输。
  • Pinentry会话启动:ASSUAN_PINENTRY_START命令告知Agent需要唤起Pinentry交互窗口。
  • 界面配置:通过SET命令自定义Pinentry的提示文本、描述和标题,让用户明确输入用途。
  • 密码获取:GETPIN命令触发Pinentry弹窗,用户输入后,响应中的PIN值会被返回,使用后必须调用assuan_free释放内存。
  • 资源清理:assuan_release释放上下文资源,避免内存泄漏。

编译与运行

确保已安装libassuan-dev(Debian/Ubuntu)或对应系统的开发包,编译命令:

gcc -o pinentry_mwe pinentry_mwe.c -lassuan

运行前需确认GPG Agent已启动(通常登录后自动运行),直接执行编译后的程序即可看到Pinentry弹窗。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 15:31:12