Hagrid
======
Hagrid is a verifying OpenPGP key server. When a new key is uploaded a
token is sent to each user ID via email. This token can be used to verify the
user ID. Keys can be queried by their verified user IDs (exact match) and their
primary keys fingerprint. Keys can be deleted by clicking a link send to all
user IDs.
License
-------
Hagrid is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Hagrid is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
License for more details.
You should have received a copy of the GNU Affero General Public
License along with Hagrid. If not, see
.
Quick Start
-----------
Building Hagrid required a working [Rust _nightly_
toolchain](https://rust-lang.org). The key server uses the filesystem to store
keys, user IDs and tokens. To run it, supply the absolute path to where you
want the database to live and the absolute path to the template directory.
```bash
cp Rocket.toml.dist Rocket.toml
cargo run --bin hagrid
```
This will spawn a web server listening on port 8080.
Hagrid uses `sendmail` for mailing, so you also need a working local mailer
setup.
Usage
-----
### HKP
Hagrid implements a subset of the [HKP][] protocol so that tools like
GnuPG and OpenKeychain can use it without modification.
[HKP]: https://tools.ietf.org/html/draft-shaw-openpgp-hkp-00
#### `GET /pks/lookup?op=get&options=mr&search=`
Returns an *ASCII Armored* key matching the query. Query may be:
- An exact email address query of the form `localpart@example.org`.
- A hexadecimal representation of a long *KeyID* of either a primary
key, or a subkey (`069C0C348DD82C19`, optionally prefixed by `0x`).
- A hexadecimal representation of a *Fingerprint* of either a primary
key, or a subkey (`8E8C33FA4626337976D97978069C0C348DD82C19`,
optionally prefixed by `0x`).
Note that while the hexadecimal digits may use either case, using
upper case letters is more efficient with Hagrid.
#### `GET /pks/lookup?op=index&options=mr&search=`
Returns a [machine-readable list][] of keys matching the query. Query may
have the forms detailed above. Hagrid always returns either one or no
keys at all.
[machine-readable list]: https://tools.ietf.org/html/draft-shaw-openpgp-hkp-00#section-5.2
#### `POST /pks/add`
Keys may be submitted using a POST request to `/pks/add`, the body of
the request being a `application/x-www-form-urlencoded` query.
`keytext` must be the keys to submit, which must be *ASCII Armored*.
More than one key may be submitted in one request.
#### Limitations
By design, Hagrid cannot (or intentionally chooses not to) implement
the full HKP protocol. The main limitations are:
- No support for `op=vindex`,
- only exact matches for user IDs are returned (i.e. `exact=on` is
always assumed),
- the `fingerprint` variable is ignored,
- the `nm` option is ignored,
- `op=index` returns either one or no keys,
- uploads are restricted to 1 MiB,
- all packets that aren't public keys, user IDs or signatures are filtered out.
### VKS
Hagrid has its own URL scheme to fetch keys.
#### `GET /vks/v1/by-fingerprint/`
Retrieves the key with the given *Fingerprint*. *Fingerprint* may
refer to the primary key, or any subkey. Hexadecimal digits MUST be
uppercase, and MUST NOT be prefixed with `0x`. The returned key is
*ASCII Armored*.
#### `GET /vks/v1/by-keyid/`
Retrieves the key with the given long *KeyID*. *KeyID* may refer to
the primary key, or any subkey. Hexadecimal digits MUST be uppercase,
and MUST NOT be prefixed with `0x`. The returned key is *ASCII
Armored*.
#### `GET /vks/v1/by-email/`
Retrieves the key with the given *User ID*. Only exact matches are
accepted. Lookup by *User ID* requires opt-in by the key's owner.
The returned key is *ASCII Armored*.
#### `POST /vks/v1/publish`
Keys may be submitted using a POST request to `/vks/v1/publish`, the
body of the request being a `multipart/form-data` query. `keytext`
must be the keys to submit, either *ASCII Armored* or not. More than
one key may be submitted in one request. Hagrid will send
verification emails to every non-expired *User ID*.
Building
--------
Building Hagrid requires a working nightly Rust toolchain. The
easiest way to get the toolchain is to download [rustup](https://rustup.rs).
After rustup is installed, get the nightly compiler and tools:
```bash
cd hagrid
rustup override set nightly
```
The web server can now be built with the cargo command:
```bash
cargo build --release
```
After compilation a binary is placed in `target/release/` called
`hagrid`. The binary is linked statically and can be copied everywhere.
```bash
cp target/release/hagrid /usr/local/bin
```
To deploy the key server copy all directories under `dist/` to a
writable location, and create a suitable configuration file.
```bash
mkdir /var/lib/hagrid
cp -R dist/* /var/lib/hagrid
cp Rocket.toml.dist /var/lib/hagrid/Rocket.toml
$EDITOR /var/lib/hagrid/Rocket.toml
/usr/bin/env --chdir=/var/lib/hagrid ROCKET_ENV=production hagrid
```
This will spawn the server in foreground. The server will put all
keys and runtime data under the base folder (`/var/lib/hagrid` in the
above example).
Reverse Proxy
-------------
Hagrid is designed to defer lookups to reverse proxy server like Nginx
and Apache. The key database is a set of 3 directories with static
files in them. The directory structure reflects Hagrids URL
scheme. This way, lookups via `/vks/v1/by-finingerprint`,
`/vks/v1/by-keyid`, and `/vks/v1/by-email` can be handled by (multiple)
simple HTTP server(s). A sample configuration for Nginx is part of the
repository (`nginx.conf`).
Community
---------
We're in `##hagrid` on Freenode.