在C++项目中为加密的单个文件进行设置

Make setup for encrypted individual files in a C++ project

本文关键字:文件 单个 设置 加密 C++ 项目      更新时间:2023-10-16

我们有一个C/C++项目,我们希望在其中加密(使用GPG)每个源文件,并使make(特别是GNUMake)无缝工作(就像现在对未加密源文件所做的那样)。

如果我们只加密C或C++文件,这似乎很容易用这样的规则来实现:

%.o : %.cc.gpg %.hh                                                             
    $(GPG) --decrypt $< | $(CXX) $(CFLAGS) -x c++ -c -o $@ -

然而,如果我们开始加密头文件,它会变得更加棘手,因为C文件可能#包括任何数量的头。因此,在我看来,首先我需要生成一个依赖列表,然后解密每一个加密的依赖列表,并进行编译。理想情况下,解密将在内存中完成,而不是在编译时留下解密的文件。

一些笔记,预计我会得到评论:

  • 用户的工作流程将涉及编辑器的GPG插件,但其余部分应尽可能无缝(即传统的基于命令行的Linux svn+make+gcc工作流程)
  • 我们正在使用subversion进行源代码管理。我们知道并同意将源存储为二进制Blob(以及其含义,例如破坏svn-diff)
  • subversion repo位于加密文件系统(LUKS)上,并且只能通过https进行访问
  • 这是一项管理要求
  • 在我对这个问题的网络研究中,我看到很多人反对加密每个源文件。正如我所说,这是一项管理要求。但是,这些参数没有解决的一件事是保护源代码不受系统管理员的影响。是的,在某种程度上,你必须信任人们,但我们的来源有点像可口可乐的配方:如果它不受控制,它可能会毁掉公司。那么,为什么要冒险呢

您有两个问题:1)在构建过程中解密文件,2)将明文保存在RAM中。第二个有点超出我的范围;我建议使用空气间隙工作站,每晚清理磁盘,并配备一个非常好的审计系统,任何指出安全漏洞的人都会得到奖励,而不是惩罚。不管怎样,让我们假设你已经解决了这个问题。(此时,您可以解密整个代码库并正常工作,但让我们尝试找到一个更严格的解决方案。)

对于解密,你已经完成了一半。我不会在%.o规则中解密,而是将其分解为单独的规则:

%.cc : %.cc.gpg                                                             
    $(GPG) --decrypt $<
%.o : %.cc %.hh                                                             
    $(CXX) $(CFLAGS) -x c++ -c -o $@ -

现在,正如您所说,您所要做的就是生成一个依赖项列表。然后,您可以扩展第一条规则以覆盖加密的标头,您就是黄金。

如果你使用的是像g++这样的文明编译器,你可以(通常)用g++ -M生成一个依赖列表,并用它来编写一个"智能"%.o规则,如这里所述,它将自动无形地处理所有依赖问题。

问题是,一开始你不能使用g++ -M,因为你处于一个粘性的循环中:你不想解密所有的头,只想解密你需要的头,所以在你知道你需要哪些头之前,你不能解密,但在你生成依赖文件之前,你不会知道这一点,这意味着运行g++,但如果还没有所需的头,g++会抛出一个错误并退出。

所以我们会作弊。假设我们有一个单独的目录,里面装满了与实际头文件同名的空头文件(使用Make构建/维护很简单)。我们可以指示g++(和Make)在那里查找它在通常位置找不到的任何标头。这还不足以实际编译对象,但足以无错误地运行g++ -M。它构建的依赖关系列表将是不完整的(因为实际的标头可能彼此#include),但对于第一次迭代来说已经足够了。Make可以解密这些标头,然后重新开始;当g++ -M的结果与上一次迭代的列表相同时,过程就完成了,所有需要的头都已解密,可以开始编译。

这个轮廓够了吗?或者你需要帮助安装螺母和螺栓吗?