OK, so Keybase was bought by Zoom and I deleted my Keybase identity. @wiktor@metacode.biz said he had a decentralized alternative.
You can find a simple description here: OpenPGP Proofs.
Here’s how I understand it:
1. on an online service, mention your fingerprint in a particular way
2. add that link to your key in a particular way
3. potentially use some software to verify it, or do it manually
Let’s do this.
Determine my fingerprint:
alex@melanobombus:~$ **gpg --fingerprint alex@gnu.org** pub rsa8192 2015-03-01 [SC] [expires: 2021-05-07] DF94 46EB 7B78 4638 7CCC 018B C78C A29B ACEC FEAE uid [ unknown] Alex Schroeder <alex@gnu.org> uid [ unknown] Alex Schroeder <kensanata@gmail.com> uid [ unknown] [jpeg image of size 5665] uid [ unknown] Alex Schroeder <alex@alexschroeder.ch> sub elg3072 2019-01-20 [E] [expires: 2021-01-30] (and many other expired and revoked keys)
The fingerprint in question, with no spaces and converted to lower case: `df9446eb7b7846387ccc018bc78ca29bacecfeae`
Make sure you’re using the keys.openpgp.org keyserver. For a modern GPG installation, your `~/.gnupg/gpg.conf` file should have this line:
keyserver hkps://keys.openpgp.org
Send your key to keyserver:
alex@melanobombus:~$ **gpg --send-key df9446eb7b7846387ccc018bc78ca29bacecfeae** gpg: sending key C78CA29BACECFEAE to hkps://keys.openpgp.org
I’m going to create a proof for my GitHub account.
Create a new Gist. Use `openpgp.md` as the filename. Write whatever but somewhere in that text, use the String `Verifying my OpenPGP key: openpgp4fpr:{FINGERPRINT}`. Here’s the Gist I created.
Now, edit your key, adding a *notation* pointing to the Gist, save it, and send the key to the keyservers.
alex@melanobombus:~$ **gpg --edit-key df9446eb7b7846387ccc018bc78ca29bacecfeae** Secret key is available. sec rsa8192/C78CA29BACECFEAE created: 2015-03-01 expires: 2021-05-07 usage: SC ssb rsa4096/0C8706F1F6881931 created: 2015-03-01 expired: 2019-02-28 usage: S ssb rsa8192/11C583644529A45C created: 2015-03-01 expired: 2019-02-28 usage: E ssb elg3072/DE6718E639D2D11F created: 2019-01-20 expires: 2021-01-30 usage: E [ unknown] (1). Alex Schroeder <alex@gnu.org> [ unknown] (2) Alex Schroeder <kensanata@gmail.com> [ unknown] (3) [jpeg image of size 5665] [ unknown] (4) Alex Schroeder <alex@alexschroeder.ch> gpg> **notation** Enter the notation: **proof@metacode.biz=https://gist.github.com/kensanata/ffb8ecad8d48c9091ad63fb767534340** No notations on user ID "Alex Schroeder <alex@gnu.org>" Adding notation: proof@metacode.biz=https://gist.github.com/kensanata/ffb8ecad8d48c9091ad63fb767534340 No notations on user ID "Alex Schroeder <kensanata@gmail.com>" Adding notation: proof@metacode.biz=https://gist.github.com/kensanata/ffb8ecad8d48c9091ad63fb767534340 No notations on user ID "[jpeg image of size 5665]" Adding notation: proof@metacode.biz=https://gist.github.com/kensanata/ffb8ecad8d48c9091ad63fb767534340 No notations on user ID "Alex Schroeder <alex@alexschroeder.ch>" Adding notation: proof@metacode.biz=https://gist.github.com/kensanata/ffb8ecad8d48c9091ad63fb767534340 sec rsa8192/C78CA29BACECFEAE created: 2015-03-01 expires: 2021-05-07 usage: SC ssb rsa4096/0C8706F1F6881931 created: 2015-03-01 expired: 2019-02-28 usage: S ssb rsa8192/11C583644529A45C created: 2015-03-01 expired: 2019-02-28 usage: E ssb elg3072/DE6718E639D2D11F created: 2019-01-20 expires: 2021-01-30 usage: E [ unknown] (1). Alex Schroeder <alex@gnu.org> [ unknown] (2) Alex Schroeder <kensanata@gmail.com> [ unknown] (3) [jpeg image of size 5665] [ unknown] (4) Alex Schroeder <alex@alexschroeder.ch> gpg> **save** alex@melanobombus:~$ **gpg --send-key df9446eb7b7846387ccc018bc78ca29bacecfeae** gpg: sending key C78CA29BACECFEAE to hkps://keys.openpgp.org
If you’re wondering about the `proof@metacode.biz` key used, there’s an explanation in the FAQ:
This e-mail-like string is actually notation key. RFC 4880 specifies this kind of format as a way to namespace custom notations. You need to create notations under the domain that you own to avoid conflicts. I used my own domain for this protocol. Ideally the notation key would be just proof. Using this kind of keys (without @ namespacing) is only allowed for IETF-approved extensions though (I did not approach them).
So, one day it might be just `proof`. But we need to agree on a key for tools to work and so `proof@metacode.biz` is as good as any.
Here’s how to manually verify the key:
alex@melanobombus:~$ **gpg --list-options show-notations --list-sigs df9446eb7b7846387ccc018bc78ca29bacecfeae | grep proof** Signature notation: proof@metacode.biz=https://gist.github.com/kensanata/ffb8ecad8d48c9091ad63fb767534340 Signature notation: proof@metacode.biz=https://gist.github.com/kensanata/ffb8ecad8d48c9091ad63fb767534340 Signature notation: proof@metacode.biz=https://gist.github.com/kensanata/ffb8ecad8d48c9091ad63fb767534340 Signature notation: proof@metacode.biz=https://gist.github.com/kensanata/ffb8ecad8d48c9091ad63fb767534340
Visit the URL and check that the fingerprint mentioned is in fact the fingerprint you used in your query. If so, verified! ✔
And here’s how to do it automatically.
You can host the web app somewhere, or use Wiktor’s installation, passing along the fingerprint in question as part of the URL:
This is soooo beautiful! 😍
Thanks, Wiktor!
That’s all I ever wanted Keybase to do for me. And now there’s a way to do this, but decentralized. This is awesome.
I’m adding my fingerprint as one of the four profile metadata elements available to me on Mastodon, followed by:
gpg --edit-key df9446eb7b7846387ccc018bc78ca29bacecfeae notation proof@metacode.biz=https://octodon.social/@kensanata save gpg --send-key df9446eb7b7846387ccc018bc78ca29bacecfeae
I’m posting the same text I used above to Reddit, followed by:
gpg --edit-key df9446eb7b7846387ccc018bc78ca29bacecfeae notation proof@metacode.biz=https://www.reddit.com/user/kensanata/comments/gfzrkn/proof_of_identity_decentralized/ save gpg --send-key df9446eb7b7846387ccc018bc78ca29bacecfeae
Remember, we’re using keys.openpgp.org. They don’t publish email addresses unless you’ve agreed to it. That means a confirmation mail per email. We need to do the following for every email address we want to make available:
1. submit it to `keys.openpgp.org`
2. get the confirmation link
3. click the link to request a confirmation mail
4. click the link in the confirmation mail
In order to get started, you have to submit your key *without* using `--send-key`. I know, it’s weird. But that’s the way to get the confirmation link:
alex@melanobombus:~$ **gpg --export alex@alexschroeder.ch | curl -T - https://keys.openpgp.org** Key successfully uploaded. Proceed with verification here: https://keys.openpgp.org/upload/...
Click the link to request the confirmation mail, wait for the confirmation mail, click the link in the confirmation mail, and now your address is listed!
Verify this by search for your email addresses on keys.openpgp.org.
Do this for every email address you want to see listed (possibly all of them).
Remember how I said above that you can pass the fingerprint of a key to the web app, like this:
https://alexschroeder.ch/openpgp/#0xdf9446eb7b7846387ccc018bc78ca29bacecfeae
If you’re self-hosting your email, there’s the option of allowing an email address instead of the fingerprint, using a Web Key Directory. One day, tools will be able to handle encryption without having to know about fingerprints. 🙂 The same is true for the web app:
https://alexschroeder.ch/openpgp/#alex@alexschroeder.ch
If you have control over a domain but don’t use it for email, there’s still a way to get this to work using a subdomain under your control and `keys.openpgp.org` but I’m not going to cover that. I would have to do that for my GNU and GMail addresses. The following section just covers the email address I receive under my own domain, `alex@alexschroeder.ch`.
In order for this to work, we need to do the following:
1. export our key
2. rename it so it matches the hash of the local part (`alex` in my case)
3. serve it from the same domain from a well-known location
Let’s determine the hash using `--with-wkd`:
alex@melanobombus:~$ **gpg --list-keys --with-wkd alex@alexschroeder.ch** pub rsa8192 2015-03-01 [SC] [expires: 2021-05-07] DF9446EB7B7846387CCC018BC78CA29BACECFEAE uid [ unknown] Alex Schroeder <alex@gnu.org> cddpr77ezsy7h967hgjydxhhmnt76n8w@gnu.org uid [ unknown] Alex Schroeder <kensanata@gmail.com> cps1z1ccmfq5zj33zg7z3s49sehtefwz@gmail.com uid [ unknown] [jpeg image of size 5665] uid [ unknown] Alex Schroeder <alex@alexschroeder.ch> cddpr77ezsy7h967hgjydxhhmnt76n8w@alexschroeder.ch sub elg3072 2019-01-20 [E] [expires: 2021-01-30]
Thus, I need to export my public key using `gpg --export alex@alexschroeder.ch > cddpr77ezsy7h967hgjydxhhmnt76n8w` and serve it from `https://alexschroeder.ch/.well-known/openpgpkey/hu/`.
In addition to that, I created a `.htaccess` file in my `openpgpkey` directory containing the following:
Options -Indexes Header set Access-Control-Allow-Origin "*"
The first line disables the listing of directory contents and the second line sets the Access-Control-Allow-Origin such that this information may be retrieved from elsewhere, not just my own server.
You can test the setup using Wiktor’s Web Key Directory page.
Sadly, when testing it from the command line, it doesn’t work as expected. Here I am, using `--locate-keys` from a different account where I don’t have access to my key:
alex@sibirocobombus:~$ **gpg --locate-keys alex@alexschroeder.ch** gpg: error retrieving 'alex@alexschroeder.ch' via WKD: No data gpg: error reading key: No data
Oops! 😭
Something’s missing. But what is it?
On your webserver, create a directory called `openpgp` with a copy of the files in the openpgp-proofs repository. The directory I’m using is accessible from the web as `https://alexschroeder.ch/openpgp`. This is important later because the script expects `proofs.json` at this location.
Run `npm install --production` in this directory. You’ll get a bunch of dependencies installed into the `node_modules` directory.
If you’re like me and you’ve set a Content Security Policy, you need to allow clients to make requests to the keyserver and to all the sites hosting the proofs. Thus, we really need to relax our CSP, unfortunately. But there’s no way around it!
In my `.htaccess` file, I put:
DirectoryIndex index.html Header set Content-Security-Policy "default-src https: data:; object-src 'none'; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'"
And here it is! 😀
Note that my primary browser is Firefox which blocks a bunch of requests so that the proofs cannot be fetched. When I use Chromium, which is less paranoid, all my proofs are verified. 👍
#Cryptography