NeoPG combines all code in a single repository, while GnuPG uses many repositories. This article explains why.
In NeoPG, all the source code is in a single repository. This is in stark contrast to GnuPG, which splits up the source code of the whole into several different repositories:
This split puts a high burden on users, developers, and distributions. Each software package must be maintained individually. There is a significant amount of code duplication across these packages. And because the components can be upgraded independently of each other, spurious warnings or errors can occur that are frustrating users.
Build instructions are shared in
passed around like trade secrets. To make it easier for me, I wrote a
small script called
speedo.mk that downloads, configures and builds
all required packages and installs them into a single directory.
Because this was such a repetetive process, I used template meta
programming in GNU Make. Those were the days! Today, speedo.mk is
part of the GnuPG distribution and recommended in the README.
Not all of this overhead and complication is necessary. For most of these libraries, there are no other users but GnuPG.1 npth, libgpg-error, libassuan and libksba are internal implementation details of GnuPG that the user needs to know nothing about.
And GPGME, which is the public interface to GnuPG for applications, requires GnuPG to work. Distributing it without GnuPG in a standalone package serves no meaningful purpose from a technical point of view.
This leaves us with libgcrypt. Libgcrypt was split from GnuPG 1 to provide a reusable crypto-library for the GNU system. And in fact, it was used by GnuTLS for some time. But in 2011 GnuTLS switched to libnettle, for performance reasons, but also because libgcrypt had, from their perspective, an unnecessary dependency on libgpg-error.
Today, libgcrypt is still is used by a couple of other packages, some
of them powerhorse applications of the free software community. I
apt-cache rdepends libgcrypt20 on Ubuntu 16.04, and
found the following:
gcry_error_tin its public interface. libotr development has stalled since 2014, with a security update in 2016.
So, it makes sense for libgcrypt to be managed as a standalone package.
Asking for a passphrase is difficult to do, because there is no standard interface for that. This means that the implementation will be different from operating to operating system, and also from use case to use case. Batch processing on the server, mobile phones, desktop environments, all require different solutions. This is a good reason to keep passphrase dialog implementations (except for basic terminal support) outside the main code base. We will take a closer look at pinentry in a future blog post.
The first thing I did for NeoPG was to combine all components of GnuPG
in a single repository (currently in a subdirectory
Immediately, this makes NeoPG easier to download, build, and modify.
But this was also done in anticipation of a major refactorisation of
the code base.
I want to replace libgcrypt with another crypto library, Botan.
Having a copy of libgcrypt in the tree helps with this restructuring,
as it allows changes at any level of the implementation. It also
makes it easier to understand the impact of any change, and which
parts of the library are still used (directly or indirectly). Botan
can also replace libksba and several parts of GnuPG itself (in
particular dirmngr and GnuPG’s pipe/filter implementation
so this is not just a matter of replacing the libgcrypt interface with
an alternative implementation. I will explain the reasons for
changing the crypto library in a future blog post.
I also want to remove the need for npth, libgpg-error and libassuan entirely. This does not mean to replace them with alternatives that provide the same interface. It means restructuring the whole code base to make these libraries unnecessary. This is easier to do “vertically” at all interface layers at the same time, one feature at a time, rather than trying to remove one library entirely, and then another. For example, some parts of these libraries are concerned about use of network sockets for communication. If the use of sockets is removed, some part in npth, some part in libgpg-error, and some part in libassuan can be removed at the same time. Again, this is much easier done if all of the source code is in one place.
Building NeoPG should be as simple as:
$ cd build $ cmake .. $ make
Of course, there are some dependencies, notably a C++ compiler, Boost, SQLite, gettext and Botan. Of these, only Botan is an “exotic” dependency that is not normally included in a distribution. If distributions are slow to pick up Botan 2, NeoPG will include a copy of Botan in the source code to make it easy for people to build.2