c over pipe实时流gpg加密

时间:2018-02-25 17:22:09

标签: c encryption pipe sh gnupg

我试图使用gpg实时加密数据。我已经直接使用libgcrypt,但我需要一个标准格式。我放弃了gpgme,因为它似乎不适合实时流应用程序。

我想要完成的是这个命令行:

gpg --passphrase hackerpass --symmetric -c

在终端中运行良好,打印标题,输出数据并以页脚结尾,使用EOF CTRL-D,完美无缺!

这是示例代码,简单的fork,双向管道,我写数据并异步等待结果 ... gpg的执行没有结束,实际上似乎数据没有到达,我只收到标题,在fd关闭gpg没有收到EOF:

#include <fcntl.h>
#include <sys/wait.h>
#include <sys/prctl.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char *argv[]) {

    pid_t pid = 0;
    int inpipefd[2];
    int outpipefd[2];
    char buf[256];
    int status;

    pipe(inpipefd);
    pipe(outpipefd);

    pid = fork();

    if (pid == 0) {
        // Child       

        dup2(outpipefd[0], STDIN_FILENO);
        dup2(inpipefd[1], STDOUT_FILENO);
        //dup2(inpipefd[1], STDERR_FILENO);

        //ask kernel to deliver SIGTERM in case the parent dies
        prctl(PR_SET_PDEATHSIG, SIGTERM);

        execlp("/bin/sh", "/bin/sh", "-c", "/usr/bin/gpg --passphrase pass --symmetric -c", (char *) NULL);

        exit(1);
    }

    //close unused pipe ends
    close(outpipefd[0]);
    close(inpipefd[1]);

    int flags;

    flags = fcntl(inpipefd[0], F_GETFL, 0);
    flags |= O_NONBLOCK;
    fcntl(inpipefd[0], F_SETFL, flags);

    // write example data       

    char *data = "dummy dummy";

    ssize_t out = write(outpipefd[1], data, strlen(data));

    if (out != strlen(data)) {
        printf("fail write\n");
        exit(-1);
    }

    close(outpipefd[1]);

    int hasPendingData = 1;

    while (hasPendingData) {

        ssize_t r = read(inpipefd[0], buf, 255);

        if (r == -1 && errno == EAGAIN) {
            // in process
            printf("no data available, wait...\n");
            usleep(500000);

        } else if (r > 0) {
            printf("Incoming %ld bytes\n", (long) r);

        } else {
            // EOF 
            hasPendingData = 0;
            printf("no mode data available, exit...\n");
        }

    }

    waitpid(pid, &status, 0);

    return 0;
}

1 个答案:

答案 0 :(得分:0)

这里只是猜测,但在子流程中有几个未闭合的重复文件描述符。在这些文件描述符关闭之前,Gpg不会获得EOF。只要任何进程都可以写入它们,它就会一直等待更多。

需要注意的另一件事是在写等待你的进程读取管道时gpg阻塞。如果发生这种情况,您的写作阶段可能会被阻止。不会发生非常少量的数据,但如果您放入任何数据量,可能会在以后发生。写入和读取都需要非阻塞并同时运行。