Certificate Authorities are a form of centralized trust for which fully decentralized websites require an alternative. CAs are at the heart of the Public Key Infrastructure that provides authenticity, integrity, and confidentiality to millions of users around the world. While the tools to provide Web3 users with the similar capabilities are mostly complete, I see gaps in authentication capabilities, some of which I have attempted to fill.

Confidentiality and integrity are largely solved problems. Confidentiality can be established with libp2p security transports and Tor. Files published through IPFS aren’t vulnerable to integrity issues as long as the content hashing scheme holds. Authentication is the only capability for which support is lacking.

If one trusts the public key of an ENS domain controller, an ENS record pointing to IPFS CID establishes authenticity for entire site. ENS records are continually updated, however, so old revisions of the site become unverifiable. Maintaining a history of ENS records would require non-trivial revisions to the ENS smart contract, and cause the data associated with a given domain to grow without bound, particularly busy sites.

Fortunately, we have an existing distributed trust model in the form of the venerable GnuPG. While GPG is famously unintuitive, front ends like Seahorse and hardware solutions like YubiKey have alleviated some of this pain, and quickstart guides abound.

An inline PGP signature makes HTML document validation difficult and corrupts a binary file, so we must use detached signatures. Signatures on one or two files at the root of the website isn’t enough; signed files can be re-bundled with corrupted or inauthentic data. Every file must be signed.

Serially signing many files with GnuPG is not fast, but modern CPUs have many threads which are frequently idle. Using GNU parallel and Python multiprocessing exhibited odd out-of-memory errors until Werner Koch, principle developer of GnuPG, explained:

This is all serialized because the gpg-agent does the actual signing. There is one gpg-agent per GNUPGHOME. Thus the easiest solution for you is to provide copies of the GNUPGHOME and either set this envvar for each process or pass –homedir=decicated-homedir-copy. You can’t use links to the same directory because we use lock files. However, it should be possible to sumlink the private-keys-v1.d sub directories.

Armed with this knowledge, I wrote a Python script that generates good PGP signatures across every file on the website while fully utilizing all 16 of my CPU’s threads. The result can be seen on brainvitamins.eth. For any given file, a corresponding .sig file should exist that can be verified using my public key.

Next step: building a browser extension to automatically verify signatures and trust pubkeys as required.