OpenPGP is an encryption and authentication system which is
extensively used at Tor.

[[_TOC_]]

# Tutorial

<!-- simple, brainless step-by-step instructions requiring little or -->
<!-- no technical background -->

# How-to

<!-- more in-depth procedure that may require interpretation -->

## Diffing OpenPGP keys, signatures and encrypted files from Git

Say you store OpenPGP keyrings in git. For example, you track package
repositories public signing keys or you have a directory of user
keys. You need to update those keys but want to make sure the update
doesn't add untrusted key material.

This guide will setup your git commands to show a meaningful diff of
binary or ascii-armored keyrings.

 1. add this to your `~/.gitconfig` (or, if you want to restrict it to
    a single repository, in `.git/config`:
    
        # handler to parse keyrings
        [diff "key"]
        textconv = gpg --batch --no-tty --with-sig-list --show-keys <

        # handler to verify signatures
        [diff "sig"]
            textconv = gpg --batch --no-tty --verify <
        
        # handler to decrypt files
        [diff "pgp"]
            textconv = gpg --batch --no-tty --decrypt <

 2. add this to your `~/.config/git/attributes` (or, the per
    repository `.gitattributes` file), so that those handlers are
    mapped to file extensions:
    
        *.key diff=key
        *.sig diff=sig
        *.pgp diff=pgp

    `.key`, `.sig`, and `.pgp` are "standard" extensions (as per
    `/etc/mime.types`), but people frequently use other extensions, so
    you might want to have this too:
    
        *.gpg diff=key
        *.asc diff=key

Then, when you change a key, `git diff` will show you something like
this, which is when the GitLab package signing key was renewed:

```
commit c29047357669cb86cf759ecb8a44e14ca6d5c130
Author: Antoine Beaupré <anarcat@debian.org>
Date:   Wed Mar 2 15:31:36 2022 -0500

    renew gitlab's key which expired yesterday

diff --git a/modules/profile/files/gitlab/gitlab-archive-keyring.gpg b/modules/profile/files/gitlab/gitlab-archive-keyring.gpg
index e38045da..3e57c8e0 100644
--- a/modules/profile/files/gitlab/gitlab-archive-keyring.gpg
+++ b/modules/profile/files/gitlab/gitlab-archive-keyring.gpg
@@ -1,7 +1,7 @@
-pub   rsa4096/3F01618A51312F3F 2020-03-02 [SC] [expired: 2022-03-02]
+pub   rsa4096/3F01618A51312F3F 2020-03-02 [SC] [expires: 2024-03-01]
       F6403F6544A38863DAA0B6E03F01618A51312F3F
 uid                            GitLab B.V. (package repository signing key) <packages@gitlab.com>
-sig 3        3F01618A51312F3F 2020-03-02  GitLab B.V. (package repository signing key) <packages@gitlab.com>
-sub   rsa4096/1193DC8C5FFF7061 2020-03-02 [E] [expired: 2022-03-02]
-sig          3F01618A51312F3F 2020-03-02  GitLab B.V. (package repository signing key) <packages@gitlab.com>
+sig 3        3F01618A51312F3F 2022-03-02  GitLab B.V. (package repository signing key) <packages@gitlab.com>
+sub   rsa4096/1193DC8C5FFF7061 2020-03-02 [E] [expires: 2024-03-01]
+sig          3F01618A51312F3F 2022-03-02  GitLab B.V. (package repository signing key) <packages@gitlab.com>
 
[...] 
```

The reasoning behind each file extension goes as follows:

 * `.key` - OpenPGP key material. process it with --show-keys < file
 * `.sig` - OpenPGP signature. process it with --verify < file
 * `.pgp` - OpenPGP encrypted material. process it with --decrypt < file
 * `.gpg` - informal. can be anything, but generally assumed to be
   binary. we treat those as OpenPGP keys, because that's the safest
   thing to do
 * `.asc` - informal. can be anything, but generally assumed to be
   ASCII-armored, assumed to be the same as `.gpg` otherwise.

We also use those options:

 * `--batch` is, well, never sure what `--batch` is for, but seems
   reasonable?
 * `--no-tty` is to force GnuPG to not assume a terminal which may
   make it prompt the user for things, which could break the pager

Note that, you might see the advice to run `gpg < file` (without any
arguments) elsewhere, but we advise against it. In theory, `gpg <
file` can do anything, but it will typically:

 1. decrypt encrypted material, or;
 2. verify signed material, or;
 3. show public key material

From what I can tell in the source code, it will also process private
key material and other nasty stuff, so it's unclear if it's actually
safe to run at all. See `do_proc_packets()` that is called with
`opt.list_packets == 0` in the GnuPG source code.

Also note that, without `<`, git passes a the payload to `gpg` through
a binary file, and GnuPG then happily decrypts it and puts in publicly
readable in `/tmp`. boom. This behavior was filed in 2017 as a bug
upstream ([T2945](https://dev.gnupg.org/T2945)) but was downgraded to a "feature request" by the
GnuPG maintainer a few weeks later. No new activity at the time of
writing (2022, five years later).

All of this is somewhat brittle: `gpg < foo` is not supposed to work
and may kill your cat. Bugs should be filed to have something that
does the right thing, or at least not kill defenseless animals.

## Pager playbook

<!-- information about common errors from the monitoring system and -->
<!-- how to deal with them. this should be easy to follow: think of -->
<!-- your future self, in a stressful situation, tired and hungry. -->

## Disaster recovery

<!-- what to do if all goes to hell. e.g. restore from backups? -->
<!-- rebuild from scratch? not necessarily those procedures (e.g. see -->
<!-- "Installation" below but some pointers. -->

# Reference

## Installation

<!-- how to setup the service from scratch -->

## SLA

<!-- this describes an acceptable level of service for this service -->

## Design

OpenPGP is standardized as [RFC4880](https://datatracker.ietf.org/doc/html/rfc4880), which defines it as such:

> OpenPGP software uses a combination of strong public-key and
> symmetric cryptography to provide security services for electronic
> communications and data storage.

The most common OpenPGP implementation is GnuPG, but there are others.

<!-- how this is built -->
<!-- should reuse and expand on the "proposed solution", it's a -->
<!-- "as-built" documented, whereas the "Proposed solution" is an -->
<!-- "architectural" document, which the final result might differ -->
<!-- from, sometimes significantly -->

<!-- a good guide to "audit" an existing project's design: -->
<!-- https://bluesock.org/~willkg/blog/dev/auditing_projects.html -->

<!-- things to evaluate here:

 * services
 * storage (databases? plain text files? cloud/S3 storage?)
 * queues (e.g. email queues, job queues, schedulers)
 * interfaces (e.g. webserver, commandline)
 * authentication (e.g. SSH, LDAP?)
 * programming languages, frameworks, versions
 * dependent services (e.g. authenticates against LDAP, or requires
   git pushes) 
 * deployments: how is code for this deployed (see also Installation)

how is this thing built, basically? -->

## Issues

<!-- such projects are never over. add a pointer to well-known issues -->
<!-- and show how to report problems. usually a link to the bugtracker -->

There is no issue tracker specifically for this project, [File][] or
[search][] for issues in the [team issue tracker][search].

 [File]: https://gitlab.torproject.org/tpo/tpa/team/-/issues/new
 [search]: https://gitlab.torproject.org/tpo/tpa/team/-/issues

## Maintainer, users, and upstream

<!-- document who deployed and operates this service, who the users -->
<!-- are, who the upstreams are, if they are still active, -->
<!-- collaborative, how do we keep up to date, -->

## Monitoring and testing

<!-- describe how this service is monitored and how it can be tested -->
<!-- after major changes like IP address changes or upgrades. describe -->
<!-- CI, test suites, linting, how security issues and upgrades are -->
<!-- tracked -->

## Logs and metrics

<!-- where are the logs? how long are they kept? any PII? -->
<!-- what about performance metrics? same questions -->

## Backups

<!-- does this service need anything special in terms of backups? -->
<!-- e.g. locking a database? special recovery procedures? -->

## Other documentation

<!-- references to upstream documentation, if relevant -->

# Discussion

## Overview

<!-- describe the overall project. should include a link to a ticket -->
<!-- that has a launch checklist -->

<!-- if this is an old project being documented, summarize the known -->
<!-- issues with the project. to quote the "audit procedure":

 5. When was the last security review done on the project? What was
    the outcome? Are there any security issues currently? Should it
    have another security review?

 6. When was the last risk assessment done? Something that would cover
    risks from the data stored, the access required, etc.

 7. Are there any in-progress projects? Technical debt cleanup?
    Migrations? What state are they in? What's the urgency? What's the
    next steps?

 8. What urgent things need to be done on this project?

-->

## Goals

<!-- include bugs to be fixed -->

### Must have

### Nice to have

### Non-Goals

## Approvals required

<!-- for example, legal, "vegas", accounting, current maintainer -->

## Proposed Solution

## Cost

## Alternatives considered

<!-- include benchmarks and procedure if relevant -->

