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

如何在C语言中通过管道实现实时流GPG对称加密?

实现实时数据流的GPG对称加密(模拟gpg --passphrase hackerpass --symmetric -c)

既然gpgme不适合实时流场景,直接调用官方的gpg命令行工具其实是最省心的方案——它已经帮你处理好了所有OpenPGP标准格式的细节(头部封装、校验和、尾部标识这些),完全和你在终端执行的命令输出一致。结合你提到的fork+双向管道方案,我们可以轻松实现实时的数据流加密。

核心思路

  • 通过fork()创建子进程,在子进程中执行gpg命令
  • 建立双向管道:父进程负责往子进程的stdin写入待加密数据,同时从子进程的stdout读取加密后的结果
  • 当所有数据写入完成后,关闭子进程的stdin(模拟终端的Ctrl+D输入EOF),触发gpg完成加密流程并输出尾部数据
  • 全程可以边写边读,完美适配实时流场景

C语言实现示例

下面是一个完整的可运行示例,包含双向管道的创建、子进程执行gpg、实时数据读写的逻辑:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>

#define BUFFER_SIZE 4096

int main() {
    int stdin_pipe[2], stdout_pipe[2];
    pid_t pid;
    char buffer[BUFFER_SIZE];
    ssize_t bytes_read, bytes_written;

    // 创建双向管道:stdin_pipe用于父->子写数据,stdout_pipe用于子->父读加密结果
    if (pipe(stdin_pipe) == -1 || pipe(stdout_pipe) == -1) {
        perror("pipe failed");
        exit(EXIT_FAILURE);
    }

    // Fork子进程
    pid = fork();
    if (pid == -1) {
        perror("fork failed");
        exit(EXIT_FAILURE);
    }

    if (pid == 0) {
        // 子进程:重定向stdin/stdout到管道,执行gpg命令
        close(stdin_pipe[1]);  // 关闭子进程不需要的写端
        close(stdout_pipe[0]); // 关闭子进程不需要的读端

        // 将stdin重定向到stdin_pipe的读端
        if (dup2(stdin_pipe[0], STDIN_FILENO) == -1) {
            perror("dup2 stdin failed");
            exit(EXIT_FAILURE);
        }
        // 将stdout重定向到stdout_pipe的写端
        if (dup2(stdout_pipe[1], STDOUT_FILENO) == -1) {
            perror("dup2 stdout failed");
            exit(EXIT_FAILURE);
        }

        // 执行gpg命令,和终端命令参数一致(--batch避免交互式提示)
        char *args[] = {"gpg", "--passphrase", "hackerpass", "--symmetric", "-c", "--batch", NULL};
        execvp("gpg", args);

        // 如果execvp返回,说明执行失败
        perror("execvp gpg failed");
        exit(EXIT_FAILURE);
    } else {
        // 父进程:负责写入数据、读取加密结果
        close(stdin_pipe[0]);  // 关闭父进程不需要的读端
        close(stdout_pipe[1]); // 关闭父进程不需要的写端

        // 示例:写入待加密的实时数据(这里可以替换成你的数据流输入)
        const char *test_data = "This is real-time stream data!\nAnother line of data.\n";
        bytes_written = write(stdin_pipe[1], test_data, strlen(test_data));
        if (bytes_written == -1) {
            perror("write to gpg stdin failed");
            exit(EXIT_FAILURE);
        }

        // 关闭stdin,告诉gpg数据已结束(模拟Ctrl+D)
        close(stdin_pipe[1]);

        // 读取加密后的结果,直到子进程输出完毕
        printf("Encrypted output:\n");
        while ((bytes_read = read(stdout_pipe[0], buffer, BUFFER_SIZE)) > 0) {
            // 这里可以将加密结果写入文件、发送到网络等,实时处理
            write(STDOUT_FILENO, buffer, bytes_read);
        }

        if (bytes_read == -1) {
            perror("read from gpg stdout failed");
            exit(EXIT_FAILURE);
        }

        // 等待子进程退出,获取退出状态
        int status;
        waitpid(pid, &status, 0);
        if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
            fprintf(stderr, "gpg process exited with error\n");
            exit(EXIT_FAILURE);
        }
    }

    return EXIT_SUCCESS;
}

关键细节说明

  • 实时流适配:你可以把示例中的test_data替换成从网络、文件或者其他实时数据源读取的内容,边读边写进管道,同时实时读取加密后的结果,完全不需要缓存整个数据流。
  • EOF处理:必须关闭子进程的stdin写端,否则gpg会一直等待输入,不会输出加密尾部。这一步对应终端里的Ctrl+D操作。
  • 安全提示:--passphrase直接写在命令行参数里会有安全风险(比如通过ps命令能看到密码),生产环境建议改用--passphrase-fd参数,从文件描述符读取密码。比如可以额外创建一个管道,父进程把密码写入这个管道,子进程通过--passphrase-fd 3读取,避免密码暴露在命令行。
  • 错误处理:代码里包含了管道创建、fork、exec、读写等步骤的错误检查,实际使用时可以根据你的场景调整错误处理逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:10:43