A simple OpenPGP public key server that validates email address ownership of uploaded keys.
Go to file
2016-06-06 19:54:44 +02:00
.elasticbeanstalk Use Amazon SES on travis 2016-06-06 19:44:12 +02:00
config Implement Email DAO for sending verification mails 2016-05-29 16:47:45 +02:00
res Use Amazon SES on travis 2016-06-06 19:44:12 +02:00
src Add support for vindex op 2016-06-02 23:32:23 +02:00
test Fix email-test.js in travis 2016-06-06 19:54:44 +02:00
.gitignore Add .vscode to gitignore 2016-05-26 13:46:45 +02:00
.jscsrc Implement MongoDB client 2016-05-26 08:35:46 +02:00
.jshintrc Implement MongoDB client 2016-05-26 08:35:46 +02:00
.travis.yml Use Amazon SES on travis 2016-06-06 19:44:12 +02:00
Gruntfile.js Implement MongoDB client 2016-05-26 08:35:46 +02:00
index.js Implement public-key requestRemove and verifyRemove 2016-06-01 08:59:25 +02:00
LICENSE Initial commit 2016-05-25 08:57:32 +02:00
package.json Use nodemailer-openpgp plugin to encrypt verification emails 2016-06-02 16:19:54 +02:00
README.md Implement hkp index/mr 2016-06-02 20:43:58 +02:00

Mailvelope Keyserver Build Status

A simple OpenPGP public key server that validates email address ownership of uploaded keys.

Why not use Web of Trust?

There are already OpenPGP key servers like the SKS keyserver that employ the Web of Trust to provide a way to authenticate a user's PGP keys. The problem with these servers are discussed here.

Privacy

The web of trust raises some valid privacy concerns. Not only is a user's social network made public, common SKS servers are also not compliant with the EU Data Protection Directive due to lack of key deletion. This key server addresses these issues by not employing the web of trust and by allowing key removal.

Usability

The main issue with the Web of Trust though is that it does not scale in terms of usability. The goal of this key server is to enable a better user experience for OpenPGP user agents by providing a more reliable source of public keys. Similar to messengers like Signal, users verify their email address by clicking on a link of a PGP encrypted message. This prevents user A from uploading a public key for user B. With this property in place, automatic key lookup is more reliable than with standard SKS servers.

This requires more trust to be placed in the service provider that hosts a key server, but we believe that this trade-off is necessary to improve the user experience for average users. Tech-savvy users or users with a threat model that requires stronger security may still choose to verify PGP key fingerprints just as before.

Standardization and (De)centralization

The idea is that an identity provider such as an email provider can host their own key directory under a common openpgpkeys subdomain. An OpenPGP supporting user agent should attempt to lookup keys under the user's domain e.g. https://openpgpkeys.example.com for user@example.com first. User agents can host their own fallback key server as well, in case a mail provider does not provide its own key directory.

Api

The key server provides a modern RESTful api over HTTPS, but is also backwards compatible to the OpenPGP HTTP Keyserver Protocol (HKP) for key upload and lookup.

HKP api

Upload a new key

POST /pks/add

HTTP Request Headers

'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'

Payload (Form data):

  • keytext: The ascii armored public PGP key to be uploaded

Example:

keytext=-----BEGIN PGP PUBLIC KEY BLOCK----- ... -----END PGP PUBLIC KEY BLOCK-----

Lookup a key

Currently only the get and index (with options=mr) operations are implemented. Other operations will return a 501 (not implemented) http error code.

By key id (get)

GET /pks/lookup?op=get&search=0x0123456789ABCDEF

By email address (get, mr)

GET /pks/lookup?op=get&options=mr&search=user@example.com

By key id (index, mr)

GET /pks/lookup?op=index&options=mr&search=0x0123456789ABCDEF

REST api

Upload new key

POST /api/v1/key

Payload (JSON):

  • publicKeyArmored: The ascii armored public PGP key to be uploaded
  • primaryEmail (optional): The ascii armored block is parsed to check for user ids, so this parameter is purely optional. Normally a verification email is sent to every user id found in the pgp key. To prevent this behaviour, user agents can specify the user's primary email address to send out only one email.

Example:

{
  "publicKeyArmored": "-----BEGIN PGP PUBLIC KEY BLOCK----- ... -----END PGP PUBLIC KEY BLOCK-----",
  "primaryEmail": "user@example.com"
}

Verify uploaded key

GET /api/v1/verify?keyid=0123456789ABCDEF&nonce=123e4567-e89b-12d3-a456-426655440000

Lookup a key

By key id

GET /api/v1/key?keyid=0123456789ABCDEF

By email address

GET /api/v1/key?email=user@example.com
GET /user/user@example.com

Request key removal

By key id

DELETE /api/v1/key?keyid=0123456789ABCDEF

By email address

DELETE /api/v1/key?email=user@example.com

Verify key removal

GET /api/v1/verifyRemove?keyid=0123456789ABCDEF&nonce=123e4567-e89b-12d3-a456-426655440000

Development

Copy the credentials.json file into the git repo root directory. This file can be changed to configure a local development installation:

cp ./res/credentials.json .

Requirements

The server is written is in JavaScript ES6 and runs on Node.js v4+. It uses MongoDB v2.4+ as its database.

Install Node.js (Mac OS)

This is how to install node on Mac OS using homebrew. For other operating systems, please refer to the Node.js download page.

brew update
brew install node

Setup local MongoDB (Mac OS)

This is the installation guide to get a local development installation on Mac OS using homebrew. For other operating systems, please refer to the MongoDB Getting Started Guide.

brew update
brew install mongodb
mongod --config /usr/local/etc/mongod.conf

Now the mongo daemon should be running in the background. To have mongo start automatically as a background service on startup you can also do:

brew services start mongodb

Now you can use the mongo CLI client to create a new test database. The username and password used here match the ones in the credentials.json file. Be sure to change them for production use:

mongo
use keyserver-test
db.createUser({ user:"keyserver-user", pwd:"trfepCpjhVrqgpXFWsEF", roles:[{ role:"readWrite", db:"keyserver-test" }] })

Setup SMTP user

The key server uses nodemailer to send out emails upon public key upload to verify email address ownership. To test this feature locally, open the credentials.json file and change the smtp.user and smtp.pass attributes to your Gmail test account. Make sure that smtp.user and sender.email match. Otherwise the Gmail SMTP server will block any emails you try to send. Also, make sure to enable Allow less secure apps in the Gmail security settings. You can read more on this in the Nodemailer documentation.

For production you should use a service like Amazon SES, Mailgun or Sendgrid. Nodemailer supports all of these out of the box.

Install dependencies and run tests

npm install && npm test

Start local server

npm start

Production

The credentials.json file can be used to configure a local development installation. For production use, the following environment variables need to be set:

  • NODE_ENV=production
  • MONGO_URI=127.0.0.1:27017/test_db
  • MONGO_USER=db_user
  • MONGO_PASS=db_password
  • SMTP_HOST=127.0.0.1
  • SMTP_PORT=465
  • SMTP_TLS=true
  • SMTP_STARTTLS=true
  • SMTP_PGP=true
  • SMTP_USER=smtp_user
  • SMTP_PASS=smtp_pass
  • SENDER_NAME="OpenPGP Key Server"
  • SENDER_EMAIL=noreply@example.com

License

AGPL v3.0

See the LICENSE file for details

Libraries

Among others, this project relies on the following open source libraries: