Realice la configuration de files individuales encryptions en un proyecto de C ++

Tenemos un proyecto de C / C ++ en el que deseamos encriptar (con GPG) cada file de código fuente único, y hacer que make (específicamente, GNU Make) funcione a la perfección (como lo hace ahora con una fuente no encriptada).

Si ciframos solo los files C o C ++, esto parece bastante fácil de lograr con una regla como esta:

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

Sin embargo, si comenzamos a cifrar files de encabezado, se vuelve mucho más complicado, ya que el file C puede include #include cualquier número de encabezados. Así que me parece que primero necesito generar una list de dependencies, luego descifrar cada una de las que está encriptada y comstackr. Idealmente, el desencryption se realizaría en la memory, en lugar de dejar files desencryptions en blanco mientras se realiza la compilation.

Algunas notas, anticipándome a los comentarios que obtendré:

  • El flujo de trabajo de los usuarios implicará los complementos de GPG para su editor, pero el rest debe ser lo más transparente posible (es decir, el flujo de trabajo de svn + make + gcc basado en command-line tradicional)
  • Estamos usando subversion para el control de fuente. Sabemos y estamos de acuerdo con que la fuente se almacene como blobs binarys (así como las implicaciones de esto, por ejemplo, al romper svn diff)
  • El repository de subversión vive en un sistema de files encriptado (LUKS), y el acceso es solo a través de https
  • Este es un requisito de gestión
  • En mi investigación en la web de este problema, he visto a mucha gente argumentar en contra de encriptar cada file fuente. Como dije, es un requisito de gestión. Pero una cosa que no se aborda con estos arguments es mantener la fuente a salvo de los administradores de sistemas. Sí, en algún momento debes confiar en la gente, pero nuestra fuente es como la receta de Coke: si no se controla, literalmente podría arruinar a la empresa. Entonces, ¿por qué correr riesgos?

Tiene dos problemas: 1) descifrar files en el process de compilation y 2) mantener el text sin formatting en la RAM. El segundo es un poco fuera de mi campo; Sugiero estaciones de trabajo con espacios de air con lavado nocturno de discos y un sistema de auditoría realmente bueno, y cualquiera que señale un defecto en la security es recompensado, no castigado . De todos modos supongamos que has resuelto ese problema. (En este punto, puede descifrar toda la base de códigos y trabajar normalmente, pero tratemos de encontrar una solución más estricta).

Para el desencryption, estás a mitad de path. En lugar de descifrar en la regla %.o , la %.o en reglas separadas:

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

Ahora, como dices, todo lo que tienes que hacer es generar una list de dependencia. Luego puedes expandir la primera regla para cubrir encabezados encriptados y estás dorado.

Si está utilizando un comstackdor civilizado como g ++, puede (en general) generar una list de dependencia con g++ -M , y usar eso para escribir una regla "inteligente" %.o tal como se describe aquí , que manejará todos los problemas de dependencia de forma automática e invisible.

El problema es que no puedes usar g++ -M al principio, porque estás en un círculo viscoso: no quieres descifrar todos los encabezados, solo los que necesitas, por lo que no puedes descifrarlos hasta que sepa qué encabezados necesita, pero no lo sabrá hasta que genere los files de dependencia, lo que significa que ejecutará g ++, pero g ++ arrojará un error y saldrá si ya no hay un encabezado necesario.

Entonces haremos trampa. Supongamos que tenemos un directory separado lleno de files de encabezado vacíos con los mismos nombres que los files de encabezado reales (triviales para comstackr / mantener con Make). Podemos dirigir g ++ (y Make) para search allí encabezados que no puede encontrar en el lugar habitual. Eso no es suficiente para comstackr realmente objects, pero es suficiente para ejecutar g++ -M sin error. La list de dependencies que construye estará incompleta (porque los encabezados reales pueden #include entre sí) pero es suficiente para la primera iteración . Make puede descifrar esos encabezados, luego comenzar de nuevo; cuando los resultados de g++ -M son los mismos que en la list de la iteración anterior, el process está completo, todos los encabezados necesarios se han desencryption y puede comenzar la compilation.

¿Es suficiente ese esquema, o necesitas ayuda con la tuerca y los pernos?