This commit is contained in:
Yarmo Mackenbach 2020-11-06 18:35:28 +01:00
parent 21c72f63e2
commit ffbc75a945
26 changed files with 613 additions and 60 deletions

View file

@ -1,6 +1,7 @@
# doip.js # doip.js
doip.js allows browsers and Node.js projects to verify decentralized online identities based on OpenPGP. doip.js allows websites and Node.js projects to verify decentralized online
identities based on OpenPGP.
## Features ## Features
@ -14,16 +15,27 @@ doip.js allows browsers and Node.js projects to verify decentralized online iden
## About Keyoxide ## About Keyoxide
[Keyoxide](https://keyoxide.org/), made by Yarmo Mackenbach, is a modern, secure and privacy-friendly platform to establish decentralized online identities using a novel concept know as [DOIP](doip.md). In an effort to make this technology accessible for other projects and stimulate the emergence of both complementary and competing projects, this project-agnostic library is [published on codeberg.org](https://codeberg.org/keyoxide/doipjs) and open sourced under the [Apache-2.0](https://codeberg.org/keyoxide/doipjs/src/branch/main/LICENSE) license. [Keyoxide](https://keyoxide.org/), made by Yarmo Mackenbach, is a modern, secure
and privacy-friendly platform to establish decentralized online identities using
a novel concept know as [DOIP](doip.md). In an effort to make this technology
accessible for other projects and stimulate the emergence of both complementary
and competing projects, this project-agnostic library is
[published on codeberg.org](https://codeberg.org/keyoxide/doipjs) and open
sourced under the
[Apache-2.0](https://codeberg.org/keyoxide/doipjs/src/branch/main/LICENSE)
license.
## Community ## Community
There's a [Keyoxide Matrix room](https://matrix.to/#/#keyoxide:matrix.org) where we discuss everything DOIP and Keyoxide. There's a [Keyoxide Matrix room](https://matrix.to/#/#keyoxide:matrix.org) where
we discuss everything DOIP and Keyoxide.
## Donate ## Donate
Please consider [donating](https://liberapay.com/Keyoxide/) if you think this project is a step in the right direction for the internet. Please consider [donating](https://liberapay.com/Keyoxide/) if you think this
project is a step in the right direction for the internet.
## Funding ## Funding
This library was realized with funding from [NLnet](https://nlnet.nl/project/Keyoxide/). This library was realized with funding from
[NLnet](https://nlnet.nl/project/Keyoxide/).

View file

@ -1,6 +1,8 @@
- Getting started - Getting started
- [Quick start](quickstart.md) - [Installation](installation.md)
- [Configuration](configuration.md) - [Quick start (Node.js)](quickstart-nodejs.md)
- [Quick start (browser)](quickstart-browser.md)
- [Terminology](terminology.md)
- Reference - Reference
- [API](api.md) - [API](api.md)
@ -8,13 +10,25 @@
- Concepts - Concepts
- [DOIP](doip.md) - [DOIP](doip.md)
- [Cryptographic keys](cryptographickeys.md)
- [Proofs](proofs.md) - [Proofs](proofs.md)
- [Claims](claims.md) - [Claims](claims.md)
- [Service providers](serviceproviders,md) - [Service providers](serviceproviders.md)
- Service providers - Service providers
- [Liberapay](serviceproviders/liberapay.md) - [dev.to](serviceproviders/devto.md)
- [discourse](serviceproviders/discourse.md)
- [dns](serviceproviders/dns.md)
- [fediverse](serviceproviders/fediverse.md)
- [gitea](serviceproviders/gitea.md)
- [github](serviceproviders/github.md)
- [gitlab](serviceproviders/gitlab.md)
- [hackernews](serviceproviders/hackernews.md)
- [liberapay](serviceproviders/liberapay.md)
- [lobste.rs](serviceproviders/lobsters.md)
- [mastodon](serviceproviders/mastodon.md)
- [reddit](serviceproviders/reddit.md)
- [twitter](serviceproviders/twitter.md)
- [xmpp](serviceproviders/xmpp.md)
- More - More
- [Changelog](changelog.md) - [Changelog](changelog.md)

View file

@ -8,6 +8,15 @@ identity, the other being a [proof](proofs.md).
A claim is always a phrase, string or URI that is expected to be found inside A claim is always a phrase, string or URI that is expected to be found inside
the proof. **The presence of a claim inside a proof verifies that claim.** the proof. **The presence of a claim inside a proof verifies that claim.**
## Claims in OpenPGP keys
DOIP assumes claims are stored in OpenPGP keys as so-called notations. The
format for all claims is the same:
```
proof@metacode.biz=...
```
## Relation with proof ## Relation with proof
The relation between proof and claim is defined by three variables: `format`, The relation between proof and claim is defined by three variables: `format`,

View file

@ -1 +0,0 @@
# Configuration

View file

@ -1 +0,0 @@
# Cryptographic keys

View file

@ -1 +1,81 @@
# Decentralized OpenPGP Identity Proofs # Decentralized OpenPGP Identity Proofs
Decentralized OpenPGP Identity Proofs, or DOIPs, are a way of identifying
and linking profiles and accounts on the internet. Take ten different websites
and make an account on each of them. How could outsiders tell they were created
by the same person? They can't directly. You could be **Alice** on website A but
**Alice123** on website B.
What if a bad actor creates an account **Alice** on a brand new website and
starts contacting people you know from website A? How could they verify this new
accounts is in fact you?
With the digital realm becoming more and more a second home in our lives, we
need tools to identify ourselves and stay safe.
## Why decentralized?
Say you have a Facebook or Google account. You can use that to create accounts
on different websites. Problem solved! That is, until the day you get an email
that your account was flagged by AI, you just lost access to all those websites
and there's no way to contact them to restore it.
This [happens way too often](https://www.businessinsider.com/google-users-locked-out-after-years-2020-10?international=true&r=US&IR=T).
Why does it happen? You are a number to them. Losing you as a user doesn't cost
them anything.
Therefore, it is imperative that new solutions give the people **sovereignty**
over their identity. How do we do this? By making new solutions
**decentralized**.
**Decentralized** simply means that there is no central authority. In the
classic model, you give your data to Facebook or Google and the truth is what
they say it is: if they say you no longer exist, then, well, you no longer
exist. In the **decentralized** model, you hold your own data and no one can
take that away from you. This also means that service providers should fight for
you to keep you as a user since **you allow them to use your data**. Any misstep
on their behalf and you can take it away.
## Why OpenPGP?
To achieve user sovereignty, DOIP relies on **OpenPGP** cryptographic keys. Read
more about those keys [here](cryptographickeys.md) but in short: they are like
documents that the whole world can read but only you can edit. In that way, you
can publish a list of profiles on websites that you have created but no one can
do that for you in an attempt to impersonate you.
## Bidirectional linking
There's a catch: simply adding a link to a profile inside your OpenPGP document
is not sufficient. If it were, you could claim any profile anywhere simply by
linking to them!
This is why DOIP uses two-way or bidirectional linking. Your key must link to a
profile and your profile must link back to the key. That is the only way to make
sure you hold both the key and the profile.
This also solves the imposter problem. A bad actor could you link to your
profile but since your profile doesn't link back to their key, DOIP will not
verify their claim. Unless they hacked your profile, in which case you have more
urgent problems.
How does a profile link to a cryptographic key? Every key can be uniquely
identified using what we call their **fingerprint**. All a profile page needs to
do is contain that fingerprint somehow. Usually, this can be added as the last
line to a biography.
Note that the service provider itself needs to do a few things to support the
verification of DOIPs. Please refer to the [list of supported service providers](serviceproviders.md)
## Adding more than one proof
The endgame of using DOIP is to add at least two profile. Proving that you own
a single profile—in a way—doesn't prove anything. The issue is that
we cannot prove that **you**, the physical being **you**, holds that key. DOIP
can only verify that "*whoever holds that key also holds that profile*".
By adding at least two profiles, you can create meaningful links between those
profiles. If someone knows **you**, the physical being **you**, is **Alice** on
website A, they will also now know that you are **Alice123** on website B,
simply because "*whoever holds that key also holds both of those profiles*".

21
docs/installation.md Normal file
View file

@ -0,0 +1,21 @@
# Installation
Install using **yarn**:
```bash
yarn add doipjs
```
Install using **NPM**:
```bash
npm install --save doipjs
```
Install on website by including the following HTML snippet:
```html
<script src="https://cdn.jsdelivr.net/npm/keyoxide@0.3.0/dist/doip.min.js"></script>
```
Next step: [quick start (Node.js)](quickstart-nodejs.md) and [quick start (browser)](quickstart-browser.md)

View file

@ -0,0 +1,14 @@
# Quick start (browser)
Basic example:
```javascript
const verifyIdentity = async (url, fp) => {
console.log(await doip.verify(url, fp))
}
verifyIdentity('dns:doip.rocks', '9f0048ac0b23301e1f77e994909f6bd6f80f485d')
```
This snippet works en will verify the [doip.rocks](https://doip.rocks) domain as
linked to Yarmo's cryptographic key using the [dns](serviceproviders/dns.md)
service provider.

16
docs/quickstart-nodejs.md Normal file
View file

@ -0,0 +1,16 @@
# Quick start (Node.js)
Basic example:
```javascript
const doip = require('doip')
const verifyIdentity = async (url, fp) => {
console.log(await doip.verify(url, fp))
}
verifyIdentity('dns:doip.rocks', '9f0048ac0b23301e1f77e994909f6bd6f80f485d')
```
This snippet works en will verify the [doip.rocks](https://doip.rocks) domain as
linked to Yarmo's cryptographic key using the [dns](serviceproviders/dns.md)
service provider.

View file

@ -1,47 +0,0 @@
# Quick start
## Installation
Install using **yarn**:
```bash
yarn add doipjs
```
Install using **NPM**:
```bash
npm install --save doipjs
```
## Usage (Node.js)
Basic example:
```javascript
const doip = require('doip')
const verifyIdentity = async (url, fp) => {
console.log(await doip.verify(url, fp))
}
verifyIdentity('dns:doip.rocks', '9f0048ac0b23301e1f77e994909f6bd6f80f485d')
```
This snippet works en will verify the [doip.rocks](https://doip.rocks) domain as
linked to Yarmo's cryptographic key using the [dns](serviceproviders/dns.md)
service provider.
## Usage (browser)
The same code as above, but for the browser:
```html
<script src="https://cdn.jsdelivr.net/npm/keyoxide@0.3.0/dist/doip.min.js"></script>
```
```javascript
const verifyIdentity = async (url, fp) => {
console.log(await doip.verify(url, fp))
}
verifyIdentity('dns:doip.rocks', '9f0048ac0b23301e1f77e994909f6bd6f80f485d')
```

View file

@ -1 +1,18 @@
# Service providers # Service providers
Currently, the following service providers are supported:
- dev.to ([documentation](serviceproviders/devto.md) - [official website](https://dev.to/))
- discourse ([documentation](serviceproviders/discourse.md) - [official website](https://www.discourse.org/))
- dns ([documentation](serviceproviders/dns.md))
- fediverse ([documentation](serviceproviders/fediverse.md))
- gitea ([documentation](serviceproviders/gitea.md) - [official website](https://gitea.io/))
- github ([documentation](serviceproviders/github.md) - [official website](https://github.com/))
- gitlab ([documentation](serviceproviders/gitlab.md) - [official website](https://about.gitlab.com/))
- hackernews ([documentation](serviceproviders/hackernews.md) - [official website](https://news.ycombinator.com/))
- liberapay ([documentation](serviceproviders/liberapay.md) - [official website](https://liberapay.com/))
- lobste.rs ([documentation](serviceproviders/lobsters.md) - [official website](https://lobste.rs/))
- mastodon ([documentation](serviceproviders/mastodon.md) - [official website](https://joinmastodon.org/))
- reddit ([documentation](serviceproviders/reddit.md) - [official website](https://www.reddit.com/))
- twitter ([documentation](serviceproviders/twitter.md) - [official website](https://twitter.com/home))
- xmpp ([documentation](serviceproviders/xmpp.md) - [official website](https://xmpp.org/))

View file

@ -0,0 +1,21 @@
# dev.to
## Proof
Proofs are defined as posts and should contain the following information:
```
This is an OpenPGP proof that connects [my OpenPGP key](https://keyoxide.org/FINGERPRINT) to [this dev.to account](https://dev.to/USERNAME). For details check out https://keyoxide.org/guides/openpgp-proofs
[Verifying my OpenPGP key: openpgp4fpr:FINGERPRINT]
```
Make sure to replace `FINGERPRINT` and `USERNAME`.
## Claim
```
https://dev.to/USERNAME/POST_TITLE
```
Make sure to replace `USERNAME` and `POST_TITLE`.

View file

@ -0,0 +1,21 @@
# discourse
## Proof
Proofs are defined by including the following information in the **About me**:
```
This is an OpenPGP proof that connects my OpenPGP key to this Discourse account. For details check out https://keyoxide.org/guides/openpgp-proofs
[Verifying my OpenPGP key: openpgp4fpr:FINGERPRINT]
```
Make sure to replace `FINGERPRINT`.
## Claim
```
https://DOMAIN/u/USERNAME
```
Make sure to replace `DOMAIN` and `USERNAME`.

View file

@ -0,0 +1,19 @@
# dns
## Proof
Proofs are defined by adding a **TXT** record to the DNS records:
```
openpgp4fpr:FINGERPRINT
```
Make sure to replace `FINGERPRINT`.
## Claim
```
dns:DOMAIN
```
Make sure to replace `DOMAIN`.

View file

@ -0,0 +1,22 @@
# fediverse
Fediverse refers to the network of ActivityPub-compatible servers.
## Proof
Proofs are defined by adding the following information to the **Bio** or
similar field:
```
[Verifying my OpenPGP key: openpgp4fpr:FINGERPRINT]
```
Make sure to replace `FINGERPRINT`.
## Claim
```
https://DOMAIN/users/USERNAME
```
Make sure to replace `DOMAIN` and `USERNAME`.

View file

@ -0,0 +1,20 @@
# gitea
## Proof
Proofs are defined by creating a public repository `gitea_proof` and setting the
description to:
```
[Verifying my OpenPGP key: openpgp4fpr:FINGERPRINT]
```
Make sure to replace `FINGERPRINT`.
## Claim
```
https://DOMAIN/USERNAME/gitea_proof
```
Make sure to replace `DOMAIN` and `USERNAME`.

View file

@ -0,0 +1,22 @@
# github
## Proof
Proofs are defined by creating a public gist and a file `openpgp.md` with the
following information:
```
This is an OpenPGP proof that connects [my OpenPGP key](https://keyoxide.org/FINGERPRINT) to [this Github account](https://github.com/USERNAME). For details check out https://keyoxide.org/guides/openpgp-proofs
[Verifying my OpenPGP key: openpgp4fpr:FINGERPRINT]
```
Make sure to replace `FINGERPRINT` and `USERNAME`.
## Claim
```
https://gist.github.com/USERNAME/GIST_ID
```
Make sure to replace `USERNAME` and `GIST_ID`.

View file

@ -0,0 +1,20 @@
# gitlab
## Proof
Proofs are defined by creating a public project with slug `gitea_proof` and
setting the description to:
```
[Verifying my OpenPGP key: openpgp4fpr:FINGERPRINT]
```
Make sure to replace `FINGERPRINT`.
## Claim
```
https://DOMAIN/USERNAME/gitlab_proof
```
Make sure to replace `DOMAIN` and `USERNAME`.

View file

@ -0,0 +1,21 @@
# hackernews
## Proof
Proofs are defined by adding the following information to the **about**:
```
This is an OpenPGP proof that connects my OpenPGP key to this Hackernews account. For details check out https://keyoxide.org/guides/openpgp-proofs
[Verifying my OpenPGP key: openpgp4fpr:FINGERPRINT]
```
Make sure to replace `FINGERPRINT`.
## Claim
```
https://news.ycombinator.com/user?id=USERNAME
```
Make sure to replace `USERNAME`.

View file

@ -1 +1,19 @@
# Liberapay # liberapay
## Proof
Proofs are defined by adding the following information to a **Statement**:
```
[Verifying my OpenPGP key: openpgp4fpr:FINGERPRINT]
```
Make sure to replace `FINGERPRINT`.
## Claim
```
https://liberapay.com/USERNAME
```
Make sure to replace `USERNAME`.

View file

@ -0,0 +1,21 @@
# lobste.rs
## Proof
Proofs are defined by adding the following information to the **About**:
```
This is an OpenPGP proof that connects my OpenPGP key to this Lobste.rs account. For details check out https://keyoxide.org/guides/openpgp-proofs
[Verifying my OpenPGP key: openpgp4fpr:FINGERPRINT]
```
Make sure to replace `FINGERPRINT`.
## Claim
```
https://lobste.rs/u/USERNAME
```
Make sure to replace `USERNAME`.

View file

@ -0,0 +1,14 @@
# mastodon
## Proof
Proofs are defined by adding an item under `Profile metadata` with `OpenPGP` as
label and the fingerprint as value.
## Claim
```
https://DOMAIN/@USERNAME
```
Make sure to replace `DOMAIN` and `USERNAME`.

View file

@ -0,0 +1,21 @@
# reddit
## Proof
Proofs are defined as posts and should contain the following information:
```
This is an OpenPGP proof that connects my OpenPGP key to this Reddit account. For details check out https://keyoxide.org/guides/openpgp-proofs
[Verifying my OpenPGP key: openpgp4fpr:FINGERPRINT]
```
Make sure to replace `FINGERPRINT`.
## Claim
```
https://reddit.com/user/USERNAME/comments/POST_ID/POST_TITLE
```
Make sure to replace `USERNAME`, `POST_ID` and `POST_TITLE`.

View file

@ -0,0 +1,21 @@
# twitter
## Proof
Proofs are defined as tweets and should contain the following information:
```
This is an OpenPGP proof that connects my OpenPGP key to this Twitter account. For details check out https://keyoxide.org/guides/openpgp-proofs
[Verifying my OpenPGP key: openpgp4fpr:FINGERPRINT]
```
Make sure to replace `FINGERPRINT`.
## Claim
```
https://twitter.com/USERNAME/status/TWEET_ID
```
Make sure to replace `USERNAME` and `TWEET_ID`.

View file

@ -0,0 +1,29 @@
# xmpp
## Proof
Proofs are defined by adding the following information to the **About** section
of the profile's vCard information using a client that support editing that
information:
```
This is an OpenPGP proof that connects my OpenPGP key to this XMPP account. For details check out https://keyoxide.org/guides/openpgp-proofs
[Verifying my OpenPGP key: openpgp4fpr:FINGERPRINT]
```
Make sure to replace `FINGERPRINT`.
## Claim
```
xmpp:XMPP_ID
```
or with OMEMO:
```
xmpp:XMPP_ID?omemo-sid-OMEMO_DEVICE_ID=OMEMO_FINGERPRINT&...
```
Make sure to replace `XMPP_ID`, `OMEMO_DEVICE_ID` and `OMEMO_FINGERPRINT`.

129
docs/terminology.md Normal file
View file

@ -0,0 +1,129 @@
# Terminology
## Claim
A piece of data that is expected to be contained with the [proof](#proof). When
found, the claim&mdash;and the identity associated with the claim&mdash;is
verified. Within the context of this project, a claim is always the fingerprint
of an [OpenPGP](#openpgp) [cryptographic key](#cryptographic-key), but formatted
in different ways depending on the [service provider](#service-provider).
For more detailed information, please refer to [Claims](claims.md).
## Cryptographic key
According to [Wikipedia](https://en.wikipedia.org/wiki/Key_(cryptography)):
> [...] a piece of information (a parameter) that determines the functional
output of a cryptographic algorithm.
Cryptographic keys can be used to encrypt/decrypt data and verify digital
signatures.
Within the context of this project, we can view cryptographic keys as documents
that everyone can read but only one person can edit. This makes it the perfect
candidate to serve as vessel for [decentralized](#decentralized)
[identity](#identity) [claims](#claim).
## Decentralized
A model for interaction between computers or nodes in a network. Its
distinguishing feature is that this model does not rely on a central authority,
unlike traditional centralized models that are used by Facebook, Google and all
other privacy-invading corporations.
A core outcome of choosing a decentralized model is that it gives the user
**sovereignty** over their data, instead of giving all the power to the central
node. This means that [service providers](#service-provider) are **allowed** to
access a user's data, courtesy of that user. It also implies that that user can
choose to block access of any [service provider](#service-provider) at any
point in time and move to a different [service provider](#service-provider). In
this new model, [service providers](#service-provider) need to fight for access
to that user data and any user-compromising service can simply be left behind.
Within the context of this project, you store your identity claims inside a
[cryptographic key](#cryptographic-key). You can then use any compatible client
software or website to verify these claims. And if you don't like that
particular client software or website, you just choose to use a different one.
## DOIP
A protocol that describes how interactions between
[cryptographic keys](#cryptographic-key) and
[service providers](#service-provider) can be used to the advantage of the
people on the internet and allow them to publicly verify their online
[identity](#identity) in a secure manner that is resistant to impersonation.
Currently, this documentation is the most elaborate description of the inner
workings of the DOIP protocol. Drafting a standard is planned.
## Fingerprint
A string of hexadecimal characters that uniquely identifies a
[cryptographic key](#cryptographic-key).
Within the context of this project, they are used to link a [profile](#profile)
page back to a single [cryptographic key](#cryptographic-key) by mentioning this
fingerprint anywhere on the [profile](#profile) page, like inside a biography.
## Identity
Within the context of this project, identity refers to a person's
**digital online identity**, the collection of [profiles](#profile) that a
person holds and that partially accounts for a person's online activity. A
physical person can have multiple online identities, for example a private
identity and a work-related identity.
That collection of [profiles](#profile) can be stored inside
[cryptographic key](#cryptographic-key).
## OpenPGP
A standard for [cryptographic keys](#cryptographic-key) defined by
[RFC 4880](https://tools.ietf.org/html/rfc4880).
## Profile
A piece of data that is created by a physical person but stored and managed on
the servers of a [service provider](#service-provider). While a person does not
own that data, it does define them as part of their online
[identity](#identity).
Usually, a [service provider](#service-provider) generates a profile page based
on that user data that displays basic information like a username, an avatar and
a biography.
## Proof
A piece of data provided a [service provider](#service-provider) that contains
at least some of the data that it stores on a specific user. That piece of data
also is publicly available to all, usually as a JSON document.
A [claim](#claim) expects the proof to contain a certain statement. For
[DOIP](#doip), this statement is a [fingerprint](#fingerprint).
For more detailed information, please refer to [Proofs](proofs.md).
## Proxy
A piece of software that handles the request for proof instead of the original
piece of software that called the proxy. This is useful when doip.js is used in
browsers. Some [service providers](#service-provider) do not allow their public
data to be accessed by other websites (so called CORS restrictions,
[Wikipedia](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)) but
requests from non-browser origin are accepted and fulfilled. Doip.js when used
in a browser will let proxy servers handle their requests for them to eliminate
this friction.
Doip.js requires a proxy server to run the open source
[doip-proxy software](https://codeberg.org/keyoxide/doip-proxy).
## Service provider
A company, organization or protocol that stores [profiles](#profile) submitted
by their users. The data associated to those [profiles](#profile) should at
least be partially made publicly available to allow identity verification using
[DOIP](#doip).
For more information, please refer to [Service providers](serviceproviders.md).