在 C++ 中对加密的单个文件进行设置项目
我们有一个 C/C++ 项目,我们希望(使用 GPG)加密每个源文件,并让 make(特别是 GNU Make)无缝工作(就像现在使用未加密源一样)。
如果我们只加密 C 或 C++ 文件,那么使用这样的规则似乎很容易完成:
%.o : %.cc.gpg %.hh
$(GPG) --decrypt $< | $(CXX) $(CFLAGS) -x c++ -c -o $@ -
但是,如果我们开始加密头文件,它会变得更加棘手,因为 C 文件可能 #include 任意数量的头。所以在我看来,首先我需要生成一个依赖项列表,然后解密每个加密的依赖项列表,然后编译。理想情况下,解密将在内存中完成,而不是在编译时将解密的文件留在周围。
一些注释,以预期我将收到的评论:
- 用户的工作流程将涉及其编辑器的 GPG 插件,但其余部分应尽可能无缝(即传统的基于命令行的 Linux svn + make + gcc 工作流程
- )使用 Subversion 进行源代码控制。我们知道并且可以接受将源存储为二进制 blob(以及这样做的含义,例如破坏 svn diff)
- Subversion 存储库位于加密文件系统(LUKS)上,并且只能通过 https 进行访问
- 是管理要求
- 这 在我对这个问题的网络研究中,我看到很多人反对加密每个源文件。正如我所说,这是管理要求。但这些论点没有解决的一件事是确保源代码免受系统管理员的侵害。是的,在某些时候你必须信任别人,但我们的消息来源有点像可口可乐的配方:如果不受控制,它实际上可能会毁掉公司。那么为什么要冒险呢?
We have a C/C++ project where we wish to encrypt (with GPG) every single source file, and have make (specifically, GNU Make) seamlessly work (as it does now with unencrypted source).
If we encrypt only the C or C++ files, this seems fairly easy to accomplish with a rule like this:
%.o : %.cc.gpg %.hh
$(GPG) --decrypt lt; | $(CXX) $(CFLAGS) -x c++ -c -o $@ -
However, if we start encrypting header files, it gets a lot trickier, as the C file may #include any number of headers. So it seems to me that first I need to generate a dependency list, then decrypt every one that is encrypted, and compile. Ideally, the decryption would be done in-memory, rather than leaving decrypted files laying around while compilation takes place.
Some notes, in anticipation of the comments I'll get:
- The users' workflow will involve GPG plugins for their editor, but the rest should be as seamless as possible (i.e. traditional commandline-based Linux svn + make + gcc workflow)
- We are using subversion for source control. We know and are OK with source being stored as binary blobs (as well as the implications of this, e.g. breaking svn diff)
- The subversion repo lives on an encrypted filesystem (LUKS), and access is only through https
- This is a management requirement
- In my web research of this problem, I've seen a lot of people argue against encrypting every source file. As I said, it's a management requirement. But one thing that is not addressed by these arguments is keeping the source safe from sysadmins. Yes, at some point you have to trust people, but our source is kind of like the recipe to Coke: if it is uncontrolled, it could literally ruin the company. So why take chances?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您有两个问题:1)在构建过程中解密文件,2)将明文保存在 RAM 中。第二个有点超出我的领域;我建议使用带有夜间磁盘擦洗功能的气隙工作站和一个非常好的审核系统,任何指出安全缺陷的人都会得到奖励,而不是惩罚。不管怎样,我们假设你已经解决了这个问题。 (此时,您可以解密整个代码库并正常工作,但让我们尝试找到更严格的解决方案。)
对于解密,您已经完成了一半。我不会在
%.o
规则中解密,而是将其分解为单独的规则:现在正如您所说,您所要做的就是生成依赖项列表。然后您可以扩展第一条规则以覆盖加密标头,这样您就成功了。
如果您使用像 g++ 这样的文明编译器,您(通常)可以使用
g++ -M
生成依赖项列表,并使用它来编写“智能”%.o 规则,如此处所述,它将自动且不可见地处理所有依赖问题。
问题是你一开始不能使用 g++ -M ,因为你处于一个粘性循环中:你不想解密所有的标头,只想解密你需要的标头,所以在知道需要哪些标头之前,您无法进行解密,但在生成依赖文件之前您不会知道这一点,这意味着运行 g++,但如果所需的标头不存在,g++ 会抛出错误并退出已经。
所以我们会作弊。假设我们有一个单独的目录,其中充满了与真实头文件同名的空头文件(使用 Make 构建/维护很简单)。我们可以指示 g++(和 Make)在那里查找它在通常位置找不到的任何标头。这还不足以实际编译对象,但足以运行
g++ -M
而不会出现错误。它构造的依赖项列表将是不完整的(因为真正的标头可能彼此#include
),但对于第一次迭代来说已经足够了。 Make 可以解密这些标头,然后重新开始;当 g++ -M 的结果与上一次迭代的列表相同时,该过程完成,所有需要的标头都已解密,可以开始编译。这个大纲足够了,还是您需要有关具体细节的帮助?
You have two problems: 1) decrypting files in the build process and 2) keeping the cleartext in RAM. The second is a little out of my field; I'd suggest air-gapped workstations with nightly disc-scrubbing and a really good auditing system, and anyone who points out a flaw in security gets rewarded, not punished. Anyway let's assume you've solved that problem. (At this point you could just decrypt the whole code base and work normally, but let's try to find a tighter solution.)
For the decryption, you're halfway there. Instead of decrypting in the
%.o
rule I'd break it into separate rules:Now as you say, all you have to do is generate a dependency list. Then you can expand the first rule to cover encrypted headers and you're golden.
If you're using a civilized compiler like g++, you can (in general) generate a dependency list with
g++ -M
, and use that to write a "smart"%.o
rule such as described here, which will handle all dependency problems automatically and invisibly.The problem is that you can't use
g++ -M
at first, because you're in a viscous circle: you don't want to decrypt all of the headers, just the ones you need, so you can't do the decryption until you know which headers you need, but you won't know that until you generate the dependency files, which means running g++, but g++ will pitch an error and quit if a needed header isn't there already.So we'll cheat. Suppose we have a separate directory full of empty header files with the same names as the real header files (trivial to build/maintain with Make). We can direct g++ (and Make) to look there for any headers it can't find in the usual place. That is not enough to actually compile objects, but it is enough to run
g++ -M
without error. The dependency list it constructs will be incomplete (because the real headers may#include
each other) but it is enough for the first iteration. Make can decrypt those headers, then start over; when the results ofg++ -M
are the same as the list from the previous iteration, the process is complete, all needed headers have been decrypted and compilation can begin.Is that outline enough, or do you need help with the nut and bolts?